@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,188 @@
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 "./IBridge.sol";
8
+ import "./IOutbox.sol";
9
+ import "../libraries/MerkleLib.sol";
10
+ import "../libraries/DelegateCallAware.sol";
11
+
12
+ contract Outbox is DelegateCallAware, IOutbox {
13
+ address public rollup; // the rollup contract
14
+ IBridge public bridge; // the bridge contract
15
+
16
+ mapping(uint256 => bool) public spent; // maps leaf number => if spent
17
+ mapping(bytes32 => bytes32) public roots; // maps root hashes => L2 block hash
18
+
19
+ struct L2ToL1Context {
20
+ uint128 l2Block;
21
+ uint128 l1Block;
22
+ uint128 timestamp;
23
+ bytes32 outputId;
24
+ address sender;
25
+ }
26
+ // Note, these variables are set and then wiped during a single transaction.
27
+ // Therefore their values don't need to be maintained, and their slots will
28
+ // be empty outside of transactions
29
+ L2ToL1Context internal context;
30
+ uint128 public constant OUTBOX_VERSION = 2;
31
+
32
+ function initialize(address _rollup, IBridge _bridge) external onlyDelegated {
33
+ if (rollup != address(0)) revert AlreadyInit();
34
+ rollup = _rollup;
35
+ bridge = _bridge;
36
+ }
37
+
38
+ function updateSendRoot(bytes32 root, bytes32 l2BlockHash) external override {
39
+ if (msg.sender != rollup) revert NotRollup(msg.sender, rollup);
40
+ roots[root] = l2BlockHash;
41
+ emit SendRootUpdated(root, l2BlockHash);
42
+ }
43
+
44
+ /// @notice When l2ToL1Sender returns a nonzero address, the message was originated by an L2 account
45
+ /// When the return value is zero, that means this is a system message
46
+ /// @dev the l2ToL1Sender behaves as the tx.origin, the msg.sender should be validated to protect against reentrancies
47
+ function l2ToL1Sender() external view override returns (address) {
48
+ return context.sender;
49
+ }
50
+
51
+ function l2ToL1Block() external view override returns (uint256) {
52
+ return uint256(context.l2Block);
53
+ }
54
+
55
+ function l2ToL1EthBlock() external view override returns (uint256) {
56
+ return uint256(context.l1Block);
57
+ }
58
+
59
+ function l2ToL1Timestamp() external view override returns (uint256) {
60
+ return uint256(context.timestamp);
61
+ }
62
+
63
+ // @deprecated batch number is now always 0
64
+ function l2ToL1BatchNum() external pure override returns (uint256) {
65
+ return 0;
66
+ }
67
+
68
+ function l2ToL1OutputId() external view override returns (bytes32) {
69
+ return context.outputId;
70
+ }
71
+
72
+ /**
73
+ * @notice Executes a messages in an Outbox entry.
74
+ * @dev Reverts if dispute period hasn't expired, since the outbox entry
75
+ * is only created once the rollup confirms the respective assertion.
76
+ * @param proof Merkle proof of message inclusion in send root
77
+ * @param index Merkle path to message
78
+ * @param l2Sender sender if original message (i.e., caller of ArbSys.sendTxToL1)
79
+ * @param to destination address for L1 contract call
80
+ * @param l2Block l2 block number at which sendTxToL1 call was made
81
+ * @param l1Block l1 block number at which sendTxToL1 call was made
82
+ * @param l2Timestamp l2 Timestamp at which sendTxToL1 call was made
83
+ * @param value wei in L1 message
84
+ * @param data abi-encoded L1 message data
85
+ */
86
+ function executeTransaction(
87
+ bytes32[] calldata proof,
88
+ uint256 index,
89
+ address l2Sender,
90
+ address to,
91
+ uint256 l2Block,
92
+ uint256 l1Block,
93
+ uint256 l2Timestamp,
94
+ uint256 value,
95
+ bytes calldata data
96
+ ) external virtual {
97
+ bytes32 outputId;
98
+ {
99
+ bytes32 userTx = calculateItemHash(
100
+ l2Sender,
101
+ to,
102
+ l2Block,
103
+ l1Block,
104
+ l2Timestamp,
105
+ value,
106
+ data
107
+ );
108
+
109
+ outputId = recordOutputAsSpent(proof, index, userTx);
110
+ emit OutBoxTransactionExecuted(to, l2Sender, 0, index);
111
+ }
112
+
113
+ // we temporarily store the previous values so the outbox can naturally
114
+ // unwind itself when there are nested calls to `executeTransaction`
115
+ L2ToL1Context memory prevContext = context;
116
+
117
+ context = L2ToL1Context({
118
+ sender: l2Sender,
119
+ l2Block: uint128(l2Block),
120
+ l1Block: uint128(l1Block),
121
+ timestamp: uint128(l2Timestamp),
122
+ outputId: outputId
123
+ });
124
+
125
+ // set and reset vars around execution so they remain valid during call
126
+ executeBridgeCall(to, value, data);
127
+
128
+ context = prevContext;
129
+ }
130
+
131
+ function recordOutputAsSpent(
132
+ bytes32[] memory proof,
133
+ uint256 index,
134
+ bytes32 item
135
+ ) internal returns (bytes32) {
136
+ if (proof.length >= 256) revert ProofTooLong(proof.length);
137
+ if (index >= 2**proof.length) revert PathNotMinimal(index, 2**proof.length);
138
+
139
+ // Hash the leaf an extra time to prove it's a leaf
140
+ bytes32 calcRoot = calculateMerkleRoot(proof, index, item);
141
+ if (roots[calcRoot] == bytes32(0)) revert UnknownRoot(calcRoot);
142
+
143
+ if (spent[index]) revert AlreadySpent(index);
144
+ spent[index] = true;
145
+
146
+ return bytes32(index);
147
+ }
148
+
149
+ function executeBridgeCall(
150
+ address to,
151
+ uint256 value,
152
+ bytes memory data
153
+ ) internal {
154
+ (bool success, bytes memory returndata) = bridge.executeCall(to, value, data);
155
+ if (!success) {
156
+ if (returndata.length > 0) {
157
+ // solhint-disable-next-line no-inline-assembly
158
+ assembly {
159
+ let returndata_size := mload(returndata)
160
+ revert(add(32, returndata), returndata_size)
161
+ }
162
+ } else {
163
+ revert BridgeCallFailed();
164
+ }
165
+ }
166
+ }
167
+
168
+ function calculateItemHash(
169
+ address l2Sender,
170
+ address to,
171
+ uint256 l2Block,
172
+ uint256 l1Block,
173
+ uint256 l2Timestamp,
174
+ uint256 value,
175
+ bytes calldata data
176
+ ) public pure returns (bytes32) {
177
+ return
178
+ keccak256(abi.encodePacked(l2Sender, to, l2Block, l1Block, l2Timestamp, value, data));
179
+ }
180
+
181
+ function calculateMerkleRoot(
182
+ bytes32[] memory proof,
183
+ uint256 path,
184
+ bytes32 item
185
+ ) public pure returns (bytes32) {
186
+ return MerkleLib.calculateRoot(proof, path, keccak256(abi.encodePacked(item)));
187
+ }
188
+ }
@@ -0,0 +1,274 @@
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 "./IBridge.sol";
8
+ import "./ISequencerInbox.sol";
9
+ import "./Messages.sol";
10
+
11
+ import {GasRefundEnabled, IGasRefunder} from "../libraries/IGasRefunder.sol";
12
+ import "../libraries/DelegateCallAware.sol";
13
+ import {MAX_DATA_SIZE} from "../libraries/Constants.sol";
14
+
15
+ /**
16
+ * @title Accepts batches from the sequencer and adds them to the rollup inbox.
17
+ * @notice Contains the inbox accumulator which is the ordering of all data and transactions to be processed by the rollup.
18
+ * As part of submitting a batch the sequencer is also expected to include items enqueued
19
+ * in the delayed inbox (Bridge.sol). If items in the delayed inbox are not included by a
20
+ * sequencer within a time limit they can be force included into the rollup inbox by anyone.
21
+ */
22
+ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox {
23
+ bytes32[] public override inboxAccs;
24
+ uint256 public totalDelayedMessagesRead;
25
+
26
+ IBridge public delayedBridge;
27
+
28
+ /// @dev The size of the batch header
29
+ uint256 public constant HEADER_LENGTH = 40;
30
+ /// @dev If the first batch data byte after the header has this bit set,
31
+ /// the sequencer inbox has authenticated the data. Currently not used.
32
+ bytes1 public constant DATA_AUTHENTICATED_FLAG = 0x40;
33
+
34
+ address public rollup;
35
+ mapping(address => bool) public isBatchPoster;
36
+ ISequencerInbox.MaxTimeVariation public maxTimeVariation;
37
+
38
+ function initialize(
39
+ IBridge delayedBridge_,
40
+ address rollup_,
41
+ ISequencerInbox.MaxTimeVariation calldata maxTimeVariation_
42
+ ) external onlyDelegated {
43
+ if (delayedBridge != IBridge(address(0))) revert AlreadyInit();
44
+ if (delayedBridge_ == IBridge(address(0))) revert HadZeroInit();
45
+ delayedBridge = delayedBridge_;
46
+ rollup = rollup_;
47
+ maxTimeVariation = maxTimeVariation_;
48
+ }
49
+
50
+ function getTimeBounds() internal view virtual returns (TimeBounds memory) {
51
+ TimeBounds memory bounds;
52
+ if (block.timestamp > maxTimeVariation.delaySeconds) {
53
+ bounds.minTimestamp = uint64(block.timestamp - maxTimeVariation.delaySeconds);
54
+ }
55
+ bounds.maxTimestamp = uint64(block.timestamp + maxTimeVariation.futureSeconds);
56
+ if (block.number > maxTimeVariation.delayBlocks) {
57
+ bounds.minBlockNumber = uint64(block.number - maxTimeVariation.delayBlocks);
58
+ }
59
+ bounds.maxBlockNumber = uint64(block.number + maxTimeVariation.futureBlocks);
60
+ return bounds;
61
+ }
62
+
63
+ /// @notice Force messages from the delayed inbox to be included in the chain
64
+ /// Callable by any address, but message can only be force-included after maxTimeVariation.delayBlocks and maxTimeVariation.delaySeconds
65
+ /// has elapsed. As part of normal behaviour the sequencer will include these messages
66
+ /// so it's only necessary to call this if the sequencer is down, or not including
67
+ /// any delayed messages.
68
+ /// @param _totalDelayedMessagesRead The total number of messages to read up to
69
+ /// @param kind The kind of the last message to be included
70
+ /// @param l1BlockAndTime The l1 block and the l1 timestamp of the last message to be included
71
+ /// @param baseFeeL1 The l1 gas price of the last message to be included
72
+ /// @param sender The sender of the last message to be included
73
+ /// @param messageDataHash The messageDataHash of the last message to be included
74
+ function forceInclusion(
75
+ uint256 _totalDelayedMessagesRead,
76
+ uint8 kind,
77
+ uint64[2] calldata l1BlockAndTime,
78
+ uint256 baseFeeL1,
79
+ address sender,
80
+ bytes32 messageDataHash
81
+ ) external {
82
+ if (_totalDelayedMessagesRead <= totalDelayedMessagesRead) revert DelayedBackwards();
83
+ bytes32 messageHash = Messages.messageHash(
84
+ kind,
85
+ sender,
86
+ l1BlockAndTime[0],
87
+ l1BlockAndTime[1],
88
+ _totalDelayedMessagesRead - 1,
89
+ baseFeeL1,
90
+ messageDataHash
91
+ );
92
+ // Can only force-include after the Sequencer-only window has expired.
93
+ if (l1BlockAndTime[0] + maxTimeVariation.delayBlocks >= block.number)
94
+ revert ForceIncludeBlockTooSoon();
95
+ if (l1BlockAndTime[1] + maxTimeVariation.delaySeconds >= block.timestamp)
96
+ revert ForceIncludeTimeTooSoon();
97
+
98
+ // Verify that message hash represents the last message sequence of delayed message to be included
99
+ bytes32 prevDelayedAcc = 0;
100
+ if (_totalDelayedMessagesRead > 1) {
101
+ prevDelayedAcc = delayedBridge.inboxAccs(_totalDelayedMessagesRead - 2);
102
+ }
103
+ if (
104
+ delayedBridge.inboxAccs(_totalDelayedMessagesRead - 1) !=
105
+ Messages.accumulateInboxMessage(prevDelayedAcc, messageHash)
106
+ ) revert IncorrectMessagePreimage();
107
+
108
+ (bytes32 dataHash, TimeBounds memory timeBounds) = formEmptyDataHash(
109
+ _totalDelayedMessagesRead
110
+ );
111
+ (bytes32 beforeAcc, bytes32 delayedAcc, bytes32 afterAcc) = addSequencerL2BatchImpl(
112
+ dataHash,
113
+ _totalDelayedMessagesRead
114
+ );
115
+ emit SequencerBatchDelivered(
116
+ inboxAccs.length - 1,
117
+ beforeAcc,
118
+ afterAcc,
119
+ delayedAcc,
120
+ totalDelayedMessagesRead,
121
+ timeBounds,
122
+ BatchDataLocation.NoData
123
+ );
124
+ }
125
+
126
+ function addSequencerL2BatchFromOrigin(
127
+ uint256 sequenceNumber,
128
+ bytes calldata data,
129
+ uint256 afterDelayedMessagesRead,
130
+ IGasRefunder gasRefunder
131
+ ) external refundsGasWithCalldata(gasRefunder, payable(msg.sender)) {
132
+ // solhint-disable-next-line avoid-tx-origin
133
+ if (msg.sender != tx.origin) revert NotOrigin();
134
+ if (!isBatchPoster[msg.sender]) revert NotBatchPoster();
135
+ if (inboxAccs.length != sequenceNumber) revert BadSequencerNumber();
136
+ (bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
137
+ data,
138
+ afterDelayedMessagesRead
139
+ );
140
+ (bytes32 beforeAcc, bytes32 delayedAcc, bytes32 afterAcc) = addSequencerL2BatchImpl(
141
+ dataHash,
142
+ afterDelayedMessagesRead
143
+ );
144
+ emit SequencerBatchDelivered(
145
+ inboxAccs.length - 1,
146
+ beforeAcc,
147
+ afterAcc,
148
+ delayedAcc,
149
+ totalDelayedMessagesRead,
150
+ timeBounds,
151
+ BatchDataLocation.TxInput
152
+ );
153
+ }
154
+
155
+ function addSequencerL2Batch(
156
+ uint256 sequenceNumber,
157
+ bytes calldata data,
158
+ uint256 afterDelayedMessagesRead,
159
+ IGasRefunder gasRefunder
160
+ ) external override refundsGasNoCalldata(gasRefunder, payable(msg.sender)) {
161
+ if (!isBatchPoster[msg.sender] && msg.sender != rollup) revert NotBatchPoster();
162
+ if (inboxAccs.length != sequenceNumber) revert BadSequencerNumber();
163
+
164
+ (bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
165
+ data,
166
+ afterDelayedMessagesRead
167
+ );
168
+ (bytes32 beforeAcc, bytes32 delayedAcc, bytes32 afterAcc) = addSequencerL2BatchImpl(
169
+ dataHash,
170
+ afterDelayedMessagesRead
171
+ );
172
+ emit SequencerBatchDelivered(
173
+ sequenceNumber,
174
+ beforeAcc,
175
+ afterAcc,
176
+ delayedAcc,
177
+ afterDelayedMessagesRead,
178
+ timeBounds,
179
+ BatchDataLocation.SeparateBatchEvent
180
+ );
181
+ emit SequencerBatchData(sequenceNumber, data);
182
+ }
183
+
184
+ function packHeader(uint256 afterDelayedMessagesRead)
185
+ internal
186
+ view
187
+ returns (bytes memory, TimeBounds memory)
188
+ {
189
+ TimeBounds memory timeBounds = getTimeBounds();
190
+ bytes memory header = abi.encodePacked(
191
+ timeBounds.minTimestamp,
192
+ timeBounds.maxTimestamp,
193
+ timeBounds.minBlockNumber,
194
+ timeBounds.maxBlockNumber,
195
+ uint64(afterDelayedMessagesRead)
196
+ );
197
+ // This must always be true from the packed encoding
198
+ assert(header.length == HEADER_LENGTH);
199
+ return (header, timeBounds);
200
+ }
201
+
202
+ function formDataHash(bytes calldata data, uint256 afterDelayedMessagesRead)
203
+ internal
204
+ view
205
+ returns (bytes32, TimeBounds memory)
206
+ {
207
+ uint256 fullDataLen = HEADER_LENGTH + data.length;
208
+ if (fullDataLen < HEADER_LENGTH) revert DataLengthOverflow();
209
+ if (fullDataLen > MAX_DATA_SIZE) revert DataTooLarge(fullDataLen, MAX_DATA_SIZE);
210
+ bytes memory fullData = new bytes(fullDataLen);
211
+ (bytes memory header, TimeBounds memory timeBounds) = packHeader(afterDelayedMessagesRead);
212
+
213
+ for (uint256 i = 0; i < HEADER_LENGTH; i++) {
214
+ fullData[i] = header[i];
215
+ }
216
+ if (data.length > 0 && (data[0] & DATA_AUTHENTICATED_FLAG) == DATA_AUTHENTICATED_FLAG) {
217
+ revert DataNotAuthenticated();
218
+ }
219
+ // copy data into fullData at offset of HEADER_LENGTH (the extra 32 offset is because solidity puts the array len first)
220
+ assembly {
221
+ calldatacopy(add(fullData, add(HEADER_LENGTH, 32)), data.offset, data.length)
222
+ }
223
+ return (keccak256(fullData), timeBounds);
224
+ }
225
+
226
+ function formEmptyDataHash(uint256 afterDelayedMessagesRead)
227
+ internal
228
+ view
229
+ returns (bytes32, TimeBounds memory)
230
+ {
231
+ (bytes memory header, TimeBounds memory timeBounds) = packHeader(afterDelayedMessagesRead);
232
+ return (keccak256(header), timeBounds);
233
+ }
234
+
235
+ function addSequencerL2BatchImpl(bytes32 dataHash, uint256 afterDelayedMessagesRead)
236
+ internal
237
+ returns (
238
+ bytes32 beforeAcc,
239
+ bytes32 delayedAcc,
240
+ bytes32 acc
241
+ )
242
+ {
243
+ if (afterDelayedMessagesRead < totalDelayedMessagesRead) revert DelayedBackwards();
244
+ if (afterDelayedMessagesRead > delayedBridge.messageCount()) revert DelayedTooFar();
245
+
246
+ if (inboxAccs.length > 0) {
247
+ beforeAcc = inboxAccs[inboxAccs.length - 1];
248
+ }
249
+ if (afterDelayedMessagesRead > 0) {
250
+ delayedAcc = delayedBridge.inboxAccs(afterDelayedMessagesRead - 1);
251
+ }
252
+
253
+ acc = keccak256(abi.encodePacked(beforeAcc, dataHash, delayedAcc));
254
+ inboxAccs.push(acc);
255
+ totalDelayedMessagesRead = afterDelayedMessagesRead;
256
+ }
257
+
258
+ function batchCount() external view override returns (uint256) {
259
+ return inboxAccs.length;
260
+ }
261
+
262
+ function setMaxTimeVariation(ISequencerInbox.MaxTimeVariation memory maxTimeVariation_)
263
+ external
264
+ override
265
+ {
266
+ if (msg.sender != rollup) revert NotRollup(msg.sender, rollup);
267
+ maxTimeVariation = maxTimeVariation_;
268
+ }
269
+
270
+ function setIsBatchPoster(address addr, bool isBatchPoster_) external override {
271
+ if (msg.sender != rollup) revert NotRollup(msg.sender, rollup);
272
+ isBatchPoster[addr] = isBatchPoster_;
273
+ }
274
+ }
@@ -0,0 +1,135 @@
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 "../state/Machine.sol";
8
+ import "../state/GlobalState.sol";
9
+
10
+ library ChallengeLib {
11
+ using MachineLib for Machine;
12
+ using ChallengeLib for Challenge;
13
+
14
+ /// @dev It's assumed that that uninitialzed challenges have mode NONE
15
+ enum ChallengeMode {
16
+ NONE,
17
+ BLOCK,
18
+ EXECUTION
19
+ }
20
+
21
+ struct Participant {
22
+ address addr;
23
+ uint256 timeLeft;
24
+ }
25
+
26
+ struct Challenge {
27
+ Participant current;
28
+ Participant next;
29
+ uint256 lastMoveTimestamp;
30
+ bytes32 wasmModuleRoot;
31
+ bytes32 challengeStateHash;
32
+ uint64 maxInboxMessages;
33
+ ChallengeMode mode;
34
+ }
35
+
36
+ struct SegmentSelection {
37
+ uint256 oldSegmentsStart;
38
+ uint256 oldSegmentsLength;
39
+ bytes32[] oldSegments;
40
+ uint256 challengePosition;
41
+ }
42
+
43
+ function timeUsedSinceLastMove(Challenge storage challenge) internal view returns (uint256) {
44
+ return block.timestamp - challenge.lastMoveTimestamp;
45
+ }
46
+
47
+ function isTimedOut(Challenge storage challenge) internal view returns (bool) {
48
+ return challenge.timeUsedSinceLastMove() > challenge.current.timeLeft;
49
+ }
50
+
51
+ function getStartMachineHash(bytes32 globalStateHash, bytes32 wasmModuleRoot)
52
+ internal
53
+ pure
54
+ returns (bytes32)
55
+ {
56
+ // Start the value stack with the function call ABI for the entrypoint
57
+ Value[] memory startingValues = new Value[](3);
58
+ startingValues[0] = ValueLib.newRefNull();
59
+ startingValues[1] = ValueLib.newI32(0);
60
+ startingValues[2] = ValueLib.newI32(0);
61
+ ValueArray memory valuesArray = ValueArray({inner: startingValues});
62
+ ValueStack memory values = ValueStack({proved: valuesArray, remainingHash: 0});
63
+ ValueStack memory internalStack;
64
+ PcStack memory blocks;
65
+ StackFrameWindow memory frameStack;
66
+
67
+ Machine memory mach = Machine({
68
+ status: MachineStatus.RUNNING,
69
+ valueStack: values,
70
+ internalStack: internalStack,
71
+ blockStack: blocks,
72
+ frameStack: frameStack,
73
+ globalStateHash: globalStateHash,
74
+ moduleIdx: 0,
75
+ functionIdx: 0,
76
+ functionPc: 0,
77
+ modulesRoot: wasmModuleRoot
78
+ });
79
+ return mach.hash();
80
+ }
81
+
82
+ function getEndMachineHash(MachineStatus status, bytes32 globalStateHash)
83
+ internal
84
+ pure
85
+ returns (bytes32)
86
+ {
87
+ if (status == MachineStatus.FINISHED) {
88
+ return keccak256(abi.encodePacked("Machine finished:", globalStateHash));
89
+ } else if (status == MachineStatus.ERRORED) {
90
+ return keccak256(abi.encodePacked("Machine errored:"));
91
+ } else if (status == MachineStatus.TOO_FAR) {
92
+ return keccak256(abi.encodePacked("Machine too far:"));
93
+ } else {
94
+ revert("BAD_BLOCK_STATUS");
95
+ }
96
+ }
97
+
98
+ function extractChallengeSegment(SegmentSelection calldata selection)
99
+ internal
100
+ pure
101
+ returns (uint256 segmentStart, uint256 segmentLength)
102
+ {
103
+ uint256 oldChallengeDegree = selection.oldSegments.length - 1;
104
+ segmentLength = selection.oldSegmentsLength / oldChallengeDegree;
105
+ // Intentionally done before challengeLength is potentially added to for the final segment
106
+ segmentStart = selection.oldSegmentsStart + segmentLength * selection.challengePosition;
107
+ if (selection.challengePosition == selection.oldSegments.length - 2) {
108
+ segmentLength += selection.oldSegmentsLength % oldChallengeDegree;
109
+ }
110
+ }
111
+
112
+ function hashChallengeState(
113
+ uint256 segmentsStart,
114
+ uint256 segmentsLength,
115
+ bytes32[] memory segments
116
+ ) internal pure returns (bytes32) {
117
+ return keccak256(abi.encodePacked(segmentsStart, segmentsLength, segments));
118
+ }
119
+
120
+ function blockStateHash(MachineStatus status, bytes32 globalStateHash)
121
+ internal
122
+ pure
123
+ returns (bytes32)
124
+ {
125
+ if (status == MachineStatus.FINISHED) {
126
+ return keccak256(abi.encodePacked("Block state:", globalStateHash));
127
+ } else if (status == MachineStatus.ERRORED) {
128
+ return keccak256(abi.encodePacked("Block state, errored:", globalStateHash));
129
+ } else if (status == MachineStatus.TOO_FAR) {
130
+ return keccak256(abi.encodePacked("Block state, too far:"));
131
+ } else {
132
+ revert("BAD_BLOCK_STATUS");
133
+ }
134
+ }
135
+ }