优化钱包代码
This commit is contained in:
parent
9a3300c468
commit
3c6d47fc15
@ -10,6 +10,7 @@ contract BEMultiSigWallet is AccessControlEnumerable {
|
|||||||
keccak256("TIMELOCK_ADMIN_ROLE");
|
keccak256("TIMELOCK_ADMIN_ROLE");
|
||||||
bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE");
|
bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE");
|
||||||
bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE");
|
bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE");
|
||||||
|
bytes32 public constant CONFIRM_ROLE = keccak256("CONFIRM_ROLE");
|
||||||
uint256 internal constant _DONE_TIMESTAMP = uint256(1);
|
uint256 internal constant _DONE_TIMESTAMP = uint256(1);
|
||||||
|
|
||||||
mapping(bytes32 => uint256) private _timestamps;
|
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`.
|
* @dev Emitted when a call is scheduled as part of operation `id`.
|
||||||
*/
|
*/
|
||||||
event CallScheduled(
|
event ScheduleAdded(bytes32 indexed id);
|
||||||
bytes32 indexed id,
|
|
||||||
uint256 indexed index,
|
|
||||||
address target,
|
|
||||||
uint256 value,
|
|
||||||
bytes data,
|
|
||||||
bytes32 predecessor,
|
|
||||||
uint256 delay
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Emitted when a call is performed as part of operation `id`.
|
* @dev Emitted when a call is performed as part of operation `id`.
|
||||||
*/
|
*/
|
||||||
event CallExecuted(
|
event ScheduleExecuted(bytes32 indexed id);
|
||||||
bytes32 indexed id,
|
|
||||||
uint256 indexed index,
|
|
||||||
address target,
|
|
||||||
uint256 value,
|
|
||||||
bytes data
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Emitted when operation `id` is cancelled.
|
* @dev Emitted when operation `id` is cancelled.
|
||||||
*/
|
*/
|
||||||
event Cancelled(bytes32 indexed id);
|
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.
|
* @dev Emitted when the minimum delay for future operations is modified.
|
||||||
@ -72,12 +59,15 @@ contract BEMultiSigWallet is AccessControlEnumerable {
|
|||||||
*/
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
uint256 _minDelay,
|
uint256 _minDelay,
|
||||||
|
uint256 _required,
|
||||||
address[] memory proposers,
|
address[] memory proposers,
|
||||||
|
address[] memory confirmers,
|
||||||
address[] memory executors
|
address[] memory executors
|
||||||
) {
|
) {
|
||||||
_setRoleAdmin(TIMELOCK_ADMIN_ROLE, TIMELOCK_ADMIN_ROLE);
|
_setRoleAdmin(TIMELOCK_ADMIN_ROLE, TIMELOCK_ADMIN_ROLE);
|
||||||
_setRoleAdmin(PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE);
|
_setRoleAdmin(PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE);
|
||||||
_setRoleAdmin(EXECUTOR_ROLE, TIMELOCK_ADMIN_ROLE);
|
_setRoleAdmin(EXECUTOR_ROLE, TIMELOCK_ADMIN_ROLE);
|
||||||
|
_setRoleAdmin(CONFIRM_ROLE, TIMELOCK_ADMIN_ROLE);
|
||||||
|
|
||||||
// deployer + self administration
|
// deployer + self administration
|
||||||
_setupRole(TIMELOCK_ADMIN_ROLE, _msgSender());
|
_setupRole(TIMELOCK_ADMIN_ROLE, _msgSender());
|
||||||
@ -88,6 +78,11 @@ contract BEMultiSigWallet is AccessControlEnumerable {
|
|||||||
_setupRole(PROPOSER_ROLE, proposers[i]);
|
_setupRole(PROPOSER_ROLE, proposers[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// register confirmers
|
||||||
|
for (uint256 i = 0; i < confirmers.length; ++i) {
|
||||||
|
_setupRole(CONFIRM_ROLE, confirmers[i]);
|
||||||
|
}
|
||||||
|
|
||||||
// register executors
|
// register executors
|
||||||
for (uint256 i = 0; i < executors.length; ++i) {
|
for (uint256 i = 0; i < executors.length; ++i) {
|
||||||
_setupRole(EXECUTOR_ROLE, executors[i]);
|
_setupRole(EXECUTOR_ROLE, executors[i]);
|
||||||
@ -95,6 +90,8 @@ contract BEMultiSigWallet is AccessControlEnumerable {
|
|||||||
|
|
||||||
minDelay = _minDelay;
|
minDelay = _minDelay;
|
||||||
emit MinDelayChange(0, minDelay);
|
emit MinDelayChange(0, minDelay);
|
||||||
|
required = _required;
|
||||||
|
emit RequirementChange(0, required);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -168,25 +165,11 @@ contract BEMultiSigWallet is AccessControlEnumerable {
|
|||||||
return _timestamps[id];
|
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
|
* @dev Returns the identifier of an operation containing a batch of
|
||||||
* transactions.
|
* transactions.
|
||||||
*/
|
*/
|
||||||
function hashOperationBatch(
|
function hashOperation(
|
||||||
address[] calldata targets,
|
address[] calldata targets,
|
||||||
uint256[] calldata values,
|
uint256[] calldata values,
|
||||||
bytes[] calldata datas,
|
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:
|
* Requirements:
|
||||||
*
|
*
|
||||||
* - the caller must have the 'proposer' role.
|
* - the caller must have the 'proposer' role.
|
||||||
*/
|
*/
|
||||||
function schedule(
|
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,
|
address[] calldata targets,
|
||||||
uint256[] calldata values,
|
uint256[] calldata values,
|
||||||
bytes[] calldata datas,
|
bytes[] calldata datas,
|
||||||
bytes32 predecessor,
|
bytes32 predecessor,
|
||||||
bytes32 salt,
|
bytes32 salt,
|
||||||
uint256 delay
|
uint256 delay
|
||||||
) public virtual onlyRole(PROPOSER_ROLE) {
|
) public virtual onlyRoleOrOpenRole(PROPOSER_ROLE) {
|
||||||
require(
|
require(
|
||||||
targets.length == values.length,
|
targets.length == values.length,
|
||||||
"BEMultiSigWallet: length mismatch"
|
"BEMultiSigWallet: length mismatch"
|
||||||
@ -244,19 +205,9 @@ contract BEMultiSigWallet is AccessControlEnumerable {
|
|||||||
"BEMultiSigWallet: length mismatch"
|
"BEMultiSigWallet: length mismatch"
|
||||||
);
|
);
|
||||||
|
|
||||||
bytes32 id = hashOperationBatch(targets, values, datas, predecessor, salt);
|
bytes32 id = hashOperation(targets, values, datas, predecessor, salt);
|
||||||
_schedule(id, delay);
|
_schedule(id, delay);
|
||||||
for (uint256 i = 0; i < targets.length; ++i) {
|
emit ScheduleAdded(id);
|
||||||
emit CallScheduled(
|
|
||||||
id,
|
|
||||||
i,
|
|
||||||
targets[i],
|
|
||||||
values[i],
|
|
||||||
datas[i],
|
|
||||||
predecessor,
|
|
||||||
delay
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -275,7 +226,7 @@ contract BEMultiSigWallet is AccessControlEnumerable {
|
|||||||
*
|
*
|
||||||
* - the caller must have the 'proposer' role.
|
* - 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(
|
require(
|
||||||
isOperationPending(id),
|
isOperationPending(id),
|
||||||
"BEMultiSigWallet: operation cannot be cancelled"
|
"BEMultiSigWallet: operation cannot be cancelled"
|
||||||
@ -285,80 +236,36 @@ contract BEMultiSigWallet is AccessControlEnumerable {
|
|||||||
emit Cancelled(id);
|
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.
|
* @dev Allows an executor to confirm multiple transactions.
|
||||||
*/
|
*/
|
||||||
function confirmTransactionBatch(
|
function confirmTransaction(
|
||||||
bytes32[] calldata ids
|
bytes32[] calldata ids
|
||||||
) public onlyRoleOrOpenRole(EXECUTOR_ROLE) {
|
) public onlyRoleOrOpenRole(CONFIRM_ROLE) {
|
||||||
for (uint256 i = 0; i < ids.length; ++i) {
|
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;
|
||||||
}
|
}
|
||||||
}
|
emit Confirmation(msg.sender, ids);
|
||||||
|
|
||||||
/**
|
|
||||||
* @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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Allows an executor to revoke multiple confirmations for a transaction.
|
* @dev Allows an executor to revoke multiple confirmations for a transaction.
|
||||||
*/
|
*/
|
||||||
function revokeConfirmationBatch(
|
function revokeConfirmation(
|
||||||
bytes32[] calldata ids
|
bytes32[] calldata ids
|
||||||
) public onlyRoleOrOpenRole(EXECUTOR_ROLE) {
|
) public onlyRoleOrOpenRole(CONFIRM_ROLE) {
|
||||||
for (uint256 i = 0; i < ids.length; ++i) {
|
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;
|
||||||
}
|
}
|
||||||
}
|
emit Revocation(msg.sender, ids);
|
||||||
|
|
||||||
/**
|
|
||||||
* @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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -370,7 +277,7 @@ contract BEMultiSigWallet is AccessControlEnumerable {
|
|||||||
*
|
*
|
||||||
* - the caller must have the 'executor' role.
|
* - the caller must have the 'executor' role.
|
||||||
*/
|
*/
|
||||||
function executeBatch(
|
function execute(
|
||||||
address[] calldata targets,
|
address[] calldata targets,
|
||||||
uint256[] calldata values,
|
uint256[] calldata values,
|
||||||
bytes[] calldata datas,
|
bytes[] calldata datas,
|
||||||
@ -386,12 +293,13 @@ contract BEMultiSigWallet is AccessControlEnumerable {
|
|||||||
"BEMultiSigWallet: length mismatch"
|
"BEMultiSigWallet: length mismatch"
|
||||||
);
|
);
|
||||||
|
|
||||||
bytes32 id = hashOperationBatch(targets, values, datas, predecessor, salt);
|
bytes32 id = hashOperation(targets, values, datas, predecessor, salt);
|
||||||
_beforeCall(id, predecessor);
|
_beforeCall(id, predecessor);
|
||||||
for (uint256 i = 0; i < targets.length; ++i) {
|
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);
|
_afterCall(id);
|
||||||
|
emit ScheduleExecuted(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -422,17 +330,9 @@ contract BEMultiSigWallet is AccessControlEnumerable {
|
|||||||
*
|
*
|
||||||
* Emits a {CallExecuted} event.
|
* Emits a {CallExecuted} event.
|
||||||
*/
|
*/
|
||||||
function _call(
|
function _call(address target, uint256 value, bytes calldata data) private {
|
||||||
bytes32 id,
|
|
||||||
uint256 index,
|
|
||||||
address target,
|
|
||||||
uint256 value,
|
|
||||||
bytes calldata data
|
|
||||||
) private {
|
|
||||||
(bool success, ) = target.call{value: value}(data);
|
(bool success, ) = target.call{value: value}(data);
|
||||||
require(success, "BEMultiSigWallet: underlying transaction reverted");
|
require(success, "BEMultiSigWallet: underlying transaction reverted");
|
||||||
|
|
||||||
emit CallExecuted(id, index, target, value, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user