@arbitrum/nitro-contracts 1.0.0-beta.8 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. package/README.md +1 -1
  2. package/hardhat.prod-config.js +4 -4
  3. package/package.json +21 -3
  4. package/src/bridge/Bridge.sol +39 -30
  5. package/src/bridge/IBridge.sol +56 -29
  6. package/src/bridge/IInbox.sol +130 -15
  7. package/src/bridge/IOutbox.sol +55 -7
  8. package/src/bridge/ISequencerInbox.sol +84 -7
  9. package/src/bridge/Inbox.sol +233 -93
  10. package/src/bridge/Outbox.sol +23 -47
  11. package/src/bridge/SequencerInbox.sol +132 -62
  12. package/src/challenge/ChallengeManager.sol +0 -9
  13. package/src/challenge/IChallengeManager.sol +0 -2
  14. package/src/libraries/AdminFallbackProxy.sol +4 -4
  15. package/src/libraries/Constants.sol +6 -0
  16. package/src/libraries/{SecondaryLogicUUPSUpgradeable.sol → DoubleLogicUUPSUpgradeable.sol} +2 -1
  17. package/src/libraries/Error.sol +12 -0
  18. package/src/libraries/IGasRefunder.sol +11 -5
  19. package/src/libraries/MerkleLib.sol +5 -3
  20. package/src/mocks/BridgeStub.sol +20 -1
  21. package/src/mocks/BridgeUnproxied.sol +17 -0
  22. package/src/mocks/InboxStub.sol +48 -3
  23. package/src/mocks/SequencerInboxStub.sol +13 -3
  24. package/src/mocks/Simple.sol +69 -0
  25. package/src/node-interface/NodeInterface.sol +35 -4
  26. package/src/precompiles/ArbGasInfo.sol +7 -4
  27. package/src/precompiles/ArbOwner.sol +9 -0
  28. package/src/precompiles/ArbOwnerPublic.sol +3 -0
  29. package/src/precompiles/ArbSys.sol +5 -2
  30. package/src/rollup/IRollupCore.sol +2 -0
  31. package/src/rollup/IRollupLogic.sol +10 -0
  32. package/src/rollup/RollupAdminLogic.sol +27 -3
  33. package/src/rollup/RollupCore.sol +3 -0
  34. package/src/rollup/RollupCreator.sol +3 -3
  35. package/src/rollup/RollupEventInbox.sol +3 -6
  36. package/src/{libraries/ArbitrumProxy.sol → rollup/RollupProxy.sol} +3 -3
  37. package/src/rollup/RollupUserLogic.sol +47 -10
  38. package/src/test-helpers/BridgeTester.sol +7 -1
  39. package/src/test-helpers/OutboxWithoutOptTester.sol +8 -8
@@ -11,7 +11,8 @@ import {
11
11
  PathNotMinimal,
12
12
  UnknownRoot,
13
13
  AlreadySpent,
14
- BridgeCallFailed
14
+ BridgeCallFailed,
15
+ HadZeroInit
15
16
  } from "../libraries/Error.sol";
16
17
  import "./IBridge.sol";
17
18
  import "./IOutbox.sol";
@@ -51,6 +52,7 @@ contract Outbox is DelegateCallAware, IOutbox {
51
52
  uint128 public constant OUTBOX_VERSION = 2;
52
53
 
53
54
  function initialize(IBridge _bridge) external onlyDelegated {
55
+ if (address(_bridge) == address(0)) revert HadZeroInit();
54
56
  if (address(bridge) != address(0)) revert AlreadyInit();
55
57
  // address zero is returned if no context is set, but the values used in storage
56
58
  // are non-zero to save users some gas (as storage refunds are usually maxed out)
@@ -66,43 +68,38 @@ contract Outbox is DelegateCallAware, IOutbox {
66
68
  rollup = address(_bridge.rollup());
67
69
  }
68
70
 
69
- function updateSendRoot(bytes32 root, bytes32 l2BlockHash) external override {
71
+ function updateSendRoot(bytes32 root, bytes32 l2BlockHash) external {
70
72
  if (msg.sender != rollup) revert NotRollup(msg.sender, rollup);
71
73
  roots[root] = l2BlockHash;
72
74
  emit SendRootUpdated(root, l2BlockHash);
73
75
  }
74
76
 
75
- /// @notice When l2ToL1Sender returns a nonzero address, the message was originated by an L2 account
76
- /// When the return value is zero, that means this is a system message
77
- /// @dev the l2ToL1Sender behaves as the tx.origin, the msg.sender should be validated to protect against reentrancies
78
- function l2ToL1Sender() external view override returns (address) {
77
+ /// @inheritdoc IOutbox
78
+ function l2ToL1Sender() external view returns (address) {
79
79
  address sender = context.sender;
80
80
  // we don't return the default context value to avoid a breaking change in the API
81
81
  if (sender == SENDER_DEFAULT_CONTEXT) return address(0);
82
82
  return sender;
83
83
  }
84
84
 
85
- /// @return l2Block return L2 block when the L2 tx was initiated or zero
86
- /// if no L2 to L1 transaction is active
87
- function l2ToL1Block() external view override returns (uint256) {
85
+ /// @inheritdoc IOutbox
86
+ function l2ToL1Block() external view returns (uint256) {
88
87
  uint128 l2Block = context.l2Block;
89
88
  // we don't return the default context value to avoid a breaking change in the API
90
89
  if (l2Block == L1BLOCK_DEFAULT_CONTEXT) return uint256(0);
91
90
  return uint256(l2Block);
92
91
  }
93
92
 
94
- /// @return l1Block return L1 block when the L2 tx was initiated or zero
95
- /// if no L2 to L1 transaction is active
96
- function l2ToL1EthBlock() external view override returns (uint256) {
93
+ /// @inheritdoc IOutbox
94
+ function l2ToL1EthBlock() external view returns (uint256) {
97
95
  uint128 l1Block = context.l1Block;
98
96
  // we don't return the default context value to avoid a breaking change in the API
99
97
  if (l1Block == L1BLOCK_DEFAULT_CONTEXT) return uint256(0);
100
98
  return uint256(l1Block);
101
99
  }
102
100
 
103
- /// @return timestamp return L2 timestamp when the L2 tx was initiated or zero
104
- /// if no L2 to L1 transaction is active
105
- function l2ToL1Timestamp() external view override returns (uint256) {
101
+ /// @inheritdoc IOutbox
102
+ function l2ToL1Timestamp() external view returns (uint256) {
106
103
  uint128 timestamp = context.timestamp;
107
104
  // we don't return the default context value to avoid a breaking change in the API
108
105
  if (timestamp == TIMESTAMP_DEFAULT_CONTEXT) return uint256(0);
@@ -110,33 +107,19 @@ contract Outbox is DelegateCallAware, IOutbox {
110
107
  }
111
108
 
112
109
  /// @notice batch number is deprecated and now always returns 0
113
- function l2ToL1BatchNum() external pure override returns (uint256) {
110
+ function l2ToL1BatchNum() external pure returns (uint256) {
114
111
  return 0;
115
112
  }
116
113
 
117
- /// @return outputId returns the unique output identifier of the L2 to L1 tx or
118
- /// zero if no L2 to L1 transaction is active
119
- function l2ToL1OutputId() external view override returns (bytes32) {
114
+ /// @inheritdoc IOutbox
115
+ function l2ToL1OutputId() external view returns (bytes32) {
120
116
  bytes32 outputId = context.outputId;
121
117
  // we don't return the default context value to avoid a breaking change in the API
122
118
  if (outputId == OUTPUTID_DEFAULT_CONTEXT) return bytes32(0);
123
119
  return outputId;
124
120
  }
125
121
 
126
- /**
127
- * @notice Executes a messages in an Outbox entry.
128
- * @dev Reverts if dispute period hasn't expired, since the outbox entry
129
- * is only created once the rollup confirms the respective assertion.
130
- * @param proof Merkle proof of message inclusion in send root
131
- * @param index Merkle path to message
132
- * @param l2Sender sender if original message (i.e., caller of ArbSys.sendTxToL1)
133
- * @param to destination address for L1 contract call
134
- * @param l2Block l2 block number at which sendTxToL1 call was made
135
- * @param l1Block l1 block number at which sendTxToL1 call was made
136
- * @param l2Timestamp l2 Timestamp at which sendTxToL1 call was made
137
- * @param value wei in L1 message
138
- * @param data abi-encoded L1 message data
139
- */
122
+ /// @inheritdoc IOutbox
140
123
  function executeTransaction(
141
124
  bytes32[] calldata proof,
142
125
  uint256 index,
@@ -147,7 +130,7 @@ contract Outbox is DelegateCallAware, IOutbox {
147
130
  uint256 l2Timestamp,
148
131
  uint256 value,
149
132
  bytes calldata data
150
- ) external override {
133
+ ) external {
151
134
  bytes32 userTx = calculateItemHash(
152
135
  l2Sender,
153
136
  to,
@@ -163,15 +146,7 @@ contract Outbox is DelegateCallAware, IOutbox {
163
146
  executeTransactionImpl(index, l2Sender, to, l2Block, l1Block, l2Timestamp, value, data);
164
147
  }
165
148
 
166
- /// @dev function used to simulate the result of a particular function call from the outbox
167
- /// it is useful for things such as gas estimates. This function includes all costs except for
168
- /// proof validation (which can be considered offchain as a somewhat of a fixed cost - it's
169
- /// not really a fixed cost, but can be treated as so with a fixed overhead for gas estimation).
170
- /// We can't include the cost of proof validation since this is intended to be used to simulate txs
171
- /// that are included in yet-to-be confirmed merkle roots. The simulation entrypoint could instead pretend
172
- /// to confirm a pending merkle root, but that would be less pratical for integrating with tooling.
173
- /// It is only possible to trigger it when the msg sender is address zero, which should be impossible
174
- /// unless under simulation in an eth_call or eth_estimateGas
149
+ /// @inheritdoc IOutbox
175
150
  function executeTransactionSimulation(
176
151
  uint256 index,
177
152
  address l2Sender,
@@ -181,7 +156,7 @@ contract Outbox is DelegateCallAware, IOutbox {
181
156
  uint256 l2Timestamp,
182
157
  uint256 value,
183
158
  bytes calldata data
184
- ) external override {
159
+ ) external {
185
160
  if (msg.sender != address(0)) revert SimulationOnlyEntrypoint();
186
161
  executeTransactionImpl(index, l2Sender, to, l2Block, l1Block, l2Timestamp, value, data);
187
162
  }
@@ -235,7 +210,8 @@ contract Outbox is DelegateCallAware, IOutbox {
235
210
  return ((replay >> bitOffset) & bytes32(uint256(1))) != bytes32(0);
236
211
  }
237
212
 
238
- function isSpent(uint256 index) external view override returns (bool) {
213
+ /// @inheritdoc IOutbox
214
+ function isSpent(uint256 index) external view returns (bool) {
239
215
  (, uint256 bitOffset, bytes32 replay) = _calcSpentIndexOffset(index);
240
216
  return _isSpent(bitOffset, replay);
241
217
  }
@@ -285,7 +261,7 @@ contract Outbox is DelegateCallAware, IOutbox {
285
261
  uint256 l2Timestamp,
286
262
  uint256 value,
287
263
  bytes calldata data
288
- ) public pure override returns (bytes32) {
264
+ ) public pure returns (bytes32) {
289
265
  return
290
266
  keccak256(abi.encodePacked(l2Sender, to, l2Block, l1Block, l2Timestamp, value, data));
291
267
  }
@@ -294,7 +270,7 @@ contract Outbox is DelegateCallAware, IOutbox {
294
270
  bytes32[] memory proof,
295
271
  uint256 path,
296
272
  bytes32 item
297
- ) public pure override returns (bytes32) {
273
+ ) public pure returns (bytes32) {
298
274
  return MerkleLib.calculateRoot(proof, path, keccak256(abi.encodePacked(item)));
299
275
  }
300
276
  }
@@ -19,7 +19,8 @@ import {
19
19
  BadSequencerNumber,
20
20
  DataNotAuthenticated,
21
21
  AlreadyValidDASKeyset,
22
- NoSuchKeyset
22
+ NoSuchKeyset,
23
+ NotForked
23
24
  } from "../libraries/Error.sol";
24
25
  import "./IBridge.sol";
25
26
  import "./IInbox.sol";
@@ -44,20 +45,16 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
44
45
 
45
46
  IBridge public bridge;
46
47
 
47
- /// @dev The size of the batch header
48
+ /// @inheritdoc ISequencerInbox
48
49
  uint256 public constant HEADER_LENGTH = 40;
49
- /// @dev If the first batch data byte after the header has this bit set,
50
- /// the sequencer inbox has authenticated the data. Currently not used.
50
+
51
+ /// @inheritdoc ISequencerInbox
51
52
  bytes1 public constant DATA_AUTHENTICATED_FLAG = 0x40;
52
53
 
53
54
  IOwnable public rollup;
54
55
  mapping(address => bool) public isBatchPoster;
55
56
  ISequencerInbox.MaxTimeVariation public maxTimeVariation;
56
57
 
57
- struct DasKeySetInfo {
58
- bool isValidKeyset;
59
- uint64 creationBlock;
60
- }
61
58
  mapping(bytes32 => DasKeySetInfo) public dasKeySetInfo;
62
59
 
63
60
  modifier onlyRollupOwner() {
@@ -65,6 +62,12 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
65
62
  _;
66
63
  }
67
64
 
65
+ uint256 internal immutable deployTimeChainId = block.chainid;
66
+
67
+ function _chainIdChanged() internal view returns (bool) {
68
+ return deployTimeChainId != block.chainid;
69
+ }
70
+
68
71
  function initialize(
69
72
  IBridge bridge_,
70
73
  ISequencerInbox.MaxTimeVariation calldata maxTimeVariation_
@@ -89,17 +92,18 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
89
92
  return bounds;
90
93
  }
91
94
 
92
- /// @notice Force messages from the delayed inbox to be included in the chain
93
- /// Callable by any address, but message can only be force-included after maxTimeVariation.delayBlocks and maxTimeVariation.delaySeconds
94
- /// has elapsed. As part of normal behaviour the sequencer will include these messages
95
- /// so it's only necessary to call this if the sequencer is down, or not including
96
- /// any delayed messages.
97
- /// @param _totalDelayedMessagesRead The total number of messages to read up to
98
- /// @param kind The kind of the last message to be included
99
- /// @param l1BlockAndTime The l1 block and the l1 timestamp of the last message to be included
100
- /// @param baseFeeL1 The l1 gas price of the last message to be included
101
- /// @param sender The sender of the last message to be included
102
- /// @param messageDataHash The messageDataHash of the last message to be included
95
+ /// @inheritdoc ISequencerInbox
96
+ function removeDelayAfterFork() external {
97
+ if (!_chainIdChanged()) revert NotForked();
98
+ maxTimeVariation = ISequencerInbox.MaxTimeVariation({
99
+ delayBlocks: 1,
100
+ futureBlocks: 1,
101
+ delaySeconds: 1,
102
+ futureSeconds: 1
103
+ });
104
+ }
105
+
106
+ /// @inheritdoc ISequencerInbox
103
107
  function forceInclusion(
104
108
  uint256 _totalDelayedMessagesRead,
105
109
  uint8 kind,
@@ -137,12 +141,23 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
137
141
  (bytes32 dataHash, TimeBounds memory timeBounds) = formEmptyDataHash(
138
142
  _totalDelayedMessagesRead
139
143
  );
144
+ uint256 __totalDelayedMessagesRead = _totalDelayedMessagesRead;
145
+ uint256 prevSeqMsgCount = bridge.sequencerReportedSubMessageCount();
146
+ uint256 newSeqMsgCount = prevSeqMsgCount +
147
+ _totalDelayedMessagesRead -
148
+ totalDelayedMessagesRead;
140
149
  (
141
150
  uint256 seqMessageIndex,
142
151
  bytes32 beforeAcc,
143
152
  bytes32 delayedAcc,
144
153
  bytes32 afterAcc
145
- ) = addSequencerL2BatchImpl(dataHash, _totalDelayedMessagesRead, 0);
154
+ ) = addSequencerL2BatchImpl(
155
+ dataHash,
156
+ __totalDelayedMessagesRead,
157
+ 0,
158
+ prevSeqMsgCount,
159
+ newSeqMsgCount
160
+ );
146
161
  emit SequencerBatchDelivered(
147
162
  seqMessageIndex,
148
163
  beforeAcc,
@@ -154,6 +169,7 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
154
169
  );
155
170
  }
156
171
 
172
+ /// @dev Deprecated in favor of the variant specifying message counts for consistency
157
173
  function addSequencerL2BatchFromOrigin(
158
174
  uint256 sequenceNumber,
159
175
  bytes calldata data,
@@ -163,6 +179,7 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
163
179
  // solhint-disable-next-line avoid-tx-origin
164
180
  if (msg.sender != tx.origin) revert NotOrigin();
165
181
  if (!isBatchPoster[msg.sender]) revert NotBatchPoster();
182
+
166
183
  (bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
167
184
  data,
168
185
  afterDelayedMessagesRead
@@ -172,7 +189,7 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
172
189
  bytes32 beforeAcc,
173
190
  bytes32 delayedAcc,
174
191
  bytes32 afterAcc
175
- ) = addSequencerL2BatchImpl(dataHash, afterDelayedMessagesRead, data.length);
192
+ ) = addSequencerL2BatchImpl(dataHash, afterDelayedMessagesRead, data.length, 0, 0);
176
193
  if (seqMessageIndex != sequenceNumber)
177
194
  revert BadSequencerNumber(seqMessageIndex, sequenceNumber);
178
195
  emit SequencerBatchDelivered(
@@ -186,38 +203,101 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
186
203
  );
187
204
  }
188
205
 
189
- function addSequencerL2Batch(
206
+ function addSequencerL2BatchFromOrigin(
190
207
  uint256 sequenceNumber,
191
208
  bytes calldata data,
192
209
  uint256 afterDelayedMessagesRead,
193
- IGasRefunder gasRefunder
194
- ) external override refundsGas(gasRefunder) {
195
- if (!isBatchPoster[msg.sender] && msg.sender != address(rollup)) revert NotBatchPoster();
196
-
210
+ IGasRefunder gasRefunder,
211
+ uint256 prevMessageCount,
212
+ uint256 newMessageCount
213
+ ) external refundsGas(gasRefunder) {
214
+ // solhint-disable-next-line avoid-tx-origin
215
+ if (msg.sender != tx.origin) revert NotOrigin();
216
+ if (!isBatchPoster[msg.sender]) revert NotBatchPoster();
197
217
  (bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
198
218
  data,
199
219
  afterDelayedMessagesRead
200
220
  );
201
- // we set the calldata length posted to 0 here since the caller isn't the origin
202
- // of the tx, so they might have not paid tx input cost for the calldata
221
+ // Reformat the stack to prevent "Stack too deep"
222
+ uint256 sequenceNumber_ = sequenceNumber;
223
+ TimeBounds memory timeBounds_ = timeBounds;
224
+ bytes32 dataHash_ = dataHash;
225
+ uint256 dataLength = data.length;
226
+ uint256 afterDelayedMessagesRead_ = afterDelayedMessagesRead;
227
+ uint256 prevMessageCount_ = prevMessageCount;
228
+ uint256 newMessageCount_ = newMessageCount;
203
229
  (
204
230
  uint256 seqMessageIndex,
205
231
  bytes32 beforeAcc,
206
232
  bytes32 delayedAcc,
207
233
  bytes32 afterAcc
208
- ) = addSequencerL2BatchImpl(dataHash, afterDelayedMessagesRead, 0);
209
- if (seqMessageIndex != sequenceNumber)
210
- revert BadSequencerNumber(seqMessageIndex, sequenceNumber);
234
+ ) = addSequencerL2BatchImpl(
235
+ dataHash_,
236
+ afterDelayedMessagesRead_,
237
+ dataLength,
238
+ prevMessageCount_,
239
+ newMessageCount_
240
+ );
241
+ if (seqMessageIndex != sequenceNumber_ && sequenceNumber_ != ~uint256(0))
242
+ revert BadSequencerNumber(seqMessageIndex, sequenceNumber_);
211
243
  emit SequencerBatchDelivered(
212
- sequenceNumber,
244
+ seqMessageIndex,
213
245
  beforeAcc,
214
246
  afterAcc,
215
247
  delayedAcc,
216
- afterDelayedMessagesRead,
217
- timeBounds,
218
- BatchDataLocation.SeparateBatchEvent
248
+ totalDelayedMessagesRead,
249
+ timeBounds_,
250
+ BatchDataLocation.TxInput
251
+ );
252
+ }
253
+
254
+ function addSequencerL2Batch(
255
+ uint256 sequenceNumber,
256
+ bytes calldata data,
257
+ uint256 afterDelayedMessagesRead,
258
+ IGasRefunder gasRefunder,
259
+ uint256 prevMessageCount,
260
+ uint256 newMessageCount
261
+ ) external override refundsGas(gasRefunder) {
262
+ if (!isBatchPoster[msg.sender] && msg.sender != address(rollup)) revert NotBatchPoster();
263
+ (bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
264
+ data,
265
+ afterDelayedMessagesRead
219
266
  );
220
- emit SequencerBatchData(sequenceNumber, data);
267
+ uint256 seqMessageIndex;
268
+ {
269
+ // Reformat the stack to prevent "Stack too deep"
270
+ uint256 sequenceNumber_ = sequenceNumber;
271
+ TimeBounds memory timeBounds_ = timeBounds;
272
+ bytes32 dataHash_ = dataHash;
273
+ uint256 afterDelayedMessagesRead_ = afterDelayedMessagesRead;
274
+ uint256 prevMessageCount_ = prevMessageCount;
275
+ uint256 newMessageCount_ = newMessageCount;
276
+ // we set the calldata length posted to 0 here since the caller isn't the origin
277
+ // of the tx, so they might have not paid tx input cost for the calldata
278
+ bytes32 beforeAcc;
279
+ bytes32 delayedAcc;
280
+ bytes32 afterAcc;
281
+ (seqMessageIndex, beforeAcc, delayedAcc, afterAcc) = addSequencerL2BatchImpl(
282
+ dataHash_,
283
+ afterDelayedMessagesRead_,
284
+ 0,
285
+ prevMessageCount_,
286
+ newMessageCount_
287
+ );
288
+ if (seqMessageIndex != sequenceNumber_ && sequenceNumber_ != ~uint256(0))
289
+ revert BadSequencerNumber(seqMessageIndex, sequenceNumber_);
290
+ emit SequencerBatchDelivered(
291
+ seqMessageIndex,
292
+ beforeAcc,
293
+ afterAcc,
294
+ delayedAcc,
295
+ totalDelayedMessagesRead,
296
+ timeBounds_,
297
+ BatchDataLocation.SeparateBatchEvent
298
+ );
299
+ }
300
+ emit SequencerBatchData(seqMessageIndex, data);
221
301
  }
222
302
 
223
303
  modifier validateBatchData(bytes calldata data) {
@@ -277,7 +357,9 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
277
357
  function addSequencerL2BatchImpl(
278
358
  bytes32 dataHash,
279
359
  uint256 afterDelayedMessagesRead,
280
- uint256 calldataLengthPosted
360
+ uint256 calldataLengthPosted,
361
+ uint256 prevMessageCount,
362
+ uint256 newMessageCount
281
363
  )
282
364
  internal
283
365
  returns (
@@ -292,7 +374,9 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
292
374
 
293
375
  (seqMessageIndex, beforeAcc, delayedAcc, acc) = bridge.enqueueSequencerMessage(
294
376
  dataHash,
295
- afterDelayedMessagesRead
377
+ afterDelayedMessagesRead,
378
+ prevMessageCount,
379
+ newMessageCount
296
380
  );
297
381
 
298
382
  totalDelayedMessagesRead = afterDelayedMessagesRead;
@@ -317,42 +401,31 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
317
401
  }
318
402
  }
319
403
 
320
- function inboxAccs(uint256 index) external view override returns (bytes32) {
404
+ function inboxAccs(uint256 index) external view returns (bytes32) {
321
405
  return bridge.sequencerInboxAccs(index);
322
406
  }
323
407
 
324
- function batchCount() external view override returns (uint256) {
408
+ function batchCount() external view returns (uint256) {
325
409
  return bridge.sequencerMessageCount();
326
410
  }
327
411
 
328
- /**
329
- * @notice Set max delay for sequencer inbox
330
- * @param maxTimeVariation_ the maximum time variation parameters
331
- */
412
+ /// @inheritdoc ISequencerInbox
332
413
  function setMaxTimeVariation(ISequencerInbox.MaxTimeVariation memory maxTimeVariation_)
333
414
  external
334
- override
335
415
  onlyRollupOwner
336
416
  {
337
417
  maxTimeVariation = maxTimeVariation_;
338
418
  emit OwnerFunctionCalled(0);
339
419
  }
340
420
 
341
- /**
342
- * @notice Updates whether an address is authorized to be a batch poster at the sequencer inbox
343
- * @param addr the address
344
- * @param isBatchPoster_ if the specified address should be authorized as a batch poster
345
- */
346
- function setIsBatchPoster(address addr, bool isBatchPoster_) external override onlyRollupOwner {
421
+ /// @inheritdoc ISequencerInbox
422
+ function setIsBatchPoster(address addr, bool isBatchPoster_) external onlyRollupOwner {
347
423
  isBatchPoster[addr] = isBatchPoster_;
348
424
  emit OwnerFunctionCalled(1);
349
425
  }
350
426
 
351
- /**
352
- * @notice Makes Data Availability Service keyset valid
353
- * @param keysetBytes bytes of the serialized keyset
354
- */
355
- function setValidKeyset(bytes calldata keysetBytes) external override onlyRollupOwner {
427
+ /// @inheritdoc ISequencerInbox
428
+ function setValidKeyset(bytes calldata keysetBytes) external onlyRollupOwner {
356
429
  uint256 ksWord = uint256(keccak256(bytes.concat(hex"fe", keccak256(keysetBytes))));
357
430
  bytes32 ksHash = bytes32(ksWord ^ (1 << 255));
358
431
  require(keysetBytes.length < 64 * 1024, "keyset is too large");
@@ -366,11 +439,8 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
366
439
  emit OwnerFunctionCalled(2);
367
440
  }
368
441
 
369
- /**
370
- * @notice Invalidates a Data Availability Service keyset
371
- * @param ksHash hash of the keyset
372
- */
373
- function invalidateKeysetHash(bytes32 ksHash) external override onlyRollupOwner {
442
+ /// @inheritdoc ISequencerInbox
443
+ function invalidateKeysetHash(bytes32 ksHash) external onlyRollupOwner {
374
444
  if (!dasKeySetInfo[ksHash].isValidKeyset) revert NoSuchKeyset(ksHash);
375
445
  // we don't delete the block creation value since its used to fetch the SetValidKeyset
376
446
  // event efficiently. The event provides the hash preimage of the key.
@@ -384,7 +454,7 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
384
454
  return dasKeySetInfo[ksHash].isValidKeyset;
385
455
  }
386
456
 
387
- /// @notice the creation block is intended to still be available after a keyset is deleted
457
+ /// @inheritdoc ISequencerInbox
388
458
  function getKeysetCreationBlock(bytes32 ksHash) external view returns (uint256) {
389
459
  DasKeySetInfo memory ksInfo = dasKeySetInfo[ksHash];
390
460
  if (ksInfo.creationBlock == 0) revert NoSuchKeyset(ksHash);
@@ -285,15 +285,6 @@ contract ChallengeManager is DelegateCallAware, IChallengeManager {
285
285
  return challenges[challengeIndex].current.addr;
286
286
  }
287
287
 
288
- function currentResponderTimeLeft(uint64 challengeIndex)
289
- public
290
- view
291
- override
292
- returns (uint256)
293
- {
294
- return challenges[challengeIndex].current.timeLeft;
295
- }
296
-
297
288
  function isTimedOut(uint64 challengeIndex) public view override returns (bool) {
298
289
  return challenges[challengeIndex].isTimedOut();
299
290
  }
@@ -67,8 +67,6 @@ interface IChallengeManager {
67
67
 
68
68
  function isTimedOut(uint64 challengeIndex) external view returns (bool);
69
69
 
70
- function currentResponderTimeLeft(uint64 challengeIndex_) external view returns (uint256);
71
-
72
70
  function clearChallenge(uint64 challengeIndex_) external;
73
71
 
74
72
  function timeout(uint64 challengeIndex_) external;
@@ -87,7 +87,7 @@ abstract contract DoubleLogicERC1967Upgrade is ERC1967Upgrade {
87
87
  try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
88
88
  require(
89
89
  slot == _IMPLEMENTATION_SECONDARY_SLOT,
90
- "ERC1967Upgrade: unsupported proxiableUUID"
90
+ "ERC1967Upgrade: unsupported secondary proxiableUUID"
91
91
  );
92
92
  } catch {
93
93
  revert("ERC1967Upgrade: new secondary implementation is not UUPS");
@@ -132,8 +132,8 @@ contract AdminFallbackProxy is Proxy, DoubleLogicERC1967Upgrade {
132
132
  require(msg.data.length >= 4, "NO_FUNC_SIG");
133
133
  // if the sender is the proxy's admin, delegate to admin logic
134
134
  // if the admin is disabled, all calls will be forwarded to user logic
135
- // admin affordances can be disabled by setting to address(1) since
136
- // `ERC1697._setAdmin()` doesn't allow address(0) to be set
135
+ // admin affordances can be disabled by setting to a no-op smart contract
136
+ // since there is a check for contract code before updating the value
137
137
  address target = _getAdmin() != msg.sender
138
138
  ? DoubleLogicERC1967Upgrade._getSecondaryImplementation()
139
139
  : ERC1967Upgrade._getImplementation();
@@ -144,7 +144,7 @@ contract AdminFallbackProxy is Proxy, DoubleLogicERC1967Upgrade {
144
144
 
145
145
  /**
146
146
  * @dev unlike transparent upgradeable proxies, this does allow the admin to fallback to a logic contract
147
- * the admin is expected to interact only with the secondary logic contract, which handles contract
147
+ * the admin is expected to interact only with the primary logic contract, which handles contract
148
148
  * upgrades using the UUPS approach
149
149
  */
150
150
  function _beforeFallback() internal override {
@@ -8,3 +8,9 @@ pragma solidity ^0.8.4;
8
8
  uint256 constant MAX_DATA_SIZE = 117964;
9
9
 
10
10
  uint64 constant NO_CHAL_INDEX = 0;
11
+
12
+ // Expected seconds per block in Ethereum PoS
13
+ uint256 constant ETH_POS_BLOCK_TIME = 12;
14
+
15
+ address constant UNISWAP_L1_TIMELOCK = 0x1a9C8182C09F50C8318d769245beA52c32BE35BC;
16
+ address constant UNISWAP_L2_FACTORY = 0x1F98431c8aD98523631AE4a59f267346ea31F984;
@@ -8,8 +8,9 @@ import {DoubleLogicERC1967Upgrade} from "./AdminFallbackProxy.sol";
8
8
  import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
9
9
 
10
10
  /// @notice An extension to OZ's UUPSUpgradeable contract to be used for handling UUPS upgrades with a DoubleLogicERC1967Upgrade proxy
11
+ /// The should be used in the primary implementation slot of the DoubleLogicUUPS proxy
11
12
  /// @dev upgrades should be handles by the primary logic contract in order to pass the `onlyProxy` check
12
- abstract contract SecondaryLogicUUPSUpgradeable is UUPSUpgradeable, DoubleLogicERC1967Upgrade {
13
+ abstract contract DoubleLogicUUPSUpgradeable is UUPSUpgradeable, DoubleLogicERC1967Upgrade {
13
14
  /// @inheritdoc UUPSUpgradeable
14
15
  function proxiableUUID() external view override notDelegated returns (bytes32) {
15
16
  return _IMPLEMENTATION_SLOT;
@@ -96,6 +96,15 @@ error RetryableData(
96
96
  bytes data
97
97
  );
98
98
 
99
+ /// @dev Thrown when a L1 chainId fork is detected
100
+ error L1Forked();
101
+
102
+ /// @dev Thrown when a L1 chainId fork is not detected
103
+ error NotForked();
104
+
105
+ /// @dev The provided gasLimit is larger than uint64
106
+ error GasLimitTooLarge();
107
+
99
108
  // Outbox Errors
100
109
 
101
110
  /// @dev The provided proof was too long
@@ -141,6 +150,9 @@ error NotBatchPoster();
141
150
  /// @dev The sequence number provided to this message was inconsistent with the number of batches already included
142
151
  error BadSequencerNumber(uint256 stored, uint256 received);
143
152
 
153
+ /// @dev The sequence message number provided to this message was inconsistent with the previous one
154
+ error BadSequencerMessageNumber(uint256 stored, uint256 received);
155
+
144
156
  /// @dev The batch data has the inbox authenticated bit set, but the batch data was not authenticated by the inbox
145
157
  error DataNotAuthenticated();
146
158
 
@@ -21,14 +21,20 @@ abstract contract GasRefundEnabled {
21
21
  uint256 startGasLeft = gasleft();
22
22
  _;
23
23
  if (address(gasRefunder) != address(0)) {
24
- uint256 calldataSize = 0;
24
+ uint256 calldataSize;
25
+ assembly {
26
+ calldataSize := calldatasize()
27
+ }
28
+ uint256 calldataWords = (calldataSize + 31) / 32;
29
+ // account for the CALLDATACOPY cost of the proxy contract, including the memory expansion cost
30
+ startGasLeft += calldataWords * 6 + (calldataWords**2) / 512;
25
31
  // if triggered in a contract call, the spender may be overrefunded by appending dummy data to the call
26
32
  // so we check if it is a top level call, which would mean the sender paid calldata as part of tx.input
27
33
  // solhint-disable-next-line avoid-tx-origin
28
- if (msg.sender == tx.origin) {
29
- assembly {
30
- calldataSize := calldatasize()
31
- }
34
+ if (msg.sender != tx.origin) {
35
+ // We can't be sure if this calldata came from the top level tx,
36
+ // so to be safe we tell the gas refunder there was no calldata.
37
+ calldataSize = 0;
32
38
  }
33
39
  gasRefunder.onGasSpent(payable(msg.sender), startGasLeft - gasleft(), calldataSize);
34
40
  }
@@ -33,9 +33,9 @@ library MerkleLib {
33
33
  uint256 proofItems = nodes.length;
34
34
  if (proofItems > 256) revert MerkleProofTooLong(proofItems, 256);
35
35
  bytes32 h = item;
36
- for (uint256 i = 0; i < proofItems; i++) {
36
+ for (uint256 i = 0; i < proofItems; ) {
37
37
  bytes32 node = nodes[i];
38
- if (route % 2 == 0) {
38
+ if ((route & (1 << i)) == 0) {
39
39
  assembly {
40
40
  mstore(0x00, h)
41
41
  mstore(0x20, node)
@@ -48,7 +48,9 @@ library MerkleLib {
48
48
  h := keccak256(0x00, 0x40)
49
49
  }
50
50
  }
51
- route /= 2;
51
+ unchecked {
52
+ ++i;
53
+ }
52
54
  }
53
55
  return h;
54
56
  }