@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.
- package/README.md +1 -1
- package/hardhat.prod-config.js +4 -4
- package/package.json +21 -3
- package/src/bridge/Bridge.sol +39 -30
- package/src/bridge/IBridge.sol +56 -29
- package/src/bridge/IInbox.sol +130 -15
- package/src/bridge/IOutbox.sol +55 -7
- package/src/bridge/ISequencerInbox.sol +84 -7
- package/src/bridge/Inbox.sol +233 -93
- package/src/bridge/Outbox.sol +23 -47
- package/src/bridge/SequencerInbox.sol +132 -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 +6 -0
- package/src/libraries/{SecondaryLogicUUPSUpgradeable.sol → DoubleLogicUUPSUpgradeable.sol} +2 -1
- package/src/libraries/Error.sol +12 -0
- package/src/libraries/IGasRefunder.sol +11 -5
- package/src/libraries/MerkleLib.sol +5 -3
- package/src/mocks/BridgeStub.sol +20 -1
- package/src/mocks/BridgeUnproxied.sol +17 -0
- package/src/mocks/InboxStub.sol +48 -3
- package/src/mocks/SequencerInboxStub.sol +13 -3
- package/src/mocks/Simple.sol +69 -0
- package/src/node-interface/NodeInterface.sol +35 -4
- package/src/precompiles/ArbGasInfo.sol +7 -4
- package/src/precompiles/ArbOwner.sol +9 -0
- package/src/precompiles/ArbOwnerPublic.sol +3 -0
- package/src/precompiles/ArbSys.sol +5 -2
- package/src/rollup/IRollupCore.sol +2 -0
- package/src/rollup/IRollupLogic.sol +10 -0
- package/src/rollup/RollupAdminLogic.sol +27 -3
- package/src/rollup/RollupCore.sol +3 -0
- package/src/rollup/RollupCreator.sol +3 -3
- package/src/rollup/RollupEventInbox.sol +3 -6
- package/src/{libraries/ArbitrumProxy.sol → rollup/RollupProxy.sol} +3 -3
- package/src/rollup/RollupUserLogic.sol +47 -10
- package/src/test-helpers/BridgeTester.sol +7 -1
- package/src/test-helpers/OutboxWithoutOptTester.sol +8 -8
package/src/mocks/BridgeStub.sol
CHANGED
@@ -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(
|
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
|
+
}
|
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,13 +134,49 @@ contract InboxStub is IInbox {
|
|
125
134
|
revert("NOT_IMPLEMENTED");
|
126
135
|
}
|
127
136
|
|
128
|
-
function
|
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
|
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
|
-
|
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
|
-
* @dev 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
|
@@ -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
|
|
@@ -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
|
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
|
@@ -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
|
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
|
}
|
@@ -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 "
|
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
|
-
|
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
|
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
|
-
|
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 "
|
8
|
-
import "
|
7
|
+
import "../libraries/AdminFallbackProxy.sol";
|
8
|
+
import "./IRollupLogic.sol";
|
9
9
|
|
10
|
-
contract
|
10
|
+
contract RollupProxy is AdminFallbackProxy {
|
11
11
|
constructor(Config memory config, ContractDependencies memory connectedContracts)
|
12
12
|
AdminFallbackProxy(
|
13
13
|
address(connectedContracts.rollupAdminLogic),
|