@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.
- package/package.json +10 -2
- 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 +154 -92
- 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 +3 -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),
|