Files
openzeppelin-contracts/contracts/access/manager/AccessManagerAdapter.sol
Francisco fa112be682 Add AccessManager contracts (#4121)
Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
Co-authored-by: Ernesto García <ernestognw@gmail.com>
2023-03-24 19:37:08 -03:00

55 lines
2.2 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./AccessManager.sol";
import "./AccessManaged.sol";
/**
* @dev This contract can be used to migrate existing {Ownable} or {AccessControl} contracts into an {AccessManager}
* system.
*
* Ownable contracts can have their ownership transferred to an instance of this adapter. AccessControl contracts can
* grant all roles to the adapter, while ideally revoking them from all other accounts. Subsequently, the permissions
* for those contracts can be managed centrally and with function granularity in the {AccessManager} instance the
* adapter is connected to.
*
* Permissioned interactions with thus migrated contracts must go through the adapter's {relay} function and will
* proceed if the function is allowed for the caller in the AccessManager instance.
*/
contract AccessManagerAdapter is AccessManaged {
bytes32 private constant _DEFAULT_ADMIN_ROLE = 0;
/**
* @dev Initializes an adapter connected to an AccessManager instance.
*/
constructor(AccessManager manager) AccessManaged(manager) {}
/**
* @dev Relays a function call to the target contract. The call will be relayed if the AccessManager allows the
* caller access to this function in the target contract, i.e. if the caller is in a team that is allowed for the
* function, or if the caller is the default admin for the AccessManager. The latter is meant to be used for
* ad hoc operations such as asset recovery.
*/
function relay(address target, bytes memory data) external payable {
bytes4 sig = bytes4(data);
AccessManager manager = AccessManager(address(authority()));
require(
manager.canCall(msg.sender, target, sig) || manager.hasRole(_DEFAULT_ADMIN_ROLE, msg.sender),
"AccessManagerAdapter: caller not allowed"
);
(bool ok, bytes memory result) = target.call{value: msg.value}(data);
assembly {
let result_pointer := add(32, result)
let result_size := mload(result)
switch ok
case true {
return(result_pointer, result_size)
}
default {
revert(result_pointer, result_size)
}
}
}
}