123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- // SPDX-License-Identifier: MIT
- // OpenZeppelin Contracts (last updated v5.1.0-rc.1) (access/manager/AccessManaged.sol)
- pragma solidity ^0.8.20;
- import {IAuthority} from "./IAuthority.sol";
- import {AuthorityUtils} from "./AuthorityUtils.sol";
- import {IAccessManager} from "./IAccessManager.sol";
- import {IAccessManaged} from "./IAccessManaged.sol";
- import {Context} from "../../utils/Context.sol";
- /**
- * @dev This contract module makes available a {restricted} modifier. Functions decorated with this modifier will be
- * permissioned according to an "authority": a contract like {AccessManager} that follows the {IAuthority} interface,
- * implementing a policy that allows certain callers to access certain functions.
- *
- * IMPORTANT: The `restricted` modifier should never be used on `internal` functions, judiciously used in `public`
- * functions, and ideally only used in `external` functions. See {restricted}.
- */
- abstract contract AccessManaged is Context, IAccessManaged {
- address private _authority;
- bool private _consumingSchedule;
- /**
- * @dev Initializes the contract connected to an initial authority.
- */
- constructor(address initialAuthority) {
- _setAuthority(initialAuthority);
- }
- /**
- * @dev Restricts access to a function as defined by the connected Authority for this contract and the
- * caller and selector of the function that entered the contract.
- *
- * [IMPORTANT]
- * ====
- * In general, this modifier should only be used on `external` functions. It is okay to use it on `public`
- * functions that are used as external entry points and are not called internally. Unless you know what you're
- * doing, it should never be used on `internal` functions. Failure to follow these rules can have critical security
- * implications! This is because the permissions are determined by the function that entered the contract, i.e. the
- * function at the bottom of the call stack, and not the function where the modifier is visible in the source code.
- * ====
- *
- * [WARNING]
- * ====
- * Avoid adding this modifier to the https://docs.soliditylang.org/en/v0.8.20/contracts.html#receive-ether-function[`receive()`]
- * function or the https://docs.soliditylang.org/en/v0.8.20/contracts.html#fallback-function[`fallback()`]. These
- * functions are the only execution paths where a function selector cannot be unambiguously determined from the calldata
- * since the selector defaults to `0x00000000` in the `receive()` function and similarly in the `fallback()` function
- * if no calldata is provided. (See {_checkCanCall}).
- *
- * The `receive()` function will always panic whereas the `fallback()` may panic depending on the calldata length.
- * ====
- */
- modifier restricted() {
- _checkCanCall(_msgSender(), _msgData());
- _;
- }
- /// @inheritdoc IAccessManaged
- function authority() public view virtual returns (address) {
- return _authority;
- }
- /// @inheritdoc IAccessManaged
- function setAuthority(address newAuthority) public virtual {
- address caller = _msgSender();
- if (caller != authority()) {
- revert AccessManagedUnauthorized(caller);
- }
- if (newAuthority.code.length == 0) {
- revert AccessManagedInvalidAuthority(newAuthority);
- }
- _setAuthority(newAuthority);
- }
- /// @inheritdoc IAccessManaged
- function isConsumingScheduledOp() public view returns (bytes4) {
- return _consumingSchedule ? this.isConsumingScheduledOp.selector : bytes4(0);
- }
- /**
- * @dev Transfers control to a new authority. Internal function with no access restriction. Allows bypassing the
- * permissions set by the current authority.
- */
- function _setAuthority(address newAuthority) internal virtual {
- _authority = newAuthority;
- emit AuthorityUpdated(newAuthority);
- }
- /**
- * @dev Reverts if the caller is not allowed to call the function identified by a selector. Panics if the calldata
- * is less than 4 bytes long.
- */
- function _checkCanCall(address caller, bytes calldata data) internal virtual {
- (bool immediate, uint32 delay) = AuthorityUtils.canCallWithDelay(
- authority(),
- caller,
- address(this),
- bytes4(data[0:4])
- );
- if (!immediate) {
- if (delay > 0) {
- _consumingSchedule = true;
- IAccessManager(authority()).consumeScheduledOp(caller, data);
- _consumingSchedule = false;
- } else {
- revert AccessManagedUnauthorized(caller);
- }
- }
- }
- }
|