diff --git a/CHANGELOG.md b/CHANGELOG.md index 93107ee59e5..7e64d89980e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ * `Ownable2Step`: extension of `Ownable` that makes the ownership transfers a two step process. ([#3620](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3620)) * `Math` and `SignedMath`: optimize function `max` by using `>` instead of `>=`. ([#3679](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3679)) * `Math`: Add `log2`, `log10` and `log256`. ([#3670](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3670)) + * Arbitrum: Update the vendored arbitrum contracts to match the nitro upgrade. ([#3692](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3692)) ### Breaking changes diff --git a/contracts/crosschain/arbitrum/LibArbitrumL1.sol b/contracts/crosschain/arbitrum/LibArbitrumL1.sol index 6b591cac413..8947f906d3a 100644 --- a/contracts/crosschain/arbitrum/LibArbitrumL1.sol +++ b/contracts/crosschain/arbitrum/LibArbitrumL1.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.4; import {IBridge as ArbitrumL1_Bridge} from "../../vendor/arbitrum/IBridge.sol"; -import {IInbox as ArbitrumL1_Inbox} from "../../vendor/arbitrum/IInbox.sol"; import {IOutbox as ArbitrumL1_Outbox} from "../../vendor/arbitrum/IOutbox.sol"; import "../errors.sol"; diff --git a/contracts/vendor/arbitrum/IArbSys.sol b/contracts/vendor/arbitrum/IArbSys.sol index 15a10451a23..eb02432d276 100644 --- a/contracts/vendor/arbitrum/IArbSys.sol +++ b/contracts/vendor/arbitrum/IArbSys.sol @@ -1,19 +1,15 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.6.0) (vendor/arbitrum/IArbSys.sol) +// Copyright 2021-2022, Offchain Labs, Inc. +// For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE +// SPDX-License-Identifier: BUSL-1.1 + pragma solidity >=0.4.21 <0.9.0; /** - * @title Precompiled contract that exists in every Arbitrum chain at address(100), 0x0000000000000000000000000000000000000064. Exposes a variety of system-level functionality. + * @title System level functionality + * @notice For use by contracts to interact with core L2-specific functionality. + * Precompiled contract that exists in every Arbitrum chain at address(100), 0x0000000000000000000000000000000000000064. */ interface IArbSys { - /** - * @notice Get internal version number identifying an ArbOS build - * @return version number as int - */ - function arbOSVersion() external pure returns (uint256); - - function arbChainID() external view returns (uint256); - /** * @notice Get Arbitrum block number (distinct from L1 block number; Arbitrum genesis block has block number 0) * @return block number as int @@ -21,43 +17,44 @@ interface IArbSys { function arbBlockNumber() external view returns (uint256); /** - * @notice Send given amount of Eth to dest from sender. - * This is a convenience function, which is equivalent to calling sendTxToL1 with empty calldataForL1. - * @param destination recipient address on L1 - * @return unique identifier for this L2-to-L1 transaction. + * @notice Get Arbitrum block hash (reverts unless currentBlockNum-256 <= arbBlockNum < currentBlockNum) + * @return block hash */ - function withdrawEth(address destination) external payable returns (uint256); + function arbBlockHash(uint256 arbBlockNum) external view returns (bytes32); /** - * @notice Send a transaction to L1 - * @param destination recipient address on L1 - * @param calldataForL1 (optional) calldata for L1 contract call - * @return a unique identifier for this L2-to-L1 transaction. + * @notice Gets the rollup's unique chain identifier + * @return Chain identifier as int */ - function sendTxToL1(address destination, bytes calldata calldataForL1) external payable returns (uint256); + function arbChainID() external view returns (uint256); /** - * @notice get the number of transactions issued by the given external account or the account sequence number of the given contract - * @param account target account - * @return the number of transactions issued by the given external account or the account sequence number of the given contract + * @notice Get internal version number identifying an ArbOS build + * @return version number as int */ - function getTransactionCount(address account) external view returns (uint256); + function arbOSVersion() external view returns (uint256); /** - * @notice get the value of target L2 storage slot - * This function is only callable from address 0 to prevent contracts from being able to call it - * @param account target account - * @param index target index of storage slot - * @return stotage value for the given account at the given index + * @notice Returns 0 since Nitro has no concept of storage gas + * @return uint 0 */ - function getStorageAt(address account, uint256 index) external view returns (uint256); + function getStorageGasAvailable() external view returns (uint256); /** - * @notice check if current call is coming from l1 - * @return true if the caller of this was called directly from L1 + * @notice (deprecated) check if current call is top level (meaning it was triggered by an EoA or a L1 contract) + * @dev this call has been deprecated and may be removed in a future release + * @return true if current execution frame is not a call by another L2 contract */ function isTopLevelCall() external view returns (bool); + /** + * @notice map L1 sender contract address to its L2 alias + * @param sender sender address + * @param unused argument no longer used + * @return aliased sender address + */ + function mapL1SenderContractAddressToL2Alias(address sender, address unused) external pure returns (address); + /** * @notice check if the caller (of this caller of this) is an aliased L1 contract address * @return true iff the caller's address is an alias for an L1 contract address @@ -71,19 +68,55 @@ interface IArbSys { function myCallersAddressWithoutAliasing() external view returns (address); /** - * @notice map L1 sender contract address to its L2 alias - * @param sender sender address - * @param dest destination address - * @return aliased sender address + * @notice Send given amount of Eth to dest from sender. + * This is a convenience function, which is equivalent to calling sendTxToL1 with empty data. + * @param destination recipient address on L1 + * @return unique identifier for this L2-to-L1 transaction. */ - function mapL1SenderContractAddressToL2Alias(address sender, address dest) external pure returns (address); + function withdrawEth(address destination) external payable returns (uint256); /** - * @notice get the caller's amount of available storage gas - * @return amount of storage gas available to the caller + * @notice Send a transaction to L1 + * @dev it is not possible to execute on the L1 any L2-to-L1 transaction which contains data + * to a contract address without any code (as enforced by the Bridge contract). + * @param destination recipient address on L1 + * @param data (optional) calldata for L1 contract call + * @return a unique identifier for this L2-to-L1 transaction. */ - function getStorageGasAvailable() external view returns (uint256); + function sendTxToL1(address destination, bytes calldata data) external payable returns (uint256); + + /** + * @notice Get send Merkle tree state + * @return size number of sends in the history + * @return root root hash of the send history + * @return partials hashes of partial subtrees in the send history tree + */ + function sendMerkleTreeState() + external + view + returns ( + uint256 size, + bytes32 root, + bytes32[] memory partials + ); + + /** + * @notice creates a send txn from L2 to L1 + * @param position = (level << 192) + leaf = (0 << 192) + leaf = leaf + */ + event L2ToL1Tx( + address caller, + address indexed destination, + uint256 indexed hash, + uint256 indexed position, + uint256 arbBlockNum, + uint256 ethBlockNum, + uint256 timestamp, + uint256 callvalue, + bytes data + ); + /// @dev DEPRECATED in favour of the new L2ToL1Tx event above after the nitro upgrade event L2ToL1Transaction( address caller, address indexed destination, @@ -96,4 +129,12 @@ interface IArbSys { uint256 callvalue, bytes data ); + + /** + * @notice logs a merkle branch for proof synthesis + * @param reserved an index meant only to align the 4th index with L2ToL1Transaction's 4th event + * @param hash the merkle hash + * @param position = (level << 192) + leaf + */ + event SendMerkleUpdate(uint256 indexed reserved, bytes32 indexed hash, uint256 indexed position); } diff --git a/contracts/vendor/arbitrum/IBridge.sol b/contracts/vendor/arbitrum/IBridge.sol index 88d5013b18c..7982fb95b3d 100644 --- a/contracts/vendor/arbitrum/IBridge.sol +++ b/contracts/vendor/arbitrum/IBridge.sol @@ -1,23 +1,9 @@ -// SPDX-License-Identifier: Apache-2.0 -// OpenZeppelin Contracts (last updated v4.6.0) (vendor/arbitrum/IBridge.sol) - -/* - * 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; +// Copyright 2021-2022, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE +// SPDX-License-Identifier: BUSL-1.1 + +// solhint-disable-next-line compiler-version +pragma solidity >=0.6.9 <0.9.0; interface IBridge { event MessageDelivered( @@ -26,41 +12,97 @@ interface IBridge { address inbox, uint8 kind, address sender, - bytes32 messageDataHash + bytes32 messageDataHash, + uint256 baseFeeL1, + uint64 timestamp ); - event BridgeCallTriggered(address indexed outbox, address indexed destAddr, uint256 amount, bytes data); + event BridgeCallTriggered(address indexed outbox, address indexed to, uint256 value, bytes data); event InboxToggle(address indexed inbox, bool enabled); event OutboxToggle(address indexed outbox, bool enabled); - function deliverMessageToInbox( + event SequencerInboxUpdated(address newSequencerInbox); + + function allowedDelayedInboxList(uint256) external returns (address); + + function allowedOutboxList(uint256) external returns (address); + + /// @dev Accumulator for delayed inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message. + function delayedInboxAccs(uint256) external view returns (bytes32); + + /// @dev Accumulator for sequencer inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message. + function sequencerInboxAccs(uint256) external view returns (bytes32); + + // OpenZeppelin: changed return type from IOwnable + function rollup() external view returns (address); + + function sequencerInbox() external view returns (address); + + function activeOutbox() external view returns (address); + + function allowedDelayedInboxes(address inbox) external view returns (bool); + + function allowedOutboxes(address outbox) external view returns (bool); + + function sequencerReportedSubMessageCount() external view returns (uint256); + + /** + * @dev Enqueue a message in the delayed inbox accumulator. + * These messages are later sequenced in the SequencerInbox, either + * by the sequencer as part of a normal batch, or by force inclusion. + */ + function enqueueDelayedMessage( uint8 kind, address sender, bytes32 messageDataHash ) external payable returns (uint256); function executeCall( - address destAddr, - uint256 amount, + address to, + uint256 value, 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 delayedMessageCount() external view returns (uint256); - function setOutbox(address inbox, bool enabled) external; + function sequencerMessageCount() external view returns (uint256); - // View functions + // ---------- onlySequencerInbox functions ---------- - function activeOutbox() external view returns (address); + function enqueueSequencerMessage( + bytes32 dataHash, + uint256 afterDelayedMessagesRead, + uint256 prevMessageCount, + uint256 newMessageCount + ) + external + returns ( + uint256 seqMessageIndex, + bytes32 beforeAcc, + bytes32 delayedAcc, + bytes32 acc + ); - function allowedInboxes(address inbox) external view returns (bool); + /** + * @dev Allows the sequencer inbox to submit a delayed message of the batchPostingReport type + * This is done through a separate function entrypoint instead of allowing the sequencer inbox + * to call `enqueueDelayedMessage` to avoid the gas overhead of an extra SLOAD in either + * every delayed inbox or every sequencer inbox call. + */ + function submitBatchSpendingReport(address batchPoster, bytes32 dataHash) external returns (uint256 msgNum); - function allowedOutboxes(address outbox) external view returns (bool); + // ---------- onlyRollupOrOwner functions ---------- + + function setSequencerInbox(address _sequencerInbox) external; + + function setDelayedInbox(address inbox, bool enabled) external; + + function setOutbox(address inbox, bool enabled) external; - function inboxAccs(uint256 index) external view returns (bytes32); + // ---------- initializer ---------- - function messageCount() external view returns (uint256); + // OpenZeppelin: changed rollup_ type from IOwnable + function initialize(address rollup_) external; } diff --git a/contracts/vendor/arbitrum/IDelayedMessageProvider.sol b/contracts/vendor/arbitrum/IDelayedMessageProvider.sol new file mode 100644 index 00000000000..9e650c87268 --- /dev/null +++ b/contracts/vendor/arbitrum/IDelayedMessageProvider.sol @@ -0,0 +1,15 @@ +// Copyright 2021-2022, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE +// SPDX-License-Identifier: BUSL-1.1 + +// solhint-disable-next-line compiler-version +pragma solidity >=0.6.9 <0.9.0; + +interface IDelayedMessageProvider { + /// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator + event InboxMessageDelivered(uint256 indexed messageNum, bytes data); + + /// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator + /// same as InboxMessageDelivered but the batch data is available in tx.input + event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum); +} diff --git a/contracts/vendor/arbitrum/IInbox.sol b/contracts/vendor/arbitrum/IInbox.sol index 75f93ed8616..4396dc18f93 100644 --- a/contracts/vendor/arbitrum/IInbox.sol +++ b/contracts/vendor/arbitrum/IInbox.sol @@ -1,92 +1,151 @@ -// SPDX-License-Identifier: Apache-2.0 -// OpenZeppelin Contracts (last updated v4.6.0) (vendor/arbitrum/IInbox.sol) - -/* - * 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 "./IMessageProvider.sol"; - -interface IInbox is IMessageProvider { +// Copyright 2021-2022, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE +// SPDX-License-Identifier: BUSL-1.1 + +// solhint-disable-next-line compiler-version +pragma solidity >=0.6.9 <0.9.0; + +import "./IBridge.sol"; +import "./IDelayedMessageProvider.sol"; + +interface IInbox is IDelayedMessageProvider { + function bridge() external view returns (IBridge); + + // OpenZeppelin: changed return type from ISequencerInbox + function sequencerInbox() external view returns (address); + + /** + * @notice Send a generic L2 message to the chain + * @dev This method is an optimization to avoid having to emit the entirety of the messageData in a log. Instead validators are expected to be able to parse the data from the transaction's input + * @param messageData Data of the message being sent + */ + function sendL2MessageFromOrigin(bytes calldata messageData) external returns (uint256); + + /** + * @notice Send a generic L2 message to the chain + * @dev This method can be used to send any type of message that doesn't require L1 validation + * @param messageData Data of the message being sent + */ function sendL2Message(bytes calldata messageData) external returns (uint256); - function sendUnsignedTransaction( - uint256 maxGas, - uint256 gasPriceBid, + function sendL1FundedUnsignedTransaction( + uint256 gasLimit, + uint256 maxFeePerGas, uint256 nonce, - address destAddr, - uint256 amount, + address to, bytes calldata data - ) external returns (uint256); + ) external payable returns (uint256); - function sendContractTransaction( - uint256 maxGas, - uint256 gasPriceBid, - address destAddr, - uint256 amount, + function sendL1FundedContractTransaction( + uint256 gasLimit, + uint256 maxFeePerGas, + address to, bytes calldata data - ) external returns (uint256); + ) external payable returns (uint256); - function sendL1FundedUnsignedTransaction( - uint256 maxGas, - uint256 gasPriceBid, + function sendUnsignedTransaction( + uint256 gasLimit, + uint256 maxFeePerGas, uint256 nonce, - address destAddr, + address to, + uint256 value, bytes calldata data - ) external payable returns (uint256); + ) external returns (uint256); - function sendL1FundedContractTransaction( - uint256 maxGas, - uint256 gasPriceBid, - address destAddr, + function sendContractTransaction( + uint256 gasLimit, + uint256 maxFeePerGas, + address to, + uint256 value, bytes calldata data - ) external payable returns (uint256); + ) external returns (uint256); + /** + * @notice Get the L1 fee for submitting a retryable + * @dev This fee can be paid by funds already in the L2 aliased address or by the current message value + * @dev This formula may change in the future, to future proof your code query this method instead of inlining!! + * @param dataLength The length of the retryable's calldata, in bytes + * @param baseFee The block basefee when the retryable is included in the chain, if 0 current block.basefee will be used + */ + function calculateRetryableSubmissionFee(uint256 dataLength, uint256 baseFee) external view returns (uint256); + + /** + * @notice Deposit eth from L1 to L2 to address of the sender if sender is an EOA, and to its aliased address if the sender is a contract + * @dev This does not trigger the fallback function when receiving in the L2 side. + * Look into retryable tickets if you are interested in this functionality. + * @dev This function should not be called inside contract constructors + */ + function depositEth() external payable returns (uint256); + + /** + * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts + * @dev all msg.value will deposited to callValueRefundAddress on L2 + * @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error + * @param to destination L2 contract address + * @param l2CallValue call value for retryable L2 message + * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee + * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance + * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled + * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) + * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) + * @param data ABI encoded data of L2 message + * @return unique message number of the retryable transaction + */ function createRetryableTicket( - address destAddr, - uint256 arbTxCallValue, + address to, + uint256 l2CallValue, uint256 maxSubmissionCost, - address submissionRefundAddress, - address valueRefundAddress, - uint256 maxGas, - uint256 gasPriceBid, + address excessFeeRefundAddress, + address callValueRefundAddress, + uint256 gasLimit, + uint256 maxFeePerGas, bytes calldata data ) external payable returns (uint256); - function createRetryableTicketNoRefundAliasRewrite( - address destAddr, - uint256 arbTxCallValue, + /** + * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts + * @dev Same as createRetryableTicket, but does not guarantee that submission will succeed by requiring the needed funds + * come from the deposit alone, rather than falling back on the user's L2 balance + * @dev Advanced usage only (does not rewrite aliases for excessFeeRefundAddress and callValueRefundAddress). + * createRetryableTicket method is the recommended standard. + * @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error + * @param to destination L2 contract address + * @param l2CallValue call value for retryable L2 message + * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee + * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance + * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled + * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) + * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error) + * @param data ABI encoded data of L2 message + * @return unique message number of the retryable transaction + */ + function unsafeCreateRetryableTicket( + address to, + uint256 l2CallValue, uint256 maxSubmissionCost, - address submissionRefundAddress, - address valueRefundAddress, - uint256 maxGas, - uint256 gasPriceBid, + address excessFeeRefundAddress, + address callValueRefundAddress, + uint256 gasLimit, + uint256 maxFeePerGas, bytes calldata data ) external payable returns (uint256); - function depositEth(uint256 maxSubmissionCost) external payable returns (uint256); + // ---------- onlyRollupOrOwner functions ---------- - function bridge() external view returns (address); + /// @notice pauses all inbox functionality + function pause() external; - function pauseCreateRetryables() external; + /// @notice unpauses all inbox functionality + function unpause() external; - function unpauseCreateRetryables() external; + // ---------- initializer ---------- - function startRewriteAddress() external; + /** + * @dev function to be called one time during the inbox upgrade process + * this is used to fix the storage slots + */ + function postUpgradeInit(IBridge _bridge) external; - function stopRewriteAddress() external; + // OpenZeppelin: changed _sequencerInbox type from ISequencerInbox + function initialize(IBridge _bridge, address _sequencerInbox) external; } diff --git a/contracts/vendor/arbitrum/IMessageProvider.sol b/contracts/vendor/arbitrum/IMessageProvider.sol deleted file mode 100644 index 88d9ba4fc8e..00000000000 --- a/contracts/vendor/arbitrum/IMessageProvider.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// OpenZeppelin Contracts (last updated v4.6.0) (vendor/arbitrum/IMessageProvider.sol) - -/* - * 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/vendor/arbitrum/IOutbox.sol b/contracts/vendor/arbitrum/IOutbox.sol index 95c10800b7f..13dd5719d0b 100644 --- a/contracts/vendor/arbitrum/IOutbox.sol +++ b/contracts/vendor/arbitrum/IOutbox.sol @@ -1,51 +1,120 @@ -// SPDX-License-Identifier: Apache-2.0 -// OpenZeppelin Contracts (last updated v4.6.0) (vendor/arbitrum/IOutbox.sol) - -/* - * 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; +// Copyright 2021-2022, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE +// SPDX-License-Identifier: BUSL-1.1 + +// solhint-disable-next-line compiler-version +pragma solidity >=0.6.9 <0.9.0; + +import "./IBridge.sol"; interface IOutbox { - event OutboxEntryCreated( - uint256 indexed batchNum, - uint256 outboxEntryIndex, - bytes32 outputRoot, - uint256 numInBatch - ); + event SendRootUpdated(bytes32 indexed blockHash, bytes32 indexed outputRoot); event OutBoxTransactionExecuted( - address indexed destAddr, + address indexed to, address indexed l2Sender, - uint256 indexed outboxEntryIndex, + uint256 indexed zero, uint256 transactionIndex ); + function rollup() external view returns (address); // the rollup contract + + function bridge() external view returns (IBridge); // the bridge contract + + function spent(uint256) external view returns (bytes32); // packed spent bitmap + + function roots(bytes32) external view returns (bytes32); // maps root hashes => L2 block hash + + // solhint-disable-next-line func-name-mixedcase + function OUTBOX_VERSION() external view returns (uint128); // the outbox version + + function updateSendRoot(bytes32 sendRoot, bytes32 l2BlockHash) external; + + /// @notice When l2ToL1Sender returns a nonzero address, the message was originated by an L2 account + /// When the return value is zero, that means this is a system message + /// @dev the l2ToL1Sender behaves as the tx.origin, the msg.sender should be validated to protect against reentrancies function l2ToL1Sender() external view returns (address); + /// @return l2Block return L2 block when the L2 tx was initiated or 0 if no L2 to L1 transaction is active function l2ToL1Block() external view returns (uint256); + /// @return l1Block return L1 block when the L2 tx was initiated or 0 if no L2 to L1 transaction is active function l2ToL1EthBlock() external view returns (uint256); + /// @return timestamp return L2 timestamp when the L2 tx was initiated or 0 if no L2 to L1 transaction is active function l2ToL1Timestamp() external view returns (uint256); - function l2ToL1BatchNum() external view returns (uint256); - + /// @return outputId returns the unique output identifier of the L2 to L1 tx or 0 if no L2 to L1 transaction is active function l2ToL1OutputId() external view returns (bytes32); - function processOutgoingMessages(bytes calldata sendsData, uint256[] calldata sendLengths) external; + /** + * @notice Executes a messages in an Outbox entry. + * @dev Reverts if dispute period hasn't expired, since the outbox entry + * is only created once the rollup confirms the respective assertion. + * @dev it is not possible to execute any L2-to-L1 transaction which contains data + * to a contract address without any code (as enforced by the Bridge contract). + * @param proof Merkle proof of message inclusion in send root + * @param index Merkle path to message + * @param l2Sender sender if original message (i.e., caller of ArbSys.sendTxToL1) + * @param to destination address for L1 contract call + * @param l2Block l2 block number at which sendTxToL1 call was made + * @param l1Block l1 block number at which sendTxToL1 call was made + * @param l2Timestamp l2 Timestamp at which sendTxToL1 call was made + * @param value wei in L1 message + * @param data abi-encoded L1 message data + */ + function executeTransaction( + bytes32[] calldata proof, + uint256 index, + address l2Sender, + address to, + uint256 l2Block, + uint256 l1Block, + uint256 l2Timestamp, + uint256 value, + bytes calldata data + ) external; + + /** + * @dev function used to simulate the result of a particular function call from the outbox + * it is useful for things such as gas estimates. This function includes all costs except for + * proof validation (which can be considered offchain as a somewhat of a fixed cost - it's + * not really a fixed cost, but can be treated as so with a fixed overhead for gas estimation). + * We can't include the cost of proof validation since this is intended to be used to simulate txs + * that are included in yet-to-be confirmed merkle roots. The simulation entrypoint could instead pretend + * to confirm a pending merkle root, but that would be less practical for integrating with tooling. + * It is only possible to trigger it when the msg sender is address zero, which should be impossible + * unless under simulation in an eth_call or eth_estimateGas + */ + function executeTransactionSimulation( + uint256 index, + address l2Sender, + address to, + uint256 l2Block, + uint256 l1Block, + uint256 l2Timestamp, + uint256 value, + bytes calldata data + ) external; + + /** + * @param index Merkle path to message + * @return true if the message has been spent + */ + function isSpent(uint256 index) external view returns (bool); + + function calculateItemHash( + address l2Sender, + address to, + uint256 l2Block, + uint256 l1Block, + uint256 l2Timestamp, + uint256 value, + bytes calldata data + ) external pure returns (bytes32); - function outboxEntryExists(uint256 batchNum) external view returns (bool); + function calculateMerkleRoot( + bytes32[] memory proof, + uint256 path, + bytes32 item + ) external pure returns (bytes32); }