@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,367 @@
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/DelegateCallAware.sol";
8
+ import "../osp/IOneStepProofEntry.sol";
9
+ import "../state/GlobalState.sol";
10
+ import "./IChallengeResultReceiver.sol";
11
+ import "./ChallengeLib.sol";
12
+ import "./IChallengeManager.sol";
13
+
14
+ import {NO_CHAL_INDEX} from "../libraries/Constants.sol";
15
+
16
+ contract ChallengeManager is DelegateCallAware, IChallengeManager {
17
+ using GlobalStateLib for GlobalState;
18
+ using MachineLib for Machine;
19
+ using ChallengeLib for ChallengeLib.Challenge;
20
+
21
+ enum ChallengeModeRequirement {
22
+ ANY,
23
+ BLOCK,
24
+ EXECUTION
25
+ }
26
+
27
+ string private constant NO_CHAL = "NO_CHAL";
28
+ uint256 private constant MAX_CHALLENGE_DEGREE = 40;
29
+
30
+ uint64 public totalChallengesCreated;
31
+ mapping(uint256 => ChallengeLib.Challenge) public challenges;
32
+
33
+ IChallengeResultReceiver public resultReceiver;
34
+
35
+ ISequencerInbox public sequencerInbox;
36
+ IBridge public delayedBridge;
37
+ IOneStepProofEntry public osp;
38
+
39
+ function challengeInfo(uint64 challengeIndex)
40
+ external
41
+ view
42
+ override
43
+ returns (ChallengeLib.Challenge memory)
44
+ {
45
+ return challenges[challengeIndex];
46
+ }
47
+
48
+ modifier takeTurn(
49
+ uint64 challengeIndex,
50
+ ChallengeLib.SegmentSelection calldata selection,
51
+ ChallengeModeRequirement expectedMode
52
+ ) {
53
+ ChallengeLib.Challenge storage challenge = challenges[challengeIndex];
54
+ require(msg.sender == currentResponder(challengeIndex), "CHAL_SENDER");
55
+ require(!isTimedOut(challengeIndex), "CHAL_DEADLINE");
56
+
57
+ if (expectedMode == ChallengeModeRequirement.ANY) {
58
+ require(challenge.mode != ChallengeLib.ChallengeMode.NONE, NO_CHAL);
59
+ } else if (expectedMode == ChallengeModeRequirement.BLOCK) {
60
+ require(challenge.mode == ChallengeLib.ChallengeMode.BLOCK, "CHAL_NOT_BLOCK");
61
+ } else if (expectedMode == ChallengeModeRequirement.EXECUTION) {
62
+ require(challenge.mode == ChallengeLib.ChallengeMode.EXECUTION, "CHAL_NOT_EXECUTION");
63
+ } else {
64
+ assert(false);
65
+ }
66
+
67
+ require(
68
+ challenge.challengeStateHash ==
69
+ ChallengeLib.hashChallengeState(
70
+ selection.oldSegmentsStart,
71
+ selection.oldSegmentsLength,
72
+ selection.oldSegments
73
+ ),
74
+ "BIS_STATE"
75
+ );
76
+ if (
77
+ selection.oldSegments.length < 2 ||
78
+ selection.challengePosition >= selection.oldSegments.length - 1
79
+ ) {
80
+ revert("BAD_CHALLENGE_POS");
81
+ }
82
+
83
+ _;
84
+
85
+ if (challenge.mode == ChallengeLib.ChallengeMode.NONE) {
86
+ // Early return since challenge must have terminated
87
+ return;
88
+ }
89
+
90
+ ChallengeLib.Participant memory current = challenge.current;
91
+ current.timeLeft -= block.timestamp - challenge.lastMoveTimestamp;
92
+
93
+ challenge.current = challenge.next;
94
+ challenge.next = current;
95
+
96
+ challenge.lastMoveTimestamp = block.timestamp;
97
+ }
98
+
99
+ function initialize(
100
+ IChallengeResultReceiver resultReceiver_,
101
+ ISequencerInbox sequencerInbox_,
102
+ IBridge delayedBridge_,
103
+ IOneStepProofEntry osp_
104
+ ) external override onlyDelegated {
105
+ require(address(resultReceiver) == address(0), "ALREADY_INIT");
106
+ require(address(resultReceiver_) != address(0), "NO_RESULT_RECEIVER");
107
+ resultReceiver = resultReceiver_;
108
+ sequencerInbox = sequencerInbox_;
109
+ delayedBridge = delayedBridge_;
110
+ osp = osp_;
111
+ }
112
+
113
+ function createChallenge(
114
+ bytes32 wasmModuleRoot_,
115
+ MachineStatus[2] calldata startAndEndMachineStatuses_,
116
+ GlobalState[2] calldata startAndEndGlobalStates_,
117
+ uint64 numBlocks,
118
+ address asserter_,
119
+ address challenger_,
120
+ uint256 asserterTimeLeft_,
121
+ uint256 challengerTimeLeft_
122
+ ) external override returns (uint64) {
123
+ require(msg.sender == address(resultReceiver), "ONLY_ROLLUP_CHAL");
124
+ bytes32[] memory segments = new bytes32[](2);
125
+ segments[0] = ChallengeLib.blockStateHash(
126
+ startAndEndMachineStatuses_[0],
127
+ startAndEndGlobalStates_[0].hash()
128
+ );
129
+ segments[1] = ChallengeLib.blockStateHash(
130
+ startAndEndMachineStatuses_[1],
131
+ startAndEndGlobalStates_[1].hash()
132
+ );
133
+
134
+ uint64 challengeIndex = ++totalChallengesCreated;
135
+ // The following is an assertion since it should never be possible, but it's an important invariant
136
+ assert(challengeIndex != NO_CHAL_INDEX);
137
+ ChallengeLib.Challenge storage challenge = challenges[challengeIndex];
138
+ challenge.wasmModuleRoot = wasmModuleRoot_;
139
+
140
+ // See validator/assertion.go ExecutionState RequiredBatches() for reasoning
141
+ uint64 maxInboxMessagesRead = startAndEndGlobalStates_[1].getInboxPosition();
142
+ if (
143
+ startAndEndMachineStatuses_[1] == MachineStatus.ERRORED ||
144
+ startAndEndGlobalStates_[1].getPositionInMessage() > 0
145
+ ) {
146
+ maxInboxMessagesRead++;
147
+ }
148
+ challenge.maxInboxMessages = maxInboxMessagesRead;
149
+ challenge.next = ChallengeLib.Participant({addr: asserter_, timeLeft: asserterTimeLeft_});
150
+ challenge.current = ChallengeLib.Participant({
151
+ addr: challenger_,
152
+ timeLeft: challengerTimeLeft_
153
+ });
154
+ challenge.lastMoveTimestamp = block.timestamp;
155
+ challenge.mode = ChallengeLib.ChallengeMode.BLOCK;
156
+
157
+ emit InitiatedChallenge(
158
+ challengeIndex,
159
+ startAndEndGlobalStates_[0],
160
+ startAndEndGlobalStates_[1]
161
+ );
162
+ completeBisection(challengeIndex, 0, numBlocks, segments);
163
+ return challengeIndex;
164
+ }
165
+
166
+ /**
167
+ * @notice Initiate the next round in the bisection by objecting to execution correctness with a bisection
168
+ * of an execution segment with the same length but a different endpoint. This is either the initial move
169
+ * or follows another execution objection
170
+ */
171
+ function bisectExecution(
172
+ uint64 challengeIndex,
173
+ ChallengeLib.SegmentSelection calldata selection,
174
+ bytes32[] calldata newSegments
175
+ ) external takeTurn(challengeIndex, selection, ChallengeModeRequirement.ANY) {
176
+ (uint256 challengeStart, uint256 challengeLength) = ChallengeLib.extractChallengeSegment(
177
+ selection
178
+ );
179
+ require(challengeLength > 1, "TOO_SHORT");
180
+ {
181
+ uint256 expectedDegree = challengeLength;
182
+ if (expectedDegree > MAX_CHALLENGE_DEGREE) {
183
+ expectedDegree = MAX_CHALLENGE_DEGREE;
184
+ }
185
+ require(newSegments.length == expectedDegree + 1, "WRONG_DEGREE");
186
+ }
187
+
188
+ requireValidBisection(selection, newSegments[0], newSegments[newSegments.length - 1]);
189
+
190
+ completeBisection(challengeIndex, challengeStart, challengeLength, newSegments);
191
+ }
192
+
193
+ function challengeExecution(
194
+ uint64 challengeIndex,
195
+ ChallengeLib.SegmentSelection calldata selection,
196
+ MachineStatus[2] calldata machineStatuses,
197
+ bytes32[2] calldata globalStateHashes,
198
+ uint256 numSteps
199
+ ) external takeTurn(challengeIndex, selection, ChallengeModeRequirement.BLOCK) {
200
+ require(numSteps >= 1, "CHALLENGE_TOO_SHORT");
201
+ require(numSteps <= OneStepProofEntryLib.MAX_STEPS, "CHALLENGE_TOO_LONG");
202
+ requireValidBisection(
203
+ selection,
204
+ ChallengeLib.blockStateHash(machineStatuses[0], globalStateHashes[0]),
205
+ ChallengeLib.blockStateHash(machineStatuses[1], globalStateHashes[1])
206
+ );
207
+
208
+ ChallengeLib.Challenge storage challenge = challenges[challengeIndex];
209
+ (uint256 executionChallengeAtSteps, uint256 challengeLength) = ChallengeLib
210
+ .extractChallengeSegment(selection);
211
+ require(challengeLength == 1, "TOO_LONG");
212
+
213
+ if (machineStatuses[0] != MachineStatus.FINISHED) {
214
+ // If the machine is in a halted state, it can't change
215
+ require(
216
+ machineStatuses[0] == machineStatuses[1] &&
217
+ globalStateHashes[0] == globalStateHashes[1],
218
+ "HALTED_CHANGE"
219
+ );
220
+ _currentWin(challengeIndex, ChallengeTerminationType.BLOCK_PROOF);
221
+ return;
222
+ }
223
+
224
+ if (machineStatuses[1] == MachineStatus.ERRORED) {
225
+ // If the machine errors, it must return to the previous global state
226
+ require(globalStateHashes[0] == globalStateHashes[1], "ERROR_CHANGE");
227
+ }
228
+
229
+ bytes32[] memory segments = new bytes32[](2);
230
+ segments[0] = ChallengeLib.getStartMachineHash(
231
+ globalStateHashes[0],
232
+ challenge.wasmModuleRoot
233
+ );
234
+ segments[1] = ChallengeLib.getEndMachineHash(machineStatuses[1], globalStateHashes[1]);
235
+
236
+ challenge.mode = ChallengeLib.ChallengeMode.EXECUTION;
237
+
238
+ completeBisection(challengeIndex, 0, numSteps, segments);
239
+
240
+ emit ExecutionChallengeBegun(challengeIndex, executionChallengeAtSteps);
241
+ }
242
+
243
+ function oneStepProveExecution(
244
+ uint64 challengeIndex,
245
+ ChallengeLib.SegmentSelection calldata selection,
246
+ bytes calldata proof
247
+ ) external takeTurn(challengeIndex, selection, ChallengeModeRequirement.EXECUTION) {
248
+ ChallengeLib.Challenge storage challenge = challenges[challengeIndex];
249
+ uint256 challengeStart;
250
+ {
251
+ uint256 challengeLength;
252
+ (challengeStart, challengeLength) = ChallengeLib.extractChallengeSegment(selection);
253
+ require(challengeLength == 1, "TOO_LONG");
254
+ }
255
+
256
+ bytes32 afterHash = osp.proveOneStep(
257
+ ExecutionContext({
258
+ maxInboxMessagesRead: challenge.maxInboxMessages,
259
+ sequencerInbox: sequencerInbox,
260
+ delayedBridge: delayedBridge
261
+ }),
262
+ challengeStart,
263
+ selection.oldSegments[selection.challengePosition],
264
+ proof
265
+ );
266
+ require(
267
+ afterHash != selection.oldSegments[selection.challengePosition + 1],
268
+ "SAME_OSP_END"
269
+ );
270
+
271
+ emit OneStepProofCompleted(challengeIndex);
272
+ _currentWin(challengeIndex, ChallengeTerminationType.EXECUTION_PROOF);
273
+ }
274
+
275
+ function timeout(uint64 challengeIndex) external override {
276
+ require(challenges[challengeIndex].mode != ChallengeLib.ChallengeMode.NONE, NO_CHAL);
277
+ require(isTimedOut(challengeIndex), "TIMEOUT_DEADLINE");
278
+ _nextWin(challengeIndex, ChallengeTerminationType.TIMEOUT);
279
+ }
280
+
281
+ function clearChallenge(uint64 challengeIndex) external override {
282
+ require(msg.sender == address(resultReceiver), "NOT_RES_RECEIVER");
283
+ require(challenges[challengeIndex].mode != ChallengeLib.ChallengeMode.NONE, NO_CHAL);
284
+ delete challenges[challengeIndex];
285
+ emit ChallengeEnded(challengeIndex, ChallengeTerminationType.CLEARED);
286
+ }
287
+
288
+ function currentResponder(uint64 challengeIndex) public view override returns (address) {
289
+ return challenges[challengeIndex].current.addr;
290
+ }
291
+
292
+ function currentResponderTimeLeft(uint64 challengeIndex)
293
+ public
294
+ view
295
+ override
296
+ returns (uint256)
297
+ {
298
+ return challenges[challengeIndex].current.timeLeft;
299
+ }
300
+
301
+ function isTimedOut(uint64 challengeIndex) public view override returns (bool) {
302
+ return challenges[challengeIndex].isTimedOut();
303
+ }
304
+
305
+ function requireValidBisection(
306
+ ChallengeLib.SegmentSelection calldata selection,
307
+ bytes32 startHash,
308
+ bytes32 endHash
309
+ ) private pure {
310
+ require(selection.oldSegments[selection.challengePosition] == startHash, "WRONG_START");
311
+ require(selection.oldSegments[selection.challengePosition + 1] != endHash, "SAME_END");
312
+ }
313
+
314
+ function completeBisection(
315
+ uint64 challengeIndex,
316
+ uint256 challengeStart,
317
+ uint256 challengeLength,
318
+ bytes32[] memory newSegments
319
+ ) private {
320
+ assert(challengeLength >= 1);
321
+ assert(newSegments.length >= 2);
322
+
323
+ bytes32 challengeStateHash = ChallengeLib.hashChallengeState(
324
+ challengeStart,
325
+ challengeLength,
326
+ newSegments
327
+ );
328
+ challenges[challengeIndex].challengeStateHash = challengeStateHash;
329
+
330
+ emit Bisected(
331
+ challengeIndex,
332
+ challengeStateHash,
333
+ challengeStart,
334
+ challengeLength,
335
+ newSegments
336
+ );
337
+ }
338
+
339
+ /// @dev This function causes the mode of the challenge to be set to NONE by deleting the challenge
340
+ function _nextWin(uint64 challengeIndex, ChallengeTerminationType reason) private {
341
+ ChallengeLib.Challenge storage challenge = challenges[challengeIndex];
342
+ address next = challenge.next.addr;
343
+ address current = challenge.current.addr;
344
+ delete challenges[challengeIndex];
345
+ resultReceiver.completeChallenge(challengeIndex, next, current);
346
+ emit ChallengeEnded(challengeIndex, reason);
347
+ }
348
+
349
+ /**
350
+ * @dev this currently sets a challenge hash of 0 - no move is possible for the next participant to progress the
351
+ * state. It is assumed that wherever this function is consumed, the turn is then adjusted for the opposite party
352
+ * to timeout. This is done as a safety measure so challenges can only be resolved by timeouts during mainnet beta.
353
+ */
354
+ function _currentWin(
355
+ uint64 challengeIndex,
356
+ ChallengeTerminationType /* reason */
357
+ ) private {
358
+ ChallengeLib.Challenge storage challenge = challenges[challengeIndex];
359
+ challenge.challengeStateHash = bytes32(0);
360
+
361
+ // address next = challenge.next.addr;
362
+ // address current = challenge.current.addr;
363
+ // delete challenges[challengeIndex];
364
+ // resultReceiver.completeChallenge(challengeIndex, current, next);
365
+ // emit ChallengeEnded(challengeIndex, reason);
366
+ }
367
+ }
@@ -0,0 +1,75 @@
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 "../bridge/IBridge.sol";
9
+ import "../bridge/ISequencerInbox.sol";
10
+ import "../osp/IOneStepProofEntry.sol";
11
+
12
+ import "./IChallengeResultReceiver.sol";
13
+
14
+ import "./ChallengeLib.sol";
15
+
16
+ interface IChallengeManager {
17
+ enum ChallengeTerminationType {
18
+ TIMEOUT,
19
+ BLOCK_PROOF,
20
+ EXECUTION_PROOF,
21
+ CLEARED
22
+ }
23
+
24
+ event InitiatedChallenge(
25
+ uint64 indexed challengeIndex,
26
+ GlobalState startState,
27
+ GlobalState endState
28
+ );
29
+
30
+ event Bisected(
31
+ uint64 indexed challengeIndex,
32
+ bytes32 indexed challengeRoot,
33
+ uint256 challengedSegmentStart,
34
+ uint256 challengedSegmentLength,
35
+ bytes32[] chainHashes
36
+ );
37
+
38
+ event ExecutionChallengeBegun(uint64 indexed challengeIndex, uint256 blockSteps);
39
+ event OneStepProofCompleted(uint64 indexed challengeIndex);
40
+
41
+ event ChallengeEnded(uint64 indexed challengeIndex, ChallengeTerminationType kind);
42
+
43
+ function initialize(
44
+ IChallengeResultReceiver resultReceiver_,
45
+ ISequencerInbox sequencerInbox_,
46
+ IBridge delayedBridge_,
47
+ IOneStepProofEntry osp_
48
+ ) external;
49
+
50
+ function createChallenge(
51
+ bytes32 wasmModuleRoot_,
52
+ MachineStatus[2] calldata startAndEndMachineStatuses_,
53
+ GlobalState[2] calldata startAndEndGlobalStates_,
54
+ uint64 numBlocks,
55
+ address asserter_,
56
+ address challenger_,
57
+ uint256 asserterTimeLeft_,
58
+ uint256 challengerTimeLeft_
59
+ ) external returns (uint64);
60
+
61
+ function challengeInfo(uint64 challengeIndex_)
62
+ external
63
+ view
64
+ returns (ChallengeLib.Challenge memory);
65
+
66
+ function currentResponder(uint64 challengeIndex) external view returns (address);
67
+
68
+ function isTimedOut(uint64 challengeIndex) external view returns (bool);
69
+
70
+ function currentResponderTimeLeft(uint64 challengeIndex_) external view returns (uint256);
71
+
72
+ function clearChallenge(uint64 challengeIndex_) external;
73
+
74
+ function timeout(uint64 challengeIndex_) external;
75
+ }
@@ -0,0 +1,13 @@
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
+ interface IChallengeResultReceiver {
8
+ function completeChallenge(
9
+ uint256 challengeIndex,
10
+ address winner,
11
+ address loser
12
+ ) external;
13
+ }
@@ -0,0 +1,29 @@
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 AddressAliasHelper {
8
+ uint160 internal constant OFFSET = uint160(0x1111000000000000000000000000000000001111);
9
+
10
+ /// @notice Utility function that converts the address in the L1 that submitted a tx to
11
+ /// the inbox to the msg.sender viewed in the L2
12
+ /// @param l1Address the address in the L1 that triggered the tx to L2
13
+ /// @return l2Address L2 address as viewed in msg.sender
14
+ function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {
15
+ unchecked {
16
+ l2Address = address(uint160(l1Address) + OFFSET);
17
+ }
18
+ }
19
+
20
+ /// @notice Utility function that converts the msg.sender viewed in the L2 to the
21
+ /// address in the L1 that submitted a tx to the inbox
22
+ /// @param l2Address L2 address as viewed in msg.sender
23
+ /// @return l1Address the address in the L1 that triggered the tx to L2
24
+ function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {
25
+ unchecked {
26
+ l1Address = address(uint160(l2Address) - OFFSET);
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,153 @@
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 "@openzeppelin/contracts/proxy/Proxy.sol";
8
+ import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol";
9
+ import "@openzeppelin/contracts/utils/Address.sol";
10
+ import "@openzeppelin/contracts/utils/StorageSlot.sol";
11
+
12
+ /// @notice An extension to OZ's ERC1967Upgrade implementation to support two logic contracts
13
+ abstract contract DoubleLogicERC1967Upgrade is ERC1967Upgrade {
14
+ using Address for address;
15
+
16
+ // This is the keccak-256 hash of "eip1967.proxy.implementation.secondary" subtracted by 1
17
+ bytes32 internal constant _IMPLEMENTATION_SECONDARY_SLOT =
18
+ 0x2b1dbce74324248c222f0ec2d5ed7bd323cfc425b336f0253c5ccfda7265546d;
19
+
20
+ // This is the keccak-256 hash of "eip1967.proxy.rollback.secondary" subtracted by 1
21
+ bytes32 private constant _ROLLBACK_SECONDARY_SLOT =
22
+ 0x49bd798cd84788856140a4cd5030756b4d08a9e4d55db725ec195f232d262a89;
23
+
24
+ /**
25
+ * @dev Emitted when the secondary implementation is upgraded.
26
+ */
27
+ event UpgradedSecondary(address indexed implementation);
28
+
29
+ /**
30
+ * @dev Returns the current secondary implementation address.
31
+ */
32
+ function _getSecondaryImplementation() internal view returns (address) {
33
+ return StorageSlot.getAddressSlot(_IMPLEMENTATION_SECONDARY_SLOT).value;
34
+ }
35
+
36
+ /**
37
+ * @dev Stores a new address in the EIP1967 implementation slot.
38
+ */
39
+ function _setSecondaryImplementation(address newImplementation) private {
40
+ require(
41
+ Address.isContract(newImplementation),
42
+ "ERC1967: new secondary implementation is not a contract"
43
+ );
44
+ StorageSlot.getAddressSlot(_IMPLEMENTATION_SECONDARY_SLOT).value = newImplementation;
45
+ }
46
+
47
+ /**
48
+ * @dev Perform secondary implementation upgrade
49
+ *
50
+ * Emits an {UpgradedSecondary} event.
51
+ */
52
+ function _upgradeSecondaryTo(address newImplementation) internal {
53
+ _setSecondaryImplementation(newImplementation);
54
+ emit UpgradedSecondary(newImplementation);
55
+ }
56
+
57
+ /**
58
+ * @dev Perform secondary implementation upgrade with additional setup call.
59
+ *
60
+ * Emits an {UpgradedSecondary} event.
61
+ */
62
+ function _upgradeSecondaryToAndCall(
63
+ address newImplementation,
64
+ bytes memory data,
65
+ bool forceCall
66
+ ) internal {
67
+ _upgradeSecondaryTo(newImplementation);
68
+ if (data.length > 0 || forceCall) {
69
+ Address.functionDelegateCall(newImplementation, data);
70
+ }
71
+ }
72
+
73
+ /**
74
+ * @dev Perform secondary implementation upgrade with security checks for UUPS proxies, and additional setup call.
75
+ *
76
+ * Emits an {UpgradedSecondary} event.
77
+ */
78
+ function _upgradeSecondaryToAndCallUUPS(
79
+ address newImplementation,
80
+ bytes memory data,
81
+ bool forceCall
82
+ ) internal {
83
+ // Upgrades from old implementations will perform a rollback test. This test requires the new
84
+ // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
85
+ // this special case will break upgrade paths from old UUPS implementation to new ones.
86
+ if (StorageSlot.getBooleanSlot(_ROLLBACK_SECONDARY_SLOT).value) {
87
+ _setSecondaryImplementation(newImplementation);
88
+ } else {
89
+ try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
90
+ require(
91
+ slot == _IMPLEMENTATION_SECONDARY_SLOT,
92
+ "ERC1967Upgrade: unsupported proxiableUUID"
93
+ );
94
+ } catch {
95
+ revert("ERC1967Upgrade: new secondary implementation is not UUPS");
96
+ }
97
+ _upgradeSecondaryToAndCall(newImplementation, data, forceCall);
98
+ }
99
+ }
100
+ }
101
+
102
+ /// @notice similar to TransparentUpgradeableProxy but allows the admin to fallback to a separate logic contract using DoubleLogicERC1967Upgrade
103
+ /// @dev this follows the UUPS pattern for upgradeability - read more at https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v4.5.0/contracts/proxy#transparent-vs-uups-proxies
104
+ contract AdminFallbackProxy is Proxy, DoubleLogicERC1967Upgrade {
105
+ /**
106
+ * @dev Initializes the upgradeable proxy with an initial implementation specified by `adminLogic` and a secondary
107
+ * logic implementation specified by `userLogic`
108
+ *
109
+ * Only the `adminAddr` is able to use the `adminLogic` functions
110
+ * All other addresses can interact with the `userLogic` functions
111
+ */
112
+ constructor(
113
+ address adminLogic,
114
+ bytes memory adminData,
115
+ address userLogic,
116
+ bytes memory userData,
117
+ address adminAddr
118
+ ) payable {
119
+ assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1));
120
+ assert(
121
+ _IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1)
122
+ );
123
+ assert(
124
+ _IMPLEMENTATION_SECONDARY_SLOT ==
125
+ bytes32(uint256(keccak256("eip1967.proxy.implementation.secondary")) - 1)
126
+ );
127
+ _changeAdmin(adminAddr);
128
+ _upgradeToAndCall(adminLogic, adminData, false);
129
+ _upgradeSecondaryToAndCall(userLogic, userData, false);
130
+ }
131
+
132
+ /// @inheritdoc Proxy
133
+ function _implementation() internal view override returns (address) {
134
+ require(msg.data.length >= 4, "NO_FUNC_SIG");
135
+ // if the sender is the proxy's admin, delegate to admin logic
136
+ // if the admin is disabled (set to addr zero), all calls will be forwarded to user logic
137
+ address target = _getAdmin() != msg.sender
138
+ ? DoubleLogicERC1967Upgrade._getSecondaryImplementation()
139
+ : ERC1967Upgrade._getImplementation();
140
+ // implementation setters already do an existence check
141
+ // require(target.isContract(), "TARGET_NOT_CONTRACT");
142
+ return target;
143
+ }
144
+
145
+ /**
146
+ * @dev unlike transparent upgradeable proxies, this does allow the admin to fallback to a logic contract
147
+ * the admin is expected to interact only with the secondary logic contract, which handles contract
148
+ * upgrades using the UUPS approach
149
+ */
150
+ function _beforeFallback() internal override {
151
+ super._beforeFallback();
152
+ }
153
+ }
@@ -0,0 +1,20 @@
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 "./AdminFallbackProxy.sol";
8
+ import "../rollup/IRollupLogic.sol";
9
+
10
+ contract ArbitrumProxy is AdminFallbackProxy {
11
+ constructor(Config memory config, ContractDependencies memory connectedContracts)
12
+ AdminFallbackProxy(
13
+ address(connectedContracts.rollupAdminLogic),
14
+ abi.encodeWithSelector(IRollupAdmin.initialize.selector, config, connectedContracts),
15
+ address(connectedContracts.rollupUserLogic),
16
+ abi.encodeWithSelector(IRollupUserAbs.initialize.selector, config.stakeToken),
17
+ config.owner
18
+ )
19
+ {}
20
+ }
@@ -0,0 +1,10 @@
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
+ // 90% of Geth's 128KB tx size limit, leaving ~13KB for proving
8
+ uint256 constant MAX_DATA_SIZE = 117964;
9
+
10
+ uint64 constant NO_CHAL_INDEX = 0;