@arbitrum/nitro-contracts 1.0.0-beta.8 → 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 (37) hide show
  1. package/package.json +10 -2
  2. package/src/bridge/Bridge.sol +39 -30
  3. package/src/bridge/IBridge.sol +56 -29
  4. package/src/bridge/IInbox.sol +130 -15
  5. package/src/bridge/IOutbox.sol +55 -7
  6. package/src/bridge/ISequencerInbox.sol +84 -7
  7. package/src/bridge/Inbox.sol +154 -92
  8. package/src/bridge/Outbox.sol +23 -47
  9. package/src/bridge/SequencerInbox.sol +132 -62
  10. package/src/challenge/ChallengeManager.sol +0 -9
  11. package/src/challenge/IChallengeManager.sol +0 -2
  12. package/src/libraries/AdminFallbackProxy.sol +4 -4
  13. package/src/libraries/Constants.sol +3 -0
  14. package/src/libraries/{SecondaryLogicUUPSUpgradeable.sol → DoubleLogicUUPSUpgradeable.sol} +2 -1
  15. package/src/libraries/Error.sol +12 -0
  16. package/src/libraries/IGasRefunder.sol +11 -5
  17. package/src/libraries/MerkleLib.sol +5 -3
  18. package/src/mocks/BridgeStub.sol +20 -1
  19. package/src/mocks/BridgeUnproxied.sol +17 -0
  20. package/src/mocks/InboxStub.sol +48 -3
  21. package/src/mocks/SequencerInboxStub.sol +13 -3
  22. package/src/mocks/Simple.sol +69 -0
  23. package/src/node-interface/NodeInterface.sol +35 -4
  24. package/src/precompiles/ArbGasInfo.sol +7 -4
  25. package/src/precompiles/ArbOwner.sol +9 -0
  26. package/src/precompiles/ArbOwnerPublic.sol +3 -0
  27. package/src/precompiles/ArbSys.sol +5 -2
  28. package/src/rollup/IRollupCore.sol +2 -0
  29. package/src/rollup/IRollupLogic.sol +10 -0
  30. package/src/rollup/RollupAdminLogic.sol +27 -3
  31. package/src/rollup/RollupCore.sol +3 -0
  32. package/src/rollup/RollupCreator.sol +3 -3
  33. package/src/rollup/RollupEventInbox.sol +3 -6
  34. package/src/{libraries/ArbitrumProxy.sol → rollup/RollupProxy.sol} +3 -3
  35. package/src/rollup/RollupUserLogic.sol +47 -10
  36. package/src/test-helpers/BridgeTester.sol +7 -1
  37. package/src/test-helpers/OutboxWithoutOptTester.sol +8 -8
@@ -8,6 +8,7 @@ pragma experimental ABIEncoderV2;
8
8
 
9
9
  import "../libraries/IGasRefunder.sol";
10
10
  import "./IDelayedMessageProvider.sol";
11
+ import "./IBridge.sol";
11
12
 
12
13
  interface ISequencerInbox is IDelayedMessageProvider {
13
14
  struct MaxTimeVariation {
@@ -51,33 +52,109 @@ interface ISequencerInbox is IDelayedMessageProvider {
51
52
  /// @dev a keyset was invalidated
52
53
  event InvalidateKeyset(bytes32 indexed keysetHash);
53
54
 
55
+ function totalDelayedMessagesRead() external view returns (uint256);
56
+
57
+ function bridge() external view returns (IBridge);
58
+
59
+ /// @dev The size of the batch header
60
+ // solhint-disable-next-line func-name-mixedcase
61
+ function HEADER_LENGTH() external view returns (uint256);
62
+
63
+ /// @dev If the first batch data byte after the header has this bit set,
64
+ /// the sequencer inbox has authenticated the data. Currently not used.
65
+ // solhint-disable-next-line func-name-mixedcase
66
+ function DATA_AUTHENTICATED_FLAG() external view returns (bytes1);
67
+
68
+ function rollup() external view returns (IOwnable);
69
+
70
+ function isBatchPoster(address) external view returns (bool);
71
+
72
+ struct DasKeySetInfo {
73
+ bool isValidKeyset;
74
+ uint64 creationBlock;
75
+ }
76
+
77
+ // https://github.com/ethereum/solidity/issues/11826
78
+ // function maxTimeVariation() external view returns (MaxTimeVariation calldata);
79
+ // function dasKeySetInfo(bytes32) external view returns (DasKeySetInfo calldata);
80
+
81
+ /// @notice Remove force inclusion delay after a L1 chainId fork
82
+ function removeDelayAfterFork() external;
83
+
84
+ /// @notice Force messages from the delayed inbox to be included in the chain
85
+ /// Callable by any address, but message can only be force-included after maxTimeVariation.delayBlocks and
86
+ /// maxTimeVariation.delaySeconds has elapsed. As part of normal behaviour the sequencer will include these
87
+ /// messages so it's only necessary to call this if the sequencer is down, or not including any delayed messages.
88
+ /// @param _totalDelayedMessagesRead The total number of messages to read up to
89
+ /// @param kind The kind of the last message to be included
90
+ /// @param l1BlockAndTime The l1 block and the l1 timestamp of the last message to be included
91
+ /// @param baseFeeL1 The l1 gas price of the last message to be included
92
+ /// @param sender The sender of the last message to be included
93
+ /// @param messageDataHash The messageDataHash of the last message to be included
94
+ function forceInclusion(
95
+ uint256 _totalDelayedMessagesRead,
96
+ uint8 kind,
97
+ uint64[2] calldata l1BlockAndTime,
98
+ uint256 baseFeeL1,
99
+ address sender,
100
+ bytes32 messageDataHash
101
+ ) external;
102
+
54
103
  function inboxAccs(uint256 index) external view returns (bytes32);
55
104
 
56
105
  function batchCount() external view returns (uint256);
57
106
 
58
- function addSequencerL2Batch(
107
+ function isValidKeysetHash(bytes32 ksHash) external view returns (bool);
108
+
109
+ /// @notice the creation block is intended to still be available after a keyset is deleted
110
+ function getKeysetCreationBlock(bytes32 ksHash) external view returns (uint256);
111
+
112
+ // ---------- BatchPoster functions ----------
113
+
114
+ function addSequencerL2BatchFromOrigin(
59
115
  uint256 sequenceNumber,
60
116
  bytes calldata data,
61
117
  uint256 afterDelayedMessagesRead,
62
118
  IGasRefunder gasRefunder
63
119
  ) external;
64
120
 
65
- // Methods only callable by rollup owner
121
+ function addSequencerL2Batch(
122
+ uint256 sequenceNumber,
123
+ bytes calldata data,
124
+ uint256 afterDelayedMessagesRead,
125
+ IGasRefunder gasRefunder,
126
+ uint256 prevMessageCount,
127
+ uint256 newMessageCount
128
+ ) external;
129
+
130
+ // ---------- onlyRollupOrOwner functions ----------
66
131
 
67
132
  /**
68
- * @notice Set max time variation from actual time for sequencer inbox
69
- * @param timeVariation the maximum time variation parameters
133
+ * @notice Set max delay for sequencer inbox
134
+ * @param maxTimeVariation_ the maximum time variation parameters
70
135
  */
71
- function setMaxTimeVariation(MaxTimeVariation memory timeVariation) external;
136
+ function setMaxTimeVariation(MaxTimeVariation memory maxTimeVariation_) external;
72
137
 
73
138
  /**
74
139
  * @notice Updates whether an address is authorized to be a batch poster at the sequencer inbox
75
140
  * @param addr the address
76
- * @param isBatchPoster if the specified address should be authorized as a batch poster
141
+ * @param isBatchPoster_ if the specified address should be authorized as a batch poster
77
142
  */
78
- function setIsBatchPoster(address addr, bool isBatchPoster) external;
143
+ function setIsBatchPoster(address addr, bool isBatchPoster_) external;
79
144
 
145
+ /**
146
+ * @notice Makes Data Availability Service keyset valid
147
+ * @param keysetBytes bytes of the serialized keyset
148
+ */
80
149
  function setValidKeyset(bytes calldata keysetBytes) external;
81
150
 
151
+ /**
152
+ * @notice Invalidates a Data Availability Service keyset
153
+ * @param ksHash hash of the keyset
154
+ */
82
155
  function invalidateKeysetHash(bytes32 ksHash) external;
156
+
157
+ // ---------- initializer ----------
158
+
159
+ function initialize(IBridge bridge_, MaxTimeVariation calldata maxTimeVariation_) external;
83
160
  }
@@ -15,7 +15,10 @@ import {
15
15
  InsufficientSubmissionCost,
16
16
  NotAllowedOrigin,
17
17
  RetryableData,
18
- NotRollupOrOwner
18
+ NotRollupOrOwner,
19
+ L1Forked,
20
+ NotForked,
21
+ GasLimitTooLarge
19
22
  } from "../libraries/Error.sol";
20
23
  import "./IInbox.sol";
21
24
  import "./ISequencerInbox.sol";
@@ -33,6 +36,7 @@ import {
33
36
  L2MessageType_unsignedContractTx
34
37
  } from "../libraries/MessageTypes.sol";
35
38
  import {MAX_DATA_SIZE} from "../libraries/Constants.sol";
39
+ import "../precompiles/ArbSys.sol";
36
40
 
37
41
  import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
38
42
  import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
@@ -43,7 +47,7 @@ import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
43
47
  * to await inclusion in the SequencerInbox
44
48
  */
45
49
  contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
46
- IBridge public override bridge;
50
+ IBridge public bridge;
47
51
  ISequencerInbox public sequencerInbox;
48
52
 
49
53
  /// ------------------------------------ allow list start ------------------------------------ ///
@@ -92,12 +96,18 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
92
96
  _;
93
97
  }
94
98
 
95
- /// @notice pauses all inbox functionality
99
+ uint256 internal immutable deployTimeChainId = block.chainid;
100
+
101
+ function _chainIdChanged() internal view returns (bool) {
102
+ return deployTimeChainId != block.chainid;
103
+ }
104
+
105
+ /// @inheritdoc IInbox
96
106
  function pause() external onlyRollupOrOwner {
97
107
  _pause();
98
108
  }
99
109
 
100
- /// @notice unpauses all inbox functionality
110
+ /// @inheritdoc IInbox
101
111
  function unpause() external onlyRollupOrOwner {
102
112
  _unpause();
103
113
  }
@@ -107,37 +117,23 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
107
117
  initializer
108
118
  onlyDelegated
109
119
  {
110
- if (address(bridge) != address(0)) revert AlreadyInit();
111
120
  bridge = _bridge;
112
121
  sequencerInbox = _sequencerInbox;
113
122
  allowListEnabled = false;
114
123
  __Pausable_init();
115
124
  }
116
125
 
117
- /// @dev function to be called one time during the inbox upgrade process
118
- /// this is used to fix the storage slots
119
- function postUpgradeInit(IBridge _bridge) external onlyDelegated onlyProxyOwner {
120
- uint8 slotsToWipe = 3;
121
- for (uint8 i = 0; i < slotsToWipe; i++) {
122
- assembly {
123
- sstore(i, 0)
124
- }
125
- }
126
- allowListEnabled = false;
127
- bridge = _bridge;
128
- }
126
+ /// @inheritdoc IInbox
127
+ function postUpgradeInit(IBridge) external onlyDelegated onlyProxyOwner {}
129
128
 
130
- /**
131
- * @notice Send a generic L2 message to the chain
132
- * @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
133
- * @param messageData Data of the message being sent
134
- */
129
+ /// @inheritdoc IInbox
135
130
  function sendL2MessageFromOrigin(bytes calldata messageData)
136
131
  external
137
132
  whenNotPaused
138
133
  onlyAllowed
139
134
  returns (uint256)
140
135
  {
136
+ if (_chainIdChanged()) revert L1Forked();
141
137
  // solhint-disable-next-line avoid-tx-origin
142
138
  if (msg.sender != tx.origin) revert NotOrigin();
143
139
  if (messageData.length > MAX_DATA_SIZE)
@@ -147,18 +143,14 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
147
143
  return msgNum;
148
144
  }
149
145
 
150
- /**
151
- * @notice Send a generic L2 message to the chain
152
- * @dev This method can be used to send any type of message that doesn't require L1 validation
153
- * @param messageData Data of the message being sent
154
- */
146
+ /// @inheritdoc IInbox
155
147
  function sendL2Message(bytes calldata messageData)
156
148
  external
157
- override
158
149
  whenNotPaused
159
150
  onlyAllowed
160
151
  returns (uint256)
161
152
  {
153
+ if (_chainIdChanged()) revert L1Forked();
162
154
  return _deliverMessage(L2_MSG, msg.sender, messageData);
163
155
  }
164
156
 
@@ -168,7 +160,11 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
168
160
  uint256 nonce,
169
161
  address to,
170
162
  bytes calldata data
171
- ) external payable virtual override whenNotPaused onlyAllowed returns (uint256) {
163
+ ) external payable whenNotPaused onlyAllowed returns (uint256) {
164
+ // arbos will discard unsigned tx with gas limit too large
165
+ if (gasLimit > type(uint64).max) {
166
+ revert GasLimitTooLarge();
167
+ }
172
168
  return
173
169
  _deliverMessage(
174
170
  L1MessageType_L2FundedByL1,
@@ -190,7 +186,11 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
190
186
  uint256 maxFeePerGas,
191
187
  address to,
192
188
  bytes calldata data
193
- ) external payable virtual override whenNotPaused onlyAllowed returns (uint256) {
189
+ ) external payable whenNotPaused onlyAllowed returns (uint256) {
190
+ // arbos will discard unsigned tx with gas limit too large
191
+ if (gasLimit > type(uint64).max) {
192
+ revert GasLimitTooLarge();
193
+ }
194
194
  return
195
195
  _deliverMessage(
196
196
  L1MessageType_L2FundedByL1,
@@ -213,7 +213,11 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
213
213
  address to,
214
214
  uint256 value,
215
215
  bytes calldata data
216
- ) external virtual override whenNotPaused onlyAllowed returns (uint256) {
216
+ ) external whenNotPaused onlyAllowed returns (uint256) {
217
+ // arbos will discard unsigned tx with gas limit too large
218
+ if (gasLimit > type(uint64).max) {
219
+ revert GasLimitTooLarge();
220
+ }
217
221
  return
218
222
  _deliverMessage(
219
223
  L2_MSG,
@@ -236,7 +240,11 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
236
240
  address to,
237
241
  uint256 value,
238
242
  bytes calldata data
239
- ) external virtual override whenNotPaused onlyAllowed returns (uint256) {
243
+ ) external whenNotPaused onlyAllowed returns (uint256) {
244
+ // arbos will discard unsigned tx with gas limit too large
245
+ if (gasLimit > type(uint64).max) {
246
+ revert GasLimitTooLarge();
247
+ }
240
248
  return
241
249
  _deliverMessage(
242
250
  L2_MSG,
@@ -252,13 +260,104 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
252
260
  );
253
261
  }
254
262
 
255
- /**
256
- * @notice Get the L1 fee for submitting a retryable
257
- * @dev This fee can be paid by funds already in the L2 aliased address or by the current message value
258
- * @dev This formula may change in the future, to future proof your code query this method instead of inlining!!
259
- * @param dataLength The length of the retryable's calldata, in bytes
260
- * @param baseFee The block basefee when the retryable is included in the chain, if 0 current block.basefee will be used
261
- */
263
+ /// @inheritdoc IInbox
264
+ function sendL1FundedUnsignedTransactionToFork(
265
+ uint256 gasLimit,
266
+ uint256 maxFeePerGas,
267
+ uint256 nonce,
268
+ address to,
269
+ bytes calldata data
270
+ ) external payable whenNotPaused onlyAllowed returns (uint256) {
271
+ if (!_chainIdChanged()) revert NotForked();
272
+ // solhint-disable-next-line avoid-tx-origin
273
+ if (msg.sender != tx.origin) revert NotOrigin();
274
+ // arbos will discard unsigned tx with gas limit too large
275
+ if (gasLimit > type(uint64).max) {
276
+ revert GasLimitTooLarge();
277
+ }
278
+ return
279
+ _deliverMessage(
280
+ L1MessageType_L2FundedByL1,
281
+ // undoing sender alias here to cancel out the aliasing
282
+ AddressAliasHelper.undoL1ToL2Alias(msg.sender),
283
+ abi.encodePacked(
284
+ L2MessageType_unsignedEOATx,
285
+ gasLimit,
286
+ maxFeePerGas,
287
+ nonce,
288
+ uint256(uint160(to)),
289
+ msg.value,
290
+ data
291
+ )
292
+ );
293
+ }
294
+
295
+ /// @inheritdoc IInbox
296
+ function sendUnsignedTransactionToFork(
297
+ uint256 gasLimit,
298
+ uint256 maxFeePerGas,
299
+ uint256 nonce,
300
+ address to,
301
+ uint256 value,
302
+ bytes calldata data
303
+ ) external whenNotPaused onlyAllowed returns (uint256) {
304
+ if (!_chainIdChanged()) revert NotForked();
305
+ // solhint-disable-next-line avoid-tx-origin
306
+ if (msg.sender != tx.origin) revert NotOrigin();
307
+ // arbos will discard unsigned tx with gas limit too large
308
+ if (gasLimit > type(uint64).max) {
309
+ revert GasLimitTooLarge();
310
+ }
311
+ return
312
+ _deliverMessage(
313
+ L2_MSG,
314
+ // undoing sender alias here to cancel out the aliasing
315
+ AddressAliasHelper.undoL1ToL2Alias(msg.sender),
316
+ abi.encodePacked(
317
+ L2MessageType_unsignedEOATx,
318
+ gasLimit,
319
+ maxFeePerGas,
320
+ nonce,
321
+ uint256(uint160(to)),
322
+ value,
323
+ data
324
+ )
325
+ );
326
+ }
327
+
328
+ /// @inheritdoc IInbox
329
+ function sendWithdrawEthToFork(
330
+ uint256 gasLimit,
331
+ uint256 maxFeePerGas,
332
+ uint256 nonce,
333
+ uint256 value,
334
+ address withdrawTo
335
+ ) external whenNotPaused onlyAllowed returns (uint256) {
336
+ if (!_chainIdChanged()) revert NotForked();
337
+ // solhint-disable-next-line avoid-tx-origin
338
+ if (msg.sender != tx.origin) revert NotOrigin();
339
+ // arbos will discard unsigned tx with gas limit too large
340
+ if (gasLimit > type(uint64).max) {
341
+ revert GasLimitTooLarge();
342
+ }
343
+ return
344
+ _deliverMessage(
345
+ L2_MSG,
346
+ // undoing sender alias here to cancel out the aliasing
347
+ AddressAliasHelper.undoL1ToL2Alias(msg.sender),
348
+ abi.encodePacked(
349
+ L2MessageType_unsignedEOATx,
350
+ gasLimit,
351
+ maxFeePerGas,
352
+ nonce,
353
+ uint256(uint160(address(100))), // ArbSys address
354
+ value,
355
+ abi.encode(ArbSys.withdrawEth.selector, withdrawTo)
356
+ )
357
+ );
358
+ }
359
+
360
+ /// @inheritdoc IInbox
262
361
  function calculateRetryableSubmissionFee(uint256 dataLength, uint256 baseFee)
263
362
  public
264
363
  view
@@ -268,20 +367,13 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
268
367
  return (1400 + 6 * dataLength) * (baseFee == 0 ? block.basefee : baseFee);
269
368
  }
270
369
 
271
- /// @notice deposit eth from L1 to L2
272
- /// @dev this does not trigger the fallback function when receiving in the L2 side.
273
- /// Look into retryable tickets if you are interested in this functionality.
274
- /// @dev this function should not be called inside contract constructors
275
- function depositEth() public payable override whenNotPaused onlyAllowed returns (uint256) {
370
+ /// @inheritdoc IInbox
371
+ function depositEth() public payable whenNotPaused onlyAllowed returns (uint256) {
276
372
  address dest = msg.sender;
277
373
 
278
374
  // solhint-disable-next-line avoid-tx-origin
279
375
  if (AddressUpgradeable.isContract(msg.sender) || tx.origin != msg.sender) {
280
376
  // isContract check fails if this function is called during a contract's constructor.
281
- // We don't adjust the address for calls coming from L1 contracts since their addresses get remapped
282
- // If the caller is an EOA, we adjust the address.
283
- // This is needed because unsigned messages to the L2 (such as retryables)
284
- // have the L1 sender address mapped.
285
377
  dest = AddressAliasHelper.applyL1ToL2Alias(msg.sender);
286
378
  }
287
379
 
@@ -294,15 +386,7 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
294
386
  }
295
387
 
296
388
  /// @notice deprecated in favour of depositEth with no parameters
297
- function depositEth(uint256)
298
- external
299
- payable
300
- virtual
301
- override
302
- whenNotPaused
303
- onlyAllowed
304
- returns (uint256)
305
- {
389
+ function depositEth(uint256) external payable whenNotPaused onlyAllowed returns (uint256) {
306
390
  return depositEth();
307
391
  }
308
392
 
@@ -318,7 +402,7 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
318
402
  * @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)
319
403
  * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
320
404
  * @param data ABI encoded data of L2 message
321
- * @return unique id for retryable transaction (keccak256(requestID, uint(0) )
405
+ * @return unique message number of the retryable transaction
322
406
  */
323
407
  function createRetryableTicketNoRefundAliasRewrite(
324
408
  address to,
@@ -329,7 +413,8 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
329
413
  uint256 gasLimit,
330
414
  uint256 maxFeePerGas,
331
415
  bytes calldata data
332
- ) external payable virtual whenNotPaused onlyAllowed returns (uint256) {
416
+ ) external payable whenNotPaused onlyAllowed returns (uint256) {
417
+ // gas limit is validated to be within uint64 in unsafeCreateRetryableTicket
333
418
  return
334
419
  unsafeCreateRetryableTicket(
335
420
  to,
@@ -343,20 +428,7 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
343
428
  );
344
429
  }
345
430
 
346
- /**
347
- * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts
348
- * @dev all msg.value will deposited to callValueRefundAddress on L2
349
- * @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error
350
- * @param to destination L2 contract address
351
- * @param l2CallValue call value for retryable L2 message
352
- * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
353
- * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance
354
- * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled
355
- * @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)
356
- * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
357
- * @param data ABI encoded data of L2 message
358
- * @return unique id for retryable transaction (keccak256(requestID, uint(0) )
359
- */
431
+ /// @inheritdoc IInbox
360
432
  function createRetryableTicket(
361
433
  address to,
362
434
  uint256 l2CallValue,
@@ -366,7 +438,7 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
366
438
  uint256 gasLimit,
367
439
  uint256 maxFeePerGas,
368
440
  bytes calldata data
369
- ) external payable virtual override whenNotPaused onlyAllowed returns (uint256) {
441
+ ) external payable whenNotPaused onlyAllowed returns (uint256) {
370
442
  // ensure the user's deposit alone will make submission succeed
371
443
  if (msg.value < (maxSubmissionCost + l2CallValue + gasLimit * maxFeePerGas)) {
372
444
  revert InsufficientValue(
@@ -386,6 +458,7 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
386
458
  callValueRefundAddress = AddressAliasHelper.applyL1ToL2Alias(callValueRefundAddress);
387
459
  }
388
460
 
461
+ // gas limit is validated to be within uint64 in unsafeCreateRetryableTicket
389
462
  return
390
463
  unsafeCreateRetryableTicket(
391
464
  to,
@@ -399,23 +472,7 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
399
472
  );
400
473
  }
401
474
 
402
- /**
403
- * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts
404
- * @dev Same as createRetryableTicket, but does not guarantee that submission will succeed by requiring the needed funds
405
- * come from the deposit alone, rather than falling back on the user's L2 balance
406
- * @dev Advanced usage only (does not rewrite aliases for excessFeeRefundAddress and callValueRefundAddress).
407
- * createRetryableTicket method is the recommended standard.
408
- * @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error
409
- * @param to destination L2 contract address
410
- * @param l2CallValue call value for retryable L2 message
411
- * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
412
- * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance
413
- * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled
414
- * @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)
415
- * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
416
- * @param data ABI encoded data of L2 message
417
- * @return unique id for retryable transaction (keccak256(requestID, uint(0) )
418
- */
475
+ /// @inheritdoc IInbox
419
476
  function unsafeCreateRetryableTicket(
420
477
  address to,
421
478
  uint256 l2CallValue,
@@ -425,7 +482,7 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
425
482
  uint256 gasLimit,
426
483
  uint256 maxFeePerGas,
427
484
  bytes calldata data
428
- ) public payable virtual override whenNotPaused onlyAllowed returns (uint256) {
485
+ ) public payable whenNotPaused onlyAllowed returns (uint256) {
429
486
  // gas price and limit of 1 should never be a valid input, so instead they are used as
430
487
  // magic values to trigger a revert in eth calls that surface data without requiring a tx trace
431
488
  if (gasLimit == 1 || maxFeePerGas == 1)
@@ -442,6 +499,11 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
442
499
  data
443
500
  );
444
501
 
502
+ // arbos will discard retryable with gas limit too large
503
+ if (gasLimit > type(uint64).max) {
504
+ revert GasLimitTooLarge();
505
+ }
506
+
445
507
  uint256 submissionFee = calculateRetryableSubmissionFee(data.length, block.basefee);
446
508
  if (maxSubmissionCost < submissionFee)
447
509
  revert InsufficientSubmissionCost(submissionFee, maxSubmissionCost);