diff --git a/contracts/access/AccessControl.sol b/contracts/access/AccessControl.sol index 354aca085ca..dd2ad64b10b 100644 --- a/contracts/access/AccessControl.sol +++ b/contracts/access/AccessControl.sol @@ -96,7 +96,7 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 { * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. */ - modifier onlySenderWithRole(bytes32 role) { + modifier onlyRole(bytes32 role) { _checkRole(role, _msgSender()); _; } diff --git a/contracts/governance/TimelockController.sol b/contracts/governance/TimelockController.sol index a39cef0089e..c8af8dbc72c 100644 --- a/contracts/governance/TimelockController.sol +++ b/contracts/governance/TimelockController.sol @@ -80,7 +80,7 @@ contract TimelockController is AccessControl { * considered. Granting a role to `address(0)` is equivalent to enabling * this role for everyone. */ - modifier onlyRole(bytes32 role) { + modifier onlyRoleOrOpenRole(bytes32 role) { require(hasRole(role, _msgSender()) || hasRole(role, address(0)), "TimelockController: sender requires permission"); _; } @@ -163,7 +163,7 @@ contract TimelockController is AccessControl { * * - the caller must have the 'proposer' role. */ - function schedule(address target, uint256 value, bytes calldata data, bytes32 predecessor, bytes32 salt, uint256 delay) public virtual onlyRole(PROPOSER_ROLE) { + function schedule(address target, uint256 value, bytes calldata data, bytes32 predecessor, bytes32 salt, uint256 delay) public virtual onlyRoleOrOpenRole(PROPOSER_ROLE) { bytes32 id = hashOperation(target, value, data, predecessor, salt); _schedule(id, delay); emit CallScheduled(id, 0, target, value, data, predecessor, delay); @@ -178,7 +178,7 @@ contract TimelockController is AccessControl { * * - the caller must have the 'proposer' role. */ - function scheduleBatch(address[] calldata targets, uint256[] calldata values, bytes[] calldata datas, bytes32 predecessor, bytes32 salt, uint256 delay) public virtual onlyRole(PROPOSER_ROLE) { + function scheduleBatch(address[] calldata targets, uint256[] calldata values, bytes[] calldata datas, bytes32 predecessor, bytes32 salt, uint256 delay) public virtual onlyRoleOrOpenRole(PROPOSER_ROLE) { require(targets.length == values.length, "TimelockController: length mismatch"); require(targets.length == datas.length, "TimelockController: length mismatch"); @@ -206,7 +206,7 @@ contract TimelockController is AccessControl { * * - the caller must have the 'proposer' role. */ - function cancel(bytes32 id) public virtual onlyRole(PROPOSER_ROLE) { + function cancel(bytes32 id) public virtual onlyRoleOrOpenRole(PROPOSER_ROLE) { require(isOperationPending(id), "TimelockController: operation cannot be cancelled"); delete _timestamps[id]; @@ -222,7 +222,7 @@ contract TimelockController is AccessControl { * * - the caller must have the 'executor' role. */ - function execute(address target, uint256 value, bytes calldata data, bytes32 predecessor, bytes32 salt) public payable virtual onlyRole(EXECUTOR_ROLE) { + function execute(address target, uint256 value, bytes calldata data, bytes32 predecessor, bytes32 salt) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) { bytes32 id = hashOperation(target, value, data, predecessor, salt); _beforeCall(predecessor); _call(id, 0, target, value, data); @@ -238,7 +238,7 @@ contract TimelockController is AccessControl { * * - the caller must have the 'executor' role. */ - function executeBatch(address[] calldata targets, uint256[] calldata values, bytes[] calldata datas, bytes32 predecessor, bytes32 salt) public payable virtual onlyRole(EXECUTOR_ROLE) { + function executeBatch(address[] calldata targets, uint256[] calldata values, bytes[] calldata datas, bytes32 predecessor, bytes32 salt) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) { require(targets.length == values.length, "TimelockController: length mismatch"); require(targets.length == datas.length, "TimelockController: length mismatch"); diff --git a/contracts/mocks/AccessControlEnumerableMock.sol b/contracts/mocks/AccessControlEnumerableMock.sol index ec2cbbb103f..7b15e3602a5 100644 --- a/contracts/mocks/AccessControlEnumerableMock.sol +++ b/contracts/mocks/AccessControlEnumerableMock.sol @@ -12,4 +12,6 @@ contract AccessControlEnumerableMock is AccessControlEnumerable { function setRoleAdmin(bytes32 roleId, bytes32 adminRoleId) public { _setRoleAdmin(roleId, adminRoleId); } + + function senderProtected(bytes32 roleId) public onlyRole(roleId) {} } diff --git a/contracts/mocks/AccessControlMock.sol b/contracts/mocks/AccessControlMock.sol index 360f0a9842e..86f51477e2d 100644 --- a/contracts/mocks/AccessControlMock.sol +++ b/contracts/mocks/AccessControlMock.sol @@ -13,5 +13,5 @@ contract AccessControlMock is AccessControl { _setRoleAdmin(roleId, adminRoleId); } - function senderProtected(bytes32 roleId) public onlySenderWithRole(roleId) {} + function senderProtected(bytes32 roleId) public onlyRole(roleId) {} }