@arbitrum/nitro-contracts 1.0.0-beta.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ }