diff --git a/contracts/Executor.sol b/contracts/Executor.sol index 8f150426..9715e8c4 100644 --- a/contracts/Executor.sol +++ b/contracts/Executor.sol @@ -13,7 +13,8 @@ contract Executor is IExternalExecutor, Ownable { address target, uint256 value, bytes calldata payload - ) external payable onlyOwner returns (bytes memory result) { + ) external payable returns (bytes memory result) { + _checkOwner(); result = Address.functionCallWithValue(target, payload, value); } diff --git a/contracts/ResealManager.sol b/contracts/ResealManager.sol index 99964e14..efac9bd1 100644 --- a/contracts/ResealManager.sol +++ b/contracts/ResealManager.sol @@ -19,7 +19,8 @@ contract ResealManager is IResealManager { EMERGENCY_PROTECTED_TIMELOCK = emergencyProtectedTimelock; } - function reseal(address[] memory sealables) public onlyGovernance { + function reseal(address[] memory sealables) public { + _checkSenderIsGovernance(); for (uint256 i = 0; i < sealables.length; ++i) { uint256 sealableResumeSinceTimestamp = ISealable(sealables[i]).getResumeSinceTimestamp(); if (sealableResumeSinceTimestamp < block.timestamp || sealableResumeSinceTimestamp == PAUSE_INFINITELY) { @@ -30,7 +31,8 @@ contract ResealManager is IResealManager { } } - function resume(address sealable) public onlyGovernance { + function resume(address sealable) public { + _checkSenderIsGovernance(); uint256 sealableResumeSinceTimestamp = ISealable(sealable).getResumeSinceTimestamp(); if (sealableResumeSinceTimestamp < block.timestamp) { revert SealableWrongPauseState(); @@ -38,11 +40,10 @@ contract ResealManager is IResealManager { Address.functionCall(sealable, abi.encodeWithSelector(ISealable.resume.selector)); } - modifier onlyGovernance() { + function _checkSenderIsGovernance() internal view { address governance = EMERGENCY_PROTECTED_TIMELOCK.getGovernance(); if (msg.sender != governance) { revert SenderIsNotGovernance(); } - _; } } diff --git a/contracts/committees/EmergencyActivationCommittee.sol b/contracts/committees/EmergencyActivationCommittee.sol index d71b6e33..b73724d2 100644 --- a/contracts/committees/EmergencyActivationCommittee.sol +++ b/contracts/committees/EmergencyActivationCommittee.sol @@ -27,7 +27,8 @@ contract EmergencyActivationCommittee is HashConsensus { /// @notice Approves the emergency activation by casting a vote /// @dev Only callable by committee members - function approveEmergencyActivate() public onlyMember { + function approveEmergencyActivate() public { + _checkSenderIsMember(); _vote(EMERGENCY_ACTIVATION_HASH, true); } diff --git a/contracts/committees/EmergencyExecutionCommittee.sol b/contracts/committees/EmergencyExecutionCommittee.sol index d146071a..d52c09f1 100644 --- a/contracts/committees/EmergencyExecutionCommittee.sol +++ b/contracts/committees/EmergencyExecutionCommittee.sol @@ -38,7 +38,8 @@ contract EmergencyExecutionCommittee is HashConsensus, ProposalsList { /// @dev Only callable by committee members /// @param proposalId The ID of the proposal to vote on /// @param _supports Indicates whether the member supports the proposal execution - function voteEmergencyExecute(uint256 proposalId, bool _supports) public onlyMember { + function voteEmergencyExecute(uint256 proposalId, bool _supports) public { + _checkSenderIsMember(); (bytes memory proposalData, bytes32 key) = _encodeEmergencyExecute(proposalId); _vote(key, _supports); _pushProposal(key, uint256(ProposalType.EmergencyExecute), proposalData); @@ -88,7 +89,8 @@ contract EmergencyExecutionCommittee is HashConsensus, ProposalsList { /// @notice Approves an emergency reset proposal /// @dev Only callable by committee members - function approveEmergencyReset() public onlyMember { + function approveEmergencyReset() public { + _checkSenderIsMember(); bytes32 proposalKey = _encodeEmergencyResetProposalKey(); _vote(proposalKey, true); _pushProposal(proposalKey, uint256(ProposalType.EmergencyReset), bytes("")); diff --git a/contracts/committees/HashConsensus.sol b/contracts/committees/HashConsensus.sol index e7916193..4df17083 100644 --- a/contracts/committees/HashConsensus.sol +++ b/contracts/committees/HashConsensus.sol @@ -113,7 +113,8 @@ abstract contract HashConsensus is Ownable { /// @dev Only callable by the owner /// @param newMember The address of the new member /// @param newQuorum The new quorum value - function addMember(address newMember, uint256 newQuorum) public onlyOwner { + function addMember(address newMember, uint256 newQuorum) public { + _checkOwner(); _addMember(newMember); if (newQuorum == 0 || newQuorum > _members.length()) { @@ -127,7 +128,9 @@ abstract contract HashConsensus is Ownable { /// @dev Only callable by the owner /// @param memberToRemove The address of the member to remove /// @param newQuorum The new quorum value - function removeMember(address memberToRemove, uint256 newQuorum) public onlyOwner { + function removeMember(address memberToRemove, uint256 newQuorum) public { + _checkOwner(); + if (!_members.contains(memberToRemove)) { revert IsNotMember(); } @@ -159,7 +162,8 @@ abstract contract HashConsensus is Ownable { /// @notice Sets the timelock duration /// @dev Only callable by the owner /// @param timelock The new timelock duration in seconds - function setTimelockDuration(uint256 timelock) public onlyOwner { + function setTimelockDuration(uint256 timelock) public { + _checkOwner(); timelockDuration = timelock; emit TimelockDurationSet(timelock); } @@ -167,7 +171,8 @@ abstract contract HashConsensus is Ownable { /// @notice Sets the quorum value /// @dev Only callable by the owner /// @param newQuorum The new quorum value - function setQuorum(uint256 newQuorum) public onlyOwner { + function setQuorum(uint256 newQuorum) public { + _checkOwner(); if (newQuorum == 0 || newQuorum > _members.length()) { revert InvalidQuorum(); } @@ -200,11 +205,10 @@ abstract contract HashConsensus is Ownable { } /// @notice Restricts access to only committee members - /// @dev Modifier to ensure that only members can call a function - modifier onlyMember() { + /// @dev Reverts if the sender is not a member + function _checkSenderIsMember() internal view { if (!_members.contains(msg.sender)) { revert SenderIsNotMember(); } - _; } } diff --git a/contracts/committees/ResealCommittee.sol b/contracts/committees/ResealCommittee.sol index 7b7d27d4..5284c9b2 100644 --- a/contracts/committees/ResealCommittee.sol +++ b/contracts/committees/ResealCommittee.sol @@ -31,7 +31,8 @@ contract ResealCommittee is HashConsensus, ProposalsList { /// @dev Allows committee members to vote on resealing a set of addresses /// @param sealables The addresses to reseal /// @param support Indicates whether the member supports the proposal - function voteReseal(address[] memory sealables, bool support) public onlyMember { + function voteReseal(address[] memory sealables, bool support) public { + _checkSenderIsMember(); (bytes memory proposalData, bytes32 key) = _encodeResealProposal(sealables); _vote(key, support); _pushProposal(key, 0, proposalData); diff --git a/contracts/committees/TiebreakerCore.sol b/contracts/committees/TiebreakerCore.sol index ee9d6978..aea111fb 100644 --- a/contracts/committees/TiebreakerCore.sol +++ b/contracts/committees/TiebreakerCore.sol @@ -42,7 +42,8 @@ contract TiebreakerCore is HashConsensus, ProposalsList { /// @notice Votes on a proposal to schedule /// @dev Allows committee members to vote on scheduling a proposal /// @param proposalId The ID of the proposal to schedule - function scheduleProposal(uint256 proposalId) public onlyMember { + function scheduleProposal(uint256 proposalId) public { + _checkSenderIsMember(); (bytes memory proposalData, bytes32 key) = _encodeScheduleProposal(proposalId); _vote(key, true); _pushProposal(key, uint256(ProposalType.ScheduleProposal), proposalData); @@ -96,7 +97,8 @@ contract TiebreakerCore is HashConsensus, ProposalsList { return _sealableResumeNonces[sealable]; } - function sealableResume(address sealable, uint256 nonce) public onlyMember { + function sealableResume(address sealable, uint256 nonce) public { + _checkSenderIsMember(); if (nonce != _sealableResumeNonces[sealable]) { revert ResumeSealableNonceMismatch(); } diff --git a/contracts/committees/TiebreakerSubCommittee.sol b/contracts/committees/TiebreakerSubCommittee.sol index 3924ecef..09f9fa4b 100644 --- a/contracts/committees/TiebreakerSubCommittee.sol +++ b/contracts/committees/TiebreakerSubCommittee.sol @@ -38,7 +38,8 @@ contract TiebreakerSubCommittee is HashConsensus, ProposalsList { /// @notice Votes on a proposal to schedule /// @dev Allows committee members to vote on scheduling a proposal /// @param proposalId The ID of the proposal to schedule - function scheduleProposal(uint256 proposalId) public onlyMember { + function scheduleProposal(uint256 proposalId) public { + _checkSenderIsMember(); (bytes memory proposalData, bytes32 key) = _encodeAproveProposal(proposalId); _vote(key, true); _pushProposal(key, uint256(ProposalType.ScheduleProposal), proposalData); diff --git a/docs/plan-b.md b/docs/plan-b.md index 1674a677..adc88c1a 100644 --- a/docs/plan-b.md +++ b/docs/plan-b.md @@ -335,7 +335,7 @@ Initializes the contract with an owner, committee members, a quorum, and the add ### Function: `EmergencyActivationCommittee.approveEmergencyActivate` ```solidity -function approveEmergencyActivate() public onlyMember +function approveEmergencyActivate() public ``` Approves the emergency activation by voting on the `EMERGENCY_ACTIVATION_HASH`. @@ -379,7 +379,7 @@ Initializes the contract with an owner, committee members, a quorum, and the add ### Function: `EmergencyExecutionCommittee.voteEmergencyExecute` ```solidity -function voteEmergencyExecute(uint256 proposalId, bool _supports) public onlyMember +function voteEmergencyExecute(uint256 proposalId, bool _supports) public ``` Allows committee members to vote on an emergency execution proposal. @@ -406,7 +406,7 @@ Executes an emergency execution proposal by calling the `emergencyExecute` funct ### Function: `EmergencyExecutionCommittee.approveEmergencyReset` ```solidity -function approveEmergencyReset() public onlyMember +function approveEmergencyReset() public ``` Approves the governance reset by voting on the reset proposal. diff --git a/docs/specification.md b/docs/specification.md index 8ff2f00f..421d1111 100644 --- a/docs/specification.md +++ b/docs/specification.md @@ -417,7 +417,7 @@ Initializes the contract with the address of the EmergencyProtectedTimelock cont ### Function ResealManager.reseal ```solidity -function reseal(address[] memory sealables) public onlyGovernance +function reseal(address[] memory sealables) public ``` Extends the pause of the specified `sealables` contracts. This function can be called by the governance address defined in the `EmergencyProtectedTimelock`. @@ -435,7 +435,7 @@ Extends the pause of the specified `sealables` contracts. This function can be c ### Function: ResealManager.resume ```solidity -function resume(address sealable) external onlyGovernance +function resume(address sealable) external ``` Resumes the specified `sealable` contract if it is scheduled to resume in the future. @@ -450,14 +450,6 @@ Resumes the specified `sealable` contract if it is scheduled to resume in the fu - `SealableWrongPauseState`: Thrown if the sealable contract is in the wrong pause state. - `SenderIsNotGovernance`: Thrown if the sender is not the governance address. -### Modifier: ResealManager.onlyGovernance - -```solidity -modifier onlyGovernance() -``` - -Ensures that the function can only be called by the governance address. - #### Preconditions - The sender MUST be the governance address obtained from the `EmergencyProtectedTimelock` contract. @@ -1139,7 +1131,7 @@ Initializes the contract with an owner, committee members, a quorum, the address ### Function: TiebreakerCore.scheduleProposal ```solidity -function scheduleProposal(uint256 proposalId) public onlyMember +function scheduleProposal(uint256 proposalId) public ``` Schedules a proposal for execution by voting on it and adding it to the proposal list. @@ -1182,7 +1174,7 @@ Returns the current nonce for resuming operations of a sealable contract. ### Function: TiebreakerCore.sealableResume ```solidity -function sealableResume(address sealable, uint256 nonce) public onlyMember +function sealableResume(address sealable, uint256 nonce) public ``` Submits a request to resume operations of a sealable contract by voting on it and adding it to the proposal list. @@ -1239,7 +1231,7 @@ Initializes the contract with an owner, committee members, a quorum, and the add ### Function: TiebreakerSubCommittee.scheduleProposal ```solidity -function scheduleProposal(uint256 proposalId) public onlyMember +function scheduleProposal(uint256 proposalId) public ``` Schedules a proposal for execution by voting on it and adding it to the proposal list. @@ -1329,7 +1321,7 @@ emergencyProtectedTimelock MUST be a valid address. ### Function: EmergencyActivationCommittee.approveEmergencyActivate ```solidity -function approveEmergencyActivate() public onlyMember +function approveEmergencyActivate() public ``` Approves the emergency activation by voting on the EMERGENCY_ACTIVATION_HASH. @@ -1387,7 +1379,7 @@ Initializes the contract with an owner, committee members, a quorum, and the add ### Function: EmergencyExecutionCommittee.voteEmergencyExecute ```solidity -function voteEmergencyExecute(uint256 proposalId, bool _supports) public onlyMember +function voteEmergencyExecute(uint256 proposalId, bool _supports) public ``` Allows committee members to vote on an emergency execution proposal. @@ -1422,7 +1414,7 @@ Emergency execution proposal MUST have reached quorum and passed the timelock du ### Function: EmergencyExecutionCommittee.approveEmergencyReset ```solidity -function approveEmergencyReset() public onlyMember +function approveEmergencyReset() public ``` Approves the governance reset by voting on the reset proposal.