@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
@@ -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),