@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.
- package/package.json +13 -2
- package/src/bridge/Bridge.sol +49 -29
- package/src/bridge/IBridge.sol +58 -45
- package/src/bridge/IDelayedMessageProvider.sol +2 -1
- package/src/bridge/IInbox.sol +133 -50
- package/src/bridge/IOutbox.sol +95 -27
- package/src/bridge/IOwnable.sol +2 -1
- package/src/bridge/ISequencerInbox.sol +79 -31
- package/src/bridge/Inbox.sol +171 -108
- package/src/bridge/Outbox.sol +26 -41
- package/src/bridge/SequencerInbox.sol +152 -62
- package/src/challenge/ChallengeManager.sol +0 -9
- package/src/challenge/IChallengeManager.sol +0 -2
- package/src/libraries/AdminFallbackProxy.sol +4 -4
- package/src/libraries/Constants.sol +3 -0
- package/src/libraries/{SecondaryLogicUUPSUpgradeable.sol → DoubleLogicUUPSUpgradeable.sol} +2 -1
- package/src/libraries/Error.sol +119 -0
- package/src/libraries/IGasRefunder.sol +13 -6
- package/src/libraries/MerkleLib.sol +5 -3
- package/src/mocks/BridgeStub.sol +22 -1
- package/src/mocks/BridgeUnproxied.sol +17 -0
- package/src/mocks/InboxStub.sol +49 -2
- package/src/mocks/SequencerInboxStub.sol +13 -3
- package/src/mocks/Simple.sol +69 -0
- package/src/node-interface/NodeInterface.sol +69 -7
- package/src/precompiles/ArbGasInfo.sol +16 -4
- package/src/precompiles/ArbOwner.sol +18 -0
- package/src/precompiles/ArbOwnerPublic.sol +3 -0
- package/src/precompiles/ArbSys.sol +7 -4
- package/src/rollup/IRollupCore.sol +2 -0
- package/src/rollup/IRollupLogic.sol +10 -0
- package/src/rollup/RollupAdminLogic.sol +69 -3
- package/src/rollup/RollupCore.sol +8 -2
- package/src/rollup/RollupCreator.sol +3 -3
- package/src/rollup/RollupEventInbox.sol +3 -6
- package/src/rollup/RollupLib.sol +1 -0
- package/src/{libraries/ArbitrumProxy.sol → rollup/RollupProxy.sol} +3 -3
- package/src/rollup/RollupUserLogic.sol +47 -10
- package/src/state/GlobalState.sol +7 -0
- package/src/test-helpers/BridgeTester.sol +17 -1
- package/src/test-helpers/InterfaceCompatibilityTester.sol +11 -0
- package/src/test-helpers/OutboxWithoutOptTester.sol +33 -7
@@ -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
|
+
}
|
package/src/mocks/InboxStub.sol
CHANGED
@@ -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
|
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,11 +134,49 @@ contract InboxStub is IInbox {
|
|
125
134
|
revert("NOT_IMPLEMENTED");
|
126
135
|
}
|
127
136
|
|
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) {
|
155
|
+
revert("NOT_IMPLEMENTED");
|
156
|
+
}
|
157
|
+
|
158
|
+
function sendWithdrawEthToFork(
|
159
|
+
uint256,
|
160
|
+
uint256,
|
161
|
+
uint256,
|
162
|
+
uint256,
|
163
|
+
address
|
164
|
+
) external returns (uint256) {
|
165
|
+
revert("NOT_IMPLEMENTED");
|
166
|
+
}
|
167
|
+
|
128
168
|
function depositEth() external payable override returns (uint256) {
|
129
169
|
revert("NOT_IMPLEMENTED");
|
130
170
|
}
|
131
171
|
|
132
|
-
function
|
172
|
+
function postUpgradeInit(IBridge _bridge) external {}
|
173
|
+
|
174
|
+
function calculateRetryableSubmissionFee(uint256, uint256)
|
175
|
+
external
|
176
|
+
pure
|
177
|
+
override
|
178
|
+
returns (uint256)
|
179
|
+
{
|
133
180
|
revert("NOT_IMPLEMENTED");
|
134
181
|
}
|
135
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
|
-
|
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,
|
package/src/mocks/Simple.sol
CHANGED
@@ -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
|
15
|
-
* Use eth_estimateGas to
|
16
|
-
*
|
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
|
@@ -33,7 +34,7 @@ interface NodeInterface {
|
|
33
34
|
|
34
35
|
/**
|
35
36
|
* @notice Constructs an outbox proof of an l2->l1 send's existence in the outbox accumulator.
|
36
|
-
* Use eth_call to call.
|
37
|
+
* @dev Use eth_call to call.
|
37
38
|
* @param size the number of elements in the accumulator
|
38
39
|
* @param leaf the position of the send in the accumulator
|
39
40
|
* @return send the l2->l1 send's hash
|
@@ -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
|
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
|
|
@@ -62,14 +63,16 @@ interface NodeInterface {
|
|
62
63
|
* @notice Gets the number of L1 confirmations of the sequencer batch producing the requested L2 block
|
63
64
|
* This gets the number of L1 confirmations for the input message producing the L2 block,
|
64
65
|
* which happens well before the L1 rollup contract confirms the L2 block.
|
65
|
-
* Throws if block doesnt exist in the L2 chain.
|
66
|
+
* Throws if block doesnt exist in the L2 chain.
|
67
|
+
* @dev Use eth_call to call.
|
66
68
|
* @param blockHash The hash of the L2 block being queried
|
67
69
|
* @return confirmations The number of L1 confirmations the sequencer batch has. Returns 0 if block not yet included in an L1 batch.
|
68
70
|
*/
|
69
71
|
function getL1Confirmations(bytes32 blockHash) external view returns (uint64 confirmations);
|
70
72
|
|
71
73
|
/**
|
72
|
-
* @notice Same as native gas estimation, but with additional info on the l1 costs.
|
74
|
+
* @notice Same as native gas estimation, but with additional info on the l1 costs.
|
75
|
+
* @dev Use eth_call to call.
|
73
76
|
* @param data the tx's calldata. Everything else like "From" and "Gas" are copied over
|
74
77
|
* @param to the tx's "To" (ignored when contractCreation is true)
|
75
78
|
* @param contractCreation whether "To" is omitted
|
@@ -91,4 +94,63 @@ interface NodeInterface {
|
|
91
94
|
uint256 baseFee,
|
92
95
|
uint256 l1BaseFeeEstimate
|
93
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
|
+
|
123
|
+
/**
|
124
|
+
* @notice Returns the proof necessary to redeem a message
|
125
|
+
* @param batchNum index of outbox entry (i.e., outgoing messages Merkle root) in array of outbox entries
|
126
|
+
* @param index index of outgoing message in outbox entry
|
127
|
+
* @return proof Merkle proof of message inclusion in outbox entry
|
128
|
+
* @return path Merkle path to message
|
129
|
+
* @return l2Sender sender if original message (i.e., caller of ArbSys.sendTxToL1)
|
130
|
+
* @return l1Dest destination address for L1 contract call
|
131
|
+
* @return l2Block l2 block number at which sendTxToL1 call was made
|
132
|
+
* @return l1Block l1 block number at which sendTxToL1 call was made
|
133
|
+
* @return timestamp l2 Timestamp at which sendTxToL1 call was made
|
134
|
+
* @return amount value in L1 message in wei
|
135
|
+
* @return calldataForL1 abi-encoded L1 message data
|
136
|
+
*/
|
137
|
+
function legacyLookupMessageBatchProof(uint256 batchNum, uint64 index)
|
138
|
+
external
|
139
|
+
view
|
140
|
+
returns (
|
141
|
+
bytes32[] memory proof,
|
142
|
+
uint256 path,
|
143
|
+
address l2Sender,
|
144
|
+
address l1Dest,
|
145
|
+
uint256 l2Block,
|
146
|
+
uint256 l1Block,
|
147
|
+
uint256 timestamp,
|
148
|
+
uint256 amount,
|
149
|
+
bytes memory calldataForL1
|
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);
|
94
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
|
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
|
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
|
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
|
68
|
+
/// @return (per L2 tx, per L1 calldata byte, per storage allocation)
|
69
69
|
function getPricesInArbGas()
|
70
70
|
external
|
71
71
|
view
|
@@ -109,4 +109,16 @@ interface ArbGasInfo {
|
|
109
109
|
|
110
110
|
/// @notice Get the forgivable amount of backlogged gas ArbOS will ignore when raising the basefee
|
111
111
|
function getGasBacklogTolerance() external view returns (uint64);
|
112
|
+
|
113
|
+
/// @notice Returns the surplus of funds for L1 batch posting payments (may be negative).
|
114
|
+
function getL1PricingSurplus() external view returns (int256);
|
115
|
+
|
116
|
+
/// @notice Returns the base charge (in L1 gas) attributed to each data batch in the calldata pricer
|
117
|
+
function getPerBatchGasCharge() external view returns (int64);
|
118
|
+
|
119
|
+
/// @notice Returns the cost amortization cap in basis points
|
120
|
+
function getAmortizedCostCapBips() external view returns (uint64);
|
121
|
+
|
122
|
+
/// @notice Returns the available funds from L1 fees
|
123
|
+
function getL1FeesAvailable() external view returns (uint256);
|
112
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
|
|
@@ -66,6 +72,18 @@ interface ArbOwner {
|
|
66
72
|
/// @notice Sets reward amount for L1 price adjustment algorithm, in wei per unit
|
67
73
|
function setL1PricingRewardRate(uint64 weiPerUnit) external;
|
68
74
|
|
75
|
+
/// @notice Set how much ArbOS charges per L1 gas spent on transaction data.
|
76
|
+
function setL1PricePerUnit(uint256 pricePerUnit) external;
|
77
|
+
|
78
|
+
/// @notice Sets the base charge (in L1 gas) attributed to each data batch in the calldata pricer
|
79
|
+
function setPerBatchGasCharge(int64 cost) external;
|
80
|
+
|
81
|
+
/// @notice Sets the cost amortization cap in basis points
|
82
|
+
function setAmortizedCostCapBips(uint64 cap) external;
|
83
|
+
|
84
|
+
/// @notice Releases surplus funds from L1PricerFundsPoolAddress for use
|
85
|
+
function releaseL1PricerSurplusFunds(uint256 maxWeiToRelease) external returns (uint256);
|
86
|
+
|
69
87
|
// Emitted when a successful call is made to this precompile
|
70
88
|
event OwnerActs(bytes4 indexed method, address indexed owner, bytes data);
|
71
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
|
}
|
@@ -36,13 +36,14 @@ interface ArbSys {
|
|
36
36
|
|
37
37
|
/**
|
38
38
|
* @notice Returns 0 since Nitro has no concept of storage gas
|
39
|
-
* @return
|
39
|
+
* @return uint 0
|
40
40
|
*/
|
41
41
|
function getStorageGasAvailable() external view returns (uint256);
|
42
42
|
|
43
43
|
/**
|
44
|
-
* @notice check if current call is
|
45
|
-
* @
|
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
|
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);
|
48
49
|
|
@@ -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
|
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
|
@@ -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/
|
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,
|
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(
|
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
|
}
|
@@ -315,4 +330,55 @@ contract RollupAdminLogic is RollupCore, IRollupAdmin, SecondaryLogicUUPSUpgrade
|
|
315
330
|
bridge.setSequencerInbox(_sequencerInbox);
|
316
331
|
emit OwnerFunctionCalled(27);
|
317
332
|
}
|
333
|
+
|
334
|
+
/**
|
335
|
+
* @notice sets the rollup's inbox reference. Does not update the bridge's view.
|
336
|
+
* @param newInbox new address of inbox
|
337
|
+
*/
|
338
|
+
function setInbox(IInbox newInbox) external {
|
339
|
+
inbox = newInbox;
|
340
|
+
emit OwnerFunctionCalled(28);
|
341
|
+
}
|
342
|
+
|
343
|
+
function createNitroMigrationGenesis(RollupLib.Assertion calldata assertion)
|
344
|
+
external
|
345
|
+
whenPaused
|
346
|
+
{
|
347
|
+
bytes32 expectedSendRoot = bytes32(0);
|
348
|
+
uint64 expectedInboxCount = 1;
|
349
|
+
|
350
|
+
require(latestNodeCreated() == 0, "NON_GENESIS_NODES_EXIST");
|
351
|
+
require(GlobalStateLib.isEmpty(assertion.beforeState.globalState), "NOT_EMPTY_BEFORE");
|
352
|
+
require(
|
353
|
+
assertion.beforeState.machineStatus == MachineStatus.FINISHED,
|
354
|
+
"BEFORE_MACHINE_NOT_FINISHED"
|
355
|
+
);
|
356
|
+
// accessors such as state.getSendRoot not available for calldata structs, only memory
|
357
|
+
require(
|
358
|
+
assertion.afterState.globalState.bytes32Vals[1] == expectedSendRoot,
|
359
|
+
"NOT_ZERO_SENDROOT"
|
360
|
+
);
|
361
|
+
require(
|
362
|
+
assertion.afterState.globalState.u64Vals[0] == expectedInboxCount,
|
363
|
+
"INBOX_NOT_AT_ONE"
|
364
|
+
);
|
365
|
+
require(assertion.afterState.globalState.u64Vals[1] == 0, "POSITION_IN_MESSAGE_NOT_ZERO");
|
366
|
+
require(
|
367
|
+
assertion.afterState.machineStatus == MachineStatus.FINISHED,
|
368
|
+
"AFTER_MACHINE_NOT_FINISHED"
|
369
|
+
);
|
370
|
+
bytes32 genesisBlockHash = assertion.afterState.globalState.bytes32Vals[0];
|
371
|
+
createNewNode(assertion, 0, expectedInboxCount, bytes32(0));
|
372
|
+
confirmNode(1, genesisBlockHash, expectedSendRoot);
|
373
|
+
emit OwnerFunctionCalled(29);
|
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
|
+
}
|
318
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;
|
@@ -552,7 +555,7 @@ abstract contract RollupCore is IRollupCore, PausableUpgradeable {
|
|
552
555
|
if (afterInboxCount == prevInboxPosition) {
|
553
556
|
require(
|
554
557
|
assertion.afterState.globalState.getPositionInMessage() >=
|
555
|
-
assertion.
|
558
|
+
assertion.beforeState.globalState.getPositionInMessage(),
|
556
559
|
"INBOX_POS_IN_MSG_BACKWARDS"
|
557
560
|
);
|
558
561
|
}
|
@@ -592,7 +595,10 @@ abstract contract RollupCore is IRollupCore, PausableUpgradeable {
|
|
592
595
|
memoryFrame.sequencerBatchAcc,
|
593
596
|
wasmModuleRoot
|
594
597
|
);
|
595
|
-
require(
|
598
|
+
require(
|
599
|
+
newNodeHash == expectedNodeHash || expectedNodeHash == bytes32(0),
|
600
|
+
"UNEXPECTED_NODE_HASH"
|
601
|
+
);
|
596
602
|
|
597
603
|
memoryFrame.node = NodeLib.createNode(
|
598
604
|
RollupLib.stateHash(assertion.afterState, memoryFrame.currentInboxSize),
|