diff --git a/contracts/bridges/ZkEVMBridgeExecutor.sol b/contracts/bridges/ZkEVMBridgeExecutor.sol new file mode 100644 index 0000000..af573e4 --- /dev/null +++ b/contracts/bridges/ZkEVMBridgeExecutor.sol @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.10; + +import {L2BridgeExecutor} from './L2BridgeExecutor.sol'; +import {IBridgeMessageReceiver} from '../dependencies/polygon-zkevm/IBridgeMessageReceiver.sol'; + +/** + * @title ZkEVMBridgeExecutor + * @author Aave + * @notice Implementation of the ZkEVM Bridge Executor, able to receive cross-chain transactions from Ethereum + */ +contract ZkEVMBridgeExecutor is L2BridgeExecutor, IBridgeMessageReceiver { + error UnauthorizedBridgeCaller(); + error NotDirectlyCallable(); + error InvalidOriginNetwork(); + error InvalidMethodId(); + + address internal constant zkEVMBridge = 0x2a3DD3EB832aF982ec71669E178424b10Dca2EDe; + uint32 internal constant _MAINNET_NETWORK_ID = 0; + + /// @inheritdoc L2BridgeExecutor + modifier onlyEthereumGovernanceExecutor() override { + revert NotDirectlyCallable(); + _; + } + + modifier onlyBridge() { + if (msg.sender != zkEVMBridge) revert UnauthorizedBridgeCaller(); + _; + } + + /** + * @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) + * @dev zkEVMBridge calls `onMessageReceived` with originSender, originNetwork and calldata. All of them are verified. + * But this also means we need queue function to not be callable, will always revert. + */ + constructor( + address ethereumGovernanceExecutor, + uint256 delay, + uint256 gracePeriod, + uint256 minimumDelay, + uint256 maximumDelay, + address guardian + ) + L2BridgeExecutor( + ethereumGovernanceExecutor, + delay, + gracePeriod, + minimumDelay, + maximumDelay, + guardian + ) + { + // Intentionally left blank + } + + function onMessageReceived( + address originAddress, + uint32 originNetwork, + bytes calldata data + ) external payable onlyBridge { + if (originAddress != _ethereumGovernanceExecutor) { + revert UnauthorizedEthereumExecutor(); + } + if (originNetwork != _MAINNET_NETWORK_ID) { + revert InvalidOriginNetwork(); + } + bytes4 methodId = bytes4(data[0:4]); + if (methodId != this.queue.selector) { + revert InvalidMethodId(); + } + + ( + address[] memory targets, + uint256[] memory values, + string[] memory signatures, + bytes[] memory calldatas, + bool[] memory withDelegatecalls + ) = abi.decode(data[4:], (address[], uint256[], string[], bytes[], bool[])); + + _queue(targets, values, signatures, calldatas, withDelegatecalls); + } +} diff --git a/contracts/dependencies/polygon-zkevm/IBridgeMessageReceiver.sol b/contracts/dependencies/polygon-zkevm/IBridgeMessageReceiver.sol new file mode 100644 index 0000000..e8b7273 --- /dev/null +++ b/contracts/dependencies/polygon-zkevm/IBridgeMessageReceiver.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: AGPL-3.0 + +pragma solidity ^0.8.10; + +/** + * @dev Define interface for PolygonZkEVM Bridge message receiver + */ +interface IBridgeMessageReceiver { + function onMessageReceived( + address originAddress, + uint32 originNetwork, + bytes memory data + ) external payable; +}