-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* contracts-bedrock: create CrossL2Inbox * contracts-bedrock: create ICrossL2Inbox * contracts-bedrock: create tests for CrossL2Inbox * contracts-bedrock: update CrossL2Inbox sol version to ^0.8.24 * contracts-bedrock: rename test to .t.sol ext * contracts-bedrock: make snapshots * contracts-bedrock: update semver-lock * contracts-bedrock: drop snapshots for CrossL2InboxTest * contracts-bedrock: update license for tests CrossL2Inbox * contracts-bedrock: add CrossL2Inbox to predeploys * contracts-bedrock: pin sol version of CrossL2Inbox to 0.8.25 * contracts-bedrock: update semver-lock for CrossL2Inbox * contracts-bedrock: add CROSS_L2_INBOX to predeploys * contracts-bedrock: make slots internal in CrossL2Inbox * contracts-bedrock: add custom errors to CrossL2Inbox * contracts-bedrock: refactor tests for CrossL2Inbox * contracts-bedrock: use TransientContext in CrossL2Inbox * contracts-bedrock: fix L2Genesis test * contracts-bedrock: minor tweaks to documentation in tests for CrossL2Inbox * contracts-bedrock: relabel BLOCKNUMBER_SLOT to BLOCK_NUMBER_SLOT in CrossL2Inbox * contracts-bedrock: update snapshots for CrossL2Inbox * contracts-bedrock: update semver-lock for CrossL2Inbox * contracts-bedrock: improve documentation for CrossL2Inbox * contracts-bedrock: update semver-lock for CrossL2Inbox * contracts-bedrock: fix tests for CrossL2Inbox * contracts-bedrock: update modifier in CrossL2Inbox * contracts-bedrock: drop arguments in custom errors for CrossL2Inbox * contracts-bedrock: update snapshots for CrossL2Inbox * contracts-bedrock: update semver-lock for CrossL2Inbox * contracts-bedrock: fix tests for CrossL2Inbox * contracts-bedrock: remove redundant lines in CrossL2Inbox * contracts-bedrock: add tests for CrossL2Inbox * contracts-bedrock: update semver-lock for CrossL2Inbox * contracts-bedrock: minor improvements to tests for CrossL2Inbox * contracts-bedrock: remove ENTERED_SLOT in CrossL2Inbox * contracts-bedrock: remove CrossL2Inbox from isSupportedPredeploy * contracts-bedrock: update semver-lock for CrossL2Inbox * contracts-bedrock: update CrossL2Inbox with eip3074 specs * contracts-bedrock: update tests for CrossL2Inbox with eip3074 specs * contracts-bedrock: improve doc in tests for CrossL2Inbox * contracts-bedrock: update snapshots for CrossL2Inbox * contracts-bedrock: update semver-lock for CrossL2Inbox
- Loading branch information
1 parent
7e93729
commit 826a7bd
Showing
7 changed files
with
749 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
169 changes: 169 additions & 0 deletions
169
packages/contracts-bedrock/snapshots/abi/CrossL2Inbox.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
[ | ||
{ | ||
"inputs": [], | ||
"name": "blockNumber", | ||
"outputs": [ | ||
{ | ||
"internalType": "uint256", | ||
"name": "", | ||
"type": "uint256" | ||
} | ||
], | ||
"stateMutability": "view", | ||
"type": "function" | ||
}, | ||
{ | ||
"inputs": [], | ||
"name": "chainId", | ||
"outputs": [ | ||
{ | ||
"internalType": "uint256", | ||
"name": "", | ||
"type": "uint256" | ||
} | ||
], | ||
"stateMutability": "view", | ||
"type": "function" | ||
}, | ||
{ | ||
"inputs": [ | ||
{ | ||
"components": [ | ||
{ | ||
"internalType": "address", | ||
"name": "origin", | ||
"type": "address" | ||
}, | ||
{ | ||
"internalType": "uint256", | ||
"name": "blockNumber", | ||
"type": "uint256" | ||
}, | ||
{ | ||
"internalType": "uint256", | ||
"name": "logIndex", | ||
"type": "uint256" | ||
}, | ||
{ | ||
"internalType": "uint256", | ||
"name": "timestamp", | ||
"type": "uint256" | ||
}, | ||
{ | ||
"internalType": "uint256", | ||
"name": "chainId", | ||
"type": "uint256" | ||
} | ||
], | ||
"internalType": "struct ICrossL2Inbox.Identifier", | ||
"name": "_id", | ||
"type": "tuple" | ||
}, | ||
{ | ||
"internalType": "address", | ||
"name": "_target", | ||
"type": "address" | ||
}, | ||
{ | ||
"internalType": "bytes", | ||
"name": "_message", | ||
"type": "bytes" | ||
} | ||
], | ||
"name": "executeMessage", | ||
"outputs": [], | ||
"stateMutability": "payable", | ||
"type": "function" | ||
}, | ||
{ | ||
"inputs": [], | ||
"name": "logIndex", | ||
"outputs": [ | ||
{ | ||
"internalType": "uint256", | ||
"name": "", | ||
"type": "uint256" | ||
} | ||
], | ||
"stateMutability": "view", | ||
"type": "function" | ||
}, | ||
{ | ||
"inputs": [], | ||
"name": "origin", | ||
"outputs": [ | ||
{ | ||
"internalType": "address", | ||
"name": "", | ||
"type": "address" | ||
} | ||
], | ||
"stateMutability": "view", | ||
"type": "function" | ||
}, | ||
{ | ||
"inputs": [], | ||
"name": "timestamp", | ||
"outputs": [ | ||
{ | ||
"internalType": "uint256", | ||
"name": "", | ||
"type": "uint256" | ||
} | ||
], | ||
"stateMutability": "view", | ||
"type": "function" | ||
}, | ||
{ | ||
"inputs": [], | ||
"name": "version", | ||
"outputs": [ | ||
{ | ||
"internalType": "string", | ||
"name": "", | ||
"type": "string" | ||
} | ||
], | ||
"stateMutability": "view", | ||
"type": "function" | ||
}, | ||
{ | ||
"anonymous": false, | ||
"inputs": [ | ||
{ | ||
"indexed": false, | ||
"internalType": "bytes", | ||
"name": "encodedId", | ||
"type": "bytes" | ||
}, | ||
{ | ||
"indexed": false, | ||
"internalType": "bytes", | ||
"name": "message", | ||
"type": "bytes" | ||
} | ||
], | ||
"name": "ExecutingMessage", | ||
"type": "event" | ||
}, | ||
{ | ||
"inputs": [], | ||
"name": "InvalidChainId", | ||
"type": "error" | ||
}, | ||
{ | ||
"inputs": [], | ||
"name": "InvalidTimestamp", | ||
"type": "error" | ||
}, | ||
{ | ||
"inputs": [], | ||
"name": "NotEntered", | ||
"type": "error" | ||
}, | ||
{ | ||
"inputs": [], | ||
"name": "TargetCallFailed", | ||
"type": "error" | ||
} | ||
] |
1 change: 1 addition & 0 deletions
1
packages/contracts-bedrock/snapshots/storageLayout/CrossL2Inbox.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
[] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.25; | ||
|
||
import { Predeploys } from "src/libraries/Predeploys.sol"; | ||
import { TransientContext, TransientReentrancyAware } from "src/libraries/TransientContext.sol"; | ||
import { ISemver } from "src/universal/ISemver.sol"; | ||
import { ICrossL2Inbox } from "src/L2/ICrossL2Inbox.sol"; | ||
|
||
/// @title IDependencySet | ||
/// @notice Interface for L1Block with only `isInDependencySet(uint256)` method. | ||
interface IDependencySet { | ||
/// @notice Returns true iff the chain associated with input chain ID is in the interop dependency set. | ||
/// Every chain is in the interop dependency set of itself. | ||
/// @param _chainId Input chain ID. | ||
/// @return True if the input chain ID corresponds to a chain in the interop dependency set, and false otherwise. | ||
function isInDependencySet(uint256 _chainId) external view returns (bool); | ||
} | ||
|
||
/// @notice Thrown when a non-written transient storage slot is attempted to be read from. | ||
error NotEntered(); | ||
|
||
/// @notice Thrown when trying to execute a cross chain message with an invalid Identifier timestamp. | ||
error InvalidTimestamp(); | ||
|
||
/// @notice Thrown when trying to execute a cross chain message with an invalid Identifier chain ID. | ||
error InvalidChainId(); | ||
|
||
/// @notice Thrown when trying to execute a cross chain message and the target call fails. | ||
error TargetCallFailed(); | ||
|
||
/// @custom:proxied | ||
/// @custom:predeploy 0x4200000000000000000000000000000000000022 | ||
/// @title CrossL2Inbox | ||
/// @notice The CrossL2Inbox is responsible for executing a cross chain message on the destination | ||
/// chain. It is permissionless to execute a cross chain message on behalf of any user. | ||
contract CrossL2Inbox is ICrossL2Inbox, ISemver, TransientReentrancyAware { | ||
/// @notice Transient storage slot that the origin for an Identifier is stored at. | ||
/// Equal to bytes32(uint256(keccak256("crossl2inbox.identifier.origin")) - 1) | ||
bytes32 internal constant ORIGIN_SLOT = 0xd2b7c5071ec59eb3ff0017d703a8ea513a7d0da4779b0dbefe845808c300c815; | ||
|
||
/// @notice Transient storage slot that the blockNumber for an Identifier is stored at. | ||
/// Equal to bytes32(uint256(keccak256("crossl2inbox.identifier.blocknumber")) - 1) | ||
bytes32 internal constant BLOCK_NUMBER_SLOT = 0x5a1da0738b7fdc60047c07bb519beb02aa32a8619de57e6258da1f1c2e020ccc; | ||
|
||
/// @notice Transient storage slot that the logIndex for an Identifier is stored at. | ||
/// Equal to bytes32(uint256(keccak256("crossl2inbox.identifier.logindex")) - 1) | ||
bytes32 internal constant LOG_INDEX_SLOT = 0xab8acc221aecea88a685fabca5b88bf3823b05f335b7b9f721ca7fe3ffb2c30d; | ||
|
||
/// @notice Transient storage slot that the timestamp for an Identifier is stored at. | ||
/// Equal to bytes32(uint256(keccak256("crossl2inbox.identifier.timestamp")) - 1) | ||
bytes32 internal constant TIMESTAMP_SLOT = 0x2e148a404a50bb94820b576997fd6450117132387be615e460fa8c5e11777e02; | ||
|
||
/// @notice Transient storage slot that the chainId for an Identifier is stored at. | ||
/// Equal to bytes32(uint256(keccak256("crossl2inbox.identifier.chainid")) - 1) | ||
bytes32 internal constant CHAINID_SLOT = 0x6e0446e8b5098b8c8193f964f1b567ec3a2bdaeba33d36acb85c1f1d3f92d313; | ||
|
||
/// @notice Semantic version. | ||
/// @custom:semver 1.0.0 | ||
string public constant version = "1.0.0"; | ||
|
||
/// @notice Emitted when a cross chain message is being executed. | ||
/// @param encodedId Encoded Identifier of the message. | ||
/// @param message Message payload being executed. | ||
event ExecutingMessage(bytes encodedId, bytes message); | ||
|
||
/// @notice Enforces that cross domain message sender and source are set. Reverts if not. | ||
/// Used to differentiate between 0 and nil in transient storage. | ||
modifier notEntered() { | ||
if (TransientContext.callDepth() == 0) revert NotEntered(); | ||
_; | ||
} | ||
|
||
/// @notice Returns the origin address of the Identifier. If not entered, reverts. | ||
/// @return Origin address of the Identifier. | ||
function origin() external view notEntered returns (address) { | ||
return address(uint160(TransientContext.get(ORIGIN_SLOT))); | ||
} | ||
|
||
/// @notice Returns the block number of the Identifier. If not entered, reverts. | ||
/// @return Block number of the Identifier. | ||
function blockNumber() external view notEntered returns (uint256) { | ||
return TransientContext.get(BLOCK_NUMBER_SLOT); | ||
} | ||
|
||
/// @notice Returns the log index of the Identifier. If not entered, reverts. | ||
/// @return Log index of the Identifier. | ||
function logIndex() external view notEntered returns (uint256) { | ||
return TransientContext.get(LOG_INDEX_SLOT); | ||
} | ||
|
||
/// @notice Returns the timestamp of the Identifier. If not entered, reverts. | ||
/// @return Timestamp of the Identifier. | ||
function timestamp() external view notEntered returns (uint256) { | ||
return TransientContext.get(TIMESTAMP_SLOT); | ||
} | ||
|
||
/// @notice Returns the chain ID of the Identifier. If not entered, reverts. | ||
/// @return _chainId The chain ID of the Identifier. | ||
function chainId() external view notEntered returns (uint256) { | ||
return TransientContext.get(CHAINID_SLOT); | ||
} | ||
|
||
/// @notice Executes a cross chain message on the destination chain. | ||
/// @param _id Identifier of the message. | ||
/// @param _target Target address to call. | ||
/// @param _message Message payload to call target with. | ||
function executeMessage( | ||
Identifier calldata _id, | ||
address _target, | ||
bytes memory _message | ||
) | ||
external | ||
payable | ||
reentrantAware | ||
{ | ||
if (_id.timestamp > block.timestamp) revert InvalidTimestamp(); | ||
if (!IDependencySet(Predeploys.L1_BLOCK_ATTRIBUTES).isInDependencySet(_id.chainId)) { | ||
revert InvalidChainId(); | ||
} | ||
|
||
// Store the Identifier in transient storage. | ||
_storeIdentifier(_id); | ||
|
||
// Call the target account with the message payload. | ||
bool success = _callWithAllGas(_target, _message); | ||
|
||
// Revert if the target call failed. | ||
if (!success) revert TargetCallFailed(); | ||
|
||
emit ExecutingMessage(abi.encode(_id), _message); | ||
} | ||
|
||
/// @notice Stores the Identifier in transient storage. | ||
/// @param _id Identifier to store. | ||
function _storeIdentifier(Identifier calldata _id) internal { | ||
TransientContext.set(ORIGIN_SLOT, uint160(_id.origin)); | ||
TransientContext.set(BLOCK_NUMBER_SLOT, _id.blockNumber); | ||
TransientContext.set(LOG_INDEX_SLOT, _id.logIndex); | ||
TransientContext.set(TIMESTAMP_SLOT, _id.timestamp); | ||
TransientContext.set(CHAINID_SLOT, _id.chainId); | ||
} | ||
|
||
/// @notice Calls the target address with the message payload and all available gas. | ||
/// @param _target Target address to call. | ||
/// @param _message Message payload to call target with. | ||
/// @return _success True if the call was successful, and false otherwise. | ||
function _callWithAllGas(address _target, bytes memory _message) internal returns (bool _success) { | ||
assembly { | ||
_success := | ||
call( | ||
gas(), // gas | ||
_target, // recipient | ||
callvalue(), // ether value | ||
add(_message, 32), // inloc | ||
mload(_message), // inlen | ||
0, // outloc | ||
0 // outlen | ||
) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
/// @title ICrossL2Inbox | ||
/// @notice Interface for the CrossL2Inbox contract. | ||
interface ICrossL2Inbox { | ||
/// @notice The struct for a pointer to a message payload in a remote (or local) chain. | ||
struct Identifier { | ||
address origin; | ||
uint256 blockNumber; | ||
uint256 logIndex; | ||
uint256 timestamp; | ||
uint256 chainId; | ||
} | ||
|
||
/// @notice Returns the origin address of the Identifier. | ||
/// @return _origin The origin address of the Identifier. | ||
function origin() external view returns (address _origin); | ||
|
||
/// @notice Returns the block number of the Identifier. | ||
/// @return _blockNumber The block number of the Identifier. | ||
function blockNumber() external view returns (uint256 _blockNumber); | ||
|
||
/// @notice Returns the log index of the Identifier. | ||
/// @return _logIndex The log index of the Identifier. | ||
function logIndex() external view returns (uint256 _logIndex); | ||
|
||
/// @notice Returns the timestamp of the Identifier. | ||
/// @return _timestamp The timestamp of the Identifier. | ||
function timestamp() external view returns (uint256 _timestamp); | ||
|
||
/// @notice Returns the chain ID of the Identifier. | ||
/// @return _chainId The chain ID of the Identifier. | ||
function chainId() external view returns (uint256 _chainId); | ||
|
||
/// @notice Executes a cross chain message on the destination chain. | ||
/// @param _id An Identifier pointing to the initiating message. | ||
/// @param _target Account that is called with _msg. | ||
/// @param _msg The message payload, matching the initiating message. | ||
function executeMessage( | ||
ICrossL2Inbox.Identifier calldata _id, | ||
address _target, | ||
bytes calldata _msg | ||
) | ||
external | ||
payable; | ||
} |
Oops, something went wrong.