From d7a17aef27cfd7fa4f18ac7a44953f4b7d9457b5 Mon Sep 17 00:00:00 2001 From: Shaleen Jain Date: Mon, 14 Feb 2022 12:19:19 +0530 Subject: [PATCH] feat: add L2 safe bridge checks --- ...eceiver.sol => BaseFastBridgeReceiver.sol} | 4 +- .../src/bridge/FastBridgeReceiverArbitrum.sol | 30 +++++++ .../src/bridge/FastBridgeReceiverGnosis.sol | 29 +++++++ .../bridge/interfaces/arbitrum/IBridge.sol | 65 +++++++++++++++ .../src/bridge/interfaces/arbitrum/IInbox.sol | 81 +++++++++++++++++++ .../interfaces/arbitrum/IMessageProvider.sol | 25 ++++++ .../bridge/interfaces/arbitrum/IOutbox.sol | 50 ++++++++++++ 7 files changed, 283 insertions(+), 1 deletion(-) rename contracts/src/bridge/{FastBridgeReceiver.sol => BaseFastBridgeReceiver.sol} (96%) create mode 100644 contracts/src/bridge/FastBridgeReceiverArbitrum.sol create mode 100644 contracts/src/bridge/FastBridgeReceiverGnosis.sol create mode 100644 contracts/src/bridge/interfaces/arbitrum/IBridge.sol create mode 100644 contracts/src/bridge/interfaces/arbitrum/IInbox.sol create mode 100644 contracts/src/bridge/interfaces/arbitrum/IMessageProvider.sol create mode 100644 contracts/src/bridge/interfaces/arbitrum/IOutbox.sol diff --git a/contracts/src/bridge/FastBridgeReceiver.sol b/contracts/src/bridge/BaseFastBridgeReceiver.sol similarity index 96% rename from contracts/src/bridge/FastBridgeReceiver.sol rename to contracts/src/bridge/BaseFastBridgeReceiver.sol index 7c1fd9715..310f74533 100644 --- a/contracts/src/bridge/FastBridgeReceiver.sol +++ b/contracts/src/bridge/BaseFastBridgeReceiver.sol @@ -12,7 +12,7 @@ pragma solidity ^0.8.0; import "./interfaces/IFastBridgeReceiver.sol"; -contract FastBridgeReceiver is IFastBridgeReceiver { +abstract contract BaseFastBridgeReceiver is IFastBridgeReceiver { address public governor; uint256 public claimDeposit; uint256 public challengeDuration; @@ -97,4 +97,6 @@ contract FastBridgeReceiver is IFastBridgeReceiver { function setChallengePeriodDuration(uint256 _challengeDuration) external onlyByGovernor { challengeDuration = _challengeDuration; } + + function onlyCrossChainSender() external virtual; } diff --git a/contracts/src/bridge/FastBridgeReceiverArbitrum.sol b/contracts/src/bridge/FastBridgeReceiverArbitrum.sol new file mode 100644 index 000000000..36fd084f2 --- /dev/null +++ b/contracts/src/bridge/FastBridgeReceiverArbitrum.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./interfaces/arbitrum/IInbox.sol"; +import "./interfaces/arbitrum/IOutbox.sol"; + +import "./BaseFastBridgeReceiver.sol"; + +contract FastBridgeReceiverArbitrum is BaseFastBridgeReceiver { + address public crossDomainSender; + IInbox public inbox; + + constructor( + address _governor, + uint256 _claimDeposit, + uint256 _challengeDuration, + address _crossDomainSender, + address _inbox + ) BaseFastBridgeReceiver(_governor, _claimDeposit, _challengeDuration) { + crossDomainSender = _crossDomainSender; + inbox = IInbox(_inbox); + } + + function onlyCrossChainSender() external override { + IOutbox outbox = IOutbox(inbox.bridge().activeOutbox()); + address l2Sender = outbox.l2ToL1Sender(); + require(l2Sender == crossDomainSender, "Only L2 target"); + } +} diff --git a/contracts/src/bridge/FastBridgeReceiverGnosis.sol b/contracts/src/bridge/FastBridgeReceiverGnosis.sol new file mode 100644 index 000000000..8c25d33d4 --- /dev/null +++ b/contracts/src/bridge/FastBridgeReceiverGnosis.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./interfaces/gnosis-chain/IAMB.sol"; + +import "./BaseFastBridgeReceiver.sol"; + +contract FastBridgeReceiverGnosis is BaseFastBridgeReceiver { + address public crossDomainSender; + IAMB public amb; + + constructor( + address _governor, + uint256 _claimDeposit, + uint256 _challengeDuration, + address _crossDomainSender, + IAMB _amb + ) BaseFastBridgeReceiver(_governor, _claimDeposit, _challengeDuration) { + crossDomainSender = _crossDomainSender; + amb = _amb; + } + + function onlyCrossChainSender() external override { + require(msg.sender == address(amb), "Only AMB allowed"); + // require(amb.messageSourceChainId() == homeChainId, "Only home chain allowed"); + require(amb.messageSender() == crossDomainSender, "Only home gateway allowed"); + } +} diff --git a/contracts/src/bridge/interfaces/arbitrum/IBridge.sol b/contracts/src/bridge/interfaces/arbitrum/IBridge.sol new file mode 100644 index 000000000..631fce68f --- /dev/null +++ b/contracts/src/bridge/interfaces/arbitrum/IBridge.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2021, Offchain Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +interface IBridge { + event MessageDelivered( + uint256 indexed messageIndex, + bytes32 indexed beforeInboxAcc, + address inbox, + uint8 kind, + address sender, + bytes32 messageDataHash + ); + + event BridgeCallTriggered(address indexed outbox, address indexed destAddr, uint256 amount, bytes data); + + event InboxToggle(address indexed inbox, bool enabled); + + event OutboxToggle(address indexed outbox, bool enabled); + + function deliverMessageToInbox( + uint8 kind, + address sender, + bytes32 messageDataHash + ) external payable returns (uint256); + + function executeCall( + address destAddr, + uint256 amount, + bytes calldata data + ) external returns (bool success, bytes memory returnData); + + // These are only callable by the admin + function setInbox(address inbox, bool enabled) external; + + function setOutbox(address inbox, bool enabled) external; + + // View functions + + function activeOutbox() external view returns (address); + + function allowedInboxes(address inbox) external view returns (bool); + + function allowedOutboxes(address outbox) external view returns (bool); + + function inboxAccs(uint256 index) external view returns (bytes32); + + function messageCount() external view returns (uint256); +} diff --git a/contracts/src/bridge/interfaces/arbitrum/IInbox.sol b/contracts/src/bridge/interfaces/arbitrum/IInbox.sol new file mode 100644 index 000000000..2b85aa0ed --- /dev/null +++ b/contracts/src/bridge/interfaces/arbitrum/IInbox.sol @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2021, Offchain Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +import "./IBridge.sol"; +import "./IMessageProvider.sol"; + +interface IInbox is IMessageProvider { + function sendL2Message(bytes calldata messageData) external returns (uint256); + + function sendUnsignedTransaction( + uint256 maxGas, + uint256 gasPriceBid, + uint256 nonce, + address destAddr, + uint256 amount, + bytes calldata data + ) external returns (uint256); + + function sendContractTransaction( + uint256 maxGas, + uint256 gasPriceBid, + address destAddr, + uint256 amount, + bytes calldata data + ) external returns (uint256); + + function sendL1FundedUnsignedTransaction( + uint256 maxGas, + uint256 gasPriceBid, + uint256 nonce, + address destAddr, + bytes calldata data + ) external payable returns (uint256); + + function sendL1FundedContractTransaction( + uint256 maxGas, + uint256 gasPriceBid, + address destAddr, + bytes calldata data + ) external payable returns (uint256); + + function createRetryableTicket( + address destAddr, + uint256 arbTxCallValue, + uint256 maxSubmissionCost, + address submissionRefundAddress, + address valueRefundAddress, + uint256 maxGas, + uint256 gasPriceBid, + bytes calldata data + ) external payable returns (uint256); + + function depositEth(uint256 maxSubmissionCost) external payable returns (uint256); + + function bridge() external view returns (IBridge); + + function pauseCreateRetryables() external; + + function unpauseCreateRetryables() external; + + function startRewriteAddress() external; + + function stopRewriteAddress() external; +} diff --git a/contracts/src/bridge/interfaces/arbitrum/IMessageProvider.sol b/contracts/src/bridge/interfaces/arbitrum/IMessageProvider.sol new file mode 100644 index 000000000..76208e215 --- /dev/null +++ b/contracts/src/bridge/interfaces/arbitrum/IMessageProvider.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2021, Offchain Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +interface IMessageProvider { + event InboxMessageDelivered(uint256 indexed messageNum, bytes data); + + event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum); +} diff --git a/contracts/src/bridge/interfaces/arbitrum/IOutbox.sol b/contracts/src/bridge/interfaces/arbitrum/IOutbox.sol new file mode 100644 index 000000000..9128a2049 --- /dev/null +++ b/contracts/src/bridge/interfaces/arbitrum/IOutbox.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2021, Offchain Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +pragma solidity ^0.8.0; + +interface IOutbox { + event OutboxEntryCreated( + uint256 indexed batchNum, + uint256 outboxEntryIndex, + bytes32 outputRoot, + uint256 numInBatch + ); + event OutBoxTransactionExecuted( + address indexed destAddr, + address indexed l2Sender, + uint256 indexed outboxEntryIndex, + uint256 transactionIndex + ); + + function l2ToL1Sender() external view returns (address); + + function l2ToL1Block() external view returns (uint256); + + function l2ToL1EthBlock() external view returns (uint256); + + function l2ToL1Timestamp() external view returns (uint256); + + function l2ToL1BatchNum() external view returns (uint256); + + function l2ToL1OutputId() external view returns (bytes32); + + function processOutgoingMessages(bytes calldata sendsData, uint256[] calldata sendLengths) external; + + function outboxEntryExists(uint256 batchNum) external view returns (bool); +}