From 3c6d47fc15914a6fa43bf5b1f03421df58f8fb2b Mon Sep 17 00:00:00 2001 From: zhl Date: Tue, 11 Apr 2023 11:41:28 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=92=B1=E5=8C=85=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contracts/core/BEMultiSigWallet.sol | 186 +++++++--------------------- 1 file changed, 43 insertions(+), 143 deletions(-) diff --git a/contracts/core/BEMultiSigWallet.sol b/contracts/core/BEMultiSigWallet.sol index 1832f96..393a16a 100644 --- a/contracts/core/BEMultiSigWallet.sol +++ b/contracts/core/BEMultiSigWallet.sol @@ -10,6 +10,7 @@ contract BEMultiSigWallet is AccessControlEnumerable { keccak256("TIMELOCK_ADMIN_ROLE"); bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE"); bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE"); + bytes32 public constant CONFIRM_ROLE = keccak256("CONFIRM_ROLE"); uint256 internal constant _DONE_TIMESTAMP = uint256(1); mapping(bytes32 => uint256) private _timestamps; @@ -20,35 +21,21 @@ contract BEMultiSigWallet is AccessControlEnumerable { /** * @dev Emitted when a call is scheduled as part of operation `id`. */ - event CallScheduled( - bytes32 indexed id, - uint256 indexed index, - address target, - uint256 value, - bytes data, - bytes32 predecessor, - uint256 delay - ); + event ScheduleAdded(bytes32 indexed id); /** * @dev Emitted when a call is performed as part of operation `id`. */ - event CallExecuted( - bytes32 indexed id, - uint256 indexed index, - address target, - uint256 value, - bytes data - ); + event ScheduleExecuted(bytes32 indexed id); /** * @dev Emitted when operation `id` is cancelled. */ event Cancelled(bytes32 indexed id); - event Confirmation(address indexed sender, bytes32 id); + event Confirmation(address indexed sender, bytes32[] ids); - event Revocation(address indexed sender, bytes32 id); + event Revocation(address indexed sender, bytes32[] ids); /** * @dev Emitted when the minimum delay for future operations is modified. @@ -72,12 +59,15 @@ contract BEMultiSigWallet is AccessControlEnumerable { */ constructor( uint256 _minDelay, + uint256 _required, address[] memory proposers, + address[] memory confirmers, address[] memory executors ) { _setRoleAdmin(TIMELOCK_ADMIN_ROLE, TIMELOCK_ADMIN_ROLE); _setRoleAdmin(PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE); _setRoleAdmin(EXECUTOR_ROLE, TIMELOCK_ADMIN_ROLE); + _setRoleAdmin(CONFIRM_ROLE, TIMELOCK_ADMIN_ROLE); // deployer + self administration _setupRole(TIMELOCK_ADMIN_ROLE, _msgSender()); @@ -88,6 +78,11 @@ contract BEMultiSigWallet is AccessControlEnumerable { _setupRole(PROPOSER_ROLE, proposers[i]); } + // register confirmers + for (uint256 i = 0; i < confirmers.length; ++i) { + _setupRole(CONFIRM_ROLE, confirmers[i]); + } + // register executors for (uint256 i = 0; i < executors.length; ++i) { _setupRole(EXECUTOR_ROLE, executors[i]); @@ -95,6 +90,8 @@ contract BEMultiSigWallet is AccessControlEnumerable { minDelay = _minDelay; emit MinDelayChange(0, minDelay); + required = _required; + emit RequirementChange(0, required); } /** @@ -168,25 +165,11 @@ contract BEMultiSigWallet is AccessControlEnumerable { return _timestamps[id]; } - /** - * @dev Returns the identifier of an operation containing a single - * transaction. - */ - function hashOperation( - address target, - uint256 value, - bytes calldata data, - bytes32 predecessor, - bytes32 salt - ) public pure virtual returns (bytes32 hash) { - return keccak256(abi.encode(target, value, data, predecessor, salt)); - } - /** * @dev Returns the identifier of an operation containing a batch of * transactions. */ - function hashOperationBatch( + function hashOperation( address[] calldata targets, uint256[] calldata values, bytes[] calldata datas, @@ -197,44 +180,22 @@ contract BEMultiSigWallet is AccessControlEnumerable { } /** - * @dev Schedule an operation containing a single transaction. + * @dev Schedule an operation containing a batch of transactions. * - * Emits a {CallScheduled} event. + * Emits one {ScheduleAdded} event per transaction in the batch. * * Requirements: * * - 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) { - bytes32 id = hashOperation(target, value, data, predecessor, salt); - _schedule(id, delay); - emit CallScheduled(id, 0, target, value, data, predecessor, delay); - } - - /** - * @dev Schedule an operation containing a batch of transactions. - * - * Emits one {CallScheduled} event per transaction in the batch. - * - * Requirements: - * - * - 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) { + ) public virtual onlyRoleOrOpenRole(PROPOSER_ROLE) { require( targets.length == values.length, "BEMultiSigWallet: length mismatch" @@ -244,19 +205,9 @@ contract BEMultiSigWallet is AccessControlEnumerable { "BEMultiSigWallet: length mismatch" ); - bytes32 id = hashOperationBatch(targets, values, datas, predecessor, salt); + bytes32 id = hashOperation(targets, values, datas, predecessor, salt); _schedule(id, delay); - for (uint256 i = 0; i < targets.length; ++i) { - emit CallScheduled( - id, - i, - targets[i], - values[i], - datas[i], - predecessor, - delay - ); - } + emit ScheduleAdded(id); } /** @@ -275,7 +226,7 @@ contract BEMultiSigWallet is AccessControlEnumerable { * * - 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), "BEMultiSigWallet: operation cannot be cancelled" @@ -285,80 +236,36 @@ contract BEMultiSigWallet is AccessControlEnumerable { emit Cancelled(id); } - /** - * @dev Allows an executor to confirm a transaction. - * Requirements - * - the caller must have the 'executor' role. - */ - function confirmTransaction( - bytes32 id - ) public onlyRoleOrOpenRole(EXECUTOR_ROLE) { - require( - isOperationPending(id), - "BEMultiSigWallet: operation not exist or finished" - ); - confirmations[id][msg.sender] = true; - emit Confirmation(msg.sender, id); - } - /** * @dev Allows an executor to confirm multiple transactions. */ - function confirmTransactionBatch( + function confirmTransaction( bytes32[] calldata ids - ) public onlyRoleOrOpenRole(EXECUTOR_ROLE) { + ) public onlyRoleOrOpenRole(CONFIRM_ROLE) { for (uint256 i = 0; i < ids.length; ++i) { - confirmTransaction(ids[i]); + require( + isOperationPending(ids[i]), + "BEMultiSigWallet: operation not exist or finished" + ); + confirmations[ids[i]][msg.sender] = true; } - } - - /** - * @dev Allows an executor to revoke a confirmation for a transaction. - * Requirements - * - the caller must have the 'executor' role. - */ - function revokeConfirmation( - bytes32 id - ) public onlyRoleOrOpenRole(EXECUTOR_ROLE) { - require( - isOperationPending(id), - "BEMultiSigWallet: operation not exist or finished" - ); - confirmations[id][msg.sender] = false; - emit Revocation(msg.sender, id); + emit Confirmation(msg.sender, ids); } /** * @dev Allows an executor to revoke multiple confirmations for a transaction. */ - function revokeConfirmationBatch( + function revokeConfirmation( bytes32[] calldata ids - ) public onlyRoleOrOpenRole(EXECUTOR_ROLE) { + ) public onlyRoleOrOpenRole(CONFIRM_ROLE) { for (uint256 i = 0; i < ids.length; ++i) { - revokeConfirmation(ids[i]); + require( + isOperationPending(ids[i]), + "BEMultiSigWallet: operation not exist or finished" + ); + confirmations[ids[i]][msg.sender] = false; } - } - - /** - * @dev Execute an (ready) operation containing a single transaction. - * - * Emits a {CallExecuted} event. - * - * Requirements: - * - * - the caller must have the '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(id, predecessor); - _call(id, 0, target, value, data); - _afterCall(id); + emit Revocation(msg.sender, ids); } /** @@ -370,7 +277,7 @@ contract BEMultiSigWallet is AccessControlEnumerable { * * - the caller must have the 'executor' role. */ - function executeBatch( + function execute( address[] calldata targets, uint256[] calldata values, bytes[] calldata datas, @@ -386,12 +293,13 @@ contract BEMultiSigWallet is AccessControlEnumerable { "BEMultiSigWallet: length mismatch" ); - bytes32 id = hashOperationBatch(targets, values, datas, predecessor, salt); + bytes32 id = hashOperation(targets, values, datas, predecessor, salt); _beforeCall(id, predecessor); for (uint256 i = 0; i < targets.length; ++i) { - _call(id, i, targets[i], values[i], datas[i]); + _call(targets[i], values[i], datas[i]); } _afterCall(id); + emit ScheduleExecuted(id); } /** @@ -422,17 +330,9 @@ contract BEMultiSigWallet is AccessControlEnumerable { * * Emits a {CallExecuted} event. */ - function _call( - bytes32 id, - uint256 index, - address target, - uint256 value, - bytes calldata data - ) private { + function _call(address target, uint256 value, bytes calldata data) private { (bool success, ) = target.call{value: value}(data); require(success, "BEMultiSigWallet: underlying transaction reverted"); - - emit CallExecuted(id, index, target, value, data); } /**