diff --git a/src/executors/ArbitrumBridgeExecutor.sol b/src/executors/ArbitrumBridgeExecutor.sol index a85690b..85f44d5 100644 --- a/src/executors/ArbitrumBridgeExecutor.sol +++ b/src/executors/ArbitrumBridgeExecutor.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.10; -import {L2BridgeExecutor} from './L2BridgeExecutor.sol'; +import { L2BridgeExecutor } from './L2BridgeExecutor.sol'; /** * @title ArbitrumBridgeExecutor @@ -10,52 +10,52 @@ import {L2BridgeExecutor} from './L2BridgeExecutor.sol'; * @dev Queuing an ActionsSet into this Executor can only be done by the L2 Address Alias of the L1 EthereumGovernanceExecutor */ contract ArbitrumBridgeExecutor is L2BridgeExecutor { - uint160 internal constant OFFSET = uint160(0x1111000000000000000000000000000000001111); + uint160 internal constant OFFSET = uint160(0x1111000000000000000000000000000000001111); - /// @notice Utility function that converts the msg.sender viewed in the L2 to the - /// address in the L1 that submitted a tx to the inbox - /// @param l2Address L2 address as viewed in msg.sender - /// @return l1Address the address in the L1 that triggered the tx to L2 - function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) { - unchecked { - l1Address = address(uint160(l2Address) - OFFSET); + /// @notice Utility function that converts the msg.sender viewed in the L2 to the + /// address in the L1 that submitted a tx to the inbox + /// @param l2Address L2 address as viewed in msg.sender + /// @return l1Address the address in the L1 that triggered the tx to L2 + function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) { + unchecked { + l1Address = address(uint160(l2Address) - OFFSET); + } } - } - /// @inheritdoc L2BridgeExecutor - modifier onlyEthereumGovernanceExecutor() override { - if (undoL1ToL2Alias(msg.sender) != _ethereumGovernanceExecutor) - revert UnauthorizedEthereumExecutor(); - _; - } + /// @inheritdoc L2BridgeExecutor + modifier onlyEthereumGovernanceExecutor() override { + if (undoL1ToL2Alias(msg.sender) != _ethereumGovernanceExecutor) + revert UnauthorizedEthereumExecutor(); + _; + } - /** - * @dev Constructor - * - * @param ethereumGovernanceExecutor The address of the EthereumGovernanceExecutor - * @param delay The delay before which an actions set can be executed - * @param gracePeriod The time period after a delay during which an actions set can be executed - * @param minimumDelay The minimum bound a delay can be set to - * @param maximumDelay The maximum bound a delay can be set to - * @param guardian The address of the guardian, which can cancel queued proposals (can be zero) - */ - constructor( - address ethereumGovernanceExecutor, - uint256 delay, - uint256 gracePeriod, - uint256 minimumDelay, - uint256 maximumDelay, - address guardian - ) - L2BridgeExecutor( - ethereumGovernanceExecutor, - delay, - gracePeriod, - minimumDelay, - maximumDelay, - guardian + /** + * @dev Constructor + * + * @param ethereumGovernanceExecutor The address of the EthereumGovernanceExecutor + * @param delay The delay before which an actions set can be executed + * @param gracePeriod The time period after a delay during which an actions set can be executed + * @param minimumDelay The minimum bound a delay can be set to + * @param maximumDelay The maximum bound a delay can be set to + * @param guardian The address of the guardian, which can cancel queued proposals (can be zero) + */ + constructor( + address ethereumGovernanceExecutor, + uint256 delay, + uint256 gracePeriod, + uint256 minimumDelay, + uint256 maximumDelay, + address guardian ) - { - // Intentionally left blank - } + L2BridgeExecutor( + ethereumGovernanceExecutor, + delay, + gracePeriod, + minimumDelay, + maximumDelay, + guardian + ) + { + // Intentionally left blank + } } diff --git a/src/executors/BridgeExecutorBase.sol b/src/executors/BridgeExecutorBase.sol index e6095a1..3c1c435 100644 --- a/src/executors/BridgeExecutorBase.sol +++ b/src/executors/BridgeExecutorBase.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.10; -import {IExecutorBase} from '../interfaces/IExecutorBase.sol'; +import { IExecutorBase } from '../interfaces/IExecutorBase.sol'; /** * @title BridgeExecutorBase @@ -11,400 +11,398 @@ import {IExecutorBase} from '../interfaces/IExecutorBase.sol'; * contract with proper access control */ abstract contract BridgeExecutorBase is IExecutorBase { - // Minimum allowed grace period, which reduces the risk of having an actions set expire due to network congestion - uint256 constant MINIMUM_GRACE_PERIOD = 10 minutes; - - // Time between queuing and execution - uint256 private _delay; - // Time after the execution time during which the actions set can be executed - uint256 private _gracePeriod; - // Minimum allowed delay - uint256 private _minimumDelay; - // Maximum allowed delay - uint256 private _maximumDelay; - // Address with the ability of canceling actions sets - address private _guardian; - - // Number of actions sets - uint256 private _actionsSetCounter; - // Map of registered actions sets (id => ActionsSet) - mapping(uint256 => ActionsSet) private _actionsSets; - // Map of queued actions (actionHash => isQueued) - mapping(bytes32 => bool) private _queuedActions; - - /** - * @dev Only guardian can call functions marked by this modifier. - **/ - modifier onlyGuardian() { - if (msg.sender != _guardian) revert NotGuardian(); - _; - } - - /** - * @dev Only this contract can call functions marked by this modifier. - **/ - modifier onlyThis() { - if (msg.sender != address(this)) revert OnlyCallableByThis(); - _; - } - - /** - * @dev Constructor - * - * @param delay The delay before which an actions set can be executed - * @param gracePeriod The time period after a delay during which an actions set can be executed - * @param minimumDelay The minimum bound a delay can be set to - * @param maximumDelay The maximum bound a delay can be set to - * @param guardian The address of the guardian, which can cancel queued proposals (can be zero) - */ - constructor( - uint256 delay, - uint256 gracePeriod, - uint256 minimumDelay, - uint256 maximumDelay, - address guardian - ) { - if ( - gracePeriod < MINIMUM_GRACE_PERIOD || - minimumDelay >= maximumDelay || - delay < minimumDelay || - delay > maximumDelay - ) revert InvalidInitParams(); - - _updateDelay(delay); - _updateGracePeriod(gracePeriod); - _updateMinimumDelay(minimumDelay); - _updateMaximumDelay(maximumDelay); - _updateGuardian(guardian); - } - - /// @inheritdoc IExecutorBase - function execute(uint256 actionsSetId) external payable override { - if (getCurrentState(actionsSetId) != ActionsSetState.Queued) revert OnlyQueuedActions(); - - ActionsSet storage actionsSet = _actionsSets[actionsSetId]; - if (block.timestamp < actionsSet.executionTime) revert TimelockNotFinished(); - - actionsSet.executed = true; - uint256 actionCount = actionsSet.targets.length; - - bytes[] memory returnedData = new bytes[](actionCount); - for (uint256 i = 0; i < actionCount; ) { - returnedData[i] = _executeTransaction( - actionsSet.targets[i], - actionsSet.values[i], - actionsSet.signatures[i], - actionsSet.calldatas[i], - actionsSet.executionTime, - actionsSet.withDelegatecalls[i] - ); - unchecked { - ++i; - } + // Minimum allowed grace period, which reduces the risk of having an actions set expire due to network congestion + uint256 constant MINIMUM_GRACE_PERIOD = 10 minutes; + + // Time between queuing and execution + uint256 private _delay; + // Time after the execution time during which the actions set can be executed + uint256 private _gracePeriod; + // Minimum allowed delay + uint256 private _minimumDelay; + // Maximum allowed delay + uint256 private _maximumDelay; + // Address with the ability of canceling actions sets + address private _guardian; + + // Number of actions sets + uint256 private _actionsSetCounter; + // Map of registered actions sets (id => ActionsSet) + mapping(uint256 => ActionsSet) private _actionsSets; + // Map of queued actions (actionHash => isQueued) + mapping(bytes32 => bool) private _queuedActions; + + /** + * @dev Only guardian can call functions marked by this modifier. + **/ + modifier onlyGuardian() { + if (msg.sender != _guardian) revert NotGuardian(); + _; } - emit ActionsSetExecuted(actionsSetId, msg.sender, returnedData); - } - - /// @inheritdoc IExecutorBase - function cancel(uint256 actionsSetId) external override onlyGuardian { - if (getCurrentState(actionsSetId) != ActionsSetState.Queued) revert OnlyQueuedActions(); - - ActionsSet storage actionsSet = _actionsSets[actionsSetId]; - actionsSet.canceled = true; - - uint256 targetsLength = actionsSet.targets.length; - for (uint256 i = 0; i < targetsLength; ) { - _cancelTransaction( - actionsSet.targets[i], - actionsSet.values[i], - actionsSet.signatures[i], - actionsSet.calldatas[i], - actionsSet.executionTime, - actionsSet.withDelegatecalls[i] - ); - unchecked { - ++i; - } + /** + * @dev Only this contract can call functions marked by this modifier. + **/ + modifier onlyThis() { + if (msg.sender != address(this)) revert OnlyCallableByThis(); + _; } - emit ActionsSetCanceled(actionsSetId); - } - - /// @inheritdoc IExecutorBase - function updateGuardian(address guardian) external override onlyThis { - _updateGuardian(guardian); - } - - /// @inheritdoc IExecutorBase - function updateDelay(uint256 delay) external override onlyThis { - _validateDelay(delay); - _updateDelay(delay); - } - - /// @inheritdoc IExecutorBase - function updateGracePeriod(uint256 gracePeriod) external override onlyThis { - if (gracePeriod < MINIMUM_GRACE_PERIOD) revert GracePeriodTooShort(); - _updateGracePeriod(gracePeriod); - } - - /// @inheritdoc IExecutorBase - function updateMinimumDelay(uint256 minimumDelay) external override onlyThis { - if (minimumDelay >= _maximumDelay) revert MinimumDelayTooLong(); - _updateMinimumDelay(minimumDelay); - _validateDelay(_delay); - } - - /// @inheritdoc IExecutorBase - function updateMaximumDelay(uint256 maximumDelay) external override onlyThis { - if (maximumDelay <= _minimumDelay) revert MaximumDelayTooShort(); - _updateMaximumDelay(maximumDelay); - _validateDelay(_delay); - } - - /// @inheritdoc IExecutorBase - function executeDelegateCall(address target, bytes calldata data) - external - payable - override - onlyThis - returns (bool, bytes memory) - { - bool success; - bytes memory resultData; - // solium-disable-next-line security/no-call-value - (success, resultData) = target.delegatecall(data); - return (success, resultData); - } - - /// @inheritdoc IExecutorBase - function receiveFunds() external payable override {} - - /// @inheritdoc IExecutorBase - function getDelay() external view override returns (uint256) { - return _delay; - } - - /// @inheritdoc IExecutorBase - function getGracePeriod() external view override returns (uint256) { - return _gracePeriod; - } - - /// @inheritdoc IExecutorBase - function getMinimumDelay() external view override returns (uint256) { - return _minimumDelay; - } - - /// @inheritdoc IExecutorBase - function getMaximumDelay() external view override returns (uint256) { - return _maximumDelay; - } - - /// @inheritdoc IExecutorBase - function getGuardian() external view override returns (address) { - return _guardian; - } - - /// @inheritdoc IExecutorBase - function getActionsSetCount() external view override returns (uint256) { - return _actionsSetCounter; - } - - /// @inheritdoc IExecutorBase - function getActionsSetById(uint256 actionsSetId) - external - view - override - returns (ActionsSet memory) - { - return _actionsSets[actionsSetId]; - } - - /// @inheritdoc IExecutorBase - function getCurrentState(uint256 actionsSetId) public view override returns (ActionsSetState) { - if (_actionsSetCounter <= actionsSetId) revert InvalidActionsSetId(); - ActionsSet storage actionsSet = _actionsSets[actionsSetId]; - if (actionsSet.canceled) { - return ActionsSetState.Canceled; - } else if (actionsSet.executed) { - return ActionsSetState.Executed; - } else if (block.timestamp > actionsSet.executionTime + _gracePeriod) { - return ActionsSetState.Expired; - } else { - return ActionsSetState.Queued; + /** + * @dev Constructor + * + * @param delay The delay before which an actions set can be executed + * @param gracePeriod The time period after a delay during which an actions set can be executed + * @param minimumDelay The minimum bound a delay can be set to + * @param maximumDelay The maximum bound a delay can be set to + * @param guardian The address of the guardian, which can cancel queued proposals (can be zero) + */ + constructor( + uint256 delay, + uint256 gracePeriod, + uint256 minimumDelay, + uint256 maximumDelay, + address guardian + ) { + if ( + gracePeriod < MINIMUM_GRACE_PERIOD || + minimumDelay >= maximumDelay || + delay < minimumDelay || + delay > maximumDelay + ) revert InvalidInitParams(); + + _updateDelay(delay); + _updateGracePeriod(gracePeriod); + _updateMinimumDelay(minimumDelay); + _updateMaximumDelay(maximumDelay); + _updateGuardian(guardian); } - } - - /// @inheritdoc IExecutorBase - function isActionQueued(bytes32 actionHash) public view override returns (bool) { - return _queuedActions[actionHash]; - } - - function _updateGuardian(address guardian) internal { - emit GuardianUpdate(_guardian, guardian); - _guardian = guardian; - } - - function _updateDelay(uint256 delay) internal { - emit DelayUpdate(_delay, delay); - _delay = delay; - } - - function _updateGracePeriod(uint256 gracePeriod) internal { - emit GracePeriodUpdate(_gracePeriod, gracePeriod); - _gracePeriod = gracePeriod; - } - - function _updateMinimumDelay(uint256 minimumDelay) internal { - emit MinimumDelayUpdate(_minimumDelay, minimumDelay); - _minimumDelay = minimumDelay; - } - - function _updateMaximumDelay(uint256 maximumDelay) internal { - emit MaximumDelayUpdate(_maximumDelay, maximumDelay); - _maximumDelay = maximumDelay; - } - - /** - * @notice Queue an ActionsSet - * @dev If a signature is empty, calldata is used for the execution, calldata is appended to signature otherwise - * @param targets Array of targets to be called by the actions set - * @param values Array of values to pass in each call by the actions set - * @param signatures Array of function signatures to encode in each call (can be empty) - * @param calldatas Array of calldata to pass in each call (can be empty) - * @param withDelegatecalls Array of whether to delegatecall for each call - **/ - function _queue( - address[] memory targets, - uint256[] memory values, - string[] memory signatures, - bytes[] memory calldatas, - bool[] memory withDelegatecalls - ) internal { - if (targets.length == 0) revert EmptyTargets(); - uint256 targetsLength = targets.length; - if ( - targetsLength != values.length || - targetsLength != signatures.length || - targetsLength != calldatas.length || - targetsLength != withDelegatecalls.length - ) revert InconsistentParamsLength(); - - uint256 actionsSetId = _actionsSetCounter; - uint256 executionTime = block.timestamp + _delay; - unchecked { - ++_actionsSetCounter; + + /// @inheritdoc IExecutorBase + function execute(uint256 actionsSetId) external payable override { + if (getCurrentState(actionsSetId) != ActionsSetState.Queued) revert OnlyQueuedActions(); + + ActionsSet storage actionsSet = _actionsSets[actionsSetId]; + if (block.timestamp < actionsSet.executionTime) revert TimelockNotFinished(); + + actionsSet.executed = true; + uint256 actionCount = actionsSet.targets.length; + + bytes[] memory returnedData = new bytes[](actionCount); + for (uint256 i = 0; i < actionCount; ) { + returnedData[i] = _executeTransaction( + actionsSet.targets[i], + actionsSet.values[i], + actionsSet.signatures[i], + actionsSet.calldatas[i], + actionsSet.executionTime, + actionsSet.withDelegatecalls[i] + ); + unchecked { + ++i; + } + } + + emit ActionsSetExecuted(actionsSetId, msg.sender, returnedData); + } + + /// @inheritdoc IExecutorBase + function cancel(uint256 actionsSetId) external override onlyGuardian { + if (getCurrentState(actionsSetId) != ActionsSetState.Queued) revert OnlyQueuedActions(); + + ActionsSet storage actionsSet = _actionsSets[actionsSetId]; + actionsSet.canceled = true; + + uint256 targetsLength = actionsSet.targets.length; + for (uint256 i = 0; i < targetsLength; ) { + _cancelTransaction( + actionsSet.targets[i], + actionsSet.values[i], + actionsSet.signatures[i], + actionsSet.calldatas[i], + actionsSet.executionTime, + actionsSet.withDelegatecalls[i] + ); + unchecked { + ++i; + } + } + + emit ActionsSetCanceled(actionsSetId); + } + + /// @inheritdoc IExecutorBase + function updateGuardian(address guardian) external override onlyThis { + _updateGuardian(guardian); + } + + /// @inheritdoc IExecutorBase + function updateDelay(uint256 delay) external override onlyThis { + _validateDelay(delay); + _updateDelay(delay); + } + + /// @inheritdoc IExecutorBase + function updateGracePeriod(uint256 gracePeriod) external override onlyThis { + if (gracePeriod < MINIMUM_GRACE_PERIOD) revert GracePeriodTooShort(); + _updateGracePeriod(gracePeriod); + } + + /// @inheritdoc IExecutorBase + function updateMinimumDelay(uint256 minimumDelay) external override onlyThis { + if (minimumDelay >= _maximumDelay) revert MinimumDelayTooLong(); + _updateMinimumDelay(minimumDelay); + _validateDelay(_delay); } - for (uint256 i = 0; i < targetsLength; ) { - bytes32 actionHash = keccak256( - abi.encode( - targets[i], - values[i], - signatures[i], - calldatas[i], - executionTime, - withDelegatecalls[i] - ) - ); - if (isActionQueued(actionHash)) revert DuplicateAction(); - _queuedActions[actionHash] = true; - unchecked { - ++i; - } + /// @inheritdoc IExecutorBase + function updateMaximumDelay(uint256 maximumDelay) external override onlyThis { + if (maximumDelay <= _minimumDelay) revert MaximumDelayTooShort(); + _updateMaximumDelay(maximumDelay); + _validateDelay(_delay); } - ActionsSet storage actionsSet = _actionsSets[actionsSetId]; - actionsSet.targets = targets; - actionsSet.values = values; - actionsSet.signatures = signatures; - actionsSet.calldatas = calldatas; - actionsSet.withDelegatecalls = withDelegatecalls; - actionsSet.executionTime = executionTime; - - emit ActionsSetQueued( - actionsSetId, - targets, - values, - signatures, - calldatas, - withDelegatecalls, - executionTime - ); - } - - function _executeTransaction( - address target, - uint256 value, - string memory signature, - bytes memory data, - uint256 executionTime, - bool withDelegatecall - ) internal returns (bytes memory) { - if (address(this).balance < value) revert InsufficientBalance(); - - bytes32 actionHash = keccak256( - abi.encode(target, value, signature, data, executionTime, withDelegatecall) - ); - _queuedActions[actionHash] = false; - - bytes memory callData; - if (bytes(signature).length == 0) { - callData = data; - } else { - callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data); + /// @inheritdoc IExecutorBase + function executeDelegateCall(address target, bytes calldata data) + external + payable + override + onlyThis + returns (bool, bytes memory) + { + bool success; + bytes memory resultData; + // solium-disable-next-line security/no-call-value + (success, resultData) = target.delegatecall(data); + return (success, resultData); } - bool success; - bytes memory resultData; - if (withDelegatecall) { - (success, resultData) = this.executeDelegateCall{value: value}(target, callData); - } else { - // solium-disable-next-line security/no-call-value - (success, resultData) = target.call{value: value}(callData); + /// @inheritdoc IExecutorBase + function receiveFunds() external payable override {} + + /// @inheritdoc IExecutorBase + function getDelay() external view override returns (uint256) { + return _delay; + } + + /// @inheritdoc IExecutorBase + function getGracePeriod() external view override returns (uint256) { + return _gracePeriod; + } + + /// @inheritdoc IExecutorBase + function getMinimumDelay() external view override returns (uint256) { + return _minimumDelay; + } + + /// @inheritdoc IExecutorBase + function getMaximumDelay() external view override returns (uint256) { + return _maximumDelay; } - return _verifyCallResult(success, resultData); - } - - function _cancelTransaction( - address target, - uint256 value, - string memory signature, - bytes memory data, - uint256 executionTime, - bool withDelegatecall - ) internal { - bytes32 actionHash = keccak256( - abi.encode(target, value, signature, data, executionTime, withDelegatecall) - ); - _queuedActions[actionHash] = false; - } - - function _validateDelay(uint256 delay) internal view { - if (delay < _minimumDelay) revert DelayShorterThanMin(); - if (delay > _maximumDelay) revert DelayLongerThanMax(); - } - - function _verifyCallResult(bool success, bytes memory returnData) - private - pure - returns (bytes memory) - { - if (success) { - return returnData; - } else { - // Look for revert reason and bubble it up if present - if (returnData.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - - // solhint-disable-next-line no-inline-assembly - assembly { - let returndata_size := mload(returnData) - revert(add(32, returnData), returndata_size) + + /// @inheritdoc IExecutorBase + function getGuardian() external view override returns (address) { + return _guardian; + } + + /// @inheritdoc IExecutorBase + function getActionsSetCount() external view override returns (uint256) { + return _actionsSetCounter; + } + + /// @inheritdoc IExecutorBase + function getActionsSetById(uint256 actionsSetId) + external + view + override + returns (ActionsSet memory) + { + return _actionsSets[actionsSetId]; + } + + /// @inheritdoc IExecutorBase + function getCurrentState(uint256 actionsSetId) public view override returns (ActionsSetState) { + if (_actionsSetCounter <= actionsSetId) revert InvalidActionsSetId(); + ActionsSet storage actionsSet = _actionsSets[actionsSetId]; + if (actionsSet.canceled) { + return ActionsSetState.Canceled; + } else if (actionsSet.executed) { + return ActionsSetState.Executed; + } else if (block.timestamp > actionsSet.executionTime + _gracePeriod) { + return ActionsSetState.Expired; + } else { + return ActionsSetState.Queued; + } + } + + /// @inheritdoc IExecutorBase + function isActionQueued(bytes32 actionHash) public view override returns (bool) { + return _queuedActions[actionHash]; + } + + function _updateGuardian(address guardian) internal { + emit GuardianUpdate(_guardian, guardian); + _guardian = guardian; + } + + function _updateDelay(uint256 delay) internal { + emit DelayUpdate(_delay, delay); + _delay = delay; + } + + function _updateGracePeriod(uint256 gracePeriod) internal { + emit GracePeriodUpdate(_gracePeriod, gracePeriod); + _gracePeriod = gracePeriod; + } + + function _updateMinimumDelay(uint256 minimumDelay) internal { + emit MinimumDelayUpdate(_minimumDelay, minimumDelay); + _minimumDelay = minimumDelay; + } + + function _updateMaximumDelay(uint256 maximumDelay) internal { + emit MaximumDelayUpdate(_maximumDelay, maximumDelay); + _maximumDelay = maximumDelay; + } + + /** + * @notice Queue an ActionsSet + * @dev If a signature is empty, calldata is used for the execution, calldata is appended to signature otherwise + * @param targets Array of targets to be called by the actions set + * @param values Array of values to pass in each call by the actions set + * @param signatures Array of function signatures to encode in each call (can be empty) + * @param calldatas Array of calldata to pass in each call (can be empty) + * @param withDelegatecalls Array of whether to delegatecall for each call + **/ + function _queue( + address[] memory targets, + uint256[] memory values, + string[] memory signatures, + bytes[] memory calldatas, + bool[] memory withDelegatecalls + ) internal { + if (targets.length == 0) revert EmptyTargets(); + uint256 targetsLength = targets.length; + if ( + targetsLength != values.length || + targetsLength != signatures.length || + targetsLength != calldatas.length || + targetsLength != withDelegatecalls.length + ) revert InconsistentParamsLength(); + + uint256 actionsSetId = _actionsSetCounter; + uint256 executionTime = block.timestamp + _delay; + unchecked { + ++_actionsSetCounter; + } + + for (uint256 i = 0; i < targetsLength; ) { + bytes32 actionHash = keccak256( + abi.encode( + targets[i], + values[i], + signatures[i], + calldatas[i], + executionTime, + withDelegatecalls[i] + ) + ); + if (isActionQueued(actionHash)) revert DuplicateAction(); + _queuedActions[actionHash] = true; + unchecked { + ++i; + } + } + + ActionsSet storage actionsSet = _actionsSets[actionsSetId]; + actionsSet.targets = targets; + actionsSet.values = values; + actionsSet.signatures = signatures; + actionsSet.calldatas = calldatas; + actionsSet.withDelegatecalls = withDelegatecalls; + actionsSet.executionTime = executionTime; + + emit ActionsSetQueued( + actionsSetId, + targets, + values, + signatures, + calldatas, + withDelegatecalls, + executionTime + ); + } + + function _executeTransaction( + address target, + uint256 value, + string memory signature, + bytes memory data, + uint256 executionTime, + bool withDelegatecall + ) internal returns (bytes memory) { + if (address(this).balance < value) revert InsufficientBalance(); + + bytes32 actionHash = keccak256( + abi.encode(target, value, signature, data, executionTime, withDelegatecall) + ); + _queuedActions[actionHash] = false; + + bytes memory callData; + if (bytes(signature).length == 0) { + callData = data; + } else { + callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data); + } + + bool success; + bytes memory resultData; + if (withDelegatecall) { + (success, resultData) = this.executeDelegateCall{value: value}(target, callData); + } else { + // solium-disable-next-line security/no-call-value + (success, resultData) = target.call{value: value}(callData); + } + return _verifyCallResult(success, resultData); + } + + function _cancelTransaction( + address target, + uint256 value, + string memory signature, + bytes memory data, + uint256 executionTime, + bool withDelegatecall + ) internal { + bytes32 actionHash = keccak256( + abi.encode(target, value, signature, data, executionTime, withDelegatecall) + ); + _queuedActions[actionHash] = false; + } + + function _validateDelay(uint256 delay) internal view { + if (delay < _minimumDelay) revert DelayShorterThanMin(); + if (delay > _maximumDelay) revert DelayLongerThanMax(); + } + + function _verifyCallResult(bool success, bytes memory returnData) + private pure returns (bytes memory) + { + if (success) { + return returnData; + } else { + // Look for revert reason and bubble it up if present + if (returnData.length > 0) { + // The easiest way to bubble the revert reason is using memory via assembly + + // solhint-disable-next-line no-inline-assembly + assembly { + let returndata_size := mload(returnData) + revert(add(32, returnData), returndata_size) + } + } else { + revert FailedActionExecution(); + } } - } else { - revert FailedActionExecution(); - } } - } } diff --git a/src/executors/GnosisBridgeExecutor.sol b/src/executors/GnosisBridgeExecutor.sol index 29e4726..9d8e46d 100644 --- a/src/executors/GnosisBridgeExecutor.sol +++ b/src/executors/GnosisBridgeExecutor.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.10; -import {BridgeExecutorBase} from './BridgeExecutorBase.sol'; +import { BridgeExecutorBase } from './BridgeExecutorBase.sol'; interface IAMB { - function messageSender() external view returns (address); + function messageSender() external view returns (address); - function messageSourceChainId() external view returns (bytes32); + function messageSourceChainId() external view returns (bytes32); } /** @@ -17,125 +17,134 @@ interface IAMB { * controller from the correct origin chain. */ contract GnosisBridgeExecutor is BridgeExecutorBase { - error UnauthorizedAMB(); - error UnauthorizedChainId(); - error UnauthorizedController(); + error UnauthorizedAMB(); + error UnauthorizedChainId(); + error UnauthorizedController(); - /** - * @dev Emitted when Amb address is updated - * @param oldAmbAddress the old address - * @param newAmbAddress the new address - **/ - event AmbAddressUpdated( - address indexed oldAmbAddress, - address indexed newAmbAddress - ); + /** + * @dev Emitted when Amb address is updated + * @param oldAmbAddress the old address + * @param newAmbAddress the new address + **/ + event AmbAddressUpdated( + address indexed oldAmbAddress, + address indexed newAmbAddress + ); - /** - * @dev Emitted when controller address is updated - * @param oldControllerAddress the old address - * @param newControllerAddress the new address - **/ - event ControllerUpdated( - address indexed oldControllerAddress, - address indexed newControllerAddress - ); + /** + * @dev Emitted when controller address is updated + * @param oldControllerAddress the old address + * @param newControllerAddress the new address + **/ + event ControllerUpdated( + address indexed oldControllerAddress, + address indexed newControllerAddress + ); - /** - * @dev Emitted when chainId is updated - * @param oldChainIdAddress the old Id - * @param newChainIdAddress the new Id - **/ - event ChainIdUpdated( - bytes32 indexed oldChainIdAddress, - bytes32 indexed newChainIdAddress - ); + /** + * @dev Emitted when chainId is updated + * @param oldChainIdAddress the old Id + * @param newChainIdAddress the new Id + **/ + event ChainIdUpdated( + bytes32 indexed oldChainIdAddress, + bytes32 indexed newChainIdAddress + ); - // Address of the AMB contract forwarding the cross-chain transaction from Ethereum - IAMB public amb; - // Address of the orginating sender of the message - address public controller; - // Chain ID of the origin - bytes32 public chainId; + // Address of the AMB contract forwarding the cross-chain transaction from Ethereum + IAMB public amb; + // Address of the orginating sender of the message + address public controller; + // Chain ID of the origin + bytes32 public chainId; - /** - * @dev Check that the amb, chainId, and owner are valid - **/ - modifier onlyValid() { - if (msg.sender != address(amb)) revert UnauthorizedAMB(); - if (amb.messageSourceChainId() != chainId) revert UnauthorizedChainId(); - if (amb.messageSender() != controller) revert UnauthorizedController(); - _; - } - /** - * @dev Constructor - * @param _amb The AMB contract on the foreign chain - * @param _controller Address of the authorized controller contract on the other side of the bridge - * @param _chainId Address of the authorized chainId from which owner can initiate transactions - * @param delay The delay before which an actions set can be executed - * @param gracePeriod The time period after a delay during which an actions set can be executed - * @param minimumDelay The minimum bound a delay can be set to - * @param maximumDelay The maximum bound a delay can be set to - * @param guardian The address of the guardian, which can cancel queued proposals (can be zero) - */ - constructor( - IAMB _amb, - address _controller, - bytes32 _chainId, - uint256 delay, - uint256 gracePeriod, - uint256 minimumDelay, - uint256 maximumDelay, - address guardian - ) BridgeExecutorBase(delay, gracePeriod, minimumDelay, maximumDelay, guardian) { - amb = _amb; - controller = _controller; - chainId = _chainId; - } + /** + * @dev Check that the amb, chainId, and owner are valid + **/ + modifier onlyValid() { + if (msg.sender != address(amb)) revert UnauthorizedAMB(); + if (amb.messageSourceChainId() != chainId) revert UnauthorizedChainId(); + if (amb.messageSender() != controller) revert UnauthorizedController(); + _; + } - /** - * @notice Queue an ActionsSet - * @dev If a signature is empty, calldata is used for the execution, calldata is appended to signature otherwise - * @param targets Array of targets to be called by the actions set - * @param values Array of values to pass in each call by the actions set - * @param signatures Array of function signatures to encode in each call by the actions (can be empty) - * @param calldatas Array of calldata to pass in each call by the actions set - * @param withDelegatecalls Array of whether to delegatecall for each call of the actions set - **/ - function queue( - address[] memory targets, - uint256[] memory values, - string[] memory signatures, - bytes[] memory calldatas, - bool[] memory withDelegatecalls - ) external onlyValid { - _queue(targets, values, signatures, calldatas, withDelegatecalls); - } + /** + * @dev Constructor + * @param _amb The AMB contract on the foreign chain + * @param _controller Address of the authorized controller contract on the other side of the bridge + * @param _chainId Address of the authorized chainId from which owner can initiate transactions + * @param delay The delay before which an actions set can be executed + * @param gracePeriod The time period after a delay during which an actions set can be executed + * @param minimumDelay The minimum bound a delay can be set to + * @param maximumDelay The maximum bound a delay can be set to + * @param guardian The address of the guardian, which can cancel queued proposals (can be zero) + */ + constructor( + IAMB _amb, + address _controller, + bytes32 _chainId, + uint256 delay, + uint256 gracePeriod, + uint256 minimumDelay, + uint256 maximumDelay, + address guardian + ) + BridgeExecutorBase( + delay, + gracePeriod, + minimumDelay, + maximumDelay, + guardian + ) + { + amb = _amb; + controller = _controller; + chainId = _chainId; + } - /// @dev Set the AMB contract address - /// @param _amb Address of the AMB contract - /// @notice This can only be called by this contract - function setAmb(address _amb) public onlyThis { - require(address(amb) != _amb, "AMB address already set to this"); - emit AmbAddressUpdated(address(amb), _amb); - amb = IAMB(_amb); - } + /** + * @notice Queue an ActionsSet + * @dev If a signature is empty, calldata is used for the execution, calldata is appended to signature otherwise + * @param targets Array of targets to be called by the actions set + * @param values Array of values to pass in each call by the actions set + * @param signatures Array of function signatures to encode in each call by the actions (can be empty) + * @param calldatas Array of calldata to pass in each call by the actions set + * @param withDelegatecalls Array of whether to delegatecall for each call of the actions set + **/ + function queue( + address[] memory targets, + uint256[] memory values, + string[] memory signatures, + bytes[] memory calldatas, + bool[] memory withDelegatecalls + ) external onlyValid { + _queue(targets, values, signatures, calldatas, withDelegatecalls); + } - /// @dev Set the approved chainId - /// @param _chainId ID of the approved network - /// @notice This can only be called by this contract - function setChainId(bytes32 _chainId) public onlyThis { - require(chainId != _chainId, "chainId already set to this"); - emit ChainIdUpdated(chainId, _chainId); - chainId = _chainId; - } + /// @dev Set the AMB contract address + /// @param _amb Address of the AMB contract + /// @notice This can only be called by this contract + function setAmb(address _amb) public onlyThis { + require(address(amb) != _amb, 'AMB address already set to this'); + emit AmbAddressUpdated(address(amb), _amb); + amb = IAMB(_amb); + } - /// @dev Set the controller address - /// @param _controller Set the address of controller on the other side of the bridge - /// @notice This can only be called by this contract - function setController(address _controller) public onlyThis { - require(controller != _controller, "controller already set to this"); - emit ControllerUpdated(controller, _controller); - controller = _controller; - } + /// @dev Set the approved chainId + /// @param _chainId ID of the approved network + /// @notice This can only be called by this contract + function setChainId(bytes32 _chainId) public onlyThis { + require(chainId != _chainId, 'chainId already set to this'); + emit ChainIdUpdated(chainId, _chainId); + chainId = _chainId; + } + + /// @dev Set the controller address + /// @param _controller Set the address of controller on the other side of the bridge + /// @notice This can only be called by this contract + function setController(address _controller) public onlyThis { + require(controller != _controller, 'controller already set to this'); + emit ControllerUpdated(controller, _controller); + controller = _controller; + } } diff --git a/src/executors/L2BridgeExecutor.sol b/src/executors/L2BridgeExecutor.sol index 06c9fe2..de02f52 100644 --- a/src/executors/L2BridgeExecutor.sol +++ b/src/executors/L2BridgeExecutor.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.10; -import {IL2BridgeExecutor} from '../interfaces/IL2BridgeExecutor.sol'; +import { IL2BridgeExecutor } from '../interfaces/IL2BridgeExecutor.sol'; -import {BridgeExecutorBase} from './BridgeExecutorBase.sol'; +import { BridgeExecutorBase } from './BridgeExecutorBase.sol'; /** * @title L2BridgeExecutor @@ -13,54 +13,62 @@ import {BridgeExecutorBase} from './BridgeExecutorBase.sol'; * contract with proper configuration and adjustments depending on the L2 */ abstract contract L2BridgeExecutor is BridgeExecutorBase, IL2BridgeExecutor { - // Address of the Ethereum Governance Executor, which should be able to queue actions sets - address internal _ethereumGovernanceExecutor; + // Address of the Ethereum Governance Executor, which should be able to queue actions sets + address internal _ethereumGovernanceExecutor; - /** - * @dev Only the Ethereum Governance Executor should be able to call functions marked by this modifier. - **/ - modifier onlyEthereumGovernanceExecutor() virtual; + /** + * @dev Only the Ethereum Governance Executor should be able to call functions marked by this modifier. + **/ + modifier onlyEthereumGovernanceExecutor() virtual; - /** - * @dev Constructor - * - * @param ethereumGovernanceExecutor The address of the EthereumGovernanceExecutor - * @param delay The delay before which an actions set can be executed - * @param gracePeriod The time period after a delay during which an actions set can be executed - * @param minimumDelay The minimum bound a delay can be set to - * @param maximumDelay The maximum bound a delay can be set to - * @param guardian The address of the guardian, which can cancel queued proposals (can be zero) - */ - constructor( - address ethereumGovernanceExecutor, - uint256 delay, - uint256 gracePeriod, - uint256 minimumDelay, - uint256 maximumDelay, - address guardian - ) BridgeExecutorBase(delay, gracePeriod, minimumDelay, maximumDelay, guardian) { - _ethereumGovernanceExecutor = ethereumGovernanceExecutor; - } + /** + * @dev Constructor + * + * @param ethereumGovernanceExecutor The address of the EthereumGovernanceExecutor + * @param delay The delay before which an actions set can be executed + * @param gracePeriod The time period after a delay during which an actions set can be executed + * @param minimumDelay The minimum bound a delay can be set to + * @param maximumDelay The maximum bound a delay can be set to + * @param guardian The address of the guardian, which can cancel queued proposals (can be zero) + */ + constructor( + address ethereumGovernanceExecutor, + uint256 delay, + uint256 gracePeriod, + uint256 minimumDelay, + uint256 maximumDelay, + address guardian + ) + BridgeExecutorBase( + delay, + gracePeriod, + minimumDelay, + maximumDelay, + guardian + ) + { + _ethereumGovernanceExecutor = ethereumGovernanceExecutor; + } - /// @inheritdoc IL2BridgeExecutor - function queue( - address[] memory targets, - uint256[] memory values, - string[] memory signatures, - bytes[] memory calldatas, - bool[] memory withDelegatecalls - ) external onlyEthereumGovernanceExecutor { - _queue(targets, values, signatures, calldatas, withDelegatecalls); - } + /// @inheritdoc IL2BridgeExecutor + function queue( + address[] memory targets, + uint256[] memory values, + string[] memory signatures, + bytes[] memory calldatas, + bool[] memory withDelegatecalls + ) external onlyEthereumGovernanceExecutor { + _queue(targets, values, signatures, calldatas, withDelegatecalls); + } - /// @inheritdoc IL2BridgeExecutor - function updateEthereumGovernanceExecutor(address ethereumGovernanceExecutor) external onlyThis { - emit EthereumGovernanceExecutorUpdate(_ethereumGovernanceExecutor, ethereumGovernanceExecutor); - _ethereumGovernanceExecutor = ethereumGovernanceExecutor; - } + /// @inheritdoc IL2BridgeExecutor + function updateEthereumGovernanceExecutor(address ethereumGovernanceExecutor) external onlyThis { + emit EthereumGovernanceExecutorUpdate(_ethereumGovernanceExecutor, ethereumGovernanceExecutor); + _ethereumGovernanceExecutor = ethereumGovernanceExecutor; + } - /// @inheritdoc IL2BridgeExecutor - function getEthereumGovernanceExecutor() external view returns (address) { - return _ethereumGovernanceExecutor; - } + /// @inheritdoc IL2BridgeExecutor + function getEthereumGovernanceExecutor() external view returns (address) { + return _ethereumGovernanceExecutor; + } } diff --git a/src/executors/OptimismBridgeExecutor.sol b/src/executors/OptimismBridgeExecutor.sol index a8facbd..ebe4724 100644 --- a/src/executors/OptimismBridgeExecutor.sol +++ b/src/executors/OptimismBridgeExecutor.sol @@ -1,12 +1,10 @@ // SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.10; -import {L2BridgeExecutor} from './L2BridgeExecutor.sol'; +import { L2BridgeExecutor } from './L2BridgeExecutor.sol'; interface ICrossDomainMessenger { - - function xDomainMessageSender() external view returns (address); - + function xDomainMessageSender() external view returns (address); } /** @@ -17,48 +15,49 @@ interface ICrossDomainMessenger { * the EthereumGovernanceExecutor as xDomainMessageSender */ contract OptimismBridgeExecutor is L2BridgeExecutor { - // Address of the Optimism L2 Cross Domain Messenger, in charge of redirecting cross-chain transactions in L2 - address public immutable OVM_L2_CROSS_DOMAIN_MESSENGER; + // Address of the Optimism L2 Cross Domain Messenger, in charge of redirecting cross-chain transactions in L2 + address public immutable OVM_L2_CROSS_DOMAIN_MESSENGER; - /// @inheritdoc L2BridgeExecutor - modifier onlyEthereumGovernanceExecutor() override { - if ( - msg.sender != OVM_L2_CROSS_DOMAIN_MESSENGER || - ICrossDomainMessenger(OVM_L2_CROSS_DOMAIN_MESSENGER).xDomainMessageSender() != - _ethereumGovernanceExecutor - ) revert UnauthorizedEthereumExecutor(); - _; - } + /// @inheritdoc L2BridgeExecutor + modifier onlyEthereumGovernanceExecutor() override { + if ( + msg.sender != OVM_L2_CROSS_DOMAIN_MESSENGER || + ICrossDomainMessenger(OVM_L2_CROSS_DOMAIN_MESSENGER) + .xDomainMessageSender() != + _ethereumGovernanceExecutor + ) revert UnauthorizedEthereumExecutor(); + _; + } - /** - * @dev Constructor - * - * @param ovmL2CrossDomainMessenger The address of the Optimism L2CrossDomainMessenger - * @param ethereumGovernanceExecutor The address of the EthereumGovernanceExecutor - * @param delay The delay before which an actions set can be executed - * @param gracePeriod The time period after a delay during which an actions set can be executed - * @param minimumDelay The minimum bound a delay can be set to - * @param maximumDelay The maximum bound a delay can be set to - * @param guardian The address of the guardian, which can cancel queued proposals (can be zero) - */ - constructor( - address ovmL2CrossDomainMessenger, - address ethereumGovernanceExecutor, - uint256 delay, - uint256 gracePeriod, - uint256 minimumDelay, - uint256 maximumDelay, - address guardian - ) - L2BridgeExecutor( - ethereumGovernanceExecutor, - delay, - gracePeriod, - minimumDelay, - maximumDelay, - guardian + /** + * @dev Constructor + * + * @param ovmL2CrossDomainMessenger The address of the Optimism L2CrossDomainMessenger + * @param ethereumGovernanceExecutor The address of the EthereumGovernanceExecutor + * @param delay The delay before which an actions set can be executed + * @param gracePeriod The time period after a delay during which an actions set can be executed + * @param minimumDelay The minimum bound a delay can be set to + * @param maximumDelay The maximum bound a delay can be set to + * @param guardian The address of the guardian, which can cancel queued proposals (can be zero) + */ + constructor( + address ovmL2CrossDomainMessenger, + address ethereumGovernanceExecutor, + uint256 delay, + uint256 gracePeriod, + uint256 minimumDelay, + uint256 maximumDelay, + address guardian ) - { - OVM_L2_CROSS_DOMAIN_MESSENGER = ovmL2CrossDomainMessenger; - } + L2BridgeExecutor( + ethereumGovernanceExecutor, + delay, + gracePeriod, + minimumDelay, + maximumDelay, + guardian + ) + { + OVM_L2_CROSS_DOMAIN_MESSENGER = ovmL2CrossDomainMessenger; + } } diff --git a/src/interfaces/IExecutorBase.sol b/src/interfaces/IExecutorBase.sol index 440c073..20fc7dc 100644 --- a/src/interfaces/IExecutorBase.sol +++ b/src/interfaces/IExecutorBase.sol @@ -7,244 +7,244 @@ pragma solidity ^0.8.10; * @notice Defines the basic interface for the ExecutorBase abstract contract */ interface IExecutorBase { - error InvalidInitParams(); - error NotGuardian(); - error OnlyCallableByThis(); - error MinimumDelayTooLong(); - error MaximumDelayTooShort(); - error GracePeriodTooShort(); - error DelayShorterThanMin(); - error DelayLongerThanMax(); - error OnlyQueuedActions(); - error TimelockNotFinished(); - error InvalidActionsSetId(); - error EmptyTargets(); - error InconsistentParamsLength(); - error DuplicateAction(); - error InsufficientBalance(); - error FailedActionExecution(); - - /** - * @notice This enum contains all possible actions set states - */ - enum ActionsSetState { - Queued, - Executed, - Canceled, - Expired - } - - /** - * @notice This struct contains the data needed to execute a specified set of actions - * @param targets Array of targets to call - * @param values Array of values to pass in each call - * @param signatures Array of function signatures to encode in each call (can be empty) - * @param calldatas Array of calldatas to pass in each call, appended to the signature at the same array index if not empty - * @param withDelegateCalls Array of whether to delegatecall for each call - * @param executionTime Timestamp starting from which the actions set can be executed - * @param executed True if the actions set has been executed, false otherwise - * @param canceled True if the actions set has been canceled, false otherwise - */ - struct ActionsSet { - address[] targets; - uint256[] values; - string[] signatures; - bytes[] calldatas; - bool[] withDelegatecalls; - uint256 executionTime; - bool executed; - bool canceled; - } - - /** - * @dev Emitted when an ActionsSet is queued - * @param id Id of the ActionsSet - * @param targets Array of targets to be called by the actions set - * @param values Array of values to pass in each call by the actions set - * @param signatures Array of function signatures to encode in each call by the actions set - * @param calldatas Array of calldata to pass in each call by the actions set - * @param withDelegatecalls Array of whether to delegatecall for each call of the actions set - * @param executionTime The timestamp at which this actions set can be executed - **/ - event ActionsSetQueued( - uint256 indexed id, - address[] targets, - uint256[] values, - string[] signatures, - bytes[] calldatas, - bool[] withDelegatecalls, - uint256 executionTime - ); - - /** - * @dev Emitted when an ActionsSet is successfully executed - * @param id Id of the ActionsSet - * @param initiatorExecution The address that triggered the ActionsSet execution - * @param returnedData The returned data from the ActionsSet execution - **/ - event ActionsSetExecuted( - uint256 indexed id, - address indexed initiatorExecution, - bytes[] returnedData - ); - - /** - * @dev Emitted when an ActionsSet is cancelled by the guardian - * @param id Id of the ActionsSet - **/ - event ActionsSetCanceled(uint256 indexed id); - - /** - * @dev Emitted when a new guardian is set - * @param oldGuardian The address of the old guardian - * @param newGuardian The address of the new guardian - **/ - event GuardianUpdate(address oldGuardian, address newGuardian); - - /** - * @dev Emitted when the delay (between queueing and execution) is updated - * @param oldDelay The value of the old delay - * @param newDelay The value of the new delay - **/ - event DelayUpdate(uint256 oldDelay, uint256 newDelay); - - /** - * @dev Emitted when the grace period (between executionTime and expiration) is updated - * @param oldGracePeriod The value of the old grace period - * @param newGracePeriod The value of the new grace period - **/ - event GracePeriodUpdate(uint256 oldGracePeriod, uint256 newGracePeriod); - - /** - * @dev Emitted when the minimum delay (lower bound of delay) is updated - * @param oldMinimumDelay The value of the old minimum delay - * @param newMinimumDelay The value of the new minimum delay - **/ - event MinimumDelayUpdate(uint256 oldMinimumDelay, uint256 newMinimumDelay); - - /** - * @dev Emitted when the maximum delay (upper bound of delay)is updated - * @param oldMaximumDelay The value of the old maximum delay - * @param newMaximumDelay The value of the new maximum delay - **/ - event MaximumDelayUpdate(uint256 oldMaximumDelay, uint256 newMaximumDelay); - - /** - * @notice Execute the ActionsSet - * @param actionsSetId The id of the ActionsSet to execute - **/ - function execute(uint256 actionsSetId) external payable; - - /** - * @notice Cancel the ActionsSet - * @param actionsSetId The id of the ActionsSet to cancel - **/ - function cancel(uint256 actionsSetId) external; - - /** - * @notice Update guardian - * @param guardian The address of the new guardian - **/ - function updateGuardian(address guardian) external; - - /** - * @notice Update the delay, time between queueing and execution of ActionsSet - * @dev It does not affect to actions set that are already queued - * @param delay The value of the delay (in seconds) - **/ - function updateDelay(uint256 delay) external; - - /** - * @notice Update the grace period, the period after the execution time during which an actions set can be executed - * @param gracePeriod The value of the grace period (in seconds) - **/ - function updateGracePeriod(uint256 gracePeriod) external; - - /** - * @notice Update the minimum allowed delay - * @param minimumDelay The value of the minimum delay (in seconds) - **/ - function updateMinimumDelay(uint256 minimumDelay) external; - - /** - * @notice Update the maximum allowed delay - * @param maximumDelay The maximum delay (in seconds) - **/ - function updateMaximumDelay(uint256 maximumDelay) external; - - /** - * @notice Allows to delegatecall a given target with an specific amount of value - * @dev This function is external so it allows to specify a defined msg.value for the delegate call, reducing - * the risk that a delegatecall gets executed with more value than intended - * @return True if the delegate call was successful, false otherwise - * @return The bytes returned by the delegate call - **/ - function executeDelegateCall(address target, bytes calldata data) - external - payable - returns (bool, bytes memory); - - /** - * @notice Allows to receive funds into the executor - * @dev Useful for actionsSet that needs funds to gets executed - */ - function receiveFunds() external payable; - - /** - * @notice Returns the delay (between queuing and execution) - * @return The value of the delay (in seconds) - **/ - function getDelay() external view returns (uint256); - - /** - * @notice Returns the grace period - * @return The value of the grace period (in seconds) - **/ - function getGracePeriod() external view returns (uint256); - - /** - * @notice Returns the minimum delay - * @return The value of the minimum delay (in seconds) - **/ - function getMinimumDelay() external view returns (uint256); - - /** - * @notice Returns the maximum delay - * @return The value of the maximum delay (in seconds) - **/ - function getMaximumDelay() external view returns (uint256); - - /** - * @notice Returns the address of the guardian - * @return The address of the guardian - **/ - function getGuardian() external view returns (address); - - /** - * @notice Returns the total number of actions sets of the executor - * @return The number of actions sets - **/ - function getActionsSetCount() external view returns (uint256); - - /** - * @notice Returns the data of an actions set - * @param actionsSetId The id of the ActionsSet - * @return The data of the ActionsSet - **/ - function getActionsSetById(uint256 actionsSetId) external view returns (ActionsSet memory); - - /** - * @notice Returns the current state of an actions set - * @param actionsSetId The id of the ActionsSet - * @return The current state of theI ActionsSet - **/ - function getCurrentState(uint256 actionsSetId) external view returns (ActionsSetState); - - /** - * @notice Returns whether an actions set (by actionHash) is queued - * @dev actionHash = keccak256(abi.encode(target, value, signature, data, executionTime, withDelegatecall)) - * @param actionHash hash of the action to be checked - * @return True if the underlying action of actionHash is queued, false otherwise - **/ - function isActionQueued(bytes32 actionHash) external view returns (bool); + error InvalidInitParams(); + error NotGuardian(); + error OnlyCallableByThis(); + error MinimumDelayTooLong(); + error MaximumDelayTooShort(); + error GracePeriodTooShort(); + error DelayShorterThanMin(); + error DelayLongerThanMax(); + error OnlyQueuedActions(); + error TimelockNotFinished(); + error InvalidActionsSetId(); + error EmptyTargets(); + error InconsistentParamsLength(); + error DuplicateAction(); + error InsufficientBalance(); + error FailedActionExecution(); + + /** + * @notice This enum contains all possible actions set states + */ + enum ActionsSetState { + Queued, + Executed, + Canceled, + Expired + } + + /** + * @notice This struct contains the data needed to execute a specified set of actions + * @param targets Array of targets to call + * @param values Array of values to pass in each call + * @param signatures Array of function signatures to encode in each call (can be empty) + * @param calldatas Array of calldatas to pass in each call, appended to the signature at the same array index if not empty + * @param withDelegateCalls Array of whether to delegatecall for each call + * @param executionTime Timestamp starting from which the actions set can be executed + * @param executed True if the actions set has been executed, false otherwise + * @param canceled True if the actions set has been canceled, false otherwise + */ + struct ActionsSet { + address[] targets; + uint256[] values; + string[] signatures; + bytes[] calldatas; + bool[] withDelegatecalls; + uint256 executionTime; + bool executed; + bool canceled; + } + + /** + * @dev Emitted when an ActionsSet is queued + * @param id Id of the ActionsSet + * @param targets Array of targets to be called by the actions set + * @param values Array of values to pass in each call by the actions set + * @param signatures Array of function signatures to encode in each call by the actions set + * @param calldatas Array of calldata to pass in each call by the actions set + * @param withDelegatecalls Array of whether to delegatecall for each call of the actions set + * @param executionTime The timestamp at which this actions set can be executed + **/ + event ActionsSetQueued( + uint256 indexed id, + address[] targets, + uint256[] values, + string[] signatures, + bytes[] calldatas, + bool[] withDelegatecalls, + uint256 executionTime + ); + + /** + * @dev Emitted when an ActionsSet is successfully executed + * @param id Id of the ActionsSet + * @param initiatorExecution The address that triggered the ActionsSet execution + * @param returnedData The returned data from the ActionsSet execution + **/ + event ActionsSetExecuted( + uint256 indexed id, + address indexed initiatorExecution, + bytes[] returnedData + ); + + /** + * @dev Emitted when an ActionsSet is cancelled by the guardian + * @param id Id of the ActionsSet + **/ + event ActionsSetCanceled(uint256 indexed id); + + /** + * @dev Emitted when a new guardian is set + * @param oldGuardian The address of the old guardian + * @param newGuardian The address of the new guardian + **/ + event GuardianUpdate(address oldGuardian, address newGuardian); + + /** + * @dev Emitted when the delay (between queueing and execution) is updated + * @param oldDelay The value of the old delay + * @param newDelay The value of the new delay + **/ + event DelayUpdate(uint256 oldDelay, uint256 newDelay); + + /** + * @dev Emitted when the grace period (between executionTime and expiration) is updated + * @param oldGracePeriod The value of the old grace period + * @param newGracePeriod The value of the new grace period + **/ + event GracePeriodUpdate(uint256 oldGracePeriod, uint256 newGracePeriod); + + /** + * @dev Emitted when the minimum delay (lower bound of delay) is updated + * @param oldMinimumDelay The value of the old minimum delay + * @param newMinimumDelay The value of the new minimum delay + **/ + event MinimumDelayUpdate(uint256 oldMinimumDelay, uint256 newMinimumDelay); + + /** + * @dev Emitted when the maximum delay (upper bound of delay)is updated + * @param oldMaximumDelay The value of the old maximum delay + * @param newMaximumDelay The value of the new maximum delay + **/ + event MaximumDelayUpdate(uint256 oldMaximumDelay, uint256 newMaximumDelay); + + /** + * @notice Execute the ActionsSet + * @param actionsSetId The id of the ActionsSet to execute + **/ + function execute(uint256 actionsSetId) external payable; + + /** + * @notice Cancel the ActionsSet + * @param actionsSetId The id of the ActionsSet to cancel + **/ + function cancel(uint256 actionsSetId) external; + + /** + * @notice Update guardian + * @param guardian The address of the new guardian + **/ + function updateGuardian(address guardian) external; + + /** + * @notice Update the delay, time between queueing and execution of ActionsSet + * @dev It does not affect to actions set that are already queued + * @param delay The value of the delay (in seconds) + **/ + function updateDelay(uint256 delay) external; + + /** + * @notice Update the grace period, the period after the execution time during which an actions set can be executed + * @param gracePeriod The value of the grace period (in seconds) + **/ + function updateGracePeriod(uint256 gracePeriod) external; + + /** + * @notice Update the minimum allowed delay + * @param minimumDelay The value of the minimum delay (in seconds) + **/ + function updateMinimumDelay(uint256 minimumDelay) external; + + /** + * @notice Update the maximum allowed delay + * @param maximumDelay The maximum delay (in seconds) + **/ + function updateMaximumDelay(uint256 maximumDelay) external; + + /** + * @notice Allows to delegatecall a given target with an specific amount of value + * @dev This function is external so it allows to specify a defined msg.value for the delegate call, reducing + * the risk that a delegatecall gets executed with more value than intended + * @return True if the delegate call was successful, false otherwise + * @return The bytes returned by the delegate call + **/ + function executeDelegateCall(address target, bytes calldata data) + external + payable + returns (bool, bytes memory); + + /** + * @notice Allows to receive funds into the executor + * @dev Useful for actionsSet that needs funds to gets executed + */ + function receiveFunds() external payable; + + /** + * @notice Returns the delay (between queuing and execution) + * @return The value of the delay (in seconds) + **/ + function getDelay() external view returns (uint256); + + /** + * @notice Returns the grace period + * @return The value of the grace period (in seconds) + **/ + function getGracePeriod() external view returns (uint256); + + /** + * @notice Returns the minimum delay + * @return The value of the minimum delay (in seconds) + **/ + function getMinimumDelay() external view returns (uint256); + + /** + * @notice Returns the maximum delay + * @return The value of the maximum delay (in seconds) + **/ + function getMaximumDelay() external view returns (uint256); + + /** + * @notice Returns the address of the guardian + * @return The address of the guardian + **/ + function getGuardian() external view returns (address); + + /** + * @notice Returns the total number of actions sets of the executor + * @return The number of actions sets + **/ + function getActionsSetCount() external view returns (uint256); + + /** + * @notice Returns the data of an actions set + * @param actionsSetId The id of the ActionsSet + * @return The data of the ActionsSet + **/ + function getActionsSetById(uint256 actionsSetId) external view returns (ActionsSet memory); + + /** + * @notice Returns the current state of an actions set + * @param actionsSetId The id of the ActionsSet + * @return The current state of theI ActionsSet + **/ + function getCurrentState(uint256 actionsSetId) external view returns (ActionsSetState); + + /** + * @notice Returns whether an actions set (by actionHash) is queued + * @dev actionHash = keccak256(abi.encode(target, value, signature, data, executionTime, withDelegatecall)) + * @param actionHash hash of the action to be checked + * @return True if the underlying action of actionHash is queued, false otherwise + **/ + function isActionQueued(bytes32 actionHash) external view returns (bool); } diff --git a/src/interfaces/IL2BridgeExecutor.sol b/src/interfaces/IL2BridgeExecutor.sol index 270c507..0080607 100644 --- a/src/interfaces/IL2BridgeExecutor.sol +++ b/src/interfaces/IL2BridgeExecutor.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.10; -import {IExecutorBase} from './IExecutorBase.sol'; +import { IExecutorBase } from './IExecutorBase.sol'; /** * @title IL2BridgeExecutorBase @@ -9,44 +9,44 @@ import {IExecutorBase} from './IExecutorBase.sol'; * @notice Defines the basic interface for the L2BridgeExecutor abstract contract */ interface IL2BridgeExecutor is IExecutorBase { - error UnauthorizedEthereumExecutor(); + error UnauthorizedEthereumExecutor(); - /** - * @dev Emitted when the Ethereum Governance Executor is updated - * @param oldEthereumGovernanceExecutor The address of the old EthereumGovernanceExecutor - * @param newEthereumGovernanceExecutor The address of the new EthereumGovernanceExecutor - **/ - event EthereumGovernanceExecutorUpdate( - address oldEthereumGovernanceExecutor, - address newEthereumGovernanceExecutor - ); + /** + * @dev Emitted when the Ethereum Governance Executor is updated + * @param oldEthereumGovernanceExecutor The address of the old EthereumGovernanceExecutor + * @param newEthereumGovernanceExecutor The address of the new EthereumGovernanceExecutor + **/ + event EthereumGovernanceExecutorUpdate( + address oldEthereumGovernanceExecutor, + address newEthereumGovernanceExecutor + ); - /** - * @notice Queue an ActionsSet - * @dev If a signature is empty, calldata is used for the execution, calldata is appended to signature otherwise - * @param targets Array of targets to be called by the actions set - * @param values Array of values to pass in each call by the actions set - * @param signatures Array of function signatures to encode in each call by the actions (can be empty) - * @param calldatas Array of calldata to pass in each call by the actions set - * @param withDelegatecalls Array of whether to delegatecall for each call of the actions set - **/ - function queue( - address[] memory targets, - uint256[] memory values, - string[] memory signatures, - bytes[] memory calldatas, - bool[] memory withDelegatecalls - ) external; + /** + * @notice Queue an ActionsSet + * @dev If a signature is empty, calldata is used for the execution, calldata is appended to signature otherwise + * @param targets Array of targets to be called by the actions set + * @param values Array of values to pass in each call by the actions set + * @param signatures Array of function signatures to encode in each call by the actions (can be empty) + * @param calldatas Array of calldata to pass in each call by the actions set + * @param withDelegatecalls Array of whether to delegatecall for each call of the actions set + **/ + function queue( + address[] memory targets, + uint256[] memory values, + string[] memory signatures, + bytes[] memory calldatas, + bool[] memory withDelegatecalls + ) external; - /** - * @notice Update the address of the Ethereum Governance Executor - * @param ethereumGovernanceExecutor The address of the new EthereumGovernanceExecutor - **/ - function updateEthereumGovernanceExecutor(address ethereumGovernanceExecutor) external; + /** + * @notice Update the address of the Ethereum Governance Executor + * @param ethereumGovernanceExecutor The address of the new EthereumGovernanceExecutor + **/ + function updateEthereumGovernanceExecutor(address ethereumGovernanceExecutor) external; - /** - * @notice Returns the address of the Ethereum Governance Executor - * @return The address of the EthereumGovernanceExecutor - **/ - function getEthereumGovernanceExecutor() external view returns (address); + /** + * @notice Returns the address of the Ethereum Governance Executor + * @return The address of the EthereumGovernanceExecutor + **/ + function getEthereumGovernanceExecutor() external view returns (address); } diff --git a/test/ArbitrumCrosschainTest.t.sol b/test/ArbitrumCrosschainTest.t.sol index e9ca25c..f1fb3ad 100644 --- a/test/ArbitrumCrosschainTest.t.sol +++ b/test/ArbitrumCrosschainTest.t.sol @@ -6,31 +6,28 @@ import 'forge-std/Test.sol'; import { Domain, ArbitrumDomain } from 'xchain-helpers/ArbitrumDomain.sol'; import { XChainForwarders } from 'xchain-helpers/XChainForwarders.sol'; -import { ArbitrumBridgeExecutor } from '../src/executors/ArbitrumBridgeExecutor.sol'; +import { ArbitrumBridgeExecutor } from '../src/executors/ArbitrumBridgeExecutor.sol'; import { IPayload } from './interfaces/IPayload.sol'; import { CrosschainPayload, CrosschainTestBase } from './CrosschainTestBase.sol'; contract ArbitrumCrosschainPayload is CrosschainPayload { - constructor(IPayload _targetPayload, address _bridgeExecutor) - CrosschainPayload(_targetPayload, _bridgeExecutor) {} + CrosschainPayload(_targetPayload, _bridgeExecutor) {} - function execute() override external { + function execute() external override { XChainForwarders.sendMessageArbitrumOne( bridgeExecutor, encodeCrosschainExecutionMessage(), 1_000_000 ); } - } -contract ArbitrumCrosschainTest is CrosschainTestBase { - +contract ArbitrumCrosschainTest is CrosschainTestBase { function deployCrosschainPayload(IPayload targetPayload, address bridgeExecutor) - public override returns(IPayload) + public override returns (IPayload) { return IPayload(new ArbitrumCrosschainPayload(targetPayload, bridgeExecutor)); } @@ -40,19 +37,18 @@ contract ArbitrumCrosschainTest is CrosschainTestBase { bridgedDomain = new ArbitrumDomain(getChain('arbitrum_one'), hostDomain); bridgedDomain.selectFork(); - bridgeExecutor = address(new ArbitrumBridgeExecutor( - defaultL2BridgeExecutorArgs.ethereumGovernanceExecutor, - defaultL2BridgeExecutorArgs.delay, - defaultL2BridgeExecutorArgs.gracePeriod, - defaultL2BridgeExecutorArgs.minimumDelay, - defaultL2BridgeExecutorArgs.maximumDelay, - defaultL2BridgeExecutorArgs.guardian - )); + bridgeExecutor = address( + new ArbitrumBridgeExecutor( + defaultL2BridgeExecutorArgs.ethereumGovernanceExecutor, + defaultL2BridgeExecutorArgs.delay, + defaultL2BridgeExecutorArgs.gracePeriod, + defaultL2BridgeExecutorArgs.minimumDelay, + defaultL2BridgeExecutorArgs.maximumDelay, + defaultL2BridgeExecutorArgs.guardian + ) + ); hostDomain.selectFork(); - vm.deal( - L1_EXECUTOR, - 0.01 ether - ); + vm.deal(L1_EXECUTOR, 0.01 ether); } } diff --git a/test/CrosschainTestBase.sol b/test/CrosschainTestBase.sol index 5b9ff8f..d443ca2 100644 --- a/test/CrosschainTestBase.sol +++ b/test/CrosschainTestBase.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; import 'forge-std/Test.sol'; -import "forge-std/console.sol"; +import 'forge-std/console.sol'; import { BridgedDomain } from 'xchain-helpers/BridgedDomain.sol'; import { Domain } from 'xchain-helpers/Domain.sol'; @@ -60,12 +60,12 @@ abstract contract CrosschainPayload is IPayload { } -abstract contract CrosschainTestBase is Test { +abstract contract CrosschainTestBase is Test { event TestEvent(); address public constant L1_EXECUTOR = 0x3300f198988e4C9C63F75dF86De36421f06af8c4; address public constant L1_PAUSE_PROXY = 0xBE8E3e3618f7474F8cB1d074A26afFef007E98FB; - address public GUARDIAN = makeAddr("guardian"); + address public GUARDIAN = makeAddr('guardian'); L2BridgeExecutorArguments public defaultL2BridgeExecutorArgs = L2BridgeExecutorArguments({ ethereumGovernanceExecutor: L1_EXECUTOR, @@ -81,7 +81,7 @@ abstract contract CrosschainTestBase is Test { address public bridgeExecutor; - function deployCrosschainPayload(IPayload targetPayload, address bridgeExecutor) public virtual returns(IPayload); + function deployCrosschainPayload(IPayload targetPayload, address bridgeExecutor) public virtual returns (IPayload); function preparePayloadExecution() public { bridgedDomain.selectFork(); @@ -90,7 +90,10 @@ abstract contract CrosschainTestBase is Test { hostDomain.selectFork(); - IPayload crosschainPayload = deployCrosschainPayload(targetPayload, bridgeExecutor); + IPayload crosschainPayload = deployCrosschainPayload( + targetPayload, + bridgeExecutor + ); vm.prank(L1_PAUSE_PROXY); IL1Executor(L1_EXECUTOR).exec( @@ -133,11 +136,7 @@ abstract contract CrosschainTestBase is Test { } function testFuzz_actionExecutionFailsBeforeTimelock(uint delay) public { - delay = bound( - delay, - 0, - defaultL2BridgeExecutorArgs.delay - 1 - ); + delay = bound(delay, 0, defaultL2BridgeExecutorArgs.delay - 1); preparePayloadExecution(); @@ -164,22 +163,31 @@ abstract contract CrosschainTestBase is Test { } function test_onlyGuardianCanCancel() public { - address notGuardian = makeAddr("notGuardian"); + address notGuardian = makeAddr('notGuardian'); preparePayloadExecution(); - assertEq(IL2BridgeExecutor(bridgeExecutor).getActionsSetById(0).canceled, false); + assertEq( + IL2BridgeExecutor(bridgeExecutor).getActionsSetById(0).canceled, + false + ); vm.expectRevert(); vm.prank(notGuardian); IL2BridgeExecutor(bridgeExecutor).cancel(0); - assertEq(IL2BridgeExecutor(bridgeExecutor).getActionsSetById(0).canceled, false); + assertEq( + IL2BridgeExecutor(bridgeExecutor).getActionsSetById(0).canceled, + false + ); vm.prank(defaultL2BridgeExecutorArgs.guardian); IL2BridgeExecutor(bridgeExecutor).cancel(0); - assertEq(IL2BridgeExecutor(bridgeExecutor).getActionsSetById(0).canceled, true); + assertEq( + IL2BridgeExecutor(bridgeExecutor).getActionsSetById(0).canceled, + true + ); } function test_canceledActionCannotBeCanceled() public { @@ -236,27 +244,63 @@ abstract contract CrosschainTestBase is Test { skip(defaultL2BridgeExecutorArgs.delay); - assertEq(IL2BridgeExecutor(bridgeExecutor).getActionsSetById(0).executed, false); - assertEq(IL2BridgeExecutor(bridgeExecutor).getActionsSetById(1).executed, false); - assertEq(IL2BridgeExecutor(bridgeExecutor).getActionsSetById(2).executed, false); + assertEq( + IL2BridgeExecutor(bridgeExecutor).getActionsSetById(0).executed, + false + ); + assertEq( + IL2BridgeExecutor(bridgeExecutor).getActionsSetById(1).executed, + false + ); + assertEq( + IL2BridgeExecutor(bridgeExecutor).getActionsSetById(2).executed, + false + ); IL2BridgeExecutor(bridgeExecutor).execute(1); - assertEq(IL2BridgeExecutor(bridgeExecutor).getActionsSetById(0).executed, false); - assertEq(IL2BridgeExecutor(bridgeExecutor).getActionsSetById(1).executed, true); - assertEq(IL2BridgeExecutor(bridgeExecutor).getActionsSetById(2).executed, false); + assertEq( + IL2BridgeExecutor(bridgeExecutor).getActionsSetById(0).executed, + false + ); + assertEq( + IL2BridgeExecutor(bridgeExecutor).getActionsSetById(1).executed, + true + ); + assertEq( + IL2BridgeExecutor(bridgeExecutor).getActionsSetById(2).executed, + false + ); IL2BridgeExecutor(bridgeExecutor).execute(2); - assertEq(IL2BridgeExecutor(bridgeExecutor).getActionsSetById(0).executed, false); - assertEq(IL2BridgeExecutor(bridgeExecutor).getActionsSetById(1).executed, true); - assertEq(IL2BridgeExecutor(bridgeExecutor).getActionsSetById(2).executed, true); + assertEq( + IL2BridgeExecutor(bridgeExecutor).getActionsSetById(0).executed, + false + ); + assertEq( + IL2BridgeExecutor(bridgeExecutor).getActionsSetById(1).executed, + true + ); + assertEq( + IL2BridgeExecutor(bridgeExecutor).getActionsSetById(2).executed, + true + ); IL2BridgeExecutor(bridgeExecutor).execute(0); - assertEq(IL2BridgeExecutor(bridgeExecutor).getActionsSetById(0).executed, true); - assertEq(IL2BridgeExecutor(bridgeExecutor).getActionsSetById(1).executed, true); - assertEq(IL2BridgeExecutor(bridgeExecutor).getActionsSetById(2).executed, true); + assertEq( + IL2BridgeExecutor(bridgeExecutor).getActionsSetById(0).executed, + true + ); + assertEq( + IL2BridgeExecutor(bridgeExecutor).getActionsSetById(1).executed, + true + ); + assertEq( + IL2BridgeExecutor(bridgeExecutor).getActionsSetById(2).executed, + true + ); } function test_selfReconfiguration() public { @@ -289,7 +333,7 @@ abstract contract CrosschainTestBase is Test { gracePeriod: 1800, minimumDelay: 100, maximumDelay: 3600, - guardian: makeAddr("newGuardian") + guardian: makeAddr('newGuardian') }); IPayload reconfigurationPayload = IPayload(new ReconfigurationPayload( @@ -302,7 +346,10 @@ abstract contract CrosschainTestBase is Test { hostDomain.selectFork(); - IPayload crosschainPayload = deployCrosschainPayload(reconfigurationPayload, bridgeExecutor); + IPayload crosschainPayload = deployCrosschainPayload( + reconfigurationPayload, + bridgeExecutor + ); vm.prank(L1_PAUSE_PROXY); IL1Executor(L1_EXECUTOR).exec( diff --git a/test/GnosisCrosschainTest.t.sol b/test/GnosisCrosschainTest.t.sol index 65bc81b..18b4aaf 100644 --- a/test/GnosisCrosschainTest.t.sol +++ b/test/GnosisCrosschainTest.t.sol @@ -20,9 +20,9 @@ import { CrosschainPayload, CrosschainTestBase } from './CrosschainTestBase.sol' contract GnosisCrosschainPayload is CrosschainPayload { constructor(IPayload _targetPayload, address _bridgeExecutor) - CrosschainPayload(_targetPayload, _bridgeExecutor) {} + CrosschainPayload(_targetPayload, _bridgeExecutor) {} - function execute() override external { + function execute() external override { XChainForwarders.sendMessageGnosis( bridgeExecutor, encodeCrosschainExecutionMessage(), @@ -33,13 +33,12 @@ contract GnosisCrosschainPayload is CrosschainPayload { } contract GnosisCrosschainTest is CrosschainTestBase { - IAMB public constant AMB = IAMB(0x75Df5AF045d91108662D8080fD1FEFAd6aA0bb59); bytes32 public constant MAINNET_CHAIN_ID = bytes32(uint256(1)); function deployCrosschainPayload(IPayload targetPayload, address bridgeExecutor) - public override returns(IPayload) + public override returns (IPayload) { return IPayload(new GnosisCrosschainPayload(targetPayload, bridgeExecutor)); } @@ -79,8 +78,8 @@ contract GnosisCrosschainTest is CrosschainTestBase { MAINNET_CHAIN_ID ); - address newAmb = makeAddr("newAMB"); - address newController = makeAddr("newController"); + address newAmb = makeAddr('newAMB'); + address newController = makeAddr('newController'); bytes32 newChainId = bytes32(uint256(2)); @@ -92,7 +91,10 @@ contract GnosisCrosschainTest is CrosschainTestBase { hostDomain.selectFork(); - IPayload crosschainPayload = deployCrosschainPayload(reconfigurationPayload, bridgeExecutor); + IPayload crosschainPayload = deployCrosschainPayload( + reconfigurationPayload, + bridgeExecutor + ); vm.prank(L1_PAUSE_PROXY); IL1Executor(L1_EXECUTOR).exec( @@ -106,18 +108,12 @@ contract GnosisCrosschainTest is CrosschainTestBase { IL2BridgeExecutor(bridgeExecutor).execute(0); - assertEq( - address(GnosisBridgeExecutor(bridgeExecutor).amb()), - newAmb - ); + assertEq(address(GnosisBridgeExecutor(bridgeExecutor).amb()), newAmb); assertEq( GnosisBridgeExecutor(bridgeExecutor).controller(), newController ); - assertEq( - GnosisBridgeExecutor(bridgeExecutor).chainId(), - newChainId - ); + assertEq(GnosisBridgeExecutor(bridgeExecutor).chainId(), newChainId); } } diff --git a/test/OptimismCrosschainTest.t.sol b/test/OptimismCrosschainTest.t.sol index 805dad2..8736471 100644 --- a/test/OptimismCrosschainTest.t.sol +++ b/test/OptimismCrosschainTest.t.sol @@ -17,9 +17,9 @@ import { CrosschainPayload, CrosschainTestBase } from './CrosschainTestBase.sol' contract OptimismCrosschainPayload is CrosschainPayload { constructor(IPayload _targetPayload, address _bridgeExecutor) - CrosschainPayload(_targetPayload, _bridgeExecutor) {} + CrosschainPayload(_targetPayload, _bridgeExecutor) {} - function execute() override external { + function execute() external override { XChainForwarders.sendMessageOptimismMainnet( bridgeExecutor, encodeCrosschainExecutionMessage(), @@ -34,7 +34,7 @@ contract OptimismCrosschainTest is CrosschainTestBase { address public constant OVM_L2_CROSS_DOMAIN_MESSENGER = 0x4200000000000000000000000000000000000007; function deployCrosschainPayload(IPayload targetPayload, address bridgeExecutor) - public override returns(IPayload) + public override returns (IPayload) { return IPayload(new OptimismCrosschainPayload(targetPayload, bridgeExecutor)); } diff --git a/test/interfaces/IPayload.sol b/test/interfaces/IPayload.sol index 4c7b5f2..4e96a47 100644 --- a/test/interfaces/IPayload.sol +++ b/test/interfaces/IPayload.sol @@ -3,6 +3,6 @@ pragma solidity ^0.8.10; interface IPayload { - function execute() external; + function execute() external; } diff --git a/test/mocks/GnosisReconfigurationPayload.sol b/test/mocks/GnosisReconfigurationPayload.sol index 75adec2..14313de 100644 --- a/test/mocks/GnosisReconfigurationPayload.sol +++ b/test/mocks/GnosisReconfigurationPayload.sol @@ -20,9 +20,9 @@ contract GnosisReconfigurationPayload is IPayload { address _newController, bytes32 _newChainId ) { - newAmb = _newAmb; + newAmb = _newAmb; newController = _newController; - newChainId = _newChainId; + newChainId = _newChainId; } function execute() external override { diff --git a/test/mocks/PayloadWithEmit.sol b/test/mocks/PayloadWithEmit.sol index 8b9c812..edd7bd5 100644 --- a/test/mocks/PayloadWithEmit.sol +++ b/test/mocks/PayloadWithEmit.sol @@ -7,9 +7,9 @@ import { IPayload } from '../interfaces/IPayload.sol'; * @dev This payload simply emits an event on execution */ contract PayloadWithEmit is IPayload { - event TestEvent(); + event TestEvent(); - function execute() external override { - emit TestEvent(); - } + function execute() external override { + emit TestEvent(); + } } diff --git a/test/mocks/ReconfigurationPayload.sol b/test/mocks/ReconfigurationPayload.sol index c294316..380b061 100644 --- a/test/mocks/ReconfigurationPayload.sol +++ b/test/mocks/ReconfigurationPayload.sol @@ -23,11 +23,11 @@ contract ReconfigurationPayload is IPayload { uint256 _newMaximumDelay, address _newGuardian ) { - newDelay = _newDelay; - newGracePeriod = _newGracePeriod; + newDelay = _newDelay; + newGracePeriod = _newGracePeriod; newMinimumDelay = _newMinimumDelay; newMaximumDelay = _newMaximumDelay; - newGuardian = _newGuardian; + newGuardian = _newGuardian; } function execute() external override {