@arbitrum/nitro-contracts 1.0.0-beta.1

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 (113) hide show
  1. package/.prettierrc +5 -0
  2. package/.solhint.json +18 -0
  3. package/deploy/BridgeStubCreator.js +10 -0
  4. package/deploy/HashProofHelper.js +13 -0
  5. package/deploy/InboxStubCreator.js +17 -0
  6. package/deploy/OneStepProofEntryCreator.js +19 -0
  7. package/deploy/OneStepProver0Creator.js +14 -0
  8. package/deploy/OneStepProverHostIoCreator.js +14 -0
  9. package/deploy/OneStepProverMathCreator.js +14 -0
  10. package/deploy/OneStepProverMemoryCreator.js +14 -0
  11. package/deploy/SequencerInboxStubCreator.js +13 -0
  12. package/deploy/ValueArrayTesterCreator.js +13 -0
  13. package/hardhat.config.ts +47 -0
  14. package/hardhat.prod-config.js +18 -0
  15. package/package.json +49 -0
  16. package/scripts/build.bash +5 -0
  17. package/src/bridge/Bridge.sol +168 -0
  18. package/src/bridge/IBridge.sol +68 -0
  19. package/src/bridge/IInbox.sol +80 -0
  20. package/src/bridge/IMessageProvider.sol +11 -0
  21. package/src/bridge/IOutbox.sol +52 -0
  22. package/src/bridge/ISequencerInbox.sol +85 -0
  23. package/src/bridge/Inbox.sol +414 -0
  24. package/src/bridge/Messages.sol +38 -0
  25. package/src/bridge/Outbox.sol +188 -0
  26. package/src/bridge/SequencerInbox.sol +274 -0
  27. package/src/challenge/ChallengeLib.sol +135 -0
  28. package/src/challenge/ChallengeManager.sol +367 -0
  29. package/src/challenge/IChallengeManager.sol +75 -0
  30. package/src/challenge/IChallengeResultReceiver.sol +13 -0
  31. package/src/libraries/AddressAliasHelper.sol +29 -0
  32. package/src/libraries/AdminFallbackProxy.sol +153 -0
  33. package/src/libraries/ArbitrumProxy.sol +20 -0
  34. package/src/libraries/Constants.sol +10 -0
  35. package/src/libraries/CryptographyPrimitives.sol +323 -0
  36. package/src/libraries/DelegateCallAware.sol +44 -0
  37. package/src/libraries/Error.sol +38 -0
  38. package/src/libraries/IGasRefunder.sol +35 -0
  39. package/src/libraries/MerkleLib.sol +46 -0
  40. package/src/libraries/MessageTypes.sol +14 -0
  41. package/src/libraries/SecondaryLogicUUPSUpgradeable.sol +58 -0
  42. package/src/libraries/UUPSNotUpgradeable.sol +56 -0
  43. package/src/mocks/BridgeStub.sol +115 -0
  44. package/src/mocks/Counter.sol +13 -0
  45. package/src/mocks/ExecutionManager.sol +41 -0
  46. package/src/mocks/InboxStub.sol +131 -0
  47. package/src/mocks/MockResultReceiver.sol +59 -0
  48. package/src/mocks/SequencerInboxStub.sol +42 -0
  49. package/src/mocks/SimpleProxy.sol +19 -0
  50. package/src/node-interface/NodeInterface.sol +50 -0
  51. package/src/osp/HashProofHelper.sol +154 -0
  52. package/src/osp/IOneStepProofEntry.sol +20 -0
  53. package/src/osp/IOneStepProver.sol +27 -0
  54. package/src/osp/OneStepProofEntry.sol +129 -0
  55. package/src/osp/OneStepProver0.sol +566 -0
  56. package/src/osp/OneStepProverHostIo.sol +357 -0
  57. package/src/osp/OneStepProverMath.sol +514 -0
  58. package/src/osp/OneStepProverMemory.sol +313 -0
  59. package/src/precompiles/ArbAddressTable.sol +60 -0
  60. package/src/precompiles/ArbAggregator.sol +62 -0
  61. package/src/precompiles/ArbBLS.sol +53 -0
  62. package/src/precompiles/ArbDebug.sol +39 -0
  63. package/src/precompiles/ArbFunctionTable.sol +29 -0
  64. package/src/precompiles/ArbGasInfo.sol +121 -0
  65. package/src/precompiles/ArbInfo.sol +15 -0
  66. package/src/precompiles/ArbOwner.sol +65 -0
  67. package/src/precompiles/ArbOwnerPublic.sol +18 -0
  68. package/src/precompiles/ArbRetryableTx.sol +89 -0
  69. package/src/precompiles/ArbStatistics.sol +29 -0
  70. package/src/precompiles/ArbSys.sol +134 -0
  71. package/src/precompiles/ArbosActs.sol +41 -0
  72. package/src/precompiles/ArbosTest.sol +14 -0
  73. package/src/rollup/BridgeCreator.sol +120 -0
  74. package/src/rollup/IRollupCore.sol +152 -0
  75. package/src/rollup/IRollupLogic.sol +183 -0
  76. package/src/rollup/Node.sol +99 -0
  77. package/src/rollup/RollupAdminLogic.sol +322 -0
  78. package/src/rollup/RollupCore.sol +627 -0
  79. package/src/rollup/RollupCreator.sol +133 -0
  80. package/src/rollup/RollupEventBridge.sol +46 -0
  81. package/src/rollup/RollupLib.sol +135 -0
  82. package/src/rollup/RollupUserLogic.sol +712 -0
  83. package/src/rollup/ValidatorUtils.sol +243 -0
  84. package/src/rollup/ValidatorWallet.sol +76 -0
  85. package/src/rollup/ValidatorWalletCreator.sol +43 -0
  86. package/src/state/Deserialize.sol +321 -0
  87. package/src/state/GlobalState.sol +44 -0
  88. package/src/state/Instructions.sol +159 -0
  89. package/src/state/Machine.sol +65 -0
  90. package/src/state/MerkleProof.sol +99 -0
  91. package/src/state/Module.sol +33 -0
  92. package/src/state/ModuleMemory.sol +42 -0
  93. package/src/state/PcArray.sol +45 -0
  94. package/src/state/PcStack.sol +32 -0
  95. package/src/state/StackFrame.sol +63 -0
  96. package/src/state/Value.sol +65 -0
  97. package/src/state/ValueArray.sol +47 -0
  98. package/src/state/ValueStack.sol +39 -0
  99. package/src/test-helpers/CryptographyPrimitivesTester.sol +27 -0
  100. package/src/test-helpers/MessageTester.sol +34 -0
  101. package/src/test-helpers/ValueArrayTester.sol +34 -0
  102. package/test/contract/arbRollup.spec.ts +869 -0
  103. package/test/contract/common/challengeLib.ts +43 -0
  104. package/test/contract/common/globalStateLib.ts +17 -0
  105. package/test/contract/common/rolluplib.ts +259 -0
  106. package/test/contract/cryptographyPrimitives.spec.ts +82 -0
  107. package/test/contract/sequencerInboxForceInclude.spec.ts +516 -0
  108. package/test/contract/utils.ts +40 -0
  109. package/test/prover/hash-proofs.ts +75 -0
  110. package/test/prover/one-step-proof.ts +93 -0
  111. package/test/prover/proofs/.gitkeep +0 -0
  112. package/test/prover/value-arrays.ts +11 -0
  113. package/tsconfig.json +13 -0
@@ -0,0 +1,52 @@
1
+ // Copyright 2021-2022, Offchain Labs, Inc.
2
+ // For license information, see https://github.com/nitro/blob/master/LICENSE
3
+ // SPDX-License-Identifier: BUSL-1.1
4
+
5
+ pragma solidity ^0.8.4;
6
+
7
+ import {AlreadyInit, NotRollup} from "../libraries/Error.sol";
8
+
9
+ /// @dev The provided proof was too long
10
+ /// @param proofLength The length of the too-long proof
11
+ error ProofTooLong(uint256 proofLength);
12
+
13
+ /// @dev The output index was greater than the maximum
14
+ /// @param index The output index
15
+ /// @param maxIndex The max the index could be
16
+ error PathNotMinimal(uint256 index, uint256 maxIndex);
17
+
18
+ /// @dev The calculated root does not exist
19
+ /// @param root The calculated root
20
+ error UnknownRoot(bytes32 root);
21
+
22
+ /// @dev The record has already been spent
23
+ /// @param index The index of the spent record
24
+ error AlreadySpent(uint256 index);
25
+
26
+ /// @dev A call to the bridge failed with no return data
27
+ error BridgeCallFailed();
28
+
29
+ interface IOutbox {
30
+ event SendRootUpdated(bytes32 indexed blockHash, bytes32 indexed outputRoot);
31
+ event OutBoxTransactionExecuted(
32
+ address indexed to,
33
+ address indexed l2Sender,
34
+ uint256 indexed zero,
35
+ uint256 transactionIndex
36
+ );
37
+
38
+ function l2ToL1Sender() external view returns (address);
39
+
40
+ function l2ToL1Block() external view returns (uint256);
41
+
42
+ function l2ToL1EthBlock() external view returns (uint256);
43
+
44
+ function l2ToL1Timestamp() external view returns (uint256);
45
+
46
+ // @deprecated batch number is now always 0
47
+ function l2ToL1BatchNum() external view returns (uint256);
48
+
49
+ function l2ToL1OutputId() external view returns (bytes32);
50
+
51
+ function updateSendRoot(bytes32 sendRoot, bytes32 l2BlockHash) external;
52
+ }
@@ -0,0 +1,85 @@
1
+ // Copyright 2021-2022, Offchain Labs, Inc.
2
+ // For license information, see https://github.com/nitro/blob/master/LICENSE
3
+ // SPDX-License-Identifier: BUSL-1.1
4
+
5
+ pragma solidity ^0.8.0;
6
+
7
+ import "../libraries/IGasRefunder.sol";
8
+ import {AlreadyInit, HadZeroInit, NotOrigin, DataTooLarge, NotRollup} from "../libraries/Error.sol";
9
+
10
+ interface ISequencerInbox {
11
+ struct MaxTimeVariation {
12
+ uint256 delayBlocks;
13
+ uint256 futureBlocks;
14
+ uint256 delaySeconds;
15
+ uint256 futureSeconds;
16
+ }
17
+
18
+ struct TimeBounds {
19
+ uint64 minTimestamp;
20
+ uint64 maxTimestamp;
21
+ uint64 minBlockNumber;
22
+ uint64 maxBlockNumber;
23
+ }
24
+
25
+ enum BatchDataLocation {
26
+ TxInput,
27
+ SeparateBatchEvent,
28
+ NoData
29
+ }
30
+
31
+ event SequencerBatchDelivered(
32
+ uint256 indexed batchSequenceNumber,
33
+ bytes32 indexed beforeAcc,
34
+ bytes32 indexed afterAcc,
35
+ bytes32 delayedAcc,
36
+ uint256 afterDelayedMessagesRead,
37
+ TimeBounds timeBounds,
38
+ BatchDataLocation dataLocation
39
+ );
40
+
41
+ /// @dev a separate event that emits batch data when this isn't easily accessible in the tx.input
42
+ event SequencerBatchData(uint256 indexed batchSequenceNumber, bytes data);
43
+
44
+ /// @dev Thrown when someone attempts to read fewer messages than have already been read
45
+ error DelayedBackwards();
46
+
47
+ /// @dev Thrown when someone attempts to read more messages than exist
48
+ error DelayedTooFar();
49
+
50
+ /// @dev Thrown if the length of the header plus the length of the batch overflows
51
+ error DataLengthOverflow();
52
+
53
+ /// @dev Force include can only read messages more blocks old than the delay period
54
+ error ForceIncludeBlockTooSoon();
55
+
56
+ /// @dev Force include can only read messages more seconds old than the delay period
57
+ error ForceIncludeTimeTooSoon();
58
+
59
+ /// @dev The message provided did not match the hash in the delayed inbox
60
+ error IncorrectMessagePreimage();
61
+
62
+ /// @dev This can only be called by the batch poster
63
+ error NotBatchPoster();
64
+
65
+ /// @dev The sequence number provided to this message was inconsistent with the number of batches already included
66
+ error BadSequencerNumber();
67
+
68
+ /// @dev The batch data has the inbox authenticated bit set, but the batch data was not authenticated by the inbox
69
+ error DataNotAuthenticated();
70
+
71
+ function inboxAccs(uint256 index) external view returns (bytes32);
72
+
73
+ function batchCount() external view returns (uint256);
74
+
75
+ function setMaxTimeVariation(MaxTimeVariation memory timeVariation) external;
76
+
77
+ function setIsBatchPoster(address addr, bool isBatchPoster_) external;
78
+
79
+ function addSequencerL2Batch(
80
+ uint256 sequenceNumber,
81
+ bytes calldata data,
82
+ uint256 afterDelayedMessagesRead,
83
+ IGasRefunder gasRefunder
84
+ ) external;
85
+ }
@@ -0,0 +1,414 @@
1
+ // Copyright 2021-2022, Offchain Labs, Inc.
2
+ // For license information, see https://github.com/nitro/blob/master/LICENSE
3
+ // SPDX-License-Identifier: BUSL-1.1
4
+
5
+ pragma solidity ^0.8.4;
6
+
7
+ import "./IInbox.sol";
8
+ import "./IBridge.sol";
9
+
10
+ import "./Messages.sol";
11
+ import "../libraries/AddressAliasHelper.sol";
12
+ import "../libraries/DelegateCallAware.sol";
13
+ import {
14
+ L2_MSG,
15
+ L1MessageType_L2FundedByL1,
16
+ L1MessageType_submitRetryableTx,
17
+ L2MessageType_unsignedEOATx,
18
+ L2MessageType_unsignedContractTx
19
+ } from "../libraries/MessageTypes.sol";
20
+ import {MAX_DATA_SIZE} from "../libraries/Constants.sol";
21
+
22
+ import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
23
+ import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
24
+ import "./Bridge.sol";
25
+
26
+ /**
27
+ * @title Inbox for user and contract originated messages
28
+ * @notice Messages created via this inbox are enqueued in the delayed accumulator
29
+ * to await inclusion in the SequencerInbox
30
+ */
31
+ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
32
+ IBridge public override bridge;
33
+
34
+ modifier onlyOwner() {
35
+ // whoevever owns the Bridge, also owns the Inbox. this is usually the rollup contract
36
+ address bridgeOwner = Bridge(address(bridge)).owner();
37
+ if (msg.sender != bridgeOwner) revert NotOwner(msg.sender, bridgeOwner);
38
+ _;
39
+ }
40
+
41
+ /// @notice pauses all inbox functionality
42
+ function pause() external onlyOwner {
43
+ _pause();
44
+ }
45
+
46
+ /// @notice unpauses all inbox functionality
47
+ function unpause() external onlyOwner {
48
+ _unpause();
49
+ }
50
+
51
+ function initialize(IBridge _bridge) external initializer onlyDelegated {
52
+ if (address(bridge) != address(0)) revert AlreadyInit();
53
+ bridge = _bridge;
54
+ __Pausable_init();
55
+ }
56
+
57
+ /// @dev function to be called one time during the inbox upgrade process
58
+ /// this is used to fix the storage slots
59
+ function postUpgradeInit(IBridge _bridge) external onlyDelegated onlyProxyOwner {
60
+ uint8 slotsToWipe = 3;
61
+ for (uint8 i = 0; i < slotsToWipe; i++) {
62
+ assembly {
63
+ sstore(i, 0)
64
+ }
65
+ }
66
+ bridge = _bridge;
67
+ }
68
+
69
+ /**
70
+ * @notice Send a generic L2 message to the chain
71
+ * @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
72
+ * @param messageData Data of the message being sent
73
+ */
74
+ function sendL2MessageFromOrigin(bytes calldata messageData)
75
+ external
76
+ whenNotPaused
77
+ returns (uint256)
78
+ {
79
+ // solhint-disable-next-line avoid-tx-origin
80
+ if (msg.sender != tx.origin) revert NotOrigin();
81
+ if (messageData.length > MAX_DATA_SIZE)
82
+ revert DataTooLarge(messageData.length, MAX_DATA_SIZE);
83
+ uint256 msgNum = deliverToBridge(L2_MSG, msg.sender, keccak256(messageData));
84
+ emit InboxMessageDeliveredFromOrigin(msgNum);
85
+ return msgNum;
86
+ }
87
+
88
+ /**
89
+ * @notice Send a generic L2 message to the chain
90
+ * @dev This method can be used to send any type of message that doesn't require L1 validation
91
+ * @param messageData Data of the message being sent
92
+ */
93
+ function sendL2Message(bytes calldata messageData)
94
+ external
95
+ override
96
+ whenNotPaused
97
+ returns (uint256)
98
+ {
99
+ if (messageData.length > MAX_DATA_SIZE)
100
+ revert DataTooLarge(messageData.length, MAX_DATA_SIZE);
101
+ uint256 msgNum = deliverToBridge(L2_MSG, msg.sender, keccak256(messageData));
102
+ emit InboxMessageDelivered(msgNum, messageData);
103
+ return msgNum;
104
+ }
105
+
106
+ function sendL1FundedUnsignedTransaction(
107
+ uint256 gasLimit,
108
+ uint256 maxFeePerGas,
109
+ uint256 nonce,
110
+ address to,
111
+ bytes calldata data
112
+ ) external payable virtual override whenNotPaused returns (uint256) {
113
+ return
114
+ _deliverMessage(
115
+ L1MessageType_L2FundedByL1,
116
+ msg.sender,
117
+ abi.encodePacked(
118
+ L2MessageType_unsignedEOATx,
119
+ gasLimit,
120
+ maxFeePerGas,
121
+ nonce,
122
+ uint256(uint160(to)),
123
+ msg.value,
124
+ data
125
+ )
126
+ );
127
+ }
128
+
129
+ function sendL1FundedContractTransaction(
130
+ uint256 gasLimit,
131
+ uint256 maxFeePerGas,
132
+ address to,
133
+ bytes calldata data
134
+ ) external payable virtual override whenNotPaused returns (uint256) {
135
+ return
136
+ _deliverMessage(
137
+ L1MessageType_L2FundedByL1,
138
+ msg.sender,
139
+ abi.encodePacked(
140
+ L2MessageType_unsignedContractTx,
141
+ gasLimit,
142
+ maxFeePerGas,
143
+ uint256(uint160(to)),
144
+ msg.value,
145
+ data
146
+ )
147
+ );
148
+ }
149
+
150
+ function sendUnsignedTransaction(
151
+ uint256 gasLimit,
152
+ uint256 maxFeePerGas,
153
+ uint256 nonce,
154
+ address to,
155
+ uint256 value,
156
+ bytes calldata data
157
+ ) external virtual override whenNotPaused returns (uint256) {
158
+ return
159
+ _deliverMessage(
160
+ L2_MSG,
161
+ msg.sender,
162
+ abi.encodePacked(
163
+ L2MessageType_unsignedEOATx,
164
+ gasLimit,
165
+ maxFeePerGas,
166
+ nonce,
167
+ uint256(uint160(to)),
168
+ value,
169
+ data
170
+ )
171
+ );
172
+ }
173
+
174
+ function sendContractTransaction(
175
+ uint256 gasLimit,
176
+ uint256 maxFeePerGas,
177
+ address to,
178
+ uint256 value,
179
+ bytes calldata data
180
+ ) external virtual override whenNotPaused returns (uint256) {
181
+ return
182
+ _deliverMessage(
183
+ L2_MSG,
184
+ msg.sender,
185
+ abi.encodePacked(
186
+ L2MessageType_unsignedContractTx,
187
+ gasLimit,
188
+ maxFeePerGas,
189
+ uint256(uint160(to)),
190
+ value,
191
+ data
192
+ )
193
+ );
194
+ }
195
+
196
+ /**
197
+ * @notice Get the L1 fee for submitting a retryable
198
+ * @dev This fee can be paid by funds already in the L2 aliased address or by the current message value
199
+ * @dev This formula may change in the future, to future proof your code query this method instead of inlining!!
200
+ * @param dataLength The length of the retryable's calldata, in bytes
201
+ * @param baseFee The block basefee when the retryable is included in the chain
202
+ */
203
+ function calculateRetryableSubmissionFee(uint256 dataLength, uint256 baseFee)
204
+ public
205
+ pure
206
+ returns (uint256)
207
+ {
208
+ return (1400 + 6 * dataLength) * baseFee;
209
+ }
210
+
211
+ /// @notice deposit eth from L1 to L2
212
+ /// @dev this function should not be called inside contract constructors
213
+ function depositEth(uint256 maxSubmissionCost)
214
+ external
215
+ payable
216
+ virtual
217
+ override
218
+ whenNotPaused
219
+ returns (uint256)
220
+ {
221
+ address sender = msg.sender;
222
+ address destinationAddress = msg.sender;
223
+
224
+ uint256 submissionFee = calculateRetryableSubmissionFee(0, block.basefee);
225
+ require(maxSubmissionCost >= submissionFee, "insufficient submission fee");
226
+
227
+ // solhint-disable-next-line avoid-tx-origin
228
+ if (!AddressUpgradeable.isContract(sender) && tx.origin == msg.sender) {
229
+ // isContract check fails if this function is called during a contract's constructor.
230
+ // We don't adjust the address for calls coming from L1 contracts since their addresses get remapped
231
+ // If the caller is an EOA, we adjust the address.
232
+ // This is needed because unsigned messages to the L2 (such as retryables)
233
+ // have the L1 sender address mapped.
234
+ // Here we preemptively reverse the mapping for EOAs so deposits work as expected
235
+ sender = AddressAliasHelper.undoL1ToL2Alias(sender);
236
+ } else {
237
+ destinationAddress = AddressAliasHelper.applyL1ToL2Alias(destinationAddress);
238
+ }
239
+
240
+ return
241
+ _deliverMessage(
242
+ L1MessageType_submitRetryableTx,
243
+ sender,
244
+ abi.encodePacked(
245
+ // the beneficiary and other refund addresses don't get rewritten by arb-os
246
+ // so we use the original msg.sender value
247
+ uint256(uint160(bytes20(destinationAddress))),
248
+ uint256(0),
249
+ msg.value,
250
+ maxSubmissionCost,
251
+ uint256(uint160(bytes20(destinationAddress))),
252
+ uint256(uint160(bytes20(destinationAddress))),
253
+ uint256(0),
254
+ uint256(0),
255
+ uint256(0),
256
+ ""
257
+ )
258
+ );
259
+ }
260
+
261
+ /**
262
+ * @notice deprecated in favour of unsafeCreateRetryableTicket
263
+ * @dev deprecated in favour of unsafeCreateRetryableTicket
264
+ * @param to destination L2 contract address
265
+ * @param l2CallValue call value for retryable L2 message
266
+ * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
267
+ * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance
268
+ * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled
269
+ * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution
270
+ * @param maxFeePerGas price bid for L2 execution
271
+ * @param data ABI encoded data of L2 message
272
+ * @return unique id for retryable transaction (keccak256(requestID, uint(0) )
273
+ */
274
+ function createRetryableTicketNoRefundAliasRewrite(
275
+ address to,
276
+ uint256 l2CallValue,
277
+ uint256 maxSubmissionCost,
278
+ address excessFeeRefundAddress,
279
+ address callValueRefundAddress,
280
+ uint256 gasLimit,
281
+ uint256 maxFeePerGas,
282
+ bytes calldata data
283
+ ) external payable virtual whenNotPaused returns (uint256) {
284
+ return
285
+ unsafeCreateRetryableTicket(
286
+ to,
287
+ l2CallValue,
288
+ maxSubmissionCost,
289
+ excessFeeRefundAddress,
290
+ callValueRefundAddress,
291
+ gasLimit,
292
+ maxFeePerGas,
293
+ data
294
+ );
295
+ }
296
+
297
+ /**
298
+ * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts
299
+ * @dev all msg.value will deposited to callValueRefundAddress on L2
300
+ * @param to destination L2 contract address
301
+ * @param l2CallValue call value for retryable L2 message
302
+ * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
303
+ * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance
304
+ * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled
305
+ * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution
306
+ * @param maxFeePerGas price bid for L2 execution
307
+ * @param data ABI encoded data of L2 message
308
+ * @return unique id for retryable transaction (keccak256(requestID, uint(0) )
309
+ */
310
+ function createRetryableTicket(
311
+ address to,
312
+ uint256 l2CallValue,
313
+ uint256 maxSubmissionCost,
314
+ address excessFeeRefundAddress,
315
+ address callValueRefundAddress,
316
+ uint256 gasLimit,
317
+ uint256 maxFeePerGas,
318
+ bytes calldata data
319
+ ) external payable virtual override whenNotPaused returns (uint256) {
320
+ // ensure the user's deposit alone will make submission succeed
321
+ require(msg.value >= maxSubmissionCost + l2CallValue, "insufficient value");
322
+
323
+ // if a refund address is a contract, we apply the alias to it
324
+ // so that it can access its funds on the L2
325
+ // since the beneficiary and other refund addresses don't get rewritten by arb-os
326
+ if (AddressUpgradeable.isContract(excessFeeRefundAddress)) {
327
+ excessFeeRefundAddress = AddressAliasHelper.applyL1ToL2Alias(excessFeeRefundAddress);
328
+ }
329
+ if (AddressUpgradeable.isContract(callValueRefundAddress)) {
330
+ // this is the beneficiary. be careful since this is the address that can cancel the retryable in the L2
331
+ callValueRefundAddress = AddressAliasHelper.applyL1ToL2Alias(callValueRefundAddress);
332
+ }
333
+
334
+ return
335
+ unsafeCreateRetryableTicket(
336
+ to,
337
+ l2CallValue,
338
+ maxSubmissionCost,
339
+ excessFeeRefundAddress,
340
+ callValueRefundAddress,
341
+ gasLimit,
342
+ maxFeePerGas,
343
+ data
344
+ );
345
+ }
346
+
347
+ /**
348
+ * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts
349
+ * @dev Same as createRetryableTicket, but does not guarantee that submission will succeed by requiring the needed funds
350
+ * come from the deposit alone, rather than falling back on the user's L2 balance
351
+ * @dev Advanced usage only (does not rewrite aliases for excessFeeRefundAddress and callValueRefundAddress).
352
+ * createRetryableTicket method is the recommended standard.
353
+ * @param to destination L2 contract address
354
+ * @param l2CallValue call value for retryable L2 message
355
+ * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
356
+ * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance
357
+ * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled
358
+ * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution
359
+ * @param maxFeePerGas price bid for L2 execution
360
+ * @param data ABI encoded data of L2 message
361
+ * @return unique id for retryable transaction (keccak256(requestID, uint(0) )
362
+ */
363
+ function unsafeCreateRetryableTicket(
364
+ address to,
365
+ uint256 l2CallValue,
366
+ uint256 maxSubmissionCost,
367
+ address excessFeeRefundAddress,
368
+ address callValueRefundAddress,
369
+ uint256 gasLimit,
370
+ uint256 maxFeePerGas,
371
+ bytes calldata data
372
+ ) public payable virtual override whenNotPaused returns (uint256) {
373
+ uint256 submissionFee = calculateRetryableSubmissionFee(data.length, block.basefee);
374
+ require(maxSubmissionCost >= submissionFee, "insufficient submission fee");
375
+
376
+ return
377
+ _deliverMessage(
378
+ L1MessageType_submitRetryableTx,
379
+ msg.sender,
380
+ abi.encodePacked(
381
+ uint256(uint160(to)),
382
+ l2CallValue,
383
+ msg.value,
384
+ maxSubmissionCost,
385
+ uint256(uint160(excessFeeRefundAddress)),
386
+ uint256(uint160(callValueRefundAddress)),
387
+ gasLimit,
388
+ maxFeePerGas,
389
+ data.length,
390
+ data
391
+ )
392
+ );
393
+ }
394
+
395
+ function _deliverMessage(
396
+ uint8 _kind,
397
+ address _sender,
398
+ bytes memory _messageData
399
+ ) internal returns (uint256) {
400
+ if (_messageData.length > MAX_DATA_SIZE)
401
+ revert DataTooLarge(_messageData.length, MAX_DATA_SIZE);
402
+ uint256 msgNum = deliverToBridge(_kind, _sender, keccak256(_messageData));
403
+ emit InboxMessageDelivered(msgNum, _messageData);
404
+ return msgNum;
405
+ }
406
+
407
+ function deliverToBridge(
408
+ uint8 kind,
409
+ address sender,
410
+ bytes32 messageDataHash
411
+ ) internal returns (uint256) {
412
+ return bridge.enqueueDelayedMessage{value: msg.value}(kind, sender, messageDataHash);
413
+ }
414
+ }
@@ -0,0 +1,38 @@
1
+ // Copyright 2021-2022, Offchain Labs, Inc.
2
+ // For license information, see https://github.com/nitro/blob/master/LICENSE
3
+ // SPDX-License-Identifier: BUSL-1.1
4
+
5
+ pragma solidity ^0.8.0;
6
+
7
+ library Messages {
8
+ function messageHash(
9
+ uint8 kind,
10
+ address sender,
11
+ uint64 blockNumber,
12
+ uint64 timestamp,
13
+ uint256 inboxSeqNum,
14
+ uint256 baseFeeL1,
15
+ bytes32 messageDataHash
16
+ ) internal pure returns (bytes32) {
17
+ return
18
+ keccak256(
19
+ abi.encodePacked(
20
+ kind,
21
+ sender,
22
+ blockNumber,
23
+ timestamp,
24
+ inboxSeqNum,
25
+ baseFeeL1,
26
+ messageDataHash
27
+ )
28
+ );
29
+ }
30
+
31
+ function accumulateInboxMessage(bytes32 prevAcc, bytes32 message)
32
+ internal
33
+ pure
34
+ returns (bytes32)
35
+ {
36
+ return keccak256(abi.encodePacked(prevAcc, message));
37
+ }
38
+ }