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

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. package/README.md +1 -1
  2. package/hardhat.prod-config.js +4 -4
  3. package/package.json +21 -3
  4. package/src/bridge/Bridge.sol +39 -30
  5. package/src/bridge/IBridge.sol +56 -29
  6. package/src/bridge/IInbox.sol +130 -15
  7. package/src/bridge/IOutbox.sol +55 -7
  8. package/src/bridge/ISequencerInbox.sol +84 -7
  9. package/src/bridge/Inbox.sol +233 -93
  10. package/src/bridge/Outbox.sol +23 -47
  11. package/src/bridge/SequencerInbox.sol +132 -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 +6 -0
  16. package/src/libraries/{SecondaryLogicUUPSUpgradeable.sol → DoubleLogicUUPSUpgradeable.sol} +2 -1
  17. package/src/libraries/Error.sol +12 -0
  18. package/src/libraries/IGasRefunder.sol +11 -5
  19. package/src/libraries/MerkleLib.sol +5 -3
  20. package/src/mocks/BridgeStub.sol +20 -1
  21. package/src/mocks/BridgeUnproxied.sol +17 -0
  22. package/src/mocks/InboxStub.sol +48 -3
  23. package/src/mocks/SequencerInboxStub.sol +13 -3
  24. package/src/mocks/Simple.sol +69 -0
  25. package/src/node-interface/NodeInterface.sol +35 -4
  26. package/src/precompiles/ArbGasInfo.sol +7 -4
  27. package/src/precompiles/ArbOwner.sol +9 -0
  28. package/src/precompiles/ArbOwnerPublic.sol +3 -0
  29. package/src/precompiles/ArbSys.sol +5 -2
  30. package/src/rollup/IRollupCore.sol +2 -0
  31. package/src/rollup/IRollupLogic.sol +10 -0
  32. package/src/rollup/RollupAdminLogic.sol +27 -3
  33. package/src/rollup/RollupCore.sol +3 -0
  34. package/src/rollup/RollupCreator.sol +3 -3
  35. package/src/rollup/RollupEventInbox.sol +3 -6
  36. package/src/{libraries/ArbitrumProxy.sol → rollup/RollupProxy.sol} +3 -3
  37. package/src/rollup/RollupUserLogic.sol +47 -10
  38. package/src/test-helpers/BridgeTester.sol +7 -1
  39. package/src/test-helpers/OutboxWithoutOptTester.sol +8 -8
@@ -5,6 +5,7 @@
5
5
  pragma solidity ^0.8.0;
6
6
 
7
7
  import "./InboxStub.sol";
8
+ import {BadSequencerMessageNumber} from "../libraries/Error.sol";
8
9
 
9
10
  import "../bridge/IBridge.sol";
10
11
 
@@ -28,6 +29,7 @@ contract BridgeStub is IBridge {
28
29
  bytes32[] public override sequencerInboxAccs;
29
30
 
30
31
  address public sequencerInbox;
32
+ uint256 public override sequencerReportedSubMessageCount;
31
33
 
32
34
  function setSequencerInbox(address _sequencerInbox) external override {
33
35
  sequencerInbox = _sequencerInbox;
@@ -59,7 +61,12 @@ contract BridgeStub is IBridge {
59
61
  );
60
62
  }
61
63
 
62
- function enqueueSequencerMessage(bytes32 dataHash, uint256 afterDelayedMessagesRead)
64
+ function enqueueSequencerMessage(
65
+ bytes32 dataHash,
66
+ uint256 afterDelayedMessagesRead,
67
+ uint256 prevMessageCount,
68
+ uint256 newMessageCount
69
+ )
63
70
  external
64
71
  returns (
65
72
  uint256 seqMessageIndex,
@@ -68,6 +75,14 @@ contract BridgeStub is IBridge {
68
75
  bytes32 acc
69
76
  )
70
77
  {
78
+ if (
79
+ sequencerReportedSubMessageCount != prevMessageCount &&
80
+ prevMessageCount != 0 &&
81
+ sequencerReportedSubMessageCount != 0
82
+ ) {
83
+ revert BadSequencerMessageNumber(sequencerReportedSubMessageCount, prevMessageCount);
84
+ }
85
+ sequencerReportedSubMessageCount = newMessageCount;
71
86
  seqMessageIndex = sequencerInboxAccs.length;
72
87
  if (sequencerInboxAccs.length > 0) {
73
88
  beforeAcc = sequencerInboxAccs[sequencerInboxAccs.length - 1];
@@ -160,4 +175,8 @@ contract BridgeStub is IBridge {
160
175
  }
161
176
 
162
177
  function acceptFundsFromOldBridge() external payable {}
178
+
179
+ function initialize(IOwnable) external pure {
180
+ revert("NOT_IMPLEMENTED");
181
+ }
163
182
  }
@@ -0,0 +1,17 @@
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 "./InboxStub.sol";
8
+ import {BadSequencerMessageNumber} from "../libraries/Error.sol";
9
+
10
+ import "../bridge/Bridge.sol";
11
+
12
+ contract BridgeUnproxied is Bridge {
13
+ constructor() {
14
+ _activeOutbox = EMPTY_ACTIVEOUTBOX;
15
+ rollup = IOwnable(msg.sender);
16
+ }
17
+ }
@@ -19,10 +19,19 @@ import {
19
19
 
20
20
  contract InboxStub is IInbox {
21
21
  IBridge public override bridge;
22
+ ISequencerInbox public override sequencerInbox;
22
23
 
23
24
  bool public paused;
24
25
 
25
- function initialize(IBridge _bridge) external {
26
+ function pause() external pure {
27
+ revert("NOT IMPLEMENTED");
28
+ }
29
+
30
+ function unpause() external pure {
31
+ revert("NOT IMPLEMENTED");
32
+ }
33
+
34
+ function initialize(IBridge _bridge, ISequencerInbox) external {
26
35
  require(address(bridge) == address(0), "ALREADY_INIT");
27
36
  bridge = _bridge;
28
37
  }
@@ -125,13 +134,49 @@ contract InboxStub is IInbox {
125
134
  revert("NOT_IMPLEMENTED");
126
135
  }
127
136
 
128
- function depositEth() external payable override returns (uint256) {
137
+ function sendL1FundedUnsignedTransactionToFork(
138
+ uint256,
139
+ uint256,
140
+ uint256,
141
+ address,
142
+ bytes calldata
143
+ ) external payable returns (uint256) {
144
+ revert("NOT_IMPLEMENTED");
145
+ }
146
+
147
+ function sendUnsignedTransactionToFork(
148
+ uint256,
149
+ uint256,
150
+ uint256,
151
+ address,
152
+ uint256,
153
+ bytes calldata
154
+ ) external returns (uint256) {
129
155
  revert("NOT_IMPLEMENTED");
130
156
  }
131
157
 
132
- function depositEth(uint256) external payable override returns (uint256) {
158
+ function sendWithdrawEthToFork(
159
+ uint256,
160
+ uint256,
161
+ uint256,
162
+ uint256,
163
+ address
164
+ ) external returns (uint256) {
165
+ revert("NOT_IMPLEMENTED");
166
+ }
167
+
168
+ function depositEth() external payable override returns (uint256) {
133
169
  revert("NOT_IMPLEMENTED");
134
170
  }
135
171
 
136
172
  function postUpgradeInit(IBridge _bridge) external {}
173
+
174
+ function calculateRetryableSubmissionFee(uint256, uint256)
175
+ external
176
+ pure
177
+ override
178
+ returns (uint256)
179
+ {
180
+ revert("NOT_IMPLEMENTED");
181
+ }
137
182
  }
@@ -5,6 +5,7 @@
5
5
  pragma solidity ^0.8.0;
6
6
 
7
7
  import "../bridge/SequencerInbox.sol";
8
+ import {INITIALIZATION_MSG_TYPE} from "../libraries/MessageTypes.sol";
8
9
 
9
10
  contract SequencerInboxStub is SequencerInbox {
10
11
  constructor(
@@ -18,14 +19,23 @@ contract SequencerInboxStub is SequencerInbox {
18
19
  isBatchPoster[sequencer_] = true;
19
20
  }
20
21
 
21
- function addInitMessage() external {
22
- (bytes32 dataHash, TimeBounds memory timeBounds) = formEmptyDataHash(0);
22
+ function addInitMessage(uint256 chainId) external {
23
+ bytes memory initMsg = abi.encodePacked(chainId);
24
+ uint256 num = bridge.enqueueDelayedMessage(
25
+ INITIALIZATION_MSG_TYPE,
26
+ address(0),
27
+ keccak256(initMsg)
28
+ );
29
+ require(num == 0, "ALREADY_DELAYED_INIT");
30
+ emit InboxMessageDelivered(num, initMsg);
31
+ (bytes32 dataHash, TimeBounds memory timeBounds) = formEmptyDataHash(1);
23
32
  (
24
33
  uint256 sequencerMessageCount,
25
34
  bytes32 beforeAcc,
26
35
  bytes32 delayedAcc,
27
36
  bytes32 afterAcc
28
- ) = addSequencerL2BatchImpl(dataHash, 0, 0);
37
+ ) = addSequencerL2BatchImpl(dataHash, 1, 0, 0, 1);
38
+ require(sequencerMessageCount == 0, "ALREADY_SEQ_INIT");
29
39
  emit SequencerBatchDelivered(
30
40
  sequencerMessageCount,
31
41
  beforeAcc,
@@ -5,6 +5,7 @@
5
5
  pragma solidity ^0.8.0;
6
6
 
7
7
  import "../precompiles/ArbRetryableTx.sol";
8
+ import "../precompiles/ArbSys.sol";
8
9
 
9
10
  contract Simple {
10
11
  uint64 public counter;
@@ -35,4 +36,72 @@ contract Simple {
35
36
  require(blockhash(block.number - 1) != blockhash(block.number - 2), "SAME_BLOCK_HASH");
36
37
  return block.number;
37
38
  }
39
+
40
+ function noop() external pure {}
41
+
42
+ function pleaseRevert() external pure {
43
+ revert("SOLIDITY_REVERTING");
44
+ }
45
+
46
+ function checkIsTopLevelOrWasAliased(bool useTopLevel, bool expected) public view {
47
+ if (useTopLevel) {
48
+ require(ArbSys(address(100)).isTopLevelCall() == expected, "UNEXPECTED_RESULT");
49
+ } else {
50
+ require(
51
+ ArbSys(address(100)).wasMyCallersAddressAliased() == expected,
52
+ "UNEXPECTED_RESULT"
53
+ );
54
+ }
55
+ }
56
+
57
+ function checkCalls(
58
+ bool useTopLevel,
59
+ bool directCase,
60
+ bool staticCase,
61
+ bool delegateCase,
62
+ bool callcodeCase,
63
+ bool callCase
64
+ ) public {
65
+ // DIRECT CALL
66
+ if (useTopLevel) {
67
+ require(ArbSys(address(100)).isTopLevelCall() == directCase, "UNEXPECTED_RESULT");
68
+ } else {
69
+ require(
70
+ ArbSys(address(100)).wasMyCallersAddressAliased() == directCase,
71
+ "UNEXPECTED_RESULT"
72
+ );
73
+ }
74
+
75
+ // STATIC CALL
76
+ this.checkIsTopLevelOrWasAliased(useTopLevel, staticCase);
77
+
78
+ // DELEGATE CALL
79
+ bytes memory data = abi.encodeWithSelector(
80
+ this.checkIsTopLevelOrWasAliased.selector,
81
+ useTopLevel,
82
+ delegateCase
83
+ );
84
+ (bool success, ) = address(this).delegatecall(data);
85
+ require(success, "DELEGATE_CALL_FAILED");
86
+
87
+ // CALLCODE
88
+ data = abi.encodeWithSelector(
89
+ this.checkIsTopLevelOrWasAliased.selector,
90
+ useTopLevel,
91
+ callcodeCase
92
+ );
93
+ assembly {
94
+ success := callcode(gas(), address(), 0, add(data, 32), mload(data), 0, 0)
95
+ }
96
+ require(success, "CALLCODE_FAILED");
97
+
98
+ // CALL
99
+ data = abi.encodeWithSelector(
100
+ this.checkIsTopLevelOrWasAliased.selector,
101
+ useTopLevel,
102
+ callCase
103
+ );
104
+ (success, ) = address(this).call(data);
105
+ require(success, "CALL_FAILED");
106
+ }
38
107
  }
@@ -11,9 +11,10 @@ pragma solidity >=0.4.21 <0.9.0;
11
11
  */
12
12
  interface NodeInterface {
13
13
  /**
14
- * @notice Estimate the cost of putting a message in the L2 inbox that is reexecuted.
15
- * @dev Use eth_estimateGas to call.
16
- * @param sender sender of the L1 and L2 transaction
14
+ * @notice Simulate the execution of a retryable ticket
15
+ * @dev Use eth_estimateGas on this call to estimate gas usage of retryable ticket
16
+ * Since gas usage is not yet known, you may need to add extra deposit (e.g. 1e18 wei) during estimation
17
+ * @param sender unaliased sender of the L1 and L2 transaction
17
18
  * @param deposit amount to deposit to sender in L2
18
19
  * @param to destination L2 contract address
19
20
  * @param l2CallValue call value for retryable L2 message
@@ -54,7 +55,7 @@ interface NodeInterface {
54
55
  * Use eth_call to call.
55
56
  * Throws if block doesn't exist, or if block number is 0. Use eth_call
56
57
  * @param blockNum The L2 block being queried
57
- * @return batch The L1 block containing the requested L2 block
58
+ * @return batch The sequencer batch number containing the requested L2 block
58
59
  */
59
60
  function findBatchContainingBlock(uint64 blockNum) external view returns (uint64 batch);
60
61
 
@@ -94,6 +95,31 @@ interface NodeInterface {
94
95
  uint256 l1BaseFeeEstimate
95
96
  );
96
97
 
98
+ /**
99
+ * @notice Estimates a transaction's l1 costs.
100
+ * @dev Use eth_call to call.
101
+ * This method is exactly like gasEstimateComponents, but doesn't include the l2 component
102
+ * so that the l1 component can be known even when the tx may fail.
103
+ * @param data the tx's calldata. Everything else like "From" and "Gas" are copied over
104
+ * @param to the tx's "To" (ignored when contractCreation is true)
105
+ * @param contractCreation whether "To" is omitted
106
+ * @return gasEstimateForL1 an estimate of the amount of gas needed for the l1 component of this tx
107
+ * @return baseFee the l2 base fee
108
+ * @return l1BaseFeeEstimate ArbOS's l1 estimate of the l1 base fee
109
+ */
110
+ function gasEstimateL1Component(
111
+ address to,
112
+ bool contractCreation,
113
+ bytes calldata data
114
+ )
115
+ external
116
+ payable
117
+ returns (
118
+ uint64 gasEstimateForL1,
119
+ uint256 baseFee,
120
+ uint256 l1BaseFeeEstimate
121
+ );
122
+
97
123
  /**
98
124
  * @notice Returns the proof necessary to redeem a message
99
125
  * @param batchNum index of outbox entry (i.e., outgoing messages Merkle root) in array of outbox entries
@@ -122,4 +148,9 @@ interface NodeInterface {
122
148
  uint256 amount,
123
149
  bytes memory calldataForL1
124
150
  );
151
+
152
+ // @notice Returns the first block produced using the Nitro codebase
153
+ // @dev returns 0 for chains like Nova that don't contain classic blocks
154
+ // @return number the block number
155
+ function nitroGenesisBlock() external pure returns (uint256 number);
125
156
  }
@@ -13,7 +13,7 @@ interface ArbGasInfo {
13
13
  /// @return return gas prices in wei
14
14
  /// (
15
15
  /// per L2 tx,
16
- /// per L1 calldata unit, (a byte, non-zero or otherwise, is 16 units)
16
+ /// per L1 calldata byte
17
17
  /// per storage allocation,
18
18
  /// per ArbGas base,
19
19
  /// per ArbGas congestion,
@@ -35,7 +35,7 @@ interface ArbGasInfo {
35
35
  /// @return return gas prices in wei
36
36
  /// (
37
37
  /// per L2 tx,
38
- /// per L1 calldata unit, (a byte, non-zero or otherwise, is 16 units)
38
+ /// per L1 calldata byte
39
39
  /// per storage allocation,
40
40
  /// per ArbGas base,
41
41
  /// per ArbGas congestion,
@@ -54,7 +54,7 @@ interface ArbGasInfo {
54
54
  );
55
55
 
56
56
  /// @notice Get prices in ArbGas for the supplied aggregator
57
- /// @return (per L2 tx, per L1 calldata unit, per storage allocation)
57
+ /// @return (per L2 tx, per L1 calldata byte, per storage allocation)
58
58
  function getPricesInArbGasWithAggregator(address aggregator)
59
59
  external
60
60
  view
@@ -65,7 +65,7 @@ interface ArbGasInfo {
65
65
  );
66
66
 
67
67
  /// @notice Get prices in ArbGas. Assumes the callers preferred validator, or the default if caller doesn't have a preferred one.
68
- /// @return (per L2 tx, per L1 calldata unit, per storage allocation)
68
+ /// @return (per L2 tx, per L1 calldata byte, per storage allocation)
69
69
  function getPricesInArbGas()
70
70
  external
71
71
  view
@@ -118,4 +118,7 @@ interface ArbGasInfo {
118
118
 
119
119
  /// @notice Returns the cost amortization cap in basis points
120
120
  function getAmortizedCostCapBips() external view returns (uint64);
121
+
122
+ /// @notice Returns the available funds from L1 fees
123
+ function getL1FeesAvailable() external view returns (uint256);
121
124
  }
@@ -48,9 +48,15 @@ interface ArbOwner {
48
48
  /// @notice Get the network fee collector
49
49
  function getNetworkFeeAccount() external view returns (address);
50
50
 
51
+ /// @notice Get the infrastructure fee collector
52
+ function getInfraFeeAccount() external view returns (address);
53
+
51
54
  /// @notice Set the network fee collector
52
55
  function setNetworkFeeAccount(address newNetworkFeeAccount) external;
53
56
 
57
+ /// @notice Set the infrastructure fee collector
58
+ function setInfraFeeAccount(address newInfraFeeAccount) external;
59
+
54
60
  /// @notice Upgrades ArbOS to the requested version at the requested timestamp
55
61
  function scheduleArbOSUpgrade(uint64 newVersion, uint64 timestamp) external;
56
62
 
@@ -75,6 +81,9 @@ interface ArbOwner {
75
81
  /// @notice Sets the cost amortization cap in basis points
76
82
  function setAmortizedCostCapBips(uint64 cap) external;
77
83
 
84
+ /// @notice Releases surplus funds from L1PricerFundsPoolAddress for use
85
+ function releaseL1PricerSurplusFunds(uint256 maxWeiToRelease) external returns (uint256);
86
+
78
87
  // Emitted when a successful call is made to this precompile
79
88
  event OwnerActs(bytes4 indexed method, address indexed owner, bytes data);
80
89
  }
@@ -15,4 +15,7 @@ interface ArbOwnerPublic {
15
15
 
16
16
  /// @notice Gets the network fee collector
17
17
  function getNetworkFeeAccount() external view returns (address);
18
+
19
+ /// @notice Get the infrastructure fee collector
20
+ function getInfraFeeAccount() external view returns (address);
18
21
  }
@@ -41,7 +41,8 @@ interface ArbSys {
41
41
  function getStorageGasAvailable() external view returns (uint256);
42
42
 
43
43
  /**
44
- * @notice check if current call is top level (meaning it was triggered by an EoA or a L1 contract)
44
+ * @notice (deprecated) check if current call is top level (meaning it was triggered by an EoA or a L1 contract)
45
+ * @dev this call has been deprecated and may be removed in a future release
45
46
  * @return true if current execution frame is not a call by another L2 contract
46
47
  */
47
48
  function isTopLevelCall() external view returns (bool);
@@ -79,6 +80,8 @@ interface ArbSys {
79
80
 
80
81
  /**
81
82
  * @notice Send a transaction to L1
83
+ * @dev it is not possible to execute on the L1 any L2-to-L1 transaction which contains data
84
+ * to a contract address without any code (as enforced by the Bridge contract).
82
85
  * @param destination recipient address on L1
83
86
  * @param data (optional) calldata for L1 contract call
84
87
  * @return a unique identifier for this L2-to-L1 transaction.
@@ -134,7 +137,7 @@ interface ArbSys {
134
137
  );
135
138
 
136
139
  /**
137
- * @notice logs a merkle branch for proof sythesis
140
+ * @notice logs a merkle branch for proof synthesis
138
141
  * @param reserved an index meant only to align the 4th index with L2ToL1Transaction's 4th event
139
142
  * @param hash the merkle hash
140
143
  * @param position = (level << 192) + leaf
@@ -77,6 +77,8 @@ interface IRollupCore {
77
77
 
78
78
  function isValidator(address) external view returns (bool);
79
79
 
80
+ function validatorWhitelistDisabled() external view returns (bool);
81
+
80
82
  /**
81
83
  * @notice Get the Node for the given index.
82
84
  */
@@ -15,6 +15,10 @@ interface IRollupUserAbs is IRollupCore, IOwnable {
15
15
  /// this allows the admin logic to ensure consistency on parameters.
16
16
  function initialize(address stakeToken) external view;
17
17
 
18
+ function removeWhitelistAfterFork() external;
19
+
20
+ function removeWhitelistAfterValidatorAfk() external;
21
+
18
22
  function isERC20Enabled() external view returns (bool);
19
23
 
20
24
  function rejectNextNode(address stakerAddress) external;
@@ -215,4 +219,10 @@ interface IRollupAdmin {
215
219
  * @param _sequencerInbox new address of sequencer inbox
216
220
  */
217
221
  function setSequencerInbox(address _sequencerInbox) external;
222
+
223
+ /**
224
+ * @notice set the validatorWhitelistDisabled flag
225
+ * @param _validatorWhitelistDisabled new value of validatorWhitelistDisabled, i.e. true = disabled
226
+ */
227
+ function setValidatorWhitelistDisabled(bool _validatorWhitelistDisabled) external;
218
228
  }
@@ -9,12 +9,12 @@ import "./RollupCore.sol";
9
9
  import "../bridge/IOutbox.sol";
10
10
  import "../bridge/ISequencerInbox.sol";
11
11
  import "../challenge/IChallengeManager.sol";
12
- import "../libraries/SecondaryLogicUUPSUpgradeable.sol";
12
+ import "../libraries/DoubleLogicUUPSUpgradeable.sol";
13
13
  import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";
14
14
 
15
15
  import {NO_CHAL_INDEX} from "../libraries/Constants.sol";
16
16
 
17
- contract RollupAdminLogic is RollupCore, IRollupAdmin, SecondaryLogicUUPSUpgradeable {
17
+ contract RollupAdminLogic is RollupCore, IRollupAdmin, DoubleLogicUUPSUpgradeable {
18
18
  function initialize(Config calldata config, ContractDependencies calldata connectedContracts)
19
19
  external
20
20
  override
@@ -37,7 +37,14 @@ contract RollupAdminLogic is RollupCore, IRollupAdmin, SecondaryLogicUUPSUpgrade
37
37
  );
38
38
 
39
39
  connectedContracts.rollupEventInbox.rollupInitialized(config.chainId);
40
- connectedContracts.sequencerInbox.addSequencerL2Batch(0, "", 1, IGasRefunder(address(0)));
40
+ connectedContracts.sequencerInbox.addSequencerL2Batch(
41
+ 0,
42
+ "",
43
+ 1,
44
+ IGasRefunder(address(0)),
45
+ 0,
46
+ 1
47
+ );
41
48
 
42
49
  validatorUtils = connectedContracts.validatorUtils;
43
50
  validatorWalletCreator = connectedContracts.validatorWalletCreator;
@@ -121,6 +128,9 @@ contract RollupAdminLogic is RollupCore, IRollupAdmin, SecondaryLogicUUPSUpgrade
121
128
  /**
122
129
  * @notice Pause interaction with the rollup contract.
123
130
  * The time spent paused is not incremented in the rollup's timing for node validation.
131
+ * @dev this function may be frontrun by a validator (ie to create a node before the system is paused).
132
+ * The pause should be called atomically with required checks to be sure the system is paused in a consistent state.
133
+ * The RollupAdmin may execute a check against the Rollup's latest node num or the ChallengeManager, then execute this function atomically with it.
124
134
  */
125
135
  function pause() external override {
126
136
  _pause();
@@ -153,6 +163,7 @@ contract RollupAdminLogic is RollupCore, IRollupAdmin, SecondaryLogicUUPSUpgrade
153
163
  * @param _val value to set in the whitelist for corresponding address
154
164
  */
155
165
  function setValidator(address[] calldata _validator, bool[] calldata _val) external override {
166
+ require(_validator.length > 0, "EMPTY_ARRAY");
156
167
  require(_validator.length == _val.length, "WRONG_LENGTH");
157
168
 
158
169
  for (uint256 i = 0; i < _validator.length; i++) {
@@ -185,6 +196,7 @@ contract RollupAdminLogic is RollupCore, IRollupAdmin, SecondaryLogicUUPSUpgrade
185
196
  * @param newConfirmPeriod new number of blocks
186
197
  */
187
198
  function setConfirmPeriodBlocks(uint64 newConfirmPeriod) external override {
199
+ require(newConfirmPeriod > 0, "INVALID_CONFIRM_PERIOD");
188
200
  confirmPeriodBlocks = newConfirmPeriod;
189
201
  emit OwnerFunctionCalled(9);
190
202
  }
@@ -247,6 +259,7 @@ contract RollupAdminLogic is RollupCore, IRollupAdmin, SecondaryLogicUUPSUpgrade
247
259
  override
248
260
  whenPaused
249
261
  {
262
+ require(stakerA.length > 0, "EMPTY_ARRAY");
250
263
  require(stakerA.length == stakerB.length, "WRONG_LENGTH");
251
264
  for (uint256 i = 0; i < stakerA.length; i++) {
252
265
  uint64 chall = inChallenge(stakerA[i], stakerB[i]);
@@ -260,7 +273,9 @@ contract RollupAdminLogic is RollupCore, IRollupAdmin, SecondaryLogicUUPSUpgrade
260
273
  }
261
274
 
262
275
  function forceRefundStaker(address[] calldata staker) external override whenPaused {
276
+ require(staker.length > 0, "EMPTY_ARRAY");
263
277
  for (uint256 i = 0; i < staker.length; i++) {
278
+ require(_stakerMap[staker[i]].currentChallenge == NO_CHAL_INDEX, "STAKER_IN_CHALL");
264
279
  reduceStakeTo(staker[i], 0);
265
280
  turnIntoZombie(staker[i]);
266
281
  }
@@ -357,4 +372,13 @@ contract RollupAdminLogic is RollupCore, IRollupAdmin, SecondaryLogicUUPSUpgrade
357
372
  confirmNode(1, genesisBlockHash, expectedSendRoot);
358
373
  emit OwnerFunctionCalled(29);
359
374
  }
375
+
376
+ /**
377
+ * @notice set the validatorWhitelistDisabled flag
378
+ * @param _validatorWhitelistDisabled new value of validatorWhitelistDisabled, i.e. true = disabled
379
+ */
380
+ function setValidatorWhitelistDisabled(bool _validatorWhitelistDisabled) external {
381
+ validatorWhitelistDisabled = _validatorWhitelistDisabled;
382
+ emit OwnerFunctionCalled(30);
383
+ }
360
384
  }
@@ -74,6 +74,8 @@ abstract contract RollupCore is IRollupCore, PausableUpgradeable {
74
74
  // The node number of the initial node
75
75
  uint64 internal constant GENESIS_NODE = 0;
76
76
 
77
+ bool public validatorWhitelistDisabled;
78
+
77
79
  /**
78
80
  * @notice Get a storage reference to the Node for the given node index
79
81
  * @param nodeNum Index of the node
@@ -502,6 +504,7 @@ abstract contract RollupCore is IRollupCore, PausableUpgradeable {
502
504
  */
503
505
  function deleteStaker(address stakerAddress) private {
504
506
  Staker storage staker = _stakerMap[stakerAddress];
507
+ require(staker.isStaked, "NOT_STAKED");
505
508
  uint64 stakerIndex = staker.index;
506
509
  _stakerList[stakerIndex] = _stakerList[_stakerList.length - 1];
507
510
  _stakerMap[_stakerList[stakerIndex]].index = stakerIndex;
@@ -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
  }
@@ -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),