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

Sign up to get free protection for your applications and to get access to all the features.
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
  }