@arbitrum/nitro-contracts 1.0.0-beta.7 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/package.json +13 -2
  2. package/src/bridge/Bridge.sol +49 -29
  3. package/src/bridge/IBridge.sol +58 -45
  4. package/src/bridge/IDelayedMessageProvider.sol +2 -1
  5. package/src/bridge/IInbox.sol +133 -50
  6. package/src/bridge/IOutbox.sol +95 -27
  7. package/src/bridge/IOwnable.sol +2 -1
  8. package/src/bridge/ISequencerInbox.sol +79 -31
  9. package/src/bridge/Inbox.sol +171 -108
  10. package/src/bridge/Outbox.sol +26 -41
  11. package/src/bridge/SequencerInbox.sol +152 -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 +3 -0
  16. package/src/libraries/{SecondaryLogicUUPSUpgradeable.sol → DoubleLogicUUPSUpgradeable.sol} +2 -1
  17. package/src/libraries/Error.sol +119 -0
  18. package/src/libraries/IGasRefunder.sol +13 -6
  19. package/src/libraries/MerkleLib.sol +5 -3
  20. package/src/mocks/BridgeStub.sol +22 -1
  21. package/src/mocks/BridgeUnproxied.sol +17 -0
  22. package/src/mocks/InboxStub.sol +49 -2
  23. package/src/mocks/SequencerInboxStub.sol +13 -3
  24. package/src/mocks/Simple.sol +69 -0
  25. package/src/node-interface/NodeInterface.sol +69 -7
  26. package/src/precompiles/ArbGasInfo.sol +16 -4
  27. package/src/precompiles/ArbOwner.sol +18 -0
  28. package/src/precompiles/ArbOwnerPublic.sol +3 -0
  29. package/src/precompiles/ArbSys.sol +7 -4
  30. package/src/rollup/IRollupCore.sol +2 -0
  31. package/src/rollup/IRollupLogic.sol +10 -0
  32. package/src/rollup/RollupAdminLogic.sol +69 -3
  33. package/src/rollup/RollupCore.sol +8 -2
  34. package/src/rollup/RollupCreator.sol +3 -3
  35. package/src/rollup/RollupEventInbox.sol +3 -6
  36. package/src/rollup/RollupLib.sol +1 -0
  37. package/src/{libraries/ArbitrumProxy.sol → rollup/RollupProxy.sol} +3 -3
  38. package/src/rollup/RollupUserLogic.sol +47 -10
  39. package/src/state/GlobalState.sol +7 -0
  40. package/src/test-helpers/BridgeTester.sol +17 -1
  41. package/src/test-helpers/InterfaceCompatibilityTester.sol +11 -0
  42. package/src/test-helpers/OutboxWithoutOptTester.sol +33 -7
@@ -4,6 +4,24 @@
4
4
 
5
5
  pragma solidity ^0.8.0;
6
6
 
7
+ import {
8
+ AlreadyInit,
9
+ HadZeroInit,
10
+ NotOrigin,
11
+ DataTooLarge,
12
+ NotRollup,
13
+ DelayedBackwards,
14
+ DelayedTooFar,
15
+ ForceIncludeBlockTooSoon,
16
+ ForceIncludeTimeTooSoon,
17
+ IncorrectMessagePreimage,
18
+ NotBatchPoster,
19
+ BadSequencerNumber,
20
+ DataNotAuthenticated,
21
+ AlreadyValidDASKeyset,
22
+ NoSuchKeyset,
23
+ NotForked
24
+ } from "../libraries/Error.sol";
7
25
  import "./IBridge.sol";
8
26
  import "./IInbox.sol";
9
27
  import "./ISequencerInbox.sol";
@@ -27,20 +45,16 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
27
45
 
28
46
  IBridge public bridge;
29
47
 
30
- /// @dev The size of the batch header
48
+ /// @inheritdoc ISequencerInbox
31
49
  uint256 public constant HEADER_LENGTH = 40;
32
- /// @dev If the first batch data byte after the header has this bit set,
33
- /// the sequencer inbox has authenticated the data. Currently not used.
50
+
51
+ /// @inheritdoc ISequencerInbox
34
52
  bytes1 public constant DATA_AUTHENTICATED_FLAG = 0x40;
35
53
 
36
54
  IOwnable public rollup;
37
55
  mapping(address => bool) public isBatchPoster;
38
56
  ISequencerInbox.MaxTimeVariation public maxTimeVariation;
39
57
 
40
- struct DasKeySetInfo {
41
- bool isValidKeyset;
42
- uint64 creationBlock;
43
- }
44
58
  mapping(bytes32 => DasKeySetInfo) public dasKeySetInfo;
45
59
 
46
60
  modifier onlyRollupOwner() {
@@ -48,6 +62,12 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
48
62
  _;
49
63
  }
50
64
 
65
+ uint256 internal immutable deployTimeChainId = block.chainid;
66
+
67
+ function _chainIdChanged() internal view returns (bool) {
68
+ return deployTimeChainId != block.chainid;
69
+ }
70
+
51
71
  function initialize(
52
72
  IBridge bridge_,
53
73
  ISequencerInbox.MaxTimeVariation calldata maxTimeVariation_
@@ -72,17 +92,18 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
72
92
  return bounds;
73
93
  }
74
94
 
75
- /// @notice Force messages from the delayed inbox to be included in the chain
76
- /// Callable by any address, but message can only be force-included after maxTimeVariation.delayBlocks and maxTimeVariation.delaySeconds
77
- /// has elapsed. As part of normal behaviour the sequencer will include these messages
78
- /// so it's only necessary to call this if the sequencer is down, or not including
79
- /// any delayed messages.
80
- /// @param _totalDelayedMessagesRead The total number of messages to read up to
81
- /// @param kind The kind of the last message to be included
82
- /// @param l1BlockAndTime The l1 block and the l1 timestamp of the last message to be included
83
- /// @param baseFeeL1 The l1 gas price of the last message to be included
84
- /// @param sender The sender of the last message to be included
85
- /// @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
86
107
  function forceInclusion(
87
108
  uint256 _totalDelayedMessagesRead,
88
109
  uint8 kind,
@@ -120,12 +141,23 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
120
141
  (bytes32 dataHash, TimeBounds memory timeBounds) = formEmptyDataHash(
121
142
  _totalDelayedMessagesRead
122
143
  );
144
+ uint256 __totalDelayedMessagesRead = _totalDelayedMessagesRead;
145
+ uint256 prevSeqMsgCount = bridge.sequencerReportedSubMessageCount();
146
+ uint256 newSeqMsgCount = prevSeqMsgCount +
147
+ _totalDelayedMessagesRead -
148
+ totalDelayedMessagesRead;
123
149
  (
124
150
  uint256 seqMessageIndex,
125
151
  bytes32 beforeAcc,
126
152
  bytes32 delayedAcc,
127
153
  bytes32 afterAcc
128
- ) = addSequencerL2BatchImpl(dataHash, _totalDelayedMessagesRead, 0);
154
+ ) = addSequencerL2BatchImpl(
155
+ dataHash,
156
+ __totalDelayedMessagesRead,
157
+ 0,
158
+ prevSeqMsgCount,
159
+ newSeqMsgCount
160
+ );
129
161
  emit SequencerBatchDelivered(
130
162
  seqMessageIndex,
131
163
  beforeAcc,
@@ -137,6 +169,7 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
137
169
  );
138
170
  }
139
171
 
172
+ /// @dev Deprecated in favor of the variant specifying message counts for consistency
140
173
  function addSequencerL2BatchFromOrigin(
141
174
  uint256 sequenceNumber,
142
175
  bytes calldata data,
@@ -146,6 +179,7 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
146
179
  // solhint-disable-next-line avoid-tx-origin
147
180
  if (msg.sender != tx.origin) revert NotOrigin();
148
181
  if (!isBatchPoster[msg.sender]) revert NotBatchPoster();
182
+
149
183
  (bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
150
184
  data,
151
185
  afterDelayedMessagesRead
@@ -155,7 +189,7 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
155
189
  bytes32 beforeAcc,
156
190
  bytes32 delayedAcc,
157
191
  bytes32 afterAcc
158
- ) = addSequencerL2BatchImpl(dataHash, afterDelayedMessagesRead, data.length);
192
+ ) = addSequencerL2BatchImpl(dataHash, afterDelayedMessagesRead, data.length, 0, 0);
159
193
  if (seqMessageIndex != sequenceNumber)
160
194
  revert BadSequencerNumber(seqMessageIndex, sequenceNumber);
161
195
  emit SequencerBatchDelivered(
@@ -169,38 +203,101 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
169
203
  );
170
204
  }
171
205
 
172
- function addSequencerL2Batch(
206
+ function addSequencerL2BatchFromOrigin(
173
207
  uint256 sequenceNumber,
174
208
  bytes calldata data,
175
209
  uint256 afterDelayedMessagesRead,
176
- IGasRefunder gasRefunder
177
- ) external override refundsGas(gasRefunder) {
178
- if (!isBatchPoster[msg.sender] && msg.sender != address(rollup)) revert NotBatchPoster();
179
-
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();
180
217
  (bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
181
218
  data,
182
219
  afterDelayedMessagesRead
183
220
  );
184
- // we set the calldata length posted to 0 here since the caller isn't the origin
185
- // 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;
186
229
  (
187
230
  uint256 seqMessageIndex,
188
231
  bytes32 beforeAcc,
189
232
  bytes32 delayedAcc,
190
233
  bytes32 afterAcc
191
- ) = addSequencerL2BatchImpl(dataHash, afterDelayedMessagesRead, 0);
192
- if (seqMessageIndex != sequenceNumber)
193
- 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_);
194
243
  emit SequencerBatchDelivered(
195
- sequenceNumber,
244
+ seqMessageIndex,
196
245
  beforeAcc,
197
246
  afterAcc,
198
247
  delayedAcc,
199
- afterDelayedMessagesRead,
200
- timeBounds,
201
- 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
202
266
  );
203
- 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);
204
301
  }
205
302
 
206
303
  modifier validateBatchData(bytes calldata data) {
@@ -260,7 +357,9 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
260
357
  function addSequencerL2BatchImpl(
261
358
  bytes32 dataHash,
262
359
  uint256 afterDelayedMessagesRead,
263
- uint256 calldataLengthPosted
360
+ uint256 calldataLengthPosted,
361
+ uint256 prevMessageCount,
362
+ uint256 newMessageCount
264
363
  )
265
364
  internal
266
365
  returns (
@@ -275,7 +374,9 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
275
374
 
276
375
  (seqMessageIndex, beforeAcc, delayedAcc, acc) = bridge.enqueueSequencerMessage(
277
376
  dataHash,
278
- afterDelayedMessagesRead
377
+ afterDelayedMessagesRead,
378
+ prevMessageCount,
379
+ newMessageCount
279
380
  );
280
381
 
281
382
  totalDelayedMessagesRead = afterDelayedMessagesRead;
@@ -300,43 +401,35 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
300
401
  }
301
402
  }
302
403
 
303
- function inboxAccs(uint256 index) external view override returns (bytes32) {
404
+ function inboxAccs(uint256 index) external view returns (bytes32) {
304
405
  return bridge.sequencerInboxAccs(index);
305
406
  }
306
407
 
307
- function batchCount() external view override returns (uint256) {
408
+ function batchCount() external view returns (uint256) {
308
409
  return bridge.sequencerMessageCount();
309
410
  }
310
411
 
311
- /**
312
- * @notice Set max delay for sequencer inbox
313
- * @param maxTimeVariation_ the maximum time variation parameters
314
- */
412
+ /// @inheritdoc ISequencerInbox
315
413
  function setMaxTimeVariation(ISequencerInbox.MaxTimeVariation memory maxTimeVariation_)
316
414
  external
317
- override
318
415
  onlyRollupOwner
319
416
  {
320
417
  maxTimeVariation = maxTimeVariation_;
321
418
  emit OwnerFunctionCalled(0);
322
419
  }
323
420
 
324
- /**
325
- * @notice Updates whether an address is authorized to be a batch poster at the sequencer inbox
326
- * @param addr the address
327
- * @param isBatchPoster_ if the specified address should be authorized as a batch poster
328
- */
329
- function setIsBatchPoster(address addr, bool isBatchPoster_) external override onlyRollupOwner {
421
+ /// @inheritdoc ISequencerInbox
422
+ function setIsBatchPoster(address addr, bool isBatchPoster_) external onlyRollupOwner {
330
423
  isBatchPoster[addr] = isBatchPoster_;
331
424
  emit OwnerFunctionCalled(1);
332
425
  }
333
426
 
334
- /**
335
- * @notice Makes Data Availability Service keyset valid
336
- * @param keysetBytes bytes of the serialized keyset
337
- */
338
- function setValidKeyset(bytes calldata keysetBytes) external override onlyRollupOwner {
339
- bytes32 ksHash = keccak256(keysetBytes);
427
+ /// @inheritdoc ISequencerInbox
428
+ function setValidKeyset(bytes calldata keysetBytes) external onlyRollupOwner {
429
+ uint256 ksWord = uint256(keccak256(bytes.concat(hex"fe", keccak256(keysetBytes))));
430
+ bytes32 ksHash = bytes32(ksWord ^ (1 << 255));
431
+ require(keysetBytes.length < 64 * 1024, "keyset is too large");
432
+
340
433
  if (dasKeySetInfo[ksHash].isValidKeyset) revert AlreadyValidDASKeyset(ksHash);
341
434
  dasKeySetInfo[ksHash] = DasKeySetInfo({
342
435
  isValidKeyset: true,
@@ -346,11 +439,8 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
346
439
  emit OwnerFunctionCalled(2);
347
440
  }
348
441
 
349
- /**
350
- * @notice Invalidates a Data Availability Service keyset
351
- * @param ksHash hash of the keyset
352
- */
353
- function invalidateKeysetHash(bytes32 ksHash) external override onlyRollupOwner {
442
+ /// @inheritdoc ISequencerInbox
443
+ function invalidateKeysetHash(bytes32 ksHash) external onlyRollupOwner {
354
444
  if (!dasKeySetInfo[ksHash].isValidKeyset) revert NoSuchKeyset(ksHash);
355
445
  // we don't delete the block creation value since its used to fetch the SetValidKeyset
356
446
  // event efficiently. The event provides the hash preimage of the key.
@@ -364,7 +454,7 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
364
454
  return dasKeySetInfo[ksHash].isValidKeyset;
365
455
  }
366
456
 
367
- /// @notice the creation block is intended to still be available after a keyset is deleted
457
+ /// @inheritdoc ISequencerInbox
368
458
  function getKeysetCreationBlock(bytes32 ksHash) external view returns (uint256) {
369
459
  DasKeySetInfo memory ksInfo = dasKeySetInfo[ksHash];
370
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,6 @@ 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;
@@ -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;
@@ -42,3 +42,122 @@ error MerkleProofTooLong(uint256 actualLength, uint256 maxProofLength);
42
42
  /// @param rollup The rollup, which would be authorized
43
43
  /// @param owner The rollup's owner, which would be authorized
44
44
  error NotRollupOrOwner(address sender, address rollup, address owner);
45
+
46
+ // Bridge Errors
47
+
48
+ /// @dev Thrown when an un-authorized address tries to access an only-inbox function
49
+ /// @param sender The un-authorized sender
50
+ error NotDelayedInbox(address sender);
51
+
52
+ /// @dev Thrown when an un-authorized address tries to access an only-sequencer-inbox function
53
+ /// @param sender The un-authorized sender
54
+ error NotSequencerInbox(address sender);
55
+
56
+ /// @dev Thrown when an un-authorized address tries to access an only-outbox function
57
+ /// @param sender The un-authorized sender
58
+ error NotOutbox(address sender);
59
+
60
+ /// @dev the provided outbox address isn't valid
61
+ /// @param outbox address of outbox being set
62
+ error InvalidOutboxSet(address outbox);
63
+
64
+ // Inbox Errors
65
+
66
+ /// @dev The contract is paused, so cannot be paused
67
+ error AlreadyPaused();
68
+
69
+ /// @dev The contract is unpaused, so cannot be unpaused
70
+ error AlreadyUnpaused();
71
+
72
+ /// @dev The contract is paused
73
+ error Paused();
74
+
75
+ /// @dev msg.value sent to the inbox isn't high enough
76
+ error InsufficientValue(uint256 expected, uint256 actual);
77
+
78
+ /// @dev submission cost provided isn't enough to create retryable ticket
79
+ error InsufficientSubmissionCost(uint256 expected, uint256 actual);
80
+
81
+ /// @dev address not allowed to interact with the given contract
82
+ error NotAllowedOrigin(address origin);
83
+
84
+ /// @dev used to convey retryable tx data in eth calls without requiring a tx trace
85
+ /// this follows a pattern similar to EIP-3668 where reverts surface call information
86
+ error RetryableData(
87
+ address from,
88
+ address to,
89
+ uint256 l2CallValue,
90
+ uint256 deposit,
91
+ uint256 maxSubmissionCost,
92
+ address excessFeeRefundAddress,
93
+ address callValueRefundAddress,
94
+ uint256 gasLimit,
95
+ uint256 maxFeePerGas,
96
+ bytes data
97
+ );
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
+
108
+ // Outbox Errors
109
+
110
+ /// @dev The provided proof was too long
111
+ /// @param proofLength The length of the too-long proof
112
+ error ProofTooLong(uint256 proofLength);
113
+
114
+ /// @dev The output index was greater than the maximum
115
+ /// @param index The output index
116
+ /// @param maxIndex The max the index could be
117
+ error PathNotMinimal(uint256 index, uint256 maxIndex);
118
+
119
+ /// @dev The calculated root does not exist
120
+ /// @param root The calculated root
121
+ error UnknownRoot(bytes32 root);
122
+
123
+ /// @dev The record has already been spent
124
+ /// @param index The index of the spent record
125
+ error AlreadySpent(uint256 index);
126
+
127
+ /// @dev A call to the bridge failed with no return data
128
+ error BridgeCallFailed();
129
+
130
+ // Sequencer Inbox Errors
131
+
132
+ /// @dev Thrown when someone attempts to read fewer messages than have already been read
133
+ error DelayedBackwards();
134
+
135
+ /// @dev Thrown when someone attempts to read more messages than exist
136
+ error DelayedTooFar();
137
+
138
+ /// @dev Force include can only read messages more blocks old than the delay period
139
+ error ForceIncludeBlockTooSoon();
140
+
141
+ /// @dev Force include can only read messages more seconds old than the delay period
142
+ error ForceIncludeTimeTooSoon();
143
+
144
+ /// @dev The message provided did not match the hash in the delayed inbox
145
+ error IncorrectMessagePreimage();
146
+
147
+ /// @dev This can only be called by the batch poster
148
+ error NotBatchPoster();
149
+
150
+ /// @dev The sequence number provided to this message was inconsistent with the number of batches already included
151
+ error BadSequencerNumber(uint256 stored, uint256 received);
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
+
156
+ /// @dev The batch data has the inbox authenticated bit set, but the batch data was not authenticated by the inbox
157
+ error DataNotAuthenticated();
158
+
159
+ /// @dev Tried to create an already valid Data Availability Service keyset
160
+ error AlreadyValidDASKeyset(bytes32);
161
+
162
+ /// @dev Tried to use or invalidate an already invalid Data Availability Service keyset
163
+ error NoSuchKeyset(bytes32);
@@ -2,7 +2,8 @@
2
2
  // For license information, see https://github.com/nitro/blob/master/LICENSE
3
3
  // SPDX-License-Identifier: BUSL-1.1
4
4
 
5
- pragma solidity >=0.6.11 <0.9.0;
5
+ // solhint-disable-next-line compiler-version
6
+ pragma solidity >=0.6.9 <0.9.0;
6
7
 
7
8
  interface IGasRefunder {
8
9
  function onGasSpent(
@@ -20,14 +21,20 @@ abstract contract GasRefundEnabled {
20
21
  uint256 startGasLeft = gasleft();
21
22
  _;
22
23
  if (address(gasRefunder) != address(0)) {
23
- 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;
24
31
  // if triggered in a contract call, the spender may be overrefunded by appending dummy data to the call
25
32
  // so we check if it is a top level call, which would mean the sender paid calldata as part of tx.input
26
33
  // solhint-disable-next-line avoid-tx-origin
27
- if (msg.sender == tx.origin) {
28
- assembly {
29
- calldataSize := calldatasize()
30
- }
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;
31
38
  }
32
39
  gasRefunder.onGasSpent(payable(msg.sender), startGasLeft - gasleft(), calldataSize);
33
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
  }
@@ -5,6 +5,7 @@
5
5
  pragma solidity ^0.8.0;
6
6
 
7
7
  import "./InboxStub.sol";
8
+ import {BadSequencerMessageNumber} from "../libraries/Error.sol";
8
9
 
9
10
  import "../bridge/IBridge.sol";
10
11
 
@@ -28,6 +29,7 @@ contract BridgeStub is IBridge {
28
29
  bytes32[] public override sequencerInboxAccs;
29
30
 
30
31
  address public sequencerInbox;
32
+ uint256 public override sequencerReportedSubMessageCount;
31
33
 
32
34
  function setSequencerInbox(address _sequencerInbox) external override {
33
35
  sequencerInbox = _sequencerInbox;
@@ -59,7 +61,12 @@ contract BridgeStub is IBridge {
59
61
  );
60
62
  }
61
63
 
62
- function enqueueSequencerMessage(bytes32 dataHash, uint256 afterDelayedMessagesRead)
64
+ function enqueueSequencerMessage(
65
+ bytes32 dataHash,
66
+ uint256 afterDelayedMessagesRead,
67
+ uint256 prevMessageCount,
68
+ uint256 newMessageCount
69
+ )
63
70
  external
64
71
  returns (
65
72
  uint256 seqMessageIndex,
@@ -68,6 +75,14 @@ contract BridgeStub is IBridge {
68
75
  bytes32 acc
69
76
  )
70
77
  {
78
+ if (
79
+ sequencerReportedSubMessageCount != prevMessageCount &&
80
+ prevMessageCount != 0 &&
81
+ sequencerReportedSubMessageCount != 0
82
+ ) {
83
+ revert BadSequencerMessageNumber(sequencerReportedSubMessageCount, prevMessageCount);
84
+ }
85
+ sequencerReportedSubMessageCount = newMessageCount;
71
86
  seqMessageIndex = sequencerInboxAccs.length;
72
87
  if (sequencerInboxAccs.length > 0) {
73
88
  beforeAcc = sequencerInboxAccs[sequencerInboxAccs.length - 1];
@@ -158,4 +173,10 @@ contract BridgeStub is IBridge {
158
173
  function rollup() external pure override returns (IOwnable) {
159
174
  revert("NOT_IMPLEMENTED");
160
175
  }
176
+
177
+ function acceptFundsFromOldBridge() external payable {}
178
+
179
+ function initialize(IOwnable) external pure {
180
+ revert("NOT_IMPLEMENTED");
181
+ }
161
182
  }