@arbitrum/nitro-contracts 1.0.0-beta.1 → 1.0.0-beta.4

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 (50) hide show
  1. package/README.md +15 -0
  2. package/package.json +12 -8
  3. package/src/bridge/IInbox.sol +9 -0
  4. package/src/bridge/Inbox.sol +19 -39
  5. package/src/libraries/AdminFallbackProxy.sol +5 -5
  6. package/src/libraries/MessageTypes.sol +1 -0
  7. package/src/mocks/InboxStub.sol +4 -0
  8. package/src/mocks/Simple.sol +30 -0
  9. package/src/node-interface/NodeInterface.sol +18 -1
  10. package/src/node-interface/NodeInterfaceDebug.sol +30 -0
  11. package/src/osp/OneStepProver0.sol +14 -0
  12. package/src/osp/OneStepProverMath.sol +2 -2
  13. package/src/precompiles/ArbOwner.sol +3 -0
  14. package/src/rollup/IRollupCore.sol +26 -2
  15. package/src/rollup/IRollupEventBridge.sol +17 -0
  16. package/src/rollup/IRollupLogic.sol +34 -2
  17. package/src/rollup/RollupCore.sol +2 -2
  18. package/src/rollup/RollupCreator.sol +5 -15
  19. package/src/rollup/RollupEventBridge.sol +2 -3
  20. package/src/rollup/RollupLib.sol +2 -2
  21. package/src/rollup/RollupUserLogic.sol +7 -3
  22. package/src/rollup/ValidatorUtils.sol +0 -1
  23. package/src/rollup/ValidatorWallet.sol +0 -1
  24. package/src/state/Instructions.sol +2 -0
  25. package/.prettierrc +0 -5
  26. package/.solhint.json +0 -18
  27. package/deploy/BridgeStubCreator.js +0 -10
  28. package/deploy/HashProofHelper.js +0 -13
  29. package/deploy/InboxStubCreator.js +0 -17
  30. package/deploy/OneStepProofEntryCreator.js +0 -19
  31. package/deploy/OneStepProver0Creator.js +0 -14
  32. package/deploy/OneStepProverHostIoCreator.js +0 -14
  33. package/deploy/OneStepProverMathCreator.js +0 -14
  34. package/deploy/OneStepProverMemoryCreator.js +0 -14
  35. package/deploy/SequencerInboxStubCreator.js +0 -13
  36. package/deploy/ValueArrayTesterCreator.js +0 -13
  37. package/hardhat.config.ts +0 -47
  38. package/src/mocks/Counter.sol +0 -13
  39. package/test/contract/arbRollup.spec.ts +0 -869
  40. package/test/contract/common/challengeLib.ts +0 -43
  41. package/test/contract/common/globalStateLib.ts +0 -17
  42. package/test/contract/common/rolluplib.ts +0 -259
  43. package/test/contract/cryptographyPrimitives.spec.ts +0 -82
  44. package/test/contract/sequencerInboxForceInclude.spec.ts +0 -516
  45. package/test/contract/utils.ts +0 -40
  46. package/test/prover/hash-proofs.ts +0 -75
  47. package/test/prover/one-step-proof.ts +0 -93
  48. package/test/prover/proofs/.gitkeep +0 -0
  49. package/test/prover/value-arrays.ts +0 -11
  50. package/tsconfig.json +0 -13
@@ -1,869 +0,0 @@
1
- /*
2
- * Copyright 2019-2020, Offchain Labs, Inc.
3
- *
4
- * Licensed under the Apache License, Version 2.0 (the "License");
5
- * you may not use this file except in compliance with the License.
6
- * You may obtain a copy of the License at
7
- *
8
- * http://www.apache.org/licenses/LICENSE-2.0
9
- *
10
- * Unless required by applicable law or agreed to in writing, software
11
- * distributed under the License is distributed on an "AS IS" BASIS,
12
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- * See the License for the specific language governing permissions and
14
- * limitations under the License.
15
- */
16
-
17
- /* eslint-env node, mocha */
18
- import { ethers, run } from "hardhat";
19
- import { Signer } from "@ethersproject/abstract-signer";
20
- import { BigNumberish, BigNumber } from "@ethersproject/bignumber";
21
- import { BytesLike, hexConcat, zeroPad } from "@ethersproject/bytes";
22
- import { ContractTransaction } from "@ethersproject/contracts";
23
- import { assert, expect } from "chai";
24
- import {
25
- BridgeCreator__factory,
26
- ChallengeManager,
27
- ChallengeManager__factory,
28
- OneStepProofEntry__factory,
29
- OneStepProver0__factory,
30
- OneStepProverHostIo__factory,
31
- OneStepProverMath__factory,
32
- OneStepProverMemory__factory,
33
- RollupAdminLogic,
34
- RollupAdminLogic__factory,
35
- RollupCreator__factory,
36
- RollupUserLogic,
37
- RollupUserLogic__factory,
38
- SequencerInbox,
39
- SequencerInbox__factory,
40
- } from "../../build/types";
41
- import { initializeAccounts } from "./utils";
42
-
43
- import { Node, RollupContract, forceCreateNode, assertionEquals } from "./common/rolluplib";
44
- import { RollupLib } from "../../build/types/RollupUserLogic";
45
- type AssertionStruct = RollupLib.AssertionStruct;
46
- type ExecutionStateStruct = RollupLib.ExecutionStateStruct;
47
- import { keccak256 } from "ethers/lib/utils";
48
- import { ConfigStruct, RollupCreatedEvent } from "../../build/types/RollupCreator";
49
- import { constants } from "ethers";
50
- import { blockStateHash, MachineStatus } from "./common/challengeLib";
51
- import * as globalStateLib from "./common/globalStateLib";
52
- import { RollupChallengeStartedEvent } from "../../build/types/IRollupCore";
53
-
54
- const zerobytes32 = ethers.constants.HashZero;
55
- const stakeRequirement = 10;
56
- const stakeToken = ethers.constants.AddressZero;
57
- const confirmationPeriodBlocks = 100;
58
- const minimumAssertionPeriod = 75;
59
- const ZERO_ADDR = ethers.constants.AddressZero;
60
- const extraChallengeTimeBlocks = 20;
61
- const wasmModuleRoot = "0x9900000000000000000000000000000000000000000000000000000000000010";
62
-
63
- // let rollup: RollupContract
64
- let rollup: RollupContract;
65
- let rollupUser: RollupUserLogic;
66
- let rollupAdmin: RollupAdminLogic;
67
- let accounts: Signer[];
68
- let validators: Signer[];
69
- let sequencerInbox: SequencerInbox;
70
- let admin: Signer;
71
- let sequencer: Signer;
72
- let challengeManager: ChallengeManager;
73
-
74
- async function getDefaultConfig(
75
- _confirmPeriodBlocks = confirmationPeriodBlocks
76
- ): Promise<ConfigStruct> {
77
- return {
78
- baseStake: stakeRequirement,
79
- chainId: stakeToken,
80
- confirmPeriodBlocks: _confirmPeriodBlocks,
81
- extraChallengeTimeBlocks: extraChallengeTimeBlocks,
82
- owner: await accounts[0].getAddress(),
83
- sequencerInboxMaxTimeVariation: {
84
- delayBlocks: (60 * 60 * 24) / 15,
85
- futureBlocks: 12,
86
- delaySeconds: 60 * 60 * 24,
87
- futureSeconds: 60 * 60,
88
- },
89
- stakeToken: stakeToken,
90
- wasmModuleRoot: wasmModuleRoot,
91
- loserStakeEscrow: ZERO_ADDR,
92
- };
93
- }
94
-
95
- const setup = async () => {
96
- const accounts = await initializeAccounts();
97
- admin = accounts[0];
98
-
99
- const user = accounts[1];
100
-
101
- const val1 = accounts[2];
102
- const val2 = accounts[3];
103
- const val3 = accounts[4];
104
- const val4 = accounts[5];
105
- sequencer = accounts[6];
106
-
107
- const oneStep0Fac = (await ethers.getContractFactory(
108
- "OneStepProver0"
109
- )) as OneStepProver0__factory;
110
- const oneStep0 = await oneStep0Fac.deploy();
111
- const oneStepMemoryFac = (await ethers.getContractFactory(
112
- "OneStepProverMemory"
113
- )) as OneStepProverMemory__factory;
114
- const oneStepMemory = await oneStepMemoryFac.deploy();
115
- const oneStepMathFac = (await ethers.getContractFactory(
116
- "OneStepProverMath"
117
- )) as OneStepProverMath__factory;
118
- const oneStepMath = await oneStepMathFac.deploy();
119
- const oneStepHostIoFac = (await ethers.getContractFactory(
120
- "OneStepProverHostIo"
121
- )) as OneStepProverHostIo__factory;
122
- const oneStepHostIo = await oneStepHostIoFac.deploy();
123
-
124
- const oneStepProofEntryFac = (await ethers.getContractFactory(
125
- "OneStepProofEntry"
126
- )) as OneStepProofEntry__factory;
127
- const oneStepProofEntry = await oneStepProofEntryFac.deploy(
128
- oneStep0.address,
129
- oneStepMemory.address,
130
- oneStepMath.address,
131
- oneStepHostIo.address
132
- );
133
-
134
- const challengeManagerTemplateFac = (await ethers.getContractFactory(
135
- "ChallengeManager"
136
- )) as ChallengeManager__factory;
137
- const challengeManagerTemplate = await challengeManagerTemplateFac.deploy();
138
-
139
- const rollupAdminLogicFac = (await ethers.getContractFactory(
140
- "RollupAdminLogic"
141
- )) as RollupAdminLogic__factory;
142
- const rollupAdminLogicTemplate = await rollupAdminLogicFac.deploy();
143
-
144
- const rollupUserLogicFac = (await ethers.getContractFactory(
145
- "RollupUserLogic"
146
- )) as RollupUserLogic__factory;
147
- const rollupUserLogicTemplate = await rollupUserLogicFac.deploy();
148
-
149
- const bridgeCreatorFac = (await ethers.getContractFactory(
150
- "BridgeCreator"
151
- )) as BridgeCreator__factory;
152
- const bridgeCreator = await bridgeCreatorFac.deploy();
153
-
154
- const rollupCreatorFac = (await ethers.getContractFactory(
155
- "RollupCreator"
156
- )) as RollupCreator__factory;
157
- const rollupCreator = await rollupCreatorFac.deploy();
158
-
159
- await rollupCreator.setTemplates(
160
- bridgeCreator.address,
161
- oneStepProofEntry.address,
162
- challengeManagerTemplate.address,
163
- rollupAdminLogicTemplate.address,
164
- rollupUserLogicTemplate.address
165
- );
166
-
167
- const nonce = await rollupCreator.signer.provider!.getTransactionCount(rollupCreator.address);
168
- const expectedRollupAddress = ethers.utils.getContractAddress({
169
- from: rollupCreator.address,
170
- nonce: nonce + 2,
171
- });
172
-
173
- const response = await rollupCreator.createRollup(
174
- await getDefaultConfig(),
175
- expectedRollupAddress
176
- );
177
- const rec = await response.wait();
178
-
179
- const rollupCreatedEvent = rollupCreator.interface.parseLog(rec.logs[rec.logs.length - 1])
180
- .args as RollupCreatedEvent["args"];
181
-
182
- const rollupAdmin = rollupAdminLogicFac
183
- .attach(expectedRollupAddress)
184
- .connect(rollupCreator.signer);
185
- const rollupUser = rollupUserLogicFac.attach(expectedRollupAddress).connect(user);
186
-
187
- await rollupAdmin.setValidator(
188
- [await val1.getAddress(), await val2.getAddress(), await val3.getAddress()],
189
- [true, true, true]
190
- );
191
-
192
- await rollupAdmin.setIsBatchPoster(await sequencer.getAddress(), true);
193
-
194
- sequencerInbox = ((await ethers.getContractFactory(
195
- "SequencerInbox"
196
- )) as SequencerInbox__factory).attach(rollupCreatedEvent.sequencerInbox);
197
-
198
- challengeManager = ((await ethers.getContractFactory(
199
- "ChallengeManager"
200
- )) as ChallengeManager__factory).attach(await rollupUser.challengeManager());
201
-
202
- return {
203
- admin,
204
- user,
205
-
206
- rollupAdmin,
207
- rollupUser,
208
-
209
- validators: [val1, val2, val3, val4],
210
-
211
- rollupAdminLogicTemplate,
212
- rollupUserLogicTemplate,
213
- blockChallengeFactory: challengeManagerTemplateFac,
214
- rollupEventBridge: await rollupAdmin.rollupEventBridge(),
215
- outbox: await rollupAdmin.outbox(),
216
- sequencerInbox: rollupCreatedEvent.sequencerInbox,
217
- delayedBridge: rollupCreatedEvent.delayedBridge,
218
- };
219
- };
220
-
221
- async function tryAdvanceChain(blocks: number): Promise<void> {
222
- try {
223
- for (let i = 0; i < blocks; i++) {
224
- await ethers.provider.send("evm_mine", []);
225
- }
226
- } catch (e) {
227
- // EVM mine failed. Try advancing the chain by sending txes if the node
228
- // is in dev mode and mints blocks when txes are sent
229
- for (let i = 0; i < blocks; i++) {
230
- const tx = await accounts[0].sendTransaction({
231
- value: 0,
232
- to: await accounts[0].getAddress(),
233
- });
234
- await tx.wait();
235
- }
236
- }
237
- }
238
-
239
- async function advancePastAssertion(blockProposed: number): Promise<void> {
240
- await tryAdvanceChain(blockProposed + confirmationPeriodBlocks);
241
- }
242
-
243
- function newRandomExecutionState() {
244
- const blockHash = keccak256(ethers.utils.randomBytes(32));
245
- const sendRoot = keccak256(ethers.utils.randomBytes(32));
246
- const machineStatus = 1;
247
-
248
- return newExecutionState(blockHash, sendRoot, 1, 0, machineStatus);
249
- }
250
-
251
- function newExecutionState(
252
- blockHash: string,
253
- sendRoot: string,
254
- inboxPosition: BigNumberish,
255
- positionInMessage: BigNumberish,
256
- machineStatus: BigNumberish
257
- ): ExecutionStateStruct {
258
- return {
259
- globalState: {
260
- bytes32Vals: [blockHash, sendRoot],
261
- u64Vals: [inboxPosition, positionInMessage],
262
- },
263
- machineStatus,
264
- };
265
- }
266
-
267
- function newRandomAssertion(prevExecutionState: ExecutionStateStruct): AssertionStruct {
268
- return {
269
- beforeState: prevExecutionState,
270
- afterState: newRandomExecutionState(),
271
- numBlocks: 10,
272
- };
273
- }
274
-
275
- async function makeSimpleNode(
276
- rollup: RollupContract,
277
- sequencerInbox: SequencerInbox,
278
- parentNode: {
279
- assertion: { afterState: ExecutionStateStruct };
280
- nodeNum: number;
281
- nodeHash: BytesLike;
282
- inboxMaxCount: BigNumber;
283
- },
284
- siblingNode?: Node,
285
- prevNode?: Node,
286
- stakeToAdd?: BigNumber
287
- ): Promise<{ tx: ContractTransaction; node: Node }> {
288
- const staker = await rollup.rollup.getStaker(await rollup.rollup.signer.getAddress());
289
-
290
- const assertion = newRandomAssertion(parentNode.assertion.afterState);
291
- const { tx, node, expectedNewNodeHash } = await rollup.stakeOnNewNode(
292
- sequencerInbox,
293
- parentNode,
294
- assertion,
295
- siblingNode,
296
- stakeToAdd
297
- );
298
-
299
- expect(assertionEquals(assertion, node.assertion), "unexpected assertion").to.be.true;
300
- assert.equal(node.nodeNum, (prevNode || siblingNode || parentNode).nodeNum + 1);
301
- assert.equal(node.nodeHash, expectedNewNodeHash);
302
-
303
- if (stakeToAdd) {
304
- const stakerAfter = await rollup.rollup.getStaker(await rollup.rollup.signer.getAddress());
305
- expect(stakerAfter.latestStakedNode.toNumber()).to.eq(node.nodeNum);
306
- expect(stakerAfter.amountStaked.toString()).to.eq(
307
- staker.amountStaked.add(stakeToAdd).toString()
308
- );
309
- }
310
- return { tx, node };
311
- }
312
-
313
- const makeSends = (count: number, batchStart = 0) => {
314
- return [...Array(count)].map((_, i) =>
315
- hexConcat([[0], zeroPad([i + batchStart], 32), zeroPad([0], 32), zeroPad([1], 32)])
316
- );
317
- };
318
-
319
- let prevNode: Node;
320
- const prevNodes: Node[] = [];
321
-
322
- function updatePrevNode(node: Node) {
323
- prevNode = node;
324
- prevNodes.push(node);
325
- }
326
-
327
- describe("ArbRollup", () => {
328
- it("should deploy contracts", async function () {
329
- accounts = await initializeAccounts();
330
-
331
- await run("deploy", { tags: "test" });
332
- });
333
-
334
- it("should initialize", async function () {
335
- const {
336
- rollupAdmin: rollupAdminContract,
337
- rollupUser: rollupUserContract,
338
- user: userI,
339
- admin: adminI,
340
- validators: validatorsI,
341
- } = await setup();
342
- rollupAdmin = rollupAdminContract;
343
- rollupUser = rollupUserContract;
344
- admin = adminI;
345
- validators = validatorsI;
346
- rollup = new RollupContract(rollupUser.connect(validators[0]));
347
- });
348
-
349
- it("should only initialize once", async function () {
350
- await expect(
351
- rollupAdmin.initialize(await getDefaultConfig(), {
352
- challengeManager: constants.AddressZero,
353
- delayedBridge: constants.AddressZero,
354
- outbox: constants.AddressZero,
355
- rollupAdminLogic: constants.AddressZero,
356
- rollupEventBridge: constants.AddressZero,
357
- rollupUserLogic: constants.AddressZero,
358
- sequencerInbox: constants.AddressZero,
359
- })
360
- ).to.be.revertedWith("Initializable: contract is already initialized");
361
- });
362
-
363
- it("should place stake on new node", async function () {
364
- await tryAdvanceChain(minimumAssertionPeriod);
365
-
366
- const initNode: {
367
- assertion: { afterState: ExecutionStateStruct };
368
- nodeNum: number;
369
- nodeHash: BytesLike;
370
- inboxMaxCount: BigNumber;
371
- } = {
372
- assertion: {
373
- afterState: {
374
- globalState: {
375
- bytes32Vals: [zerobytes32, zerobytes32],
376
- u64Vals: [0, 0],
377
- },
378
- machineStatus: MachineStatus.FINISHED,
379
- },
380
- },
381
- inboxMaxCount: BigNumber.from(1),
382
- nodeHash: zerobytes32,
383
- nodeNum: 0,
384
- };
385
-
386
- const stake = await rollup.currentRequiredStake();
387
- const { node } = await makeSimpleNode(
388
- rollup,
389
- sequencerInbox,
390
- initNode,
391
- undefined,
392
- undefined,
393
- stake
394
- );
395
- updatePrevNode(node);
396
- });
397
-
398
- it("should let a new staker place on existing node", async function () {
399
- const stake = await rollup.currentRequiredStake();
400
- await rollupUser
401
- .connect(validators[2])
402
- .newStakeOnExistingNode(1, prevNode.nodeHash, { value: stake });
403
- });
404
-
405
- it("should move stake to a new node", async function () {
406
- await tryAdvanceChain(minimumAssertionPeriod);
407
- const { node } = await makeSimpleNode(rollup, sequencerInbox, prevNode);
408
- updatePrevNode(node);
409
- });
410
-
411
- it("should let the second staker place on the new node", async function () {
412
- await rollup.connect(validators[2]).stakeOnExistingNode(2, prevNode.nodeHash);
413
- });
414
-
415
- it("should confirm node", async function () {
416
- await tryAdvanceChain(confirmationPeriodBlocks * 2);
417
-
418
- await rollup.confirmNextNode(prevNodes[0]);
419
- });
420
-
421
- it("should confirm next node", async function () {
422
- await tryAdvanceChain(minimumAssertionPeriod);
423
- await rollup.confirmNextNode(prevNodes[1]);
424
- });
425
-
426
- let challengedNode: Node;
427
- let validNode: Node;
428
- it("should let the first staker make another node", async function () {
429
- await tryAdvanceChain(minimumAssertionPeriod);
430
- const { node } = await makeSimpleNode(rollup, sequencerInbox, prevNode);
431
- challengedNode = node;
432
- validNode = node;
433
- });
434
-
435
- let challengerNode: Node;
436
- it("should let the second staker make a conflicting node", async function () {
437
- await tryAdvanceChain(minimumAssertionPeriod);
438
- const { node } = await makeSimpleNode(
439
- rollup.connect(validators[2]),
440
- sequencerInbox,
441
- prevNode,
442
- validNode
443
- );
444
- challengerNode = node;
445
- });
446
-
447
- it("should fail to confirm first staker node", async function () {
448
- await advancePastAssertion(challengedNode.proposedBlock);
449
- await expect(rollup.confirmNextNode(validNode)).to.be.revertedWith("NOT_ALL_STAKED");
450
- });
451
-
452
- let challengeIndex: number;
453
- it("should initiate a challenge", async function () {
454
- const tx = rollup.createChallenge(
455
- await validators[0].getAddress(),
456
- await validators[2].getAddress(),
457
- challengedNode,
458
- challengerNode
459
- );
460
- const receipt = await (await tx).wait();
461
- const ev = rollup.rollup.interface.parseLog(receipt.logs![receipt.logs!.length - 1]);
462
- expect(ev.name).to.equal("RollupChallengeStarted");
463
-
464
- const parsedEv = ev.args as RollupChallengeStartedEvent["args"];
465
- challengeIndex = parsedEv.challengeIndex.toNumber();
466
- });
467
-
468
- it("should make a new node", async function () {
469
- const { node } = await makeSimpleNode(
470
- rollup,
471
- sequencerInbox,
472
- validNode,
473
- undefined,
474
- challengerNode
475
- );
476
- challengedNode = node;
477
- });
478
-
479
- it("new staker should make a conflicting node", async function () {
480
- const stake = await rollup.currentRequiredStake();
481
- await rollup.rollup
482
- .connect(validators[1])
483
- .newStakeOnExistingNode(3, validNode.nodeHash, { value: stake.add(50) });
484
-
485
- const { node } = await makeSimpleNode(
486
- rollup.connect(validators[1]),
487
- sequencerInbox,
488
- validNode,
489
- challengedNode
490
- );
491
- challengerNode = node;
492
- });
493
-
494
- it("asserter should win via timeout", async function () {
495
- await advancePastAssertion(challengedNode.proposedBlock);
496
- await challengeManager.connect(validators[0]).timeout(challengeIndex);
497
- });
498
-
499
- it("confirm first staker node", async function () {
500
- await rollup.confirmNextNode(validNode);
501
- });
502
-
503
- it("should reject out of order second node", async function () {
504
- await rollup.rejectNextNode(stakeToken);
505
- });
506
-
507
- it("should initiate another challenge", async function () {
508
- const tx = rollup.createChallenge(
509
- await validators[0].getAddress(),
510
- await validators[1].getAddress(),
511
- challengedNode,
512
- challengerNode
513
- );
514
- const receipt = await (await tx).wait();
515
- const ev = rollup.rollup.interface.parseLog(receipt.logs![receipt.logs!.length - 1]);
516
- expect(ev.name).to.equal("RollupChallengeStarted");
517
- const parsedEv = ev.args as RollupChallengeStartedEvent["args"];
518
- challengeIndex = parsedEv.challengeIndex.toNumber();
519
-
520
- await expect(
521
- rollup.rollup.completeChallenge(
522
- challengeIndex,
523
- await sequencer.getAddress(),
524
- await validators[3].getAddress()
525
- )
526
- ).to.be.revertedWith("WRONG_SENDER");
527
- });
528
-
529
- it("challenger should reply in challenge", async function () {
530
- const seg0 = blockStateHash(
531
- BigNumber.from(challengerNode.assertion.beforeState.machineStatus),
532
- globalStateLib.hash(challengerNode.assertion.beforeState.globalState)
533
- );
534
-
535
- const seg1 = blockStateHash(
536
- BigNumber.from(challengedNode.assertion.afterState.machineStatus),
537
- globalStateLib.hash(challengedNode.assertion.afterState.globalState)
538
- );
539
- await challengeManager.connect(validators[1]).bisectExecution(
540
- challengeIndex,
541
- {
542
- challengePosition: BigNumber.from(0),
543
- oldSegments: [seg0, seg1],
544
- oldSegmentsLength: BigNumber.from(challengedNode.assertion.numBlocks),
545
- oldSegmentsStart: 0,
546
- },
547
- [
548
- seg0,
549
- zerobytes32,
550
- zerobytes32,
551
- zerobytes32,
552
- zerobytes32,
553
- zerobytes32,
554
- zerobytes32,
555
- zerobytes32,
556
- zerobytes32,
557
- zerobytes32,
558
- zerobytes32,
559
- ]
560
- );
561
- });
562
-
563
- it("challenger should win via timeout", async function () {
564
- await advancePastAssertion(challengedNode.proposedBlock);
565
- await challengeManager.timeout(challengeIndex);
566
- });
567
-
568
- it("should reject out of order second node", async function () {
569
- await rollup.rejectNextNode(await validators[1].getAddress());
570
- });
571
-
572
- it("confirm next node", async function () {
573
- await tryAdvanceChain(confirmationPeriodBlocks);
574
- await rollup.confirmNextNode(challengerNode);
575
- });
576
-
577
- it("should add and remove stakes correctly", async function () {
578
- /*
579
- RollupUser functions that alter stake and their respective Core logic
580
-
581
- user: newStake
582
- core: createNewStake
583
-
584
- user: addToDeposit
585
- core: increaseStakeBy
586
-
587
- user: reduceDeposit
588
- core: reduceStakeTo
589
-
590
- user: returnOldDeposit
591
- core: withdrawStaker
592
-
593
- user: withdrawStakerFunds
594
- core: withdrawFunds
595
- */
596
-
597
- const initialStake = await rollup.rollup.amountStaked(await validators[1].getAddress());
598
-
599
- await rollup.connect(validators[1]).reduceDeposit(initialStake);
600
-
601
- await expect(
602
- rollup.connect(validators[1]).reduceDeposit(initialStake.add(1))
603
- ).to.be.revertedWith("TOO_LITTLE_STAKE");
604
-
605
- await rollup
606
- .connect(validators[1])
607
- .addToDeposit(await validators[1].getAddress(), { value: 5 });
608
-
609
- await rollup.connect(validators[1]).reduceDeposit(5);
610
-
611
- const prevBalance = await validators[1].getBalance();
612
- const prevWithdrawablefunds = await rollup.rollup.withdrawableFunds(
613
- await validators[1].getAddress()
614
- );
615
-
616
- const tx = await rollup.rollup
617
- .connect(validators[1])
618
- .withdrawStakerFunds(await validators[1].getAddress());
619
- const receipt = await tx.wait();
620
- const gasPaid = receipt.gasUsed.mul(receipt.effectiveGasPrice);
621
-
622
- const postBalance = await validators[1].getBalance();
623
- const postWithdrawablefunds = await rollup.rollup.withdrawableFunds(
624
- await validators[1].getAddress()
625
- );
626
-
627
- expect(postWithdrawablefunds).to.equal(0);
628
- expect(postBalance.add(gasPaid)).to.equal(prevBalance.add(prevWithdrawablefunds));
629
-
630
- // this gets deposit and removes staker
631
- await rollup.rollup.connect(validators[1]).returnOldDeposit(await validators[1].getAddress());
632
- // all stake is now removed
633
- });
634
-
635
- it("should allow removing zombies", async function () {
636
- const zombieCount = (await rollup.rollup.connect(validators[2]).zombieCount()).toNumber();
637
- for (let i = 0; i < zombieCount; i++) {
638
- await rollup.rollup.connect(validators[2]).removeZombie(0, 1024);
639
- }
640
- });
641
-
642
- it("should pause the contracts then resume", async function () {
643
- const prevIsPaused = await rollup.rollup.paused();
644
- expect(prevIsPaused).to.equal(false);
645
-
646
- await rollupAdmin.pause();
647
-
648
- const postIsPaused = await rollup.rollup.paused();
649
- expect(postIsPaused).to.equal(true);
650
-
651
- await expect(
652
- rollup.connect(validators[1]).addToDeposit(await validators[1].getAddress(), { value: 5 })
653
- ).to.be.revertedWith("Pausable: paused");
654
-
655
- await rollupAdmin.resume();
656
- });
657
-
658
- it("should allow admin to alter rollup while paused", async function () {
659
- const prevLatestConfirmed = await rollup.rollup.latestConfirmed();
660
- expect(prevLatestConfirmed.toNumber()).to.equal(6);
661
- // prevNode is prevLatestConfirmed
662
- prevNode = challengerNode;
663
-
664
- const stake = await rollup.currentRequiredStake();
665
-
666
- const { node: node1 } = await makeSimpleNode(
667
- rollup,
668
- sequencerInbox,
669
- prevNode,
670
- undefined,
671
- undefined,
672
- stake
673
- );
674
- const node1Num = await rollup.rollup.latestNodeCreated();
675
- expect(node1Num.toNumber(), "node1num").to.eq(node1.nodeNum);
676
-
677
- await tryAdvanceChain(minimumAssertionPeriod);
678
-
679
- const { node: node2 } = await makeSimpleNode(
680
- rollup.connect(validators[2]),
681
- sequencerInbox,
682
- prevNode,
683
- node1,
684
- undefined,
685
- stake
686
- );
687
- const node2Num = await rollup.rollup.latestNodeCreated();
688
- expect(node2Num.toNumber(), "node2num").to.eq(node2.nodeNum);
689
-
690
- const tx = await rollup.createChallenge(
691
- await validators[0].getAddress(),
692
- await validators[2].getAddress(),
693
- node1,
694
- node2
695
- );
696
- const receipt = await tx.wait();
697
- const ev = rollup.rollup.interface.parseLog(receipt.logs![receipt.logs!.length - 1]);
698
- expect(ev.name).to.equal("RollupChallengeStarted");
699
- const parsedEv = ev.args as RollupChallengeStartedEvent["args"];
700
- challengeIndex = parsedEv.challengeIndex.toNumber();
701
-
702
- expect(await challengeManager.currentResponder(challengeIndex), "turn challenger").to.eq(
703
- await validators[2].getAddress()
704
- );
705
-
706
- await expect(
707
- rollupAdmin.forceResolveChallenge(
708
- [await validators[0].getAddress()],
709
- [await validators[2].getAddress()]
710
- ),
711
- "force resolve"
712
- ).to.be.revertedWith("Pausable: not paused");
713
-
714
- await expect(
715
- rollup.createChallenge(
716
- await validators[0].getAddress(),
717
- await validators[2].getAddress(),
718
- node1,
719
- node2
720
- ),
721
- "create challenge"
722
- ).to.be.revertedWith("IN_CHAL");
723
-
724
- await rollupAdmin.pause();
725
-
726
- await rollupAdmin.forceResolveChallenge(
727
- [await validators[0].getAddress()],
728
- [await validators[2].getAddress()]
729
- );
730
-
731
- // challenge should have been destroyed
732
- expect(await challengeManager.currentResponder(challengeIndex), "turn reset").to.equal(
733
- constants.AddressZero
734
- );
735
-
736
- const challengeA = await rollupAdmin.currentChallenge(await validators[0].getAddress());
737
- const challengeB = await rollupAdmin.currentChallenge(await validators[2].getAddress());
738
-
739
- expect(challengeA).to.equal(ZERO_ADDR);
740
- expect(challengeB).to.equal(ZERO_ADDR);
741
-
742
- await rollupAdmin.forceRefundStaker([
743
- await validators[0].getAddress(),
744
- await validators[2].getAddress(),
745
- ]);
746
-
747
- const adminAssertion = newRandomAssertion(prevNode.assertion.afterState);
748
- const { node: forceCreatedNode1 } = await forceCreateNode(
749
- rollupAdmin,
750
- sequencerInbox,
751
- prevNode,
752
- adminAssertion,
753
- node2
754
- );
755
- expect(assertionEquals(forceCreatedNode1.assertion, adminAssertion), "assertion error").to.be
756
- .true;
757
-
758
- const adminNodeNum = await rollup.rollup.latestNodeCreated();
759
- const midLatestConfirmed = await rollup.rollup.latestConfirmed();
760
- expect(midLatestConfirmed.toNumber()).to.equal(6);
761
-
762
- expect(adminNodeNum.toNumber()).to.equal(node2Num.toNumber() + 1);
763
-
764
- const adminAssertion2 = newRandomAssertion(prevNode.assertion.afterState);
765
- const { node: forceCreatedNode2 } = await forceCreateNode(
766
- rollupAdmin,
767
- sequencerInbox,
768
- prevNode,
769
- adminAssertion2,
770
- forceCreatedNode1
771
- );
772
-
773
- const postLatestCreated = await rollup.rollup.latestNodeCreated();
774
-
775
- await rollupAdmin.forceConfirmNode(
776
- adminNodeNum,
777
- adminAssertion.afterState.globalState.bytes32Vals[0],
778
- adminAssertion.afterState.globalState.bytes32Vals[1]
779
- );
780
-
781
- const postLatestConfirmed = await rollup.rollup.latestConfirmed();
782
- expect(postLatestCreated).to.equal(adminNodeNum.add(1));
783
- expect(postLatestConfirmed).to.equal(adminNodeNum);
784
-
785
- await rollupAdmin.resume();
786
-
787
- // should create node after resuming
788
-
789
- prevNode = forceCreatedNode1;
790
-
791
- await tryAdvanceChain(minimumAssertionPeriod);
792
-
793
- await expect(
794
- makeSimpleNode(
795
- rollup.connect(validators[2]),
796
- sequencerInbox,
797
- prevNode,
798
- undefined,
799
- forceCreatedNode2,
800
- stake
801
- )
802
- ).to.be.revertedWith("STAKER_IS_ZOMBIE");
803
-
804
- await expect(
805
- makeSimpleNode(rollup.connect(validators[2]), sequencerInbox, prevNode)
806
- ).to.be.revertedWith("NOT_STAKED");
807
-
808
- await rollup.rollup.connect(validators[2]).removeOldZombies(0);
809
-
810
- await makeSimpleNode(
811
- rollup.connect(validators[2]),
812
- sequencerInbox,
813
- prevNode,
814
- undefined,
815
- forceCreatedNode2,
816
- stake
817
- );
818
- });
819
-
820
- it("should initialize a fresh rollup", async function () {
821
- const {
822
- rollupAdmin: rollupAdminContract,
823
- rollupUser: rollupUserContract,
824
- user: userI,
825
- admin: adminI,
826
- validators: validatorsI,
827
- } = await setup();
828
- rollupAdmin = rollupAdminContract;
829
- rollupUser = rollupUserContract;
830
- admin = adminI;
831
- validators = validatorsI;
832
- rollup = new RollupContract(rollupUser.connect(validators[0]));
833
- });
834
-
835
- it("should stake on initial node again", async function () {
836
- await tryAdvanceChain(minimumAssertionPeriod);
837
-
838
- const initNode: {
839
- assertion: { afterState: ExecutionStateStruct };
840
- nodeNum: number;
841
- nodeHash: BytesLike;
842
- inboxMaxCount: BigNumber;
843
- } = {
844
- assertion: {
845
- afterState: {
846
- globalState: {
847
- bytes32Vals: [zerobytes32, zerobytes32],
848
- u64Vals: [0, 0],
849
- },
850
- machineStatus: MachineStatus.FINISHED,
851
- },
852
- },
853
- inboxMaxCount: BigNumber.from(1),
854
- nodeHash: zerobytes32,
855
- nodeNum: 0,
856
- };
857
-
858
- const stake = await rollup.currentRequiredStake();
859
- const { node } = await makeSimpleNode(
860
- rollup,
861
- sequencerInbox,
862
- initNode,
863
- undefined,
864
- undefined,
865
- stake
866
- );
867
- updatePrevNode(node);
868
- });
869
- });