@arbitrum/nitro-contracts 1.0.0-beta.7 → 1.0.0-beta.8
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 +5 -2
- package/src/bridge/Bridge.sol +11 -0
- package/src/bridge/IBridge.sol +4 -18
- package/src/bridge/IDelayedMessageProvider.sol +2 -1
- package/src/bridge/IInbox.sol +4 -36
- package/src/bridge/IOutbox.sol +43 -23
- package/src/bridge/IOwnable.sol +2 -1
- package/src/bridge/ISequencerInbox.sol +3 -32
- package/src/bridge/Inbox.sol +20 -19
- package/src/bridge/Outbox.sol +14 -5
- package/src/bridge/SequencerInbox.sol +21 -1
- package/src/libraries/Error.sol +107 -0
- package/src/libraries/IGasRefunder.sol +2 -1
- package/src/mocks/BridgeStub.sol +2 -0
- package/src/mocks/InboxStub.sol +2 -0
- package/src/node-interface/NodeInterface.sol +35 -4
- package/src/precompiles/ArbGasInfo.sol +9 -0
- package/src/precompiles/ArbOwner.sol +9 -0
- package/src/precompiles/ArbSys.sol +3 -3
- package/src/rollup/RollupAdminLogic.sol +42 -0
- package/src/rollup/RollupCore.sol +5 -2
- package/src/rollup/RollupLib.sol +1 -0
- package/src/state/GlobalState.sol +7 -0
- package/src/test-helpers/BridgeTester.sol +10 -0
- package/src/test-helpers/InterfaceCompatibilityTester.sol +11 -0
- package/src/test-helpers/OutboxWithoutOptTester.sol +29 -3
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@arbitrum/nitro-contracts",
|
3
|
-
"version": "1.0.0-beta.
|
3
|
+
"version": "1.0.0-beta.8",
|
4
4
|
"description": "Layer 2 precompiles and rollup for Arbitrum Nitro",
|
5
5
|
"author": "Offchain Labs, Inc.",
|
6
6
|
"license": "BUSL-1.1",
|
@@ -21,7 +21,10 @@
|
|
21
21
|
"build": "./scripts/build.bash",
|
22
22
|
"solhint": "solhint -f table src/**/*.sol",
|
23
23
|
"prettier:solidity": "prettier --write src/**/*.sol",
|
24
|
-
"hardhat:prod": "hardhat --config hardhat.prod-config.js"
|
24
|
+
"hardhat:prod": "hardhat --config hardhat.prod-config.js",
|
25
|
+
"build:0.6": "INTERFACE_TESTER_SOLC_VERSION=0.6.9 yarn run build",
|
26
|
+
"build:0.7": "INTERFACE_TESTER_SOLC_VERSION=0.7.0 yarn run build",
|
27
|
+
"test:compatibility": "yarn run build:0.6 && yarn run build:0.7"
|
25
28
|
},
|
26
29
|
"dependencies": {
|
27
30
|
"@openzeppelin/contracts": "4.5.0",
|
package/src/bridge/Bridge.sol
CHANGED
@@ -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 "./IBridge.sol";
|
11
19
|
import "./Messages.sol";
|
12
20
|
import "../libraries/DelegateCallAware.sol";
|
@@ -260,4 +268,7 @@ contract Bridge is Initializable, DelegateCallAware, IBridge {
|
|
260
268
|
function sequencerMessageCount() external view override returns (uint256) {
|
261
269
|
return sequencerInboxAccs.length;
|
262
270
|
}
|
271
|
+
|
272
|
+
/// @dev For the classic -> nitro migration. TODO: remove post-migration.
|
273
|
+
function acceptFundsFromOldBridge() external payable {}
|
263
274
|
}
|
package/src/bridge/IBridge.sol
CHANGED
@@ -2,27 +2,11 @@
|
|
2
2
|
// For license information, see https://github.com/nitro/blob/master/LICENSE
|
3
3
|
// SPDX-License-Identifier: BUSL-1.1
|
4
4
|
|
5
|
-
|
5
|
+
// solhint-disable-next-line compiler-version
|
6
|
+
pragma solidity >=0.6.9 <0.9.0;
|
6
7
|
|
7
|
-
import {NotContract, NotRollupOrOwner} from "../libraries/Error.sol";
|
8
8
|
import "./IOwnable.sol";
|
9
9
|
|
10
|
-
/// @dev Thrown when an un-authorized address tries to access an only-inbox function
|
11
|
-
/// @param sender The un-authorized sender
|
12
|
-
error NotDelayedInbox(address sender);
|
13
|
-
|
14
|
-
/// @dev Thrown when an un-authorized address tries to access an only-sequencer-inbox function
|
15
|
-
/// @param sender The un-authorized sender
|
16
|
-
error NotSequencerInbox(address sender);
|
17
|
-
|
18
|
-
/// @dev Thrown when an un-authorized address tries to access an only-outbox function
|
19
|
-
/// @param sender The un-authorized sender
|
20
|
-
error NotOutbox(address sender);
|
21
|
-
|
22
|
-
/// @dev the provided outbox address isn't valid
|
23
|
-
/// @param outbox address of outbox being set
|
24
|
-
error InvalidOutboxSet(address outbox);
|
25
|
-
|
26
10
|
interface IBridge {
|
27
11
|
event MessageDelivered(
|
28
12
|
uint256 indexed messageIndex,
|
@@ -99,4 +83,6 @@ interface IBridge {
|
|
99
83
|
function sequencerMessageCount() external view returns (uint256);
|
100
84
|
|
101
85
|
function rollup() external view returns (IOwnable);
|
86
|
+
|
87
|
+
function acceptFundsFromOldBridge() external payable;
|
102
88
|
}
|
@@ -2,7 +2,8 @@
|
|
2
2
|
// For license information, see https://github.com/nitro/blob/master/LICENSE
|
3
3
|
// SPDX-License-Identifier: BUSL-1.1
|
4
4
|
|
5
|
-
|
5
|
+
// solhint-disable-next-line compiler-version
|
6
|
+
pragma solidity >=0.6.9 <0.9.0;
|
6
7
|
|
7
8
|
interface IDelayedMessageProvider {
|
8
9
|
/// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator
|
package/src/bridge/IInbox.sol
CHANGED
@@ -2,44 +2,11 @@
|
|
2
2
|
// For license information, see https://github.com/nitro/blob/master/LICENSE
|
3
3
|
// SPDX-License-Identifier: BUSL-1.1
|
4
4
|
|
5
|
-
|
5
|
+
// solhint-disable-next-line compiler-version
|
6
|
+
pragma solidity >=0.6.9 <0.9.0;
|
6
7
|
|
7
8
|
import "./IBridge.sol";
|
8
9
|
import "./IDelayedMessageProvider.sol";
|
9
|
-
import {AlreadyInit, NotOrigin, DataTooLarge} from "../libraries/Error.sol";
|
10
|
-
|
11
|
-
/// @dev The contract is paused, so cannot be paused
|
12
|
-
error AlreadyPaused();
|
13
|
-
|
14
|
-
/// @dev The contract is unpaused, so cannot be unpaused
|
15
|
-
error AlreadyUnpaused();
|
16
|
-
|
17
|
-
/// @dev The contract is paused
|
18
|
-
error Paused();
|
19
|
-
|
20
|
-
/// @dev msg.value sent to the inbox isn't high enough
|
21
|
-
error InsufficientValue(uint256 expected, uint256 actual);
|
22
|
-
|
23
|
-
/// @dev submission cost provided isn't enough to create retryable ticket
|
24
|
-
error InsufficientSubmissionCost(uint256 expected, uint256 actual);
|
25
|
-
|
26
|
-
/// @dev address not allowed to interact with the given contract
|
27
|
-
error NotAllowedOrigin(address origin);
|
28
|
-
|
29
|
-
/// @dev used to convey retryable tx data in eth calls without requiring a tx trace
|
30
|
-
/// this follows a pattern similar to EIP-3668 where reverts surface call information
|
31
|
-
error RetryableData(
|
32
|
-
address from,
|
33
|
-
address to,
|
34
|
-
uint256 l2CallValue,
|
35
|
-
uint256 deposit,
|
36
|
-
uint256 maxSubmissionCost,
|
37
|
-
address excessFeeRefundAddress,
|
38
|
-
address callValueRefundAddress,
|
39
|
-
uint256 gasLimit,
|
40
|
-
uint256 maxFeePerGas,
|
41
|
-
bytes data
|
42
|
-
);
|
43
10
|
|
44
11
|
interface IInbox is IDelayedMessageProvider {
|
45
12
|
function sendL2Message(bytes calldata messageData) external returns (uint256);
|
@@ -88,7 +55,6 @@ interface IInbox is IDelayedMessageProvider {
|
|
88
55
|
bytes calldata data
|
89
56
|
) external payable returns (uint256);
|
90
57
|
|
91
|
-
/// @notice TEMPORARILY DISABLED as exact mechanics are being worked out
|
92
58
|
/// @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error
|
93
59
|
function unsafeCreateRetryableTicket(
|
94
60
|
address to,
|
@@ -107,4 +73,6 @@ interface IInbox is IDelayedMessageProvider {
|
|
107
73
|
function depositEth(uint256 maxSubmissionCost) external payable returns (uint256);
|
108
74
|
|
109
75
|
function bridge() external view returns (IBridge);
|
76
|
+
|
77
|
+
function postUpgradeInit(IBridge _bridge) external;
|
110
78
|
}
|
package/src/bridge/IOutbox.sol
CHANGED
@@ -2,29 +2,8 @@
|
|
2
2
|
// For license information, see https://github.com/nitro/blob/master/LICENSE
|
3
3
|
// SPDX-License-Identifier: BUSL-1.1
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
import {AlreadyInit, NotRollup} from "../libraries/Error.sol";
|
8
|
-
|
9
|
-
/// @dev The provided proof was too long
|
10
|
-
/// @param proofLength The length of the too-long proof
|
11
|
-
error ProofTooLong(uint256 proofLength);
|
12
|
-
|
13
|
-
/// @dev The output index was greater than the maximum
|
14
|
-
/// @param index The output index
|
15
|
-
/// @param maxIndex The max the index could be
|
16
|
-
error PathNotMinimal(uint256 index, uint256 maxIndex);
|
17
|
-
|
18
|
-
/// @dev The calculated root does not exist
|
19
|
-
/// @param root The calculated root
|
20
|
-
error UnknownRoot(bytes32 root);
|
21
|
-
|
22
|
-
/// @dev The record has already been spent
|
23
|
-
/// @param index The index of the spent record
|
24
|
-
error AlreadySpent(uint256 index);
|
25
|
-
|
26
|
-
/// @dev A call to the bridge failed with no return data
|
27
|
-
error BridgeCallFailed();
|
5
|
+
// solhint-disable-next-line compiler-version
|
6
|
+
pragma solidity >=0.6.9 <0.9.0;
|
28
7
|
|
29
8
|
interface IOutbox {
|
30
9
|
event SendRootUpdated(bytes32 indexed blockHash, bytes32 indexed outputRoot);
|
@@ -49,4 +28,45 @@ interface IOutbox {
|
|
49
28
|
function l2ToL1OutputId() external view returns (bytes32);
|
50
29
|
|
51
30
|
function updateSendRoot(bytes32 sendRoot, bytes32 l2BlockHash) external;
|
31
|
+
|
32
|
+
function executeTransaction(
|
33
|
+
bytes32[] calldata proof,
|
34
|
+
uint256 index,
|
35
|
+
address l2Sender,
|
36
|
+
address to,
|
37
|
+
uint256 l2Block,
|
38
|
+
uint256 l1Block,
|
39
|
+
uint256 l2Timestamp,
|
40
|
+
uint256 value,
|
41
|
+
bytes calldata data
|
42
|
+
) external;
|
43
|
+
|
44
|
+
function executeTransactionSimulation(
|
45
|
+
uint256 index,
|
46
|
+
address l2Sender,
|
47
|
+
address to,
|
48
|
+
uint256 l2Block,
|
49
|
+
uint256 l1Block,
|
50
|
+
uint256 l2Timestamp,
|
51
|
+
uint256 value,
|
52
|
+
bytes calldata data
|
53
|
+
) external;
|
54
|
+
|
55
|
+
function isSpent(uint256) external view returns (bool);
|
56
|
+
|
57
|
+
function calculateItemHash(
|
58
|
+
address l2Sender,
|
59
|
+
address to,
|
60
|
+
uint256 l2Block,
|
61
|
+
uint256 l1Block,
|
62
|
+
uint256 l2Timestamp,
|
63
|
+
uint256 value,
|
64
|
+
bytes calldata data
|
65
|
+
) external pure returns (bytes32);
|
66
|
+
|
67
|
+
function calculateMerkleRoot(
|
68
|
+
bytes32[] memory proof,
|
69
|
+
uint256 path,
|
70
|
+
bytes32 item
|
71
|
+
) external pure returns (bytes32);
|
52
72
|
}
|
package/src/bridge/IOwnable.sol
CHANGED
@@ -2,7 +2,8 @@
|
|
2
2
|
// For license information, see https://github.com/nitro/blob/master/LICENSE
|
3
3
|
// SPDX-License-Identifier: BUSL-1.1
|
4
4
|
|
5
|
-
|
5
|
+
// solhint-disable-next-line compiler-version
|
6
|
+
pragma solidity >=0.4.21 <0.9.0;
|
6
7
|
|
7
8
|
interface IOwnable {
|
8
9
|
function owner() external view returns (address);
|
@@ -2,10 +2,11 @@
|
|
2
2
|
// For license information, see https://github.com/nitro/blob/master/LICENSE
|
3
3
|
// SPDX-License-Identifier: BUSL-1.1
|
4
4
|
|
5
|
-
|
5
|
+
// solhint-disable-next-line compiler-version
|
6
|
+
pragma solidity >=0.6.9 <0.9.0;
|
7
|
+
pragma experimental ABIEncoderV2;
|
6
8
|
|
7
9
|
import "../libraries/IGasRefunder.sol";
|
8
|
-
import {AlreadyInit, HadZeroInit, NotOrigin, DataTooLarge, NotRollup} from "../libraries/Error.sol";
|
9
10
|
import "./IDelayedMessageProvider.sol";
|
10
11
|
|
11
12
|
interface ISequencerInbox is IDelayedMessageProvider {
|
@@ -50,36 +51,6 @@ interface ISequencerInbox is IDelayedMessageProvider {
|
|
50
51
|
/// @dev a keyset was invalidated
|
51
52
|
event InvalidateKeyset(bytes32 indexed keysetHash);
|
52
53
|
|
53
|
-
/// @dev Thrown when someone attempts to read fewer messages than have already been read
|
54
|
-
error DelayedBackwards();
|
55
|
-
|
56
|
-
/// @dev Thrown when someone attempts to read more messages than exist
|
57
|
-
error DelayedTooFar();
|
58
|
-
|
59
|
-
/// @dev Force include can only read messages more blocks old than the delay period
|
60
|
-
error ForceIncludeBlockTooSoon();
|
61
|
-
|
62
|
-
/// @dev Force include can only read messages more seconds old than the delay period
|
63
|
-
error ForceIncludeTimeTooSoon();
|
64
|
-
|
65
|
-
/// @dev The message provided did not match the hash in the delayed inbox
|
66
|
-
error IncorrectMessagePreimage();
|
67
|
-
|
68
|
-
/// @dev This can only be called by the batch poster
|
69
|
-
error NotBatchPoster();
|
70
|
-
|
71
|
-
/// @dev The sequence number provided to this message was inconsistent with the number of batches already included
|
72
|
-
error BadSequencerNumber(uint256 stored, uint256 received);
|
73
|
-
|
74
|
-
/// @dev The batch data has the inbox authenticated bit set, but the batch data was not authenticated by the inbox
|
75
|
-
error DataNotAuthenticated();
|
76
|
-
|
77
|
-
/// @dev Tried to create an already valid Data Availability Service keyset
|
78
|
-
error AlreadyValidDASKeyset(bytes32);
|
79
|
-
|
80
|
-
/// @dev Tried to use or invalidate an already invalid Data Availability Service keyset
|
81
|
-
error NoSuchKeyset(bytes32);
|
82
|
-
|
83
54
|
function inboxAccs(uint256 index) external view returns (bytes32);
|
84
55
|
|
85
56
|
function batchCount() external view returns (uint256);
|
package/src/bridge/Inbox.sol
CHANGED
@@ -4,6 +4,19 @@
|
|
4
4
|
|
5
5
|
pragma solidity ^0.8.4;
|
6
6
|
|
7
|
+
import {
|
8
|
+
AlreadyInit,
|
9
|
+
NotOrigin,
|
10
|
+
DataTooLarge,
|
11
|
+
AlreadyPaused,
|
12
|
+
AlreadyUnpaused,
|
13
|
+
Paused,
|
14
|
+
InsufficientValue,
|
15
|
+
InsufficientSubmissionCost,
|
16
|
+
NotAllowedOrigin,
|
17
|
+
RetryableData,
|
18
|
+
NotRollupOrOwner
|
19
|
+
} from "../libraries/Error.sol";
|
7
20
|
import "./IInbox.sol";
|
8
21
|
import "./ISequencerInbox.sol";
|
9
22
|
import "./IBridge.sol";
|
@@ -244,14 +257,15 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
|
|
244
257
|
* @dev This fee can be paid by funds already in the L2 aliased address or by the current message value
|
245
258
|
* @dev This formula may change in the future, to future proof your code query this method instead of inlining!!
|
246
259
|
* @param dataLength The length of the retryable's calldata, in bytes
|
247
|
-
* @param baseFee The block basefee when the retryable is included in the chain
|
260
|
+
* @param baseFee The block basefee when the retryable is included in the chain, if 0 current block.basefee will be used
|
248
261
|
*/
|
249
262
|
function calculateRetryableSubmissionFee(uint256 dataLength, uint256 baseFee)
|
250
263
|
public
|
251
|
-
|
264
|
+
view
|
252
265
|
returns (uint256)
|
253
266
|
{
|
254
|
-
|
267
|
+
// Use current block basefee if baseFee parameter is 0
|
268
|
+
return (1400 + 6 * dataLength) * (baseFee == 0 ? block.basefee : baseFee);
|
255
269
|
}
|
256
270
|
|
257
271
|
/// @notice deposit eth from L1 to L2
|
@@ -373,7 +387,7 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
|
|
373
387
|
}
|
374
388
|
|
375
389
|
return
|
376
|
-
|
390
|
+
unsafeCreateRetryableTicket(
|
377
391
|
to,
|
378
392
|
l2CallValue,
|
379
393
|
maxSubmissionCost,
|
@@ -402,7 +416,7 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
|
|
402
416
|
* @param data ABI encoded data of L2 message
|
403
417
|
* @return unique id for retryable transaction (keccak256(requestID, uint(0) )
|
404
418
|
*/
|
405
|
-
function
|
419
|
+
function unsafeCreateRetryableTicket(
|
406
420
|
address to,
|
407
421
|
uint256 l2CallValue,
|
408
422
|
uint256 maxSubmissionCost,
|
@@ -411,7 +425,7 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
|
|
411
425
|
uint256 gasLimit,
|
412
426
|
uint256 maxFeePerGas,
|
413
427
|
bytes calldata data
|
414
|
-
)
|
428
|
+
) public payable virtual override whenNotPaused onlyAllowed returns (uint256) {
|
415
429
|
// gas price and limit of 1 should never be a valid input, so instead they are used as
|
416
430
|
// magic values to trigger a revert in eth calls that surface data without requiring a tx trace
|
417
431
|
if (gasLimit == 1 || maxFeePerGas == 1)
|
@@ -451,19 +465,6 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
|
|
451
465
|
);
|
452
466
|
}
|
453
467
|
|
454
|
-
function unsafeCreateRetryableTicket(
|
455
|
-
address,
|
456
|
-
uint256,
|
457
|
-
uint256,
|
458
|
-
address,
|
459
|
-
address,
|
460
|
-
uint256,
|
461
|
-
uint256,
|
462
|
-
bytes calldata
|
463
|
-
) public payable override returns (uint256) {
|
464
|
-
revert("UNSAFE_RETRYABLES_TEMPORARILY_DISABLED");
|
465
|
-
}
|
466
|
-
|
467
468
|
function _deliverMessage(
|
468
469
|
uint8 _kind,
|
469
470
|
address _sender,
|
package/src/bridge/Outbox.sol
CHANGED
@@ -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 "./IBridge.sol";
|
8
17
|
import "./IOutbox.sol";
|
9
18
|
import "../libraries/MerkleLib.sol";
|
@@ -138,7 +147,7 @@ contract Outbox is DelegateCallAware, IOutbox {
|
|
138
147
|
uint256 l2Timestamp,
|
139
148
|
uint256 value,
|
140
149
|
bytes calldata data
|
141
|
-
) external {
|
150
|
+
) external override {
|
142
151
|
bytes32 userTx = calculateItemHash(
|
143
152
|
l2Sender,
|
144
153
|
to,
|
@@ -172,7 +181,7 @@ contract Outbox is DelegateCallAware, IOutbox {
|
|
172
181
|
uint256 l2Timestamp,
|
173
182
|
uint256 value,
|
174
183
|
bytes calldata data
|
175
|
-
) external {
|
184
|
+
) external override {
|
176
185
|
if (msg.sender != address(0)) revert SimulationOnlyEntrypoint();
|
177
186
|
executeTransactionImpl(index, l2Sender, to, l2Block, l1Block, l2Timestamp, value, data);
|
178
187
|
}
|
@@ -226,7 +235,7 @@ contract Outbox is DelegateCallAware, IOutbox {
|
|
226
235
|
return ((replay >> bitOffset) & bytes32(uint256(1))) != bytes32(0);
|
227
236
|
}
|
228
237
|
|
229
|
-
function isSpent(uint256 index) external view returns (bool) {
|
238
|
+
function isSpent(uint256 index) external view override returns (bool) {
|
230
239
|
(, uint256 bitOffset, bytes32 replay) = _calcSpentIndexOffset(index);
|
231
240
|
return _isSpent(bitOffset, replay);
|
232
241
|
}
|
@@ -276,7 +285,7 @@ contract Outbox is DelegateCallAware, IOutbox {
|
|
276
285
|
uint256 l2Timestamp,
|
277
286
|
uint256 value,
|
278
287
|
bytes calldata data
|
279
|
-
) public pure returns (bytes32) {
|
288
|
+
) public pure override returns (bytes32) {
|
280
289
|
return
|
281
290
|
keccak256(abi.encodePacked(l2Sender, to, l2Block, l1Block, l2Timestamp, value, data));
|
282
291
|
}
|
@@ -285,7 +294,7 @@ contract Outbox is DelegateCallAware, IOutbox {
|
|
285
294
|
bytes32[] memory proof,
|
286
295
|
uint256 path,
|
287
296
|
bytes32 item
|
288
|
-
) public pure returns (bytes32) {
|
297
|
+
) public pure override returns (bytes32) {
|
289
298
|
return MerkleLib.calculateRoot(proof, path, keccak256(abi.encodePacked(item)));
|
290
299
|
}
|
291
300
|
}
|
@@ -4,6 +4,23 @@
|
|
4
4
|
|
5
5
|
pragma solidity ^0.8.0;
|
6
6
|
|
7
|
+
import {
|
8
|
+
AlreadyInit,
|
9
|
+
HadZeroInit,
|
10
|
+
NotOrigin,
|
11
|
+
DataTooLarge,
|
12
|
+
NotRollup,
|
13
|
+
DelayedBackwards,
|
14
|
+
DelayedTooFar,
|
15
|
+
ForceIncludeBlockTooSoon,
|
16
|
+
ForceIncludeTimeTooSoon,
|
17
|
+
IncorrectMessagePreimage,
|
18
|
+
NotBatchPoster,
|
19
|
+
BadSequencerNumber,
|
20
|
+
DataNotAuthenticated,
|
21
|
+
AlreadyValidDASKeyset,
|
22
|
+
NoSuchKeyset
|
23
|
+
} from "../libraries/Error.sol";
|
7
24
|
import "./IBridge.sol";
|
8
25
|
import "./IInbox.sol";
|
9
26
|
import "./ISequencerInbox.sol";
|
@@ -336,7 +353,10 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
336
353
|
* @param keysetBytes bytes of the serialized keyset
|
337
354
|
*/
|
338
355
|
function setValidKeyset(bytes calldata keysetBytes) external override onlyRollupOwner {
|
339
|
-
|
356
|
+
uint256 ksWord = uint256(keccak256(bytes.concat(hex"fe", keccak256(keysetBytes))));
|
357
|
+
bytes32 ksHash = bytes32(ksWord ^ (1 << 255));
|
358
|
+
require(keysetBytes.length < 64 * 1024, "keyset is too large");
|
359
|
+
|
340
360
|
if (dasKeySetInfo[ksHash].isValidKeyset) revert AlreadyValidDASKeyset(ksHash);
|
341
361
|
dasKeySetInfo[ksHash] = DasKeySetInfo({
|
342
362
|
isValidKeyset: true,
|
package/src/libraries/Error.sol
CHANGED
@@ -42,3 +42,110 @@ error MerkleProofTooLong(uint256 actualLength, uint256 maxProofLength);
|
|
42
42
|
/// @param rollup The rollup, which would be authorized
|
43
43
|
/// @param owner The rollup's owner, which would be authorized
|
44
44
|
error NotRollupOrOwner(address sender, address rollup, address owner);
|
45
|
+
|
46
|
+
// Bridge Errors
|
47
|
+
|
48
|
+
/// @dev Thrown when an un-authorized address tries to access an only-inbox function
|
49
|
+
/// @param sender The un-authorized sender
|
50
|
+
error NotDelayedInbox(address sender);
|
51
|
+
|
52
|
+
/// @dev Thrown when an un-authorized address tries to access an only-sequencer-inbox function
|
53
|
+
/// @param sender The un-authorized sender
|
54
|
+
error NotSequencerInbox(address sender);
|
55
|
+
|
56
|
+
/// @dev Thrown when an un-authorized address tries to access an only-outbox function
|
57
|
+
/// @param sender The un-authorized sender
|
58
|
+
error NotOutbox(address sender);
|
59
|
+
|
60
|
+
/// @dev the provided outbox address isn't valid
|
61
|
+
/// @param outbox address of outbox being set
|
62
|
+
error InvalidOutboxSet(address outbox);
|
63
|
+
|
64
|
+
// Inbox Errors
|
65
|
+
|
66
|
+
/// @dev The contract is paused, so cannot be paused
|
67
|
+
error AlreadyPaused();
|
68
|
+
|
69
|
+
/// @dev The contract is unpaused, so cannot be unpaused
|
70
|
+
error AlreadyUnpaused();
|
71
|
+
|
72
|
+
/// @dev The contract is paused
|
73
|
+
error Paused();
|
74
|
+
|
75
|
+
/// @dev msg.value sent to the inbox isn't high enough
|
76
|
+
error InsufficientValue(uint256 expected, uint256 actual);
|
77
|
+
|
78
|
+
/// @dev submission cost provided isn't enough to create retryable ticket
|
79
|
+
error InsufficientSubmissionCost(uint256 expected, uint256 actual);
|
80
|
+
|
81
|
+
/// @dev address not allowed to interact with the given contract
|
82
|
+
error NotAllowedOrigin(address origin);
|
83
|
+
|
84
|
+
/// @dev used to convey retryable tx data in eth calls without requiring a tx trace
|
85
|
+
/// this follows a pattern similar to EIP-3668 where reverts surface call information
|
86
|
+
error RetryableData(
|
87
|
+
address from,
|
88
|
+
address to,
|
89
|
+
uint256 l2CallValue,
|
90
|
+
uint256 deposit,
|
91
|
+
uint256 maxSubmissionCost,
|
92
|
+
address excessFeeRefundAddress,
|
93
|
+
address callValueRefundAddress,
|
94
|
+
uint256 gasLimit,
|
95
|
+
uint256 maxFeePerGas,
|
96
|
+
bytes data
|
97
|
+
);
|
98
|
+
|
99
|
+
// Outbox Errors
|
100
|
+
|
101
|
+
/// @dev The provided proof was too long
|
102
|
+
/// @param proofLength The length of the too-long proof
|
103
|
+
error ProofTooLong(uint256 proofLength);
|
104
|
+
|
105
|
+
/// @dev The output index was greater than the maximum
|
106
|
+
/// @param index The output index
|
107
|
+
/// @param maxIndex The max the index could be
|
108
|
+
error PathNotMinimal(uint256 index, uint256 maxIndex);
|
109
|
+
|
110
|
+
/// @dev The calculated root does not exist
|
111
|
+
/// @param root The calculated root
|
112
|
+
error UnknownRoot(bytes32 root);
|
113
|
+
|
114
|
+
/// @dev The record has already been spent
|
115
|
+
/// @param index The index of the spent record
|
116
|
+
error AlreadySpent(uint256 index);
|
117
|
+
|
118
|
+
/// @dev A call to the bridge failed with no return data
|
119
|
+
error BridgeCallFailed();
|
120
|
+
|
121
|
+
// Sequencer Inbox Errors
|
122
|
+
|
123
|
+
/// @dev Thrown when someone attempts to read fewer messages than have already been read
|
124
|
+
error DelayedBackwards();
|
125
|
+
|
126
|
+
/// @dev Thrown when someone attempts to read more messages than exist
|
127
|
+
error DelayedTooFar();
|
128
|
+
|
129
|
+
/// @dev Force include can only read messages more blocks old than the delay period
|
130
|
+
error ForceIncludeBlockTooSoon();
|
131
|
+
|
132
|
+
/// @dev Force include can only read messages more seconds old than the delay period
|
133
|
+
error ForceIncludeTimeTooSoon();
|
134
|
+
|
135
|
+
/// @dev The message provided did not match the hash in the delayed inbox
|
136
|
+
error IncorrectMessagePreimage();
|
137
|
+
|
138
|
+
/// @dev This can only be called by the batch poster
|
139
|
+
error NotBatchPoster();
|
140
|
+
|
141
|
+
/// @dev The sequence number provided to this message was inconsistent with the number of batches already included
|
142
|
+
error BadSequencerNumber(uint256 stored, uint256 received);
|
143
|
+
|
144
|
+
/// @dev The batch data has the inbox authenticated bit set, but the batch data was not authenticated by the inbox
|
145
|
+
error DataNotAuthenticated();
|
146
|
+
|
147
|
+
/// @dev Tried to create an already valid Data Availability Service keyset
|
148
|
+
error AlreadyValidDASKeyset(bytes32);
|
149
|
+
|
150
|
+
/// @dev Tried to use or invalidate an already invalid Data Availability Service keyset
|
151
|
+
error NoSuchKeyset(bytes32);
|
@@ -2,7 +2,8 @@
|
|
2
2
|
// For license information, see https://github.com/nitro/blob/master/LICENSE
|
3
3
|
// SPDX-License-Identifier: BUSL-1.1
|
4
4
|
|
5
|
-
|
5
|
+
// solhint-disable-next-line compiler-version
|
6
|
+
pragma solidity >=0.6.9 <0.9.0;
|
6
7
|
|
7
8
|
interface IGasRefunder {
|
8
9
|
function onGasSpent(
|
package/src/mocks/BridgeStub.sol
CHANGED
package/src/mocks/InboxStub.sol
CHANGED
@@ -12,7 +12,7 @@ pragma solidity >=0.4.21 <0.9.0;
|
|
12
12
|
interface NodeInterface {
|
13
13
|
/**
|
14
14
|
* @notice Estimate the cost of putting a message in the L2 inbox that is reexecuted.
|
15
|
-
* Use eth_estimateGas to call.
|
15
|
+
* @dev Use eth_estimateGas to call.
|
16
16
|
* @param sender sender of the L1 and L2 transaction
|
17
17
|
* @param deposit amount to deposit to sender in L2
|
18
18
|
* @param to destination L2 contract address
|
@@ -33,7 +33,7 @@ interface NodeInterface {
|
|
33
33
|
|
34
34
|
/**
|
35
35
|
* @notice Constructs an outbox proof of an l2->l1 send's existence in the outbox accumulator.
|
36
|
-
* Use eth_call to call.
|
36
|
+
* @dev Use eth_call to call.
|
37
37
|
* @param size the number of elements in the accumulator
|
38
38
|
* @param leaf the position of the send in the accumulator
|
39
39
|
* @return send the l2->l1 send's hash
|
@@ -62,14 +62,16 @@ interface NodeInterface {
|
|
62
62
|
* @notice Gets the number of L1 confirmations of the sequencer batch producing the requested L2 block
|
63
63
|
* This gets the number of L1 confirmations for the input message producing the L2 block,
|
64
64
|
* which happens well before the L1 rollup contract confirms the L2 block.
|
65
|
-
* Throws if block doesnt exist in the L2 chain.
|
65
|
+
* Throws if block doesnt exist in the L2 chain.
|
66
|
+
* @dev Use eth_call to call.
|
66
67
|
* @param blockHash The hash of the L2 block being queried
|
67
68
|
* @return confirmations The number of L1 confirmations the sequencer batch has. Returns 0 if block not yet included in an L1 batch.
|
68
69
|
*/
|
69
70
|
function getL1Confirmations(bytes32 blockHash) external view returns (uint64 confirmations);
|
70
71
|
|
71
72
|
/**
|
72
|
-
* @notice Same as native gas estimation, but with additional info on the l1 costs.
|
73
|
+
* @notice Same as native gas estimation, but with additional info on the l1 costs.
|
74
|
+
* @dev Use eth_call to call.
|
73
75
|
* @param data the tx's calldata. Everything else like "From" and "Gas" are copied over
|
74
76
|
* @param to the tx's "To" (ignored when contractCreation is true)
|
75
77
|
* @param contractCreation whether "To" is omitted
|
@@ -91,4 +93,33 @@ interface NodeInterface {
|
|
91
93
|
uint256 baseFee,
|
92
94
|
uint256 l1BaseFeeEstimate
|
93
95
|
);
|
96
|
+
|
97
|
+
/**
|
98
|
+
* @notice Returns the proof necessary to redeem a message
|
99
|
+
* @param batchNum index of outbox entry (i.e., outgoing messages Merkle root) in array of outbox entries
|
100
|
+
* @param index index of outgoing message in outbox entry
|
101
|
+
* @return proof Merkle proof of message inclusion in outbox entry
|
102
|
+
* @return path Merkle path to message
|
103
|
+
* @return l2Sender sender if original message (i.e., caller of ArbSys.sendTxToL1)
|
104
|
+
* @return l1Dest destination address for L1 contract call
|
105
|
+
* @return l2Block l2 block number at which sendTxToL1 call was made
|
106
|
+
* @return l1Block l1 block number at which sendTxToL1 call was made
|
107
|
+
* @return timestamp l2 Timestamp at which sendTxToL1 call was made
|
108
|
+
* @return amount value in L1 message in wei
|
109
|
+
* @return calldataForL1 abi-encoded L1 message data
|
110
|
+
*/
|
111
|
+
function legacyLookupMessageBatchProof(uint256 batchNum, uint64 index)
|
112
|
+
external
|
113
|
+
view
|
114
|
+
returns (
|
115
|
+
bytes32[] memory proof,
|
116
|
+
uint256 path,
|
117
|
+
address l2Sender,
|
118
|
+
address l1Dest,
|
119
|
+
uint256 l2Block,
|
120
|
+
uint256 l1Block,
|
121
|
+
uint256 timestamp,
|
122
|
+
uint256 amount,
|
123
|
+
bytes memory calldataForL1
|
124
|
+
);
|
94
125
|
}
|
@@ -109,4 +109,13 @@ 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);
|
112
121
|
}
|
@@ -66,6 +66,15 @@ interface ArbOwner {
|
|
66
66
|
/// @notice Sets reward amount for L1 price adjustment algorithm, in wei per unit
|
67
67
|
function setL1PricingRewardRate(uint64 weiPerUnit) external;
|
68
68
|
|
69
|
+
/// @notice Set how much ArbOS charges per L1 gas spent on transaction data.
|
70
|
+
function setL1PricePerUnit(uint256 pricePerUnit) external;
|
71
|
+
|
72
|
+
/// @notice Sets the base charge (in L1 gas) attributed to each data batch in the calldata pricer
|
73
|
+
function setPerBatchGasCharge(int64 cost) external;
|
74
|
+
|
75
|
+
/// @notice Sets the cost amortization cap in basis points
|
76
|
+
function setAmortizedCostCapBips(uint64 cap) external;
|
77
|
+
|
69
78
|
// Emitted when a successful call is made to this precompile
|
70
79
|
event OwnerActs(bytes4 indexed method, address indexed owner, bytes data);
|
71
80
|
}
|
@@ -36,13 +36,13 @@ 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
|
-
* @return true if
|
44
|
+
* @notice check if current call is top level (meaning it was triggered by an EoA or a L1 contract)
|
45
|
+
* @return true if current execution frame is not a call by another L2 contract
|
46
46
|
*/
|
47
47
|
function isTopLevelCall() external view returns (bool);
|
48
48
|
|
@@ -315,4 +315,46 @@ contract RollupAdminLogic is RollupCore, IRollupAdmin, SecondaryLogicUUPSUpgrade
|
|
315
315
|
bridge.setSequencerInbox(_sequencerInbox);
|
316
316
|
emit OwnerFunctionCalled(27);
|
317
317
|
}
|
318
|
+
|
319
|
+
/**
|
320
|
+
* @notice sets the rollup's inbox reference. Does not update the bridge's view.
|
321
|
+
* @param newInbox new address of inbox
|
322
|
+
*/
|
323
|
+
function setInbox(IInbox newInbox) external {
|
324
|
+
inbox = newInbox;
|
325
|
+
emit OwnerFunctionCalled(28);
|
326
|
+
}
|
327
|
+
|
328
|
+
function createNitroMigrationGenesis(RollupLib.Assertion calldata assertion)
|
329
|
+
external
|
330
|
+
whenPaused
|
331
|
+
{
|
332
|
+
bytes32 expectedSendRoot = bytes32(0);
|
333
|
+
uint64 expectedInboxCount = 1;
|
334
|
+
|
335
|
+
require(latestNodeCreated() == 0, "NON_GENESIS_NODES_EXIST");
|
336
|
+
require(GlobalStateLib.isEmpty(assertion.beforeState.globalState), "NOT_EMPTY_BEFORE");
|
337
|
+
require(
|
338
|
+
assertion.beforeState.machineStatus == MachineStatus.FINISHED,
|
339
|
+
"BEFORE_MACHINE_NOT_FINISHED"
|
340
|
+
);
|
341
|
+
// accessors such as state.getSendRoot not available for calldata structs, only memory
|
342
|
+
require(
|
343
|
+
assertion.afterState.globalState.bytes32Vals[1] == expectedSendRoot,
|
344
|
+
"NOT_ZERO_SENDROOT"
|
345
|
+
);
|
346
|
+
require(
|
347
|
+
assertion.afterState.globalState.u64Vals[0] == expectedInboxCount,
|
348
|
+
"INBOX_NOT_AT_ONE"
|
349
|
+
);
|
350
|
+
require(assertion.afterState.globalState.u64Vals[1] == 0, "POSITION_IN_MESSAGE_NOT_ZERO");
|
351
|
+
require(
|
352
|
+
assertion.afterState.machineStatus == MachineStatus.FINISHED,
|
353
|
+
"AFTER_MACHINE_NOT_FINISHED"
|
354
|
+
);
|
355
|
+
bytes32 genesisBlockHash = assertion.afterState.globalState.bytes32Vals[0];
|
356
|
+
createNewNode(assertion, 0, expectedInboxCount, bytes32(0));
|
357
|
+
confirmNode(1, genesisBlockHash, expectedSendRoot);
|
358
|
+
emit OwnerFunctionCalled(29);
|
359
|
+
}
|
318
360
|
}
|
@@ -552,7 +552,7 @@ abstract contract RollupCore is IRollupCore, PausableUpgradeable {
|
|
552
552
|
if (afterInboxCount == prevInboxPosition) {
|
553
553
|
require(
|
554
554
|
assertion.afterState.globalState.getPositionInMessage() >=
|
555
|
-
assertion.
|
555
|
+
assertion.beforeState.globalState.getPositionInMessage(),
|
556
556
|
"INBOX_POS_IN_MSG_BACKWARDS"
|
557
557
|
);
|
558
558
|
}
|
@@ -592,7 +592,10 @@ abstract contract RollupCore is IRollupCore, PausableUpgradeable {
|
|
592
592
|
memoryFrame.sequencerBatchAcc,
|
593
593
|
wasmModuleRoot
|
594
594
|
);
|
595
|
-
require(
|
595
|
+
require(
|
596
|
+
newNodeHash == expectedNodeHash || expectedNodeHash == bytes32(0),
|
597
|
+
"UNEXPECTED_NODE_HASH"
|
598
|
+
);
|
596
599
|
|
597
600
|
memoryFrame.node = NodeLib.createNode(
|
598
601
|
RollupLib.stateHash(assertion.afterState, memoryFrame.currentInboxSize),
|
package/src/rollup/RollupLib.sol
CHANGED
@@ -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";
|
@@ -220,4 +228,6 @@ contract BridgeTester is Initializable, DelegateCallAware, IBridge {
|
|
220
228
|
}
|
221
229
|
|
222
230
|
receive() external payable {}
|
231
|
+
|
232
|
+
function acceptFundsFromOldBridge() external payable {}
|
223
233
|
}
|
@@ -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";
|
@@ -93,7 +102,7 @@ contract OutboxWithoutOptTester is DelegateCallAware, IOutbox {
|
|
93
102
|
uint256 l2Timestamp,
|
94
103
|
uint256 value,
|
95
104
|
bytes calldata data
|
96
|
-
) external virtual {
|
105
|
+
) external virtual override {
|
97
106
|
bytes32 outputId;
|
98
107
|
{
|
99
108
|
bytes32 userTx = calculateItemHash(
|
@@ -128,6 +137,23 @@ contract OutboxWithoutOptTester is DelegateCallAware, IOutbox {
|
|
128
137
|
context = prevContext;
|
129
138
|
}
|
130
139
|
|
140
|
+
function executeTransactionSimulation(
|
141
|
+
uint256,
|
142
|
+
address,
|
143
|
+
address,
|
144
|
+
uint256,
|
145
|
+
uint256,
|
146
|
+
uint256,
|
147
|
+
uint256,
|
148
|
+
bytes calldata
|
149
|
+
) external pure override {
|
150
|
+
revert("Not implemented");
|
151
|
+
}
|
152
|
+
|
153
|
+
function isSpent(uint256) external pure override returns (bool) {
|
154
|
+
revert("Not implemented");
|
155
|
+
}
|
156
|
+
|
131
157
|
function recordOutputAsSpent(
|
132
158
|
bytes32[] memory proof,
|
133
159
|
uint256 index,
|
@@ -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
|
}
|