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