@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
@@ -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
|
}
|
package/src/rollup/RollupLib.sol
CHANGED
@@ -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),
|
@@ -9,6 +9,7 @@ import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
|
|
9
9
|
import {IRollupUser} from "./IRollupLogic.sol";
|
10
10
|
import "../libraries/UUPSNotUpgradeable.sol";
|
11
11
|
import "./RollupCore.sol";
|
12
|
+
import {ETH_POS_BLOCK_TIME} from "../libraries/Constants.sol";
|
12
13
|
|
13
14
|
abstract contract AbsRollupUserLogic is
|
14
15
|
RollupCore,
|
@@ -20,10 +21,43 @@ abstract contract AbsRollupUserLogic is
|
|
20
21
|
using GlobalStateLib for GlobalState;
|
21
22
|
|
22
23
|
modifier onlyValidator() {
|
23
|
-
require(isValidator[msg.sender], "NOT_VALIDATOR");
|
24
|
+
require(isValidator[msg.sender] || validatorWhitelistDisabled, "NOT_VALIDATOR");
|
24
25
|
_;
|
25
26
|
}
|
26
27
|
|
28
|
+
uint256 internal immutable deployTimeChainId = block.chainid;
|
29
|
+
|
30
|
+
function _chainIdChanged() internal view returns (bool) {
|
31
|
+
return deployTimeChainId != block.chainid;
|
32
|
+
}
|
33
|
+
|
34
|
+
/**
|
35
|
+
* @notice Extra number of blocks the validator can remain inactive before considered inactive
|
36
|
+
* This is 7 days assuming a 13.2 seconds block time
|
37
|
+
*/
|
38
|
+
uint256 public constant VALIDATOR_AFK_BLOCKS = 45818;
|
39
|
+
|
40
|
+
function _validatorIsAfk() internal view returns (bool) {
|
41
|
+
Node memory latestNode = getNodeStorage(latestNodeCreated());
|
42
|
+
if (latestNode.createdAtBlock == 0) return false;
|
43
|
+
if (latestNode.createdAtBlock + confirmPeriodBlocks + VALIDATOR_AFK_BLOCKS < block.number) {
|
44
|
+
return true;
|
45
|
+
}
|
46
|
+
return false;
|
47
|
+
}
|
48
|
+
|
49
|
+
function removeWhitelistAfterFork() external {
|
50
|
+
require(!validatorWhitelistDisabled, "WHITELIST_DISABLED");
|
51
|
+
require(_chainIdChanged(), "CHAIN_ID_NOT_CHANGED");
|
52
|
+
validatorWhitelistDisabled = true;
|
53
|
+
}
|
54
|
+
|
55
|
+
function removeWhitelistAfterValidatorAfk() external {
|
56
|
+
require(!validatorWhitelistDisabled, "WHITELIST_DISABLED");
|
57
|
+
require(_validatorIsAfk(), "VALIDATOR_NOT_AFK");
|
58
|
+
validatorWhitelistDisabled = true;
|
59
|
+
}
|
60
|
+
|
27
61
|
function isERC20Enabled() public view override returns (bool) {
|
28
62
|
return stakeToken != address(0);
|
29
63
|
}
|
@@ -239,7 +273,7 @@ abstract contract AbsRollupUserLogic is
|
|
239
273
|
* @param globalStates The before and after global state for the first assertion
|
240
274
|
* @param numBlocks The number of L2 blocks contained in the first assertion
|
241
275
|
* @param secondExecutionHash The execution hash of the second assertion
|
242
|
-
* @param
|
276
|
+
* @param proposedBlocks L1 block numbers that the two nodes were proposed at
|
243
277
|
* @param wasmModuleRoots The wasm module roots at the time of the creation of each assertion
|
244
278
|
*/
|
245
279
|
function createChallenge(
|
@@ -249,7 +283,7 @@ abstract contract AbsRollupUserLogic is
|
|
249
283
|
GlobalState[2] calldata globalStates,
|
250
284
|
uint64 numBlocks,
|
251
285
|
bytes32 secondExecutionHash,
|
252
|
-
uint256[2] calldata
|
286
|
+
uint256[2] calldata proposedBlocks,
|
253
287
|
bytes32[2] calldata wasmModuleRoots
|
254
288
|
) external onlyValidator whenNotPaused {
|
255
289
|
require(nodeNums[0] < nodeNums[1], "WRONG_ORDER");
|
@@ -274,7 +308,7 @@ abstract contract AbsRollupUserLogic is
|
|
274
308
|
node1.challengeHash ==
|
275
309
|
RollupLib.challengeRootHash(
|
276
310
|
RollupLib.executionHash(machineStatuses, globalStates, numBlocks),
|
277
|
-
|
311
|
+
proposedBlocks[0],
|
278
312
|
wasmModuleRoots[0]
|
279
313
|
),
|
280
314
|
"CHAL_HASH1"
|
@@ -284,18 +318,18 @@ abstract contract AbsRollupUserLogic is
|
|
284
318
|
node2.challengeHash ==
|
285
319
|
RollupLib.challengeRootHash(
|
286
320
|
secondExecutionHash,
|
287
|
-
|
321
|
+
proposedBlocks[1],
|
288
322
|
wasmModuleRoots[1]
|
289
323
|
),
|
290
324
|
"CHAL_HASH2"
|
291
325
|
);
|
292
326
|
|
293
327
|
// Calculate upper limit for allowed node proposal time:
|
294
|
-
uint256
|
328
|
+
uint256 commonEndBlock = getNodeStorage(node1.prevNum).firstChildBlock +
|
295
329
|
// Dispute start: dispute timer for a node starts when its first child is created
|
296
|
-
(node1.deadlineBlock -
|
330
|
+
(node1.deadlineBlock - proposedBlocks[0]) +
|
297
331
|
extraChallengeTimeBlocks; // add dispute window to dispute start time
|
298
|
-
if (
|
332
|
+
if (commonEndBlock < proposedBlocks[1]) {
|
299
333
|
// The 2nd node was created too late; loses challenge automatically.
|
300
334
|
completeChallengeImpl(stakers[0], stakers[1]);
|
301
335
|
return;
|
@@ -307,8 +341,9 @@ abstract contract AbsRollupUserLogic is
|
|
307
341
|
globalStates,
|
308
342
|
numBlocks,
|
309
343
|
wasmModuleRoots,
|
310
|
-
|
311
|
-
|
344
|
+
// convert from block counts to real second based timestamps
|
345
|
+
(commonEndBlock - proposedBlocks[0]) * ETH_POS_BLOCK_TIME,
|
346
|
+
(commonEndBlock - proposedBlocks[1]) * ETH_POS_BLOCK_TIME
|
312
347
|
); // trusted external call
|
313
348
|
|
314
349
|
challengeStarted(stakers[0], stakers[1], challengeIndex);
|
@@ -366,6 +401,8 @@ abstract contract AbsRollupUserLogic is
|
|
366
401
|
uint256 amountWon = remainingLoserStake / 2;
|
367
402
|
increaseStakeBy(winningStaker, amountWon);
|
368
403
|
remainingLoserStake -= amountWon;
|
404
|
+
// We deliberately leave loser in challenge state to prevent them from
|
405
|
+
// doing certain thing that are allowed only to parties not in a challenge
|
369
406
|
clearChallenge(winningStaker);
|
370
407
|
// Credit the other half to the loserStakeEscrow address
|
371
408
|
increaseWithdrawableFunds(loserStakeEscrow, remainingLoserStake);
|
@@ -41,4 +41,11 @@ library GlobalStateLib {
|
|
41
41
|
function getPositionInMessage(GlobalState memory state) internal pure returns (uint64) {
|
42
42
|
return state.u64Vals[1];
|
43
43
|
}
|
44
|
+
|
45
|
+
function isEmpty(GlobalState calldata state) internal pure returns (bool) {
|
46
|
+
return (state.bytes32Vals[0] == bytes32(0) &&
|
47
|
+
state.bytes32Vals[1] == bytes32(0) &&
|
48
|
+
state.u64Vals[0] == 0 &&
|
49
|
+
state.u64Vals[1] == 0);
|
50
|
+
}
|
44
51
|
}
|
@@ -7,6 +7,14 @@ pragma solidity ^0.8.4;
|
|
7
7
|
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
|
8
8
|
import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
|
9
9
|
|
10
|
+
import {
|
11
|
+
NotContract,
|
12
|
+
NotRollupOrOwner,
|
13
|
+
NotDelayedInbox,
|
14
|
+
NotSequencerInbox,
|
15
|
+
NotOutbox,
|
16
|
+
InvalidOutboxSet
|
17
|
+
} from "../libraries/Error.sol";
|
10
18
|
import "../bridge/IBridge.sol";
|
11
19
|
import "../bridge/Messages.sol";
|
12
20
|
import "../libraries/DelegateCallAware.sol";
|
@@ -56,6 +64,7 @@ contract BridgeTester is Initializable, DelegateCallAware, IBridge {
|
|
56
64
|
bytes32[] public override delayedInboxAccs;
|
57
65
|
|
58
66
|
bytes32[] public override sequencerInboxAccs;
|
67
|
+
uint256 public override sequencerReportedSubMessageCount;
|
59
68
|
|
60
69
|
address private constant EMPTY_ACTIVEOUTBOX = address(type(uint160).max);
|
61
70
|
|
@@ -77,7 +86,12 @@ contract BridgeTester is Initializable, DelegateCallAware, IBridge {
|
|
77
86
|
return allowedOutboxesMap[outbox].allowed;
|
78
87
|
}
|
79
88
|
|
80
|
-
function enqueueSequencerMessage(
|
89
|
+
function enqueueSequencerMessage(
|
90
|
+
bytes32 dataHash,
|
91
|
+
uint256 afterDelayedMessagesRead,
|
92
|
+
uint256 prevMessageCount,
|
93
|
+
uint256 newMessageCount
|
94
|
+
)
|
81
95
|
external
|
82
96
|
returns (
|
83
97
|
uint256 seqMessageIndex,
|
@@ -220,4 +234,6 @@ contract BridgeTester is Initializable, DelegateCallAware, IBridge {
|
|
220
234
|
}
|
221
235
|
|
222
236
|
receive() external payable {}
|
237
|
+
|
238
|
+
function acceptFundsFromOldBridge() external payable {}
|
223
239
|
}
|
@@ -0,0 +1,11 @@
|
|
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
|
+
// solhint-disable-next-line compiler-version
|
6
|
+
pragma solidity >=0.6.9 <0.9.0;
|
7
|
+
|
8
|
+
import "../bridge/IBridge.sol";
|
9
|
+
import "../bridge/IOutbox.sol";
|
10
|
+
import "../bridge/IInbox.sol";
|
11
|
+
import "../bridge/ISequencerInbox.sol";
|
@@ -4,6 +4,15 @@
|
|
4
4
|
|
5
5
|
pragma solidity ^0.8.4;
|
6
6
|
|
7
|
+
import {
|
8
|
+
AlreadyInit,
|
9
|
+
NotRollup,
|
10
|
+
ProofTooLong,
|
11
|
+
PathNotMinimal,
|
12
|
+
UnknownRoot,
|
13
|
+
AlreadySpent,
|
14
|
+
BridgeCallFailed
|
15
|
+
} from "../libraries/Error.sol";
|
7
16
|
import "../bridge/IBridge.sol";
|
8
17
|
import "../bridge/IOutbox.sol";
|
9
18
|
import "../libraries/MerkleLib.sol";
|
@@ -13,7 +22,11 @@ contract OutboxWithoutOptTester is DelegateCallAware, IOutbox {
|
|
13
22
|
address public rollup; // the rollup contract
|
14
23
|
IBridge public bridge; // the bridge contract
|
15
24
|
|
16
|
-
|
25
|
+
function spent(uint256) external pure override returns (bytes32) {
|
26
|
+
revert("NOT_IMPLEMETED");
|
27
|
+
}
|
28
|
+
|
29
|
+
mapping(uint256 => bool) public isSpent; // maps leaf number => if spent
|
17
30
|
mapping(bytes32 => bytes32) public roots; // maps root hashes => L2 block hash
|
18
31
|
|
19
32
|
struct L2ToL1Context {
|
@@ -61,7 +74,7 @@ contract OutboxWithoutOptTester is DelegateCallAware, IOutbox {
|
|
61
74
|
}
|
62
75
|
|
63
76
|
// @deprecated batch number is now always 0
|
64
|
-
function l2ToL1BatchNum() external pure
|
77
|
+
function l2ToL1BatchNum() external pure returns (uint256) {
|
65
78
|
return 0;
|
66
79
|
}
|
67
80
|
|
@@ -93,7 +106,7 @@ contract OutboxWithoutOptTester is DelegateCallAware, IOutbox {
|
|
93
106
|
uint256 l2Timestamp,
|
94
107
|
uint256 value,
|
95
108
|
bytes calldata data
|
96
|
-
) external virtual {
|
109
|
+
) external virtual override {
|
97
110
|
bytes32 outputId;
|
98
111
|
{
|
99
112
|
bytes32 userTx = calculateItemHash(
|
@@ -128,6 +141,19 @@ contract OutboxWithoutOptTester is DelegateCallAware, IOutbox {
|
|
128
141
|
context = prevContext;
|
129
142
|
}
|
130
143
|
|
144
|
+
function executeTransactionSimulation(
|
145
|
+
uint256,
|
146
|
+
address,
|
147
|
+
address,
|
148
|
+
uint256,
|
149
|
+
uint256,
|
150
|
+
uint256,
|
151
|
+
uint256,
|
152
|
+
bytes calldata
|
153
|
+
) external pure override {
|
154
|
+
revert("Not implemented");
|
155
|
+
}
|
156
|
+
|
131
157
|
function recordOutputAsSpent(
|
132
158
|
bytes32[] memory proof,
|
133
159
|
uint256 index,
|
@@ -140,8 +166,8 @@ contract OutboxWithoutOptTester is DelegateCallAware, IOutbox {
|
|
140
166
|
bytes32 calcRoot = calculateMerkleRoot(proof, index, item);
|
141
167
|
if (roots[calcRoot] == bytes32(0)) revert UnknownRoot(calcRoot);
|
142
168
|
|
143
|
-
if (
|
144
|
-
|
169
|
+
if (isSpent[index]) revert AlreadySpent(index);
|
170
|
+
isSpent[index] = true;
|
145
171
|
|
146
172
|
return bytes32(index);
|
147
173
|
}
|
@@ -173,7 +199,7 @@ contract OutboxWithoutOptTester is DelegateCallAware, IOutbox {
|
|
173
199
|
uint256 l2Timestamp,
|
174
200
|
uint256 value,
|
175
201
|
bytes calldata data
|
176
|
-
) public pure returns (bytes32) {
|
202
|
+
) public pure override returns (bytes32) {
|
177
203
|
return
|
178
204
|
keccak256(abi.encodePacked(l2Sender, to, l2Block, l1Block, l2Timestamp, value, data));
|
179
205
|
}
|
@@ -182,7 +208,7 @@ contract OutboxWithoutOptTester is DelegateCallAware, IOutbox {
|
|
182
208
|
bytes32[] memory proof,
|
183
209
|
uint256 path,
|
184
210
|
bytes32 item
|
185
|
-
) public pure returns (bytes32) {
|
211
|
+
) public pure override returns (bytes32) {
|
186
212
|
return MerkleLib.calculateRoot(proof, path, keccak256(abi.encodePacked(item)));
|
187
213
|
}
|
188
214
|
}
|