-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Timelock Fixes * remove constant * adds selector pausing logic * checks for txHash on cancelation * unify execution for multisigs * slither fix * opitmization * slither fix
- Loading branch information
1 parent
d73e83f
commit 122e116
Showing
3 changed files
with
142 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,13 +2,16 @@ | |
pragma solidity >=0.8.18; | ||
|
||
import { AccessManager } from "openzeppelin/access/manager/AccessManager.sol"; | ||
import { Address } from "@openzeppelin/contracts/utils/Address.sol"; | ||
|
||
/** | ||
* @title Timelock | ||
* @author Puffer Finance | ||
* @custom:security-contact [email protected] | ||
*/ | ||
contract Timelock { | ||
using Address for address; | ||
|
||
/** | ||
* @notice Error to be thrown when a bad address is encountered | ||
*/ | ||
|
@@ -33,6 +36,11 @@ contract Timelock { | |
*/ | ||
error Locked(bytes32 txHash, uint256 lockedUntil); | ||
|
||
/** | ||
* @notice Error to be thrown when an the params are invalid | ||
*/ | ||
error InvalidParams(); | ||
|
||
/** | ||
* @notice Emitted when the delay changes from `oldDelay` to `newDelay` | ||
*/ | ||
|
@@ -155,12 +163,40 @@ contract Timelock { | |
bytes[] memory callDatas = new bytes[](targets.length); | ||
|
||
for (uint256 i = 0; i < targets.length; ++i) { | ||
// slither-disable-next-line calls-loop | ||
callDatas[i] = abi.encodeCall(AccessManager.setTargetClosed, (targets[i], true)); | ||
} | ||
|
||
ACCESS_MANAGER.multicall(callDatas); | ||
} | ||
|
||
/** | ||
* @notice Pauses the system by closing access to specified targets selectors | ||
* @param targets An array of addresses to which access will be paused | ||
* @param selectors An array of selectors to which access will be paused | ||
*/ | ||
function pauseSelectors(address[] calldata targets, bytes4[][] calldata selectors) public { | ||
if (targets.length != selectors.length) { | ||
revert InvalidParams(); | ||
} | ||
|
||
// Community multisig can call this by via executeTransaction | ||
if (msg.sender != pauserMultisig && msg.sender != address(this)) { | ||
revert Unauthorized(); | ||
} | ||
|
||
bytes[] memory callDatas = new bytes[](targets.length); | ||
|
||
for (uint256 i = 0; i < targets.length; ++i) { | ||
// slither-disable-next-line calls-loop | ||
callDatas[i] = abi.encodeCall( | ||
AccessManager.setTargetFunctionRole, (targets[i], selectors[i], ACCESS_MANAGER.ADMIN_ROLE()) | ||
); | ||
} | ||
|
||
ACCESS_MANAGER.multicall(callDatas); | ||
} | ||
|
||
/** | ||
* @notice Cancels a queued transaction | ||
* @param target The address to which the transaction was to be sent | ||
|
@@ -174,6 +210,12 @@ contract Timelock { | |
} | ||
|
||
bytes32 txHash = keccak256(abi.encode(target, callData, operationId)); | ||
|
||
// slither-disable-next-line incorrect-equality | ||
if (queue[txHash] == 0) { | ||
revert InvalidTransaction(txHash); | ||
} | ||
|
||
queue[txHash] = 0; | ||
|
||
emit TransactionCanceled(txHash, target, callData, operationId); | ||
|
@@ -185,41 +227,36 @@ contract Timelock { | |
* @param target The address to which the transaction will be sent | ||
* @param callData The data to be sent along with the transaction | ||
* @param operationId The id of the operation used to identify the transaction | ||
* @return success A boolean indicating whether the transaction was successful | ||
* @return returnData The data returned by the transaction | ||
*/ | ||
function executeTransaction(address target, bytes calldata callData, uint256 operationId) | ||
external | ||
returns (bool success, bytes memory returnData) | ||
returns (bytes memory returnData) | ||
{ | ||
// Community Multisig can do things without any delay | ||
if (msg.sender == COMMUNITY_MULTISIG) { | ||
return _executeTransaction(target, callData); | ||
} | ||
|
||
// Operations multisig needs to queue it and then execute after a delay | ||
if (msg.sender != OPERATIONS_MULTISIG) { | ||
revert Unauthorized(); | ||
} | ||
|
||
bytes32 txHash = keccak256(abi.encode(target, callData, operationId)); | ||
uint256 lockedUntil = queue[txHash]; | ||
|
||
// slither-disable-next-line incorrect-equality | ||
if (lockedUntil == 0) { | ||
revert InvalidTransaction(txHash); | ||
} | ||
|
||
if (block.timestamp < lockedUntil) { | ||
revert Locked(txHash, lockedUntil); | ||
if (msg.sender == OPERATIONS_MULTISIG) { | ||
uint256 lockedUntil = queue[txHash]; | ||
// Operations Multisig must follow queue and delay rules | ||
// slither-disable-next-line incorrect-equality | ||
if (lockedUntil == 0) { | ||
revert InvalidTransaction(txHash); | ||
} | ||
if (block.timestamp < lockedUntil) { | ||
revert Locked(txHash, lockedUntil); | ||
} | ||
} else if (msg.sender != COMMUNITY_MULTISIG) { | ||
// All other senders are unauthorized | ||
revert Unauthorized(); | ||
} | ||
|
||
queue[txHash] = 0; | ||
(success, returnData) = _executeTransaction(target, callData); | ||
|
||
emit TransactionExecuted(txHash, target, callData, operationId); | ||
// Execute the transaction | ||
// slither-disable-next-line arbitrary-send-eth | ||
returnData = target.functionCall(callData); | ||
|
||
return (success, returnData); | ||
emit TransactionExecuted(txHash, target, callData, operationId); | ||
} | ||
|
||
/** | ||
|
@@ -260,11 +297,6 @@ contract Timelock { | |
delay = newDelay; | ||
} | ||
|
||
function _executeTransaction(address target, bytes calldata callData) internal returns (bool, bytes memory) { | ||
// slither-disable-next-line arbitrary-send-eth | ||
return target.call(callData); | ||
} | ||
|
||
function _validateAddresses( | ||
address communityMultisig, | ||
address operationsMultisig, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters