@arbitrum/nitro-contracts 1.0.0-beta.7 → 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 (42) hide show
  1. package/package.json +13 -2
  2. package/src/bridge/Bridge.sol +49 -29
  3. package/src/bridge/IBridge.sol +58 -45
  4. package/src/bridge/IDelayedMessageProvider.sol +2 -1
  5. package/src/bridge/IInbox.sol +133 -50
  6. package/src/bridge/IOutbox.sol +95 -27
  7. package/src/bridge/IOwnable.sol +2 -1
  8. package/src/bridge/ISequencerInbox.sol +79 -31
  9. package/src/bridge/Inbox.sol +171 -108
  10. package/src/bridge/Outbox.sol +26 -41
  11. package/src/bridge/SequencerInbox.sol +152 -62
  12. package/src/challenge/ChallengeManager.sol +0 -9
  13. package/src/challenge/IChallengeManager.sol +0 -2
  14. package/src/libraries/AdminFallbackProxy.sol +4 -4
  15. package/src/libraries/Constants.sol +3 -0
  16. package/src/libraries/{SecondaryLogicUUPSUpgradeable.sol → DoubleLogicUUPSUpgradeable.sol} +2 -1
  17. package/src/libraries/Error.sol +119 -0
  18. package/src/libraries/IGasRefunder.sol +13 -6
  19. package/src/libraries/MerkleLib.sol +5 -3
  20. package/src/mocks/BridgeStub.sol +22 -1
  21. package/src/mocks/BridgeUnproxied.sol +17 -0
  22. package/src/mocks/InboxStub.sol +49 -2
  23. package/src/mocks/SequencerInboxStub.sol +13 -3
  24. package/src/mocks/Simple.sol +69 -0
  25. package/src/node-interface/NodeInterface.sol +69 -7
  26. package/src/precompiles/ArbGasInfo.sol +16 -4
  27. package/src/precompiles/ArbOwner.sol +18 -0
  28. package/src/precompiles/ArbOwnerPublic.sol +3 -0
  29. package/src/precompiles/ArbSys.sol +7 -4
  30. package/src/rollup/IRollupCore.sol +2 -0
  31. package/src/rollup/IRollupLogic.sol +10 -0
  32. package/src/rollup/RollupAdminLogic.sol +69 -3
  33. package/src/rollup/RollupCore.sol +8 -2
  34. package/src/rollup/RollupCreator.sol +3 -3
  35. package/src/rollup/RollupEventInbox.sol +3 -6
  36. package/src/rollup/RollupLib.sol +1 -0
  37. package/src/{libraries/ArbitrumProxy.sol → rollup/RollupProxy.sol} +3 -3
  38. package/src/rollup/RollupUserLogic.sol +47 -10
  39. package/src/state/GlobalState.sol +7 -0
  40. package/src/test-helpers/BridgeTester.sol +17 -1
  41. package/src/test-helpers/InterfaceCompatibilityTester.sol +11 -0
  42. package/src/test-helpers/OutboxWithoutOptTester.sol +33 -7
@@ -10,7 +10,7 @@ import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
10
10
  import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
11
11
  import "@openzeppelin/contracts/access/Ownable.sol";
12
12
 
13
- import "../libraries/ArbitrumProxy.sol";
13
+ import "./RollupProxy.sol";
14
14
 
15
15
  contract RollupCreator is Ownable {
16
16
  event RollupCreated(
@@ -59,7 +59,7 @@ contract RollupCreator is Ownable {
59
59
  IInbox inbox;
60
60
  IRollupEventInbox rollupEventInbox;
61
61
  IOutbox outbox;
62
- ArbitrumProxy rollup;
62
+ RollupProxy rollup;
63
63
  }
64
64
 
65
65
  // After this setup:
@@ -104,7 +104,7 @@ contract RollupCreator is Ownable {
104
104
  osp
105
105
  );
106
106
 
107
- frame.rollup = new ArbitrumProxy(
107
+ frame.rollup = new RollupProxy(
108
108
  config,
109
109
  ContractDependencies({
110
110
  bridge: frame.bridge,
@@ -9,16 +9,12 @@ import "../bridge/IBridge.sol";
9
9
  import "../bridge/IDelayedMessageProvider.sol";
10
10
  import "../libraries/DelegateCallAware.sol";
11
11
  import {INITIALIZATION_MSG_TYPE} from "../libraries/MessageTypes.sol";
12
+ import {AlreadyInit, HadZeroInit} from "../libraries/Error.sol";
12
13
 
13
14
  /**
14
15
  * @title The inbox for rollup protocol events
15
16
  */
16
17
  contract RollupEventInbox is IRollupEventInbox, IDelayedMessageProvider, DelegateCallAware {
17
- uint8 internal constant CREATE_NODE_EVENT = 0;
18
- uint8 internal constant CONFIRM_NODE_EVENT = 1;
19
- uint8 internal constant REJECT_NODE_EVENT = 2;
20
- uint8 internal constant STAKE_CREATED_EVENT = 3;
21
-
22
18
  IBridge public override bridge;
23
19
  address public override rollup;
24
20
 
@@ -28,7 +24,8 @@ contract RollupEventInbox is IRollupEventInbox, IDelayedMessageProvider, Delegat
28
24
  }
29
25
 
30
26
  function initialize(IBridge _bridge) external override onlyDelegated {
31
- require(address(bridge) == address(0), "ALREADY_INIT");
27
+ if (address(bridge) != address(0)) revert AlreadyInit();
28
+ if (address(_bridge) == address(0)) revert HadZeroInit();
32
29
  bridge = _bridge;
33
30
  rollup = address(_bridge.rollup());
34
31
  }
@@ -24,6 +24,7 @@ struct Config {
24
24
  address owner;
25
25
  address loserStakeEscrow;
26
26
  uint256 chainId;
27
+ uint64 genesisBlockNum;
27
28
  ISequencerInbox.MaxTimeVariation sequencerInboxMaxTimeVariation;
28
29
  }
29
30
 
@@ -4,10 +4,10 @@
4
4
 
5
5
  pragma solidity ^0.8.0;
6
6
 
7
- import "./AdminFallbackProxy.sol";
8
- import "../rollup/IRollupLogic.sol";
7
+ import "../libraries/AdminFallbackProxy.sol";
8
+ import "./IRollupLogic.sol";
9
9
 
10
- contract ArbitrumProxy is AdminFallbackProxy {
10
+ contract RollupProxy is AdminFallbackProxy {
11
11
  constructor(Config memory config, ContractDependencies memory connectedContracts)
12
12
  AdminFallbackProxy(
13
13
  address(connectedContracts.rollupAdminLogic),
@@ -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);
@@ -41,4 +41,11 @@ library GlobalStateLib {
41
41
  function getPositionInMessage(GlobalState memory state) internal pure returns (uint64) {
42
42
  return state.u64Vals[1];
43
43
  }
44
+
45
+ function isEmpty(GlobalState calldata state) internal pure returns (bool) {
46
+ return (state.bytes32Vals[0] == bytes32(0) &&
47
+ state.bytes32Vals[1] == bytes32(0) &&
48
+ state.u64Vals[0] == 0 &&
49
+ state.u64Vals[1] == 0);
50
+ }
44
51
  }
@@ -7,6 +7,14 @@ pragma solidity ^0.8.4;
7
7
  import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
8
8
  import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
9
9
 
10
+ import {
11
+ NotContract,
12
+ NotRollupOrOwner,
13
+ NotDelayedInbox,
14
+ NotSequencerInbox,
15
+ NotOutbox,
16
+ InvalidOutboxSet
17
+ } from "../libraries/Error.sol";
10
18
  import "../bridge/IBridge.sol";
11
19
  import "../bridge/Messages.sol";
12
20
  import "../libraries/DelegateCallAware.sol";
@@ -56,6 +64,7 @@ contract BridgeTester is Initializable, DelegateCallAware, IBridge {
56
64
  bytes32[] public override delayedInboxAccs;
57
65
 
58
66
  bytes32[] public override sequencerInboxAccs;
67
+ uint256 public override sequencerReportedSubMessageCount;
59
68
 
60
69
  address private constant EMPTY_ACTIVEOUTBOX = address(type(uint160).max);
61
70
 
@@ -77,7 +86,12 @@ contract BridgeTester is Initializable, DelegateCallAware, IBridge {
77
86
  return allowedOutboxesMap[outbox].allowed;
78
87
  }
79
88
 
80
- function enqueueSequencerMessage(bytes32 dataHash, uint256 afterDelayedMessagesRead)
89
+ function enqueueSequencerMessage(
90
+ bytes32 dataHash,
91
+ uint256 afterDelayedMessagesRead,
92
+ uint256 prevMessageCount,
93
+ uint256 newMessageCount
94
+ )
81
95
  external
82
96
  returns (
83
97
  uint256 seqMessageIndex,
@@ -220,4 +234,6 @@ contract BridgeTester is Initializable, DelegateCallAware, IBridge {
220
234
  }
221
235
 
222
236
  receive() external payable {}
237
+
238
+ function acceptFundsFromOldBridge() external payable {}
223
239
  }
@@ -0,0 +1,11 @@
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
+ // solhint-disable-next-line compiler-version
6
+ pragma solidity >=0.6.9 <0.9.0;
7
+
8
+ import "../bridge/IBridge.sol";
9
+ import "../bridge/IOutbox.sol";
10
+ import "../bridge/IInbox.sol";
11
+ import "../bridge/ISequencerInbox.sol";
@@ -4,6 +4,15 @@
4
4
 
5
5
  pragma solidity ^0.8.4;
6
6
 
7
+ import {
8
+ AlreadyInit,
9
+ NotRollup,
10
+ ProofTooLong,
11
+ PathNotMinimal,
12
+ UnknownRoot,
13
+ AlreadySpent,
14
+ BridgeCallFailed
15
+ } from "../libraries/Error.sol";
7
16
  import "../bridge/IBridge.sol";
8
17
  import "../bridge/IOutbox.sol";
9
18
  import "../libraries/MerkleLib.sol";
@@ -13,7 +22,11 @@ contract OutboxWithoutOptTester is DelegateCallAware, IOutbox {
13
22
  address public rollup; // the rollup contract
14
23
  IBridge public bridge; // the bridge contract
15
24
 
16
- 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
17
30
  mapping(bytes32 => bytes32) public roots; // maps root hashes => L2 block hash
18
31
 
19
32
  struct L2ToL1Context {
@@ -61,7 +74,7 @@ contract OutboxWithoutOptTester is DelegateCallAware, IOutbox {
61
74
  }
62
75
 
63
76
  // @deprecated batch number is now always 0
64
- function l2ToL1BatchNum() external pure override returns (uint256) {
77
+ function l2ToL1BatchNum() external pure returns (uint256) {
65
78
  return 0;
66
79
  }
67
80
 
@@ -93,7 +106,7 @@ contract OutboxWithoutOptTester is DelegateCallAware, IOutbox {
93
106
  uint256 l2Timestamp,
94
107
  uint256 value,
95
108
  bytes calldata data
96
- ) external virtual {
109
+ ) external virtual override {
97
110
  bytes32 outputId;
98
111
  {
99
112
  bytes32 userTx = calculateItemHash(
@@ -128,6 +141,19 @@ contract OutboxWithoutOptTester is DelegateCallAware, IOutbox {
128
141
  context = prevContext;
129
142
  }
130
143
 
144
+ function executeTransactionSimulation(
145
+ uint256,
146
+ address,
147
+ address,
148
+ uint256,
149
+ uint256,
150
+ uint256,
151
+ uint256,
152
+ bytes calldata
153
+ ) external pure override {
154
+ revert("Not implemented");
155
+ }
156
+
131
157
  function recordOutputAsSpent(
132
158
  bytes32[] memory proof,
133
159
  uint256 index,
@@ -140,8 +166,8 @@ contract OutboxWithoutOptTester is DelegateCallAware, IOutbox {
140
166
  bytes32 calcRoot = calculateMerkleRoot(proof, index, item);
141
167
  if (roots[calcRoot] == bytes32(0)) revert UnknownRoot(calcRoot);
142
168
 
143
- if (spent[index]) revert AlreadySpent(index);
144
- spent[index] = true;
169
+ if (isSpent[index]) revert AlreadySpent(index);
170
+ isSpent[index] = true;
145
171
 
146
172
  return bytes32(index);
147
173
  }
@@ -173,7 +199,7 @@ contract OutboxWithoutOptTester is DelegateCallAware, IOutbox {
173
199
  uint256 l2Timestamp,
174
200
  uint256 value,
175
201
  bytes calldata data
176
- ) public pure returns (bytes32) {
202
+ ) public pure override returns (bytes32) {
177
203
  return
178
204
  keccak256(abi.encodePacked(l2Sender, to, l2Block, l1Block, l2Timestamp, value, data));
179
205
  }
@@ -182,7 +208,7 @@ contract OutboxWithoutOptTester is DelegateCallAware, IOutbox {
182
208
  bytes32[] memory proof,
183
209
  uint256 path,
184
210
  bytes32 item
185
- ) public pure returns (bytes32) {
211
+ ) public pure override returns (bytes32) {
186
212
  return MerkleLib.calculateRoot(proof, path, keccak256(abi.encodePacked(item)));
187
213
  }
188
214
  }