Skip to content

Commit fb45215

Browse files
authored
Add Interop Start timestamp to CrossL2Inbox (ethereum-optimism#11398)
* add interop start timestamp to CrossL2Inbox with tests * change to function, add assertions, update tests * correct the preimage of interop start storage slot * rename custome error * require id timestamp must be > interopStartTime not >=, update tests to use realistic interopStartTime (non-zero) * bump CrossL2Inbox semver, run just semver-lock & just snapshots * add natspec for setInteropStart * update semver lock
1 parent 872ff5d commit fb45215

File tree

5 files changed

+233
-22
lines changed

5 files changed

+233
-22
lines changed

packages/contracts-bedrock/semver-lock.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@
6868
"sourceCodeHash": "0x3a725791a0f5ed84dc46dcdae26f6170a759b2fe3dc360d704356d088b76cfd6"
6969
},
7070
"src/L2/CrossL2Inbox.sol": {
71-
"initCodeHash": "0x80124454d2127d5ff340b0ef048be6d5bf5984e84c75021b6a1ffa81703a2503",
72-
"sourceCodeHash": "0xfb26fc80fbc7febdc91ac73ea91ceb479b238e0e81804a0a21192d78c261a755"
71+
"initCodeHash": "0x071b53cd8cf0503af856c4ee0ee34643e85059d53c096453891225472e02abfa",
72+
"sourceCodeHash": "0x3c78129b91d9f06afa4787d4b3039f45a3b22b3edf5155ed73d4f0c3ab33c6c8"
7373
},
7474
"src/L2/ETHLiquidity.sol": {
7575
"initCodeHash": "0x98177562fca0de0dfea5313c9acefe2fdbd73dee5ce6c1232055601f208f0177",

packages/contracts-bedrock/snapshots/abi/CrossL2Inbox.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,19 @@
7575
"stateMutability": "payable",
7676
"type": "function"
7777
},
78+
{
79+
"inputs": [],
80+
"name": "interopStart",
81+
"outputs": [
82+
{
83+
"internalType": "uint256",
84+
"name": "interopStart_",
85+
"type": "uint256"
86+
}
87+
],
88+
"stateMutability": "view",
89+
"type": "function"
90+
},
7891
{
7992
"inputs": [],
8093
"name": "logIndex",
@@ -101,6 +114,13 @@
101114
"stateMutability": "view",
102115
"type": "function"
103116
},
117+
{
118+
"inputs": [],
119+
"name": "setInteropStart",
120+
"outputs": [],
121+
"stateMutability": "nonpayable",
122+
"type": "function"
123+
},
104124
{
105125
"inputs": [],
106126
"name": "timestamp",
@@ -218,6 +238,11 @@
218238
"name": "ExecutingMessage",
219239
"type": "event"
220240
},
241+
{
242+
"inputs": [],
243+
"name": "InteropStartAlreadySet",
244+
"type": "error"
245+
},
221246
{
222247
"inputs": [],
223248
"name": "InvalidChainId",
@@ -228,6 +253,11 @@
228253
"name": "InvalidTimestamp",
229254
"type": "error"
230255
},
256+
{
257+
"inputs": [],
258+
"name": "NotDepositor",
259+
"type": "error"
260+
},
231261
{
232262
"inputs": [],
233263
"name": "NotEntered",

packages/contracts-bedrock/src/L2/CrossL2Inbox.sol

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ interface IDependencySet {
1717
function isInDependencySet(uint256 _chainId) external view returns (bool);
1818
}
1919

20+
/// @notice Thrown when the caller is not DEPOSITOR_ACCOUNT when calling `setInteropStart()`
21+
error NotDepositor();
22+
23+
/// @notice Thrown when attempting to set interop start when it's already set.
24+
error InteropStartAlreadySet();
25+
2026
/// @notice Thrown when a non-written transient storage slot is attempted to be read from.
2127
error NotEntered();
2228

@@ -35,6 +41,10 @@ error TargetCallFailed();
3541
/// @notice The CrossL2Inbox is responsible for executing a cross chain message on the destination
3642
/// chain. It is permissionless to execute a cross chain message on behalf of any user.
3743
contract CrossL2Inbox is ICrossL2Inbox, ISemver, TransientReentrancyAware {
44+
/// @notice Storage slot that the interop start timestamp is stored at.
45+
/// Equal to bytes32(uint256(keccak256("crossl2inbox.interopstart")) - 1)
46+
bytes32 internal constant INTEROP_START_SLOT = 0x5c769ee0ee8887661922049dc52480bb60322d765161507707dd9b190af5c149;
47+
3848
/// @notice Transient storage slot that the origin for an Identifier is stored at.
3949
/// Equal to bytes32(uint256(keccak256("crossl2inbox.identifier.origin")) - 1)
4050
bytes32 internal constant ORIGIN_SLOT = 0xd2b7c5071ec59eb3ff0017d703a8ea513a7d0da4779b0dbefe845808c300c815;
@@ -55,15 +65,42 @@ contract CrossL2Inbox is ICrossL2Inbox, ISemver, TransientReentrancyAware {
5565
/// Equal to bytes32(uint256(keccak256("crossl2inbox.identifier.chainid")) - 1)
5666
bytes32 internal constant CHAINID_SLOT = 0x6e0446e8b5098b8c8193f964f1b567ec3a2bdaeba33d36acb85c1f1d3f92d313;
5767

68+
/// @notice The address that represents the system caller responsible for L1 attributes
69+
/// transactions.
70+
address internal constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001;
71+
5872
/// @notice Semantic version.
59-
/// @custom:semver 1.0.0-beta.4
60-
string public constant version = "1.0.0-beta.4";
73+
/// @custom:semver 1.0.0-beta.5
74+
string public constant version = "1.0.0-beta.5";
6175

6276
/// @notice Emitted when a cross chain message is being executed.
6377
/// @param msgHash Hash of message payload being executed.
6478
/// @param id Encoded Identifier of the message.
6579
event ExecutingMessage(bytes32 indexed msgHash, Identifier id);
6680

81+
/// @notice Sets the Interop Start Timestamp for this chain. Can only be performed once and when the caller is the
82+
/// DEPOSITOR_ACCOUNT.
83+
function setInteropStart() external {
84+
// Check that caller is the DEPOSITOR_ACCOUNT
85+
if (msg.sender != DEPOSITOR_ACCOUNT) revert NotDepositor();
86+
87+
// Check that it has not been set already
88+
if (interopStart() != 0) revert InteropStartAlreadySet();
89+
90+
// Set Interop Start to block.timestamp
91+
assembly {
92+
sstore(INTEROP_START_SLOT, timestamp())
93+
}
94+
}
95+
96+
/// @notice Returns the interop start timestamp.
97+
/// @return interopStart_ interop start timestamp.
98+
function interopStart() public view returns (uint256 interopStart_) {
99+
assembly {
100+
interopStart_ := sload(INTEROP_START_SLOT)
101+
}
102+
}
103+
67104
/// @notice Returns the origin address of the Identifier. If not entered, reverts.
68105
/// @return Origin address of the Identifier.
69106
function origin() external view notEntered returns (address) {
@@ -140,7 +177,7 @@ contract CrossL2Inbox is ICrossL2Inbox, ISemver, TransientReentrancyAware {
140177
/// is in the destination chain's dependency set.
141178
/// @param _id Identifier of the message.
142179
function _checkIdentifier(Identifier calldata _id) internal view {
143-
if (_id.timestamp > block.timestamp) revert InvalidTimestamp();
180+
if (_id.timestamp > block.timestamp || _id.timestamp <= interopStart()) revert InvalidTimestamp();
144181
if (!IDependencySet(Predeploys.L1_BLOCK_ATTRIBUTES).isInDependencySet(_id.chainId)) {
145182
revert InvalidChainId();
146183
}

packages/contracts-bedrock/src/L2/ICrossL2Inbox.sol

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ interface ICrossL2Inbox {
1313
uint256 chainId;
1414
}
1515

16+
/// @notice Returns the interop start timestamp.
17+
/// @return interopStart_ interop start timestamp.
18+
function interopStart() external view returns (uint256 interopStart_);
19+
1620
/// @notice Returns the origin address of the Identifier.
1721
/// @return _origin The origin address of the Identifier.
1822
function origin() external view returns (address _origin);
@@ -44,4 +48,12 @@ interface ICrossL2Inbox {
4448
)
4549
external
4650
payable;
51+
52+
/// @notice Validates a cross chain message on the destination chain
53+
/// and emits an ExecutingMessage event. This function is useful
54+
/// for applications that understand the schema of the _message payload and want to
55+
/// process it in a custom way.
56+
/// @param _id Identifier of the message.
57+
/// @param _msgHash Hash of the message payload to call target with.
58+
function validateMessage(Identifier calldata _id, bytes32 _msgHash) external;
4759
}

0 commit comments

Comments
 (0)