@arbitrum/nitro-contracts 1.0.0-beta.8 → 1.0.0

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 (37) hide show
  1. package/package.json +10 -2
  2. package/src/bridge/Bridge.sol +39 -30
  3. package/src/bridge/IBridge.sol +56 -29
  4. package/src/bridge/IInbox.sol +130 -15
  5. package/src/bridge/IOutbox.sol +55 -7
  6. package/src/bridge/ISequencerInbox.sol +84 -7
  7. package/src/bridge/Inbox.sol +154 -92
  8. package/src/bridge/Outbox.sol +23 -47
  9. package/src/bridge/SequencerInbox.sol +132 -62
  10. package/src/challenge/ChallengeManager.sol +0 -9
  11. package/src/challenge/IChallengeManager.sol +0 -2
  12. package/src/libraries/AdminFallbackProxy.sol +4 -4
  13. package/src/libraries/Constants.sol +3 -0
  14. package/src/libraries/{SecondaryLogicUUPSUpgradeable.sol → DoubleLogicUUPSUpgradeable.sol} +2 -1
  15. package/src/libraries/Error.sol +12 -0
  16. package/src/libraries/IGasRefunder.sol +11 -5
  17. package/src/libraries/MerkleLib.sol +5 -3
  18. package/src/mocks/BridgeStub.sol +20 -1
  19. package/src/mocks/BridgeUnproxied.sol +17 -0
  20. package/src/mocks/InboxStub.sol +48 -3
  21. package/src/mocks/SequencerInboxStub.sol +13 -3
  22. package/src/mocks/Simple.sol +69 -0
  23. package/src/node-interface/NodeInterface.sol +35 -4
  24. package/src/precompiles/ArbGasInfo.sol +7 -4
  25. package/src/precompiles/ArbOwner.sol +9 -0
  26. package/src/precompiles/ArbOwnerPublic.sol +3 -0
  27. package/src/precompiles/ArbSys.sol +5 -2
  28. package/src/rollup/IRollupCore.sol +2 -0
  29. package/src/rollup/IRollupLogic.sol +10 -0
  30. package/src/rollup/RollupAdminLogic.sol +27 -3
  31. package/src/rollup/RollupCore.sol +3 -0
  32. package/src/rollup/RollupCreator.sol +3 -3
  33. package/src/rollup/RollupEventInbox.sol +3 -6
  34. package/src/{libraries/ArbitrumProxy.sol → rollup/RollupProxy.sol} +3 -3
  35. package/src/rollup/RollupUserLogic.sol +47 -10
  36. package/src/test-helpers/BridgeTester.sol +7 -1
  37. package/src/test-helpers/OutboxWithoutOptTester.sol +8 -8
@@ -9,6 +9,7 @@ import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
9
9
  import {IRollupUser} from "./IRollupLogic.sol";
10
10
  import "../libraries/UUPSNotUpgradeable.sol";
11
11
  import "./RollupCore.sol";
12
+ import {ETH_POS_BLOCK_TIME} from "../libraries/Constants.sol";
12
13
 
13
14
  abstract contract AbsRollupUserLogic is
14
15
  RollupCore,
@@ -20,10 +21,43 @@ abstract contract AbsRollupUserLogic is
20
21
  using GlobalStateLib for GlobalState;
21
22
 
22
23
  modifier onlyValidator() {
23
- require(isValidator[msg.sender], "NOT_VALIDATOR");
24
+ require(isValidator[msg.sender] || validatorWhitelistDisabled, "NOT_VALIDATOR");
24
25
  _;
25
26
  }
26
27
 
28
+ uint256 internal immutable deployTimeChainId = block.chainid;
29
+
30
+ function _chainIdChanged() internal view returns (bool) {
31
+ return deployTimeChainId != block.chainid;
32
+ }
33
+
34
+ /**
35
+ * @notice Extra number of blocks the validator can remain inactive before considered inactive
36
+ * This is 7 days assuming a 13.2 seconds block time
37
+ */
38
+ uint256 public constant VALIDATOR_AFK_BLOCKS = 45818;
39
+
40
+ function _validatorIsAfk() internal view returns (bool) {
41
+ Node memory latestNode = getNodeStorage(latestNodeCreated());
42
+ if (latestNode.createdAtBlock == 0) return false;
43
+ if (latestNode.createdAtBlock + confirmPeriodBlocks + VALIDATOR_AFK_BLOCKS < block.number) {
44
+ return true;
45
+ }
46
+ return false;
47
+ }
48
+
49
+ function removeWhitelistAfterFork() external {
50
+ require(!validatorWhitelistDisabled, "WHITELIST_DISABLED");
51
+ require(_chainIdChanged(), "CHAIN_ID_NOT_CHANGED");
52
+ validatorWhitelistDisabled = true;
53
+ }
54
+
55
+ function removeWhitelistAfterValidatorAfk() external {
56
+ require(!validatorWhitelistDisabled, "WHITELIST_DISABLED");
57
+ require(_validatorIsAfk(), "VALIDATOR_NOT_AFK");
58
+ validatorWhitelistDisabled = true;
59
+ }
60
+
27
61
  function isERC20Enabled() public view override returns (bool) {
28
62
  return stakeToken != address(0);
29
63
  }
@@ -239,7 +273,7 @@ abstract contract AbsRollupUserLogic is
239
273
  * @param globalStates The before and after global state for the first assertion
240
274
  * @param numBlocks The number of L2 blocks contained in the first assertion
241
275
  * @param secondExecutionHash The execution hash of the second assertion
242
- * @param proposedTimes Times that the two nodes were proposed
276
+ * @param proposedBlocks L1 block numbers that the two nodes were proposed at
243
277
  * @param wasmModuleRoots The wasm module roots at the time of the creation of each assertion
244
278
  */
245
279
  function createChallenge(
@@ -249,7 +283,7 @@ abstract contract AbsRollupUserLogic is
249
283
  GlobalState[2] calldata globalStates,
250
284
  uint64 numBlocks,
251
285
  bytes32 secondExecutionHash,
252
- uint256[2] calldata proposedTimes,
286
+ uint256[2] calldata proposedBlocks,
253
287
  bytes32[2] calldata wasmModuleRoots
254
288
  ) external onlyValidator whenNotPaused {
255
289
  require(nodeNums[0] < nodeNums[1], "WRONG_ORDER");
@@ -274,7 +308,7 @@ abstract contract AbsRollupUserLogic is
274
308
  node1.challengeHash ==
275
309
  RollupLib.challengeRootHash(
276
310
  RollupLib.executionHash(machineStatuses, globalStates, numBlocks),
277
- proposedTimes[0],
311
+ proposedBlocks[0],
278
312
  wasmModuleRoots[0]
279
313
  ),
280
314
  "CHAL_HASH1"
@@ -284,18 +318,18 @@ abstract contract AbsRollupUserLogic is
284
318
  node2.challengeHash ==
285
319
  RollupLib.challengeRootHash(
286
320
  secondExecutionHash,
287
- proposedTimes[1],
321
+ proposedBlocks[1],
288
322
  wasmModuleRoots[1]
289
323
  ),
290
324
  "CHAL_HASH2"
291
325
  );
292
326
 
293
327
  // Calculate upper limit for allowed node proposal time:
294
- uint256 commonEndTime = getNodeStorage(node1.prevNum).firstChildBlock +
328
+ uint256 commonEndBlock = getNodeStorage(node1.prevNum).firstChildBlock +
295
329
  // Dispute start: dispute timer for a node starts when its first child is created
296
- (node1.deadlineBlock - proposedTimes[0]) +
330
+ (node1.deadlineBlock - proposedBlocks[0]) +
297
331
  extraChallengeTimeBlocks; // add dispute window to dispute start time
298
- if (commonEndTime < proposedTimes[1]) {
332
+ if (commonEndBlock < proposedBlocks[1]) {
299
333
  // The 2nd node was created too late; loses challenge automatically.
300
334
  completeChallengeImpl(stakers[0], stakers[1]);
301
335
  return;
@@ -307,8 +341,9 @@ abstract contract AbsRollupUserLogic is
307
341
  globalStates,
308
342
  numBlocks,
309
343
  wasmModuleRoots,
310
- commonEndTime - proposedTimes[0],
311
- commonEndTime - proposedTimes[1]
344
+ // convert from block counts to real second based timestamps
345
+ (commonEndBlock - proposedBlocks[0]) * ETH_POS_BLOCK_TIME,
346
+ (commonEndBlock - proposedBlocks[1]) * ETH_POS_BLOCK_TIME
312
347
  ); // trusted external call
313
348
 
314
349
  challengeStarted(stakers[0], stakers[1], challengeIndex);
@@ -366,6 +401,8 @@ abstract contract AbsRollupUserLogic is
366
401
  uint256 amountWon = remainingLoserStake / 2;
367
402
  increaseStakeBy(winningStaker, amountWon);
368
403
  remainingLoserStake -= amountWon;
404
+ // We deliberately leave loser in challenge state to prevent them from
405
+ // doing certain thing that are allowed only to parties not in a challenge
369
406
  clearChallenge(winningStaker);
370
407
  // Credit the other half to the loserStakeEscrow address
371
408
  increaseWithdrawableFunds(loserStakeEscrow, remainingLoserStake);
@@ -64,6 +64,7 @@ contract BridgeTester is Initializable, DelegateCallAware, IBridge {
64
64
  bytes32[] public override delayedInboxAccs;
65
65
 
66
66
  bytes32[] public override sequencerInboxAccs;
67
+ uint256 public override sequencerReportedSubMessageCount;
67
68
 
68
69
  address private constant EMPTY_ACTIVEOUTBOX = address(type(uint160).max);
69
70
 
@@ -85,7 +86,12 @@ contract BridgeTester is Initializable, DelegateCallAware, IBridge {
85
86
  return allowedOutboxesMap[outbox].allowed;
86
87
  }
87
88
 
88
- function enqueueSequencerMessage(bytes32 dataHash, uint256 afterDelayedMessagesRead)
89
+ function enqueueSequencerMessage(
90
+ bytes32 dataHash,
91
+ uint256 afterDelayedMessagesRead,
92
+ uint256 prevMessageCount,
93
+ uint256 newMessageCount
94
+ )
89
95
  external
90
96
  returns (
91
97
  uint256 seqMessageIndex,
@@ -22,7 +22,11 @@ contract OutboxWithoutOptTester is DelegateCallAware, IOutbox {
22
22
  address public rollup; // the rollup contract
23
23
  IBridge public bridge; // the bridge contract
24
24
 
25
- mapping(uint256 => bool) public spent; // maps leaf number => if spent
25
+ function spent(uint256) external pure override returns (bytes32) {
26
+ revert("NOT_IMPLEMETED");
27
+ }
28
+
29
+ mapping(uint256 => bool) public isSpent; // maps leaf number => if spent
26
30
  mapping(bytes32 => bytes32) public roots; // maps root hashes => L2 block hash
27
31
 
28
32
  struct L2ToL1Context {
@@ -70,7 +74,7 @@ contract OutboxWithoutOptTester is DelegateCallAware, IOutbox {
70
74
  }
71
75
 
72
76
  // @deprecated batch number is now always 0
73
- function l2ToL1BatchNum() external pure override returns (uint256) {
77
+ function l2ToL1BatchNum() external pure returns (uint256) {
74
78
  return 0;
75
79
  }
76
80
 
@@ -150,10 +154,6 @@ contract OutboxWithoutOptTester is DelegateCallAware, IOutbox {
150
154
  revert("Not implemented");
151
155
  }
152
156
 
153
- function isSpent(uint256) external pure override returns (bool) {
154
- revert("Not implemented");
155
- }
156
-
157
157
  function recordOutputAsSpent(
158
158
  bytes32[] memory proof,
159
159
  uint256 index,
@@ -166,8 +166,8 @@ contract OutboxWithoutOptTester is DelegateCallAware, IOutbox {
166
166
  bytes32 calcRoot = calculateMerkleRoot(proof, index, item);
167
167
  if (roots[calcRoot] == bytes32(0)) revert UnknownRoot(calcRoot);
168
168
 
169
- if (spent[index]) revert AlreadySpent(index);
170
- spent[index] = true;
169
+ if (isSpent[index]) revert AlreadySpent(index);
170
+ isSpent[index] = true;
171
171
 
172
172
  return bytes32(index);
173
173
  }