@arbitrum/nitro-contracts 1.0.0-beta.5 → 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 +6 -2
- package/src/bridge/Bridge.sol +138 -32
- package/src/bridge/IBridge.sol +34 -14
- package/src/bridge/IDelayedMessageProvider.sol +15 -0
- package/src/bridge/IInbox.sol +8 -19
- package/src/bridge/IOutbox.sol +43 -23
- package/src/bridge/IOwnable.sol +10 -0
- package/src/bridge/ISequencerInbox.sol +30 -32
- package/src/bridge/Inbox.sol +133 -35
- package/src/bridge/Outbox.sol +145 -33
- package/src/bridge/SequencerInbox.sol +179 -60
- package/src/challenge/ChallengeLib.sol +0 -2
- package/src/challenge/ChallengeManager.sol +4 -8
- package/src/challenge/IChallengeManager.sol +1 -1
- package/src/libraries/Error.sol +113 -0
- package/src/libraries/IGasRefunder.sol +15 -14
- package/src/libraries/MerkleLib.sol +11 -2
- package/src/libraries/MessageTypes.sol +1 -0
- package/src/mocks/BridgeStub.sol +69 -21
- package/src/mocks/InboxStub.sol +2 -0
- package/src/mocks/SequencerInboxStub.sol +10 -8
- package/src/mocks/Simple.sol +8 -0
- package/src/node-interface/NodeInterface.sol +62 -4
- package/src/osp/IOneStepProver.sol +1 -2
- package/src/osp/OneStepProver0.sol +1 -87
- package/src/osp/OneStepProverHostIo.sol +5 -6
- package/src/osp/OneStepProverMath.sol +37 -27
- package/src/osp/OneStepProverMemory.sol +3 -4
- package/src/precompiles/ArbAggregator.sol +23 -33
- package/src/precompiles/ArbBLS.sol +1 -43
- package/src/precompiles/ArbGasInfo.sol +10 -19
- package/src/precompiles/ArbOwner.sol +21 -15
- package/src/precompiles/ArbRetryableTx.sol +10 -1
- package/src/precompiles/ArbSys.sol +4 -4
- package/src/precompiles/ArbosActs.sol +9 -2
- package/src/rollup/BridgeCreator.sol +23 -28
- package/src/rollup/IRollupCore.sol +3 -3
- package/src/rollup/{IRollupEventBridge.sol → IRollupEventInbox.sol} +2 -2
- package/src/rollup/IRollupLogic.sol +21 -18
- package/src/rollup/RollupAdminLogic.sol +72 -34
- package/src/rollup/RollupCore.sol +20 -9
- package/src/rollup/RollupCreator.sol +21 -11
- package/src/rollup/{RollupEventBridge.sol → RollupEventInbox.sol} +10 -10
- package/src/rollup/RollupLib.sol +21 -5
- package/src/rollup/RollupUserLogic.sol +10 -18
- package/src/rollup/ValidatorWallet.sol +125 -8
- package/src/rollup/ValidatorWalletCreator.sol +11 -6
- package/src/state/Deserialize.sol +3 -22
- package/src/state/GlobalState.sol +7 -0
- package/src/state/Instructions.sol +2 -10
- package/src/state/Machine.sol +0 -4
- package/src/state/ModuleMemory.sol +2 -1
- package/src/state/Value.sol +2 -3
- package/src/test-helpers/BridgeTester.sol +233 -0
- package/src/test-helpers/InterfaceCompatibilityTester.sol +11 -0
- package/src/test-helpers/OutboxWithoutOptTester.sol +214 -0
- package/src/test-helpers/RollupMock.sol +21 -0
- package/src/bridge/IMessageProvider.sol +0 -11
- package/src/state/PcStack.sol +0 -32
@@ -4,10 +4,30 @@
|
|
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";
|
25
|
+
import "./IInbox.sol";
|
8
26
|
import "./ISequencerInbox.sol";
|
27
|
+
import "../rollup/IRollupLogic.sol";
|
9
28
|
import "./Messages.sol";
|
10
29
|
|
30
|
+
import {L1MessageType_batchPostingReport} from "../libraries/MessageTypes.sol";
|
11
31
|
import {GasRefundEnabled, IGasRefunder} from "../libraries/IGasRefunder.sol";
|
12
32
|
import "../libraries/DelegateCallAware.sol";
|
13
33
|
import {MAX_DATA_SIZE} from "../libraries/Constants.sol";
|
@@ -20,10 +40,9 @@ import {MAX_DATA_SIZE} from "../libraries/Constants.sol";
|
|
20
40
|
* sequencer within a time limit they can be force included into the rollup inbox by anyone.
|
21
41
|
*/
|
22
42
|
contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox {
|
23
|
-
bytes32[] public override inboxAccs;
|
24
43
|
uint256 public totalDelayedMessagesRead;
|
25
44
|
|
26
|
-
IBridge public
|
45
|
+
IBridge public bridge;
|
27
46
|
|
28
47
|
/// @dev The size of the batch header
|
29
48
|
uint256 public constant HEADER_LENGTH = 40;
|
@@ -31,19 +50,29 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
31
50
|
/// the sequencer inbox has authenticated the data. Currently not used.
|
32
51
|
bytes1 public constant DATA_AUTHENTICATED_FLAG = 0x40;
|
33
52
|
|
34
|
-
|
53
|
+
IOwnable public rollup;
|
35
54
|
mapping(address => bool) public isBatchPoster;
|
36
55
|
ISequencerInbox.MaxTimeVariation public maxTimeVariation;
|
37
56
|
|
57
|
+
struct DasKeySetInfo {
|
58
|
+
bool isValidKeyset;
|
59
|
+
uint64 creationBlock;
|
60
|
+
}
|
61
|
+
mapping(bytes32 => DasKeySetInfo) public dasKeySetInfo;
|
62
|
+
|
63
|
+
modifier onlyRollupOwner() {
|
64
|
+
if (msg.sender != rollup.owner()) revert NotOwner(msg.sender, address(rollup));
|
65
|
+
_;
|
66
|
+
}
|
67
|
+
|
38
68
|
function initialize(
|
39
|
-
IBridge
|
40
|
-
address rollup_,
|
69
|
+
IBridge bridge_,
|
41
70
|
ISequencerInbox.MaxTimeVariation calldata maxTimeVariation_
|
42
71
|
) external onlyDelegated {
|
43
|
-
if (
|
44
|
-
if (
|
45
|
-
|
46
|
-
rollup =
|
72
|
+
if (bridge != IBridge(address(0))) revert AlreadyInit();
|
73
|
+
if (bridge_ == IBridge(address(0))) revert HadZeroInit();
|
74
|
+
bridge = bridge_;
|
75
|
+
rollup = bridge_.rollup();
|
47
76
|
maxTimeVariation = maxTimeVariation_;
|
48
77
|
}
|
49
78
|
|
@@ -98,22 +127,24 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
98
127
|
// Verify that message hash represents the last message sequence of delayed message to be included
|
99
128
|
bytes32 prevDelayedAcc = 0;
|
100
129
|
if (_totalDelayedMessagesRead > 1) {
|
101
|
-
prevDelayedAcc =
|
130
|
+
prevDelayedAcc = bridge.delayedInboxAccs(_totalDelayedMessagesRead - 2);
|
102
131
|
}
|
103
132
|
if (
|
104
|
-
|
133
|
+
bridge.delayedInboxAccs(_totalDelayedMessagesRead - 1) !=
|
105
134
|
Messages.accumulateInboxMessage(prevDelayedAcc, messageHash)
|
106
135
|
) revert IncorrectMessagePreimage();
|
107
136
|
|
108
137
|
(bytes32 dataHash, TimeBounds memory timeBounds) = formEmptyDataHash(
|
109
138
|
_totalDelayedMessagesRead
|
110
139
|
);
|
111
|
-
(
|
112
|
-
|
113
|
-
|
114
|
-
|
140
|
+
(
|
141
|
+
uint256 seqMessageIndex,
|
142
|
+
bytes32 beforeAcc,
|
143
|
+
bytes32 delayedAcc,
|
144
|
+
bytes32 afterAcc
|
145
|
+
) = addSequencerL2BatchImpl(dataHash, _totalDelayedMessagesRead, 0);
|
115
146
|
emit SequencerBatchDelivered(
|
116
|
-
|
147
|
+
seqMessageIndex,
|
117
148
|
beforeAcc,
|
118
149
|
afterAcc,
|
119
150
|
delayedAcc,
|
@@ -128,21 +159,24 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
128
159
|
bytes calldata data,
|
129
160
|
uint256 afterDelayedMessagesRead,
|
130
161
|
IGasRefunder gasRefunder
|
131
|
-
) external
|
162
|
+
) external refundsGas(gasRefunder) {
|
132
163
|
// solhint-disable-next-line avoid-tx-origin
|
133
164
|
if (msg.sender != tx.origin) revert NotOrigin();
|
134
165
|
if (!isBatchPoster[msg.sender]) revert NotBatchPoster();
|
135
|
-
if (inboxAccs.length != sequenceNumber) revert BadSequencerNumber();
|
136
166
|
(bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
|
137
167
|
data,
|
138
168
|
afterDelayedMessagesRead
|
139
169
|
);
|
140
|
-
(
|
141
|
-
|
142
|
-
|
143
|
-
|
170
|
+
(
|
171
|
+
uint256 seqMessageIndex,
|
172
|
+
bytes32 beforeAcc,
|
173
|
+
bytes32 delayedAcc,
|
174
|
+
bytes32 afterAcc
|
175
|
+
) = addSequencerL2BatchImpl(dataHash, afterDelayedMessagesRead, data.length);
|
176
|
+
if (seqMessageIndex != sequenceNumber)
|
177
|
+
revert BadSequencerNumber(seqMessageIndex, sequenceNumber);
|
144
178
|
emit SequencerBatchDelivered(
|
145
|
-
|
179
|
+
sequenceNumber,
|
146
180
|
beforeAcc,
|
147
181
|
afterAcc,
|
148
182
|
delayedAcc,
|
@@ -157,18 +191,23 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
157
191
|
bytes calldata data,
|
158
192
|
uint256 afterDelayedMessagesRead,
|
159
193
|
IGasRefunder gasRefunder
|
160
|
-
) external override
|
161
|
-
if (!isBatchPoster[msg.sender] && msg.sender != rollup) revert NotBatchPoster();
|
162
|
-
if (inboxAccs.length != sequenceNumber) revert BadSequencerNumber();
|
194
|
+
) external override refundsGas(gasRefunder) {
|
195
|
+
if (!isBatchPoster[msg.sender] && msg.sender != address(rollup)) revert NotBatchPoster();
|
163
196
|
|
164
197
|
(bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
|
165
198
|
data,
|
166
199
|
afterDelayedMessagesRead
|
167
200
|
);
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
201
|
+
// we set the calldata length posted to 0 here since the caller isn't the origin
|
202
|
+
// of the tx, so they might have not paid tx input cost for the calldata
|
203
|
+
(
|
204
|
+
uint256 seqMessageIndex,
|
205
|
+
bytes32 beforeAcc,
|
206
|
+
bytes32 delayedAcc,
|
207
|
+
bytes32 afterAcc
|
208
|
+
) = addSequencerL2BatchImpl(dataHash, afterDelayedMessagesRead, 0);
|
209
|
+
if (seqMessageIndex != sequenceNumber)
|
210
|
+
revert BadSequencerNumber(seqMessageIndex, sequenceNumber);
|
172
211
|
emit SequencerBatchDelivered(
|
173
212
|
sequenceNumber,
|
174
213
|
beforeAcc,
|
@@ -181,6 +220,22 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
181
220
|
emit SequencerBatchData(sequenceNumber, data);
|
182
221
|
}
|
183
222
|
|
223
|
+
modifier validateBatchData(bytes calldata data) {
|
224
|
+
uint256 fullDataLen = HEADER_LENGTH + data.length;
|
225
|
+
if (fullDataLen > MAX_DATA_SIZE) revert DataTooLarge(fullDataLen, MAX_DATA_SIZE);
|
226
|
+
if (data.length > 0 && (data[0] & DATA_AUTHENTICATED_FLAG) == DATA_AUTHENTICATED_FLAG) {
|
227
|
+
revert DataNotAuthenticated();
|
228
|
+
}
|
229
|
+
// the first byte is used to identify the type of batch data
|
230
|
+
// das batches expect to have the type byte set, followed by the keyset (so they should have at least 33 bytes)
|
231
|
+
if (data.length >= 33 && data[0] & 0x80 != 0) {
|
232
|
+
// we skip the first byte, then read the next 32 bytes for the keyset
|
233
|
+
bytes32 dasKeysetHash = bytes32(data[1:33]);
|
234
|
+
if (!dasKeySetInfo[dasKeysetHash].isValidKeyset) revert NoSuchKeyset(dasKeysetHash);
|
235
|
+
}
|
236
|
+
_;
|
237
|
+
}
|
238
|
+
|
184
239
|
function packHeader(uint256 afterDelayedMessagesRead)
|
185
240
|
internal
|
186
241
|
view
|
@@ -202,25 +257,12 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
202
257
|
function formDataHash(bytes calldata data, uint256 afterDelayedMessagesRead)
|
203
258
|
internal
|
204
259
|
view
|
260
|
+
validateBatchData(data)
|
205
261
|
returns (bytes32, TimeBounds memory)
|
206
262
|
{
|
207
|
-
uint256 fullDataLen = HEADER_LENGTH + data.length;
|
208
|
-
if (fullDataLen < HEADER_LENGTH) revert DataLengthOverflow();
|
209
|
-
if (fullDataLen > MAX_DATA_SIZE) revert DataTooLarge(fullDataLen, MAX_DATA_SIZE);
|
210
|
-
bytes memory fullData = new bytes(fullDataLen);
|
211
263
|
(bytes memory header, TimeBounds memory timeBounds) = packHeader(afterDelayedMessagesRead);
|
212
|
-
|
213
|
-
|
214
|
-
fullData[i] = header[i];
|
215
|
-
}
|
216
|
-
if (data.length > 0 && (data[0] & DATA_AUTHENTICATED_FLAG) == DATA_AUTHENTICATED_FLAG) {
|
217
|
-
revert DataNotAuthenticated();
|
218
|
-
}
|
219
|
-
// copy data into fullData at offset of HEADER_LENGTH (the extra 32 offset is because solidity puts the array len first)
|
220
|
-
assembly {
|
221
|
-
calldatacopy(add(fullData, add(HEADER_LENGTH, 32)), data.offset, data.length)
|
222
|
-
}
|
223
|
-
return (keccak256(fullData), timeBounds);
|
264
|
+
bytes32 dataHash = keccak256(bytes.concat(header, data));
|
265
|
+
return (dataHash, timeBounds);
|
224
266
|
}
|
225
267
|
|
226
268
|
function formEmptyDataHash(uint256 afterDelayedMessagesRead)
|
@@ -232,43 +274,120 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
232
274
|
return (keccak256(header), timeBounds);
|
233
275
|
}
|
234
276
|
|
235
|
-
function addSequencerL2BatchImpl(
|
277
|
+
function addSequencerL2BatchImpl(
|
278
|
+
bytes32 dataHash,
|
279
|
+
uint256 afterDelayedMessagesRead,
|
280
|
+
uint256 calldataLengthPosted
|
281
|
+
)
|
236
282
|
internal
|
237
283
|
returns (
|
284
|
+
uint256 seqMessageIndex,
|
238
285
|
bytes32 beforeAcc,
|
239
286
|
bytes32 delayedAcc,
|
240
287
|
bytes32 acc
|
241
288
|
)
|
242
289
|
{
|
243
290
|
if (afterDelayedMessagesRead < totalDelayedMessagesRead) revert DelayedBackwards();
|
244
|
-
if (afterDelayedMessagesRead >
|
291
|
+
if (afterDelayedMessagesRead > bridge.delayedMessageCount()) revert DelayedTooFar();
|
245
292
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
delayedAcc = delayedBridge.inboxAccs(afterDelayedMessagesRead - 1);
|
251
|
-
}
|
293
|
+
(seqMessageIndex, beforeAcc, delayedAcc, acc) = bridge.enqueueSequencerMessage(
|
294
|
+
dataHash,
|
295
|
+
afterDelayedMessagesRead
|
296
|
+
);
|
252
297
|
|
253
|
-
acc = keccak256(abi.encodePacked(beforeAcc, dataHash, delayedAcc));
|
254
|
-
inboxAccs.push(acc);
|
255
298
|
totalDelayedMessagesRead = afterDelayedMessagesRead;
|
299
|
+
|
300
|
+
if (calldataLengthPosted > 0) {
|
301
|
+
// this msg isn't included in the current sequencer batch, but instead added to
|
302
|
+
// the delayed messages queue that is yet to be included
|
303
|
+
address batchPoster = msg.sender;
|
304
|
+
bytes memory spendingReportMsg = abi.encodePacked(
|
305
|
+
block.timestamp,
|
306
|
+
batchPoster,
|
307
|
+
dataHash,
|
308
|
+
seqMessageIndex,
|
309
|
+
block.basefee
|
310
|
+
);
|
311
|
+
uint256 msgNum = bridge.submitBatchSpendingReport(
|
312
|
+
batchPoster,
|
313
|
+
keccak256(spendingReportMsg)
|
314
|
+
);
|
315
|
+
// this is the same event used by Inbox.sol after including a message to the delayed message accumulator
|
316
|
+
emit InboxMessageDelivered(msgNum, spendingReportMsg);
|
317
|
+
}
|
318
|
+
}
|
319
|
+
|
320
|
+
function inboxAccs(uint256 index) external view override returns (bytes32) {
|
321
|
+
return bridge.sequencerInboxAccs(index);
|
256
322
|
}
|
257
323
|
|
258
324
|
function batchCount() external view override returns (uint256) {
|
259
|
-
return
|
325
|
+
return bridge.sequencerMessageCount();
|
260
326
|
}
|
261
327
|
|
328
|
+
/**
|
329
|
+
* @notice Set max delay for sequencer inbox
|
330
|
+
* @param maxTimeVariation_ the maximum time variation parameters
|
331
|
+
*/
|
262
332
|
function setMaxTimeVariation(ISequencerInbox.MaxTimeVariation memory maxTimeVariation_)
|
263
333
|
external
|
264
334
|
override
|
335
|
+
onlyRollupOwner
|
265
336
|
{
|
266
|
-
if (msg.sender != rollup) revert NotRollup(msg.sender, rollup);
|
267
337
|
maxTimeVariation = maxTimeVariation_;
|
338
|
+
emit OwnerFunctionCalled(0);
|
268
339
|
}
|
269
340
|
|
270
|
-
|
271
|
-
|
341
|
+
/**
|
342
|
+
* @notice Updates whether an address is authorized to be a batch poster at the sequencer inbox
|
343
|
+
* @param addr the address
|
344
|
+
* @param isBatchPoster_ if the specified address should be authorized as a batch poster
|
345
|
+
*/
|
346
|
+
function setIsBatchPoster(address addr, bool isBatchPoster_) external override onlyRollupOwner {
|
272
347
|
isBatchPoster[addr] = isBatchPoster_;
|
348
|
+
emit OwnerFunctionCalled(1);
|
349
|
+
}
|
350
|
+
|
351
|
+
/**
|
352
|
+
* @notice Makes Data Availability Service keyset valid
|
353
|
+
* @param keysetBytes bytes of the serialized keyset
|
354
|
+
*/
|
355
|
+
function setValidKeyset(bytes calldata keysetBytes) external override onlyRollupOwner {
|
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
|
+
|
360
|
+
if (dasKeySetInfo[ksHash].isValidKeyset) revert AlreadyValidDASKeyset(ksHash);
|
361
|
+
dasKeySetInfo[ksHash] = DasKeySetInfo({
|
362
|
+
isValidKeyset: true,
|
363
|
+
creationBlock: uint64(block.number)
|
364
|
+
});
|
365
|
+
emit SetValidKeyset(ksHash, keysetBytes);
|
366
|
+
emit OwnerFunctionCalled(2);
|
367
|
+
}
|
368
|
+
|
369
|
+
/**
|
370
|
+
* @notice Invalidates a Data Availability Service keyset
|
371
|
+
* @param ksHash hash of the keyset
|
372
|
+
*/
|
373
|
+
function invalidateKeysetHash(bytes32 ksHash) external override onlyRollupOwner {
|
374
|
+
if (!dasKeySetInfo[ksHash].isValidKeyset) revert NoSuchKeyset(ksHash);
|
375
|
+
// we don't delete the block creation value since its used to fetch the SetValidKeyset
|
376
|
+
// event efficiently. The event provides the hash preimage of the key.
|
377
|
+
// this is still needed when syncing the chain after a keyset is invalidated.
|
378
|
+
dasKeySetInfo[ksHash].isValidKeyset = false;
|
379
|
+
emit InvalidateKeyset(ksHash);
|
380
|
+
emit OwnerFunctionCalled(3);
|
381
|
+
}
|
382
|
+
|
383
|
+
function isValidKeysetHash(bytes32 ksHash) external view returns (bool) {
|
384
|
+
return dasKeySetInfo[ksHash].isValidKeyset;
|
385
|
+
}
|
386
|
+
|
387
|
+
/// @notice the creation block is intended to still be available after a keyset is deleted
|
388
|
+
function getKeysetCreationBlock(bytes32 ksHash) external view returns (uint256) {
|
389
|
+
DasKeySetInfo memory ksInfo = dasKeySetInfo[ksHash];
|
390
|
+
if (ksInfo.creationBlock == 0) revert NoSuchKeyset(ksHash);
|
391
|
+
return uint256(ksInfo.creationBlock);
|
273
392
|
}
|
274
393
|
}
|
@@ -61,14 +61,12 @@ library ChallengeLib {
|
|
61
61
|
ValueArray memory valuesArray = ValueArray({inner: startingValues});
|
62
62
|
ValueStack memory values = ValueStack({proved: valuesArray, remainingHash: 0});
|
63
63
|
ValueStack memory internalStack;
|
64
|
-
PcStack memory blocks;
|
65
64
|
StackFrameWindow memory frameStack;
|
66
65
|
|
67
66
|
Machine memory mach = Machine({
|
68
67
|
status: MachineStatus.RUNNING,
|
69
68
|
valueStack: values,
|
70
69
|
internalStack: internalStack,
|
71
|
-
blockStack: blocks,
|
72
70
|
frameStack: frameStack,
|
73
71
|
globalStateHash: globalStateHash,
|
74
72
|
moduleIdx: 0,
|
@@ -33,7 +33,7 @@ contract ChallengeManager is DelegateCallAware, IChallengeManager {
|
|
33
33
|
IChallengeResultReceiver public resultReceiver;
|
34
34
|
|
35
35
|
ISequencerInbox public sequencerInbox;
|
36
|
-
IBridge public
|
36
|
+
IBridge public bridge;
|
37
37
|
IOneStepProofEntry public osp;
|
38
38
|
|
39
39
|
function challengeInfo(uint64 challengeIndex)
|
@@ -99,14 +99,14 @@ contract ChallengeManager is DelegateCallAware, IChallengeManager {
|
|
99
99
|
function initialize(
|
100
100
|
IChallengeResultReceiver resultReceiver_,
|
101
101
|
ISequencerInbox sequencerInbox_,
|
102
|
-
IBridge
|
102
|
+
IBridge bridge_,
|
103
103
|
IOneStepProofEntry osp_
|
104
104
|
) external override onlyDelegated {
|
105
105
|
require(address(resultReceiver) == address(0), "ALREADY_INIT");
|
106
106
|
require(address(resultReceiver_) != address(0), "NO_RESULT_RECEIVER");
|
107
107
|
resultReceiver = resultReceiver_;
|
108
108
|
sequencerInbox = sequencerInbox_;
|
109
|
-
|
109
|
+
bridge = bridge_;
|
110
110
|
osp = osp_;
|
111
111
|
}
|
112
112
|
|
@@ -254,11 +254,7 @@ contract ChallengeManager is DelegateCallAware, IChallengeManager {
|
|
254
254
|
}
|
255
255
|
|
256
256
|
bytes32 afterHash = osp.proveOneStep(
|
257
|
-
ExecutionContext({
|
258
|
-
maxInboxMessagesRead: challenge.maxInboxMessages,
|
259
|
-
sequencerInbox: sequencerInbox,
|
260
|
-
delayedBridge: delayedBridge
|
261
|
-
}),
|
257
|
+
ExecutionContext({maxInboxMessagesRead: challenge.maxInboxMessages, bridge: bridge}),
|
262
258
|
challengeStart,
|
263
259
|
selection.oldSegments[selection.challengePosition],
|
264
260
|
proof
|
package/src/libraries/Error.sol
CHANGED
@@ -36,3 +36,116 @@ error NotContract(address addr);
|
|
36
36
|
/// @param actualLength The length of the merkle proof provided
|
37
37
|
/// @param maxProofLength The max length a merkle proof can have
|
38
38
|
error MerkleProofTooLong(uint256 actualLength, uint256 maxProofLength);
|
39
|
+
|
40
|
+
/// @dev Thrown when an un-authorized address tries to access an admin function
|
41
|
+
/// @param sender The un-authorized sender
|
42
|
+
/// @param rollup The rollup, which would be authorized
|
43
|
+
/// @param owner The rollup's owner, which would be authorized
|
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(
|
@@ -13,23 +14,23 @@ interface IGasRefunder {
|
|
13
14
|
}
|
14
15
|
|
15
16
|
abstract contract GasRefundEnabled {
|
16
|
-
|
17
|
+
/// @dev this refunds the sender for execution costs of the tx
|
18
|
+
/// calldata costs are only refunded if `msg.sender == tx.origin` to guarantee the value refunded relates to charging
|
19
|
+
/// for the `tx.input`. this avoids a possible attack where you generate large calldata from a contract and get over-refunded
|
20
|
+
modifier refundsGas(IGasRefunder gasRefunder) {
|
17
21
|
uint256 startGasLeft = gasleft();
|
18
22
|
_;
|
19
23
|
if (address(gasRefunder) != address(0)) {
|
20
|
-
uint256 calldataSize;
|
21
|
-
|
22
|
-
|
24
|
+
uint256 calldataSize = 0;
|
25
|
+
// if triggered in a contract call, the spender may be overrefunded by appending dummy data to the call
|
26
|
+
// so we check if it is a top level call, which would mean the sender paid calldata as part of tx.input
|
27
|
+
// solhint-disable-next-line avoid-tx-origin
|
28
|
+
if (msg.sender == tx.origin) {
|
29
|
+
assembly {
|
30
|
+
calldataSize := calldatasize()
|
31
|
+
}
|
23
32
|
}
|
24
|
-
gasRefunder.onGasSpent(
|
25
|
-
}
|
26
|
-
}
|
27
|
-
|
28
|
-
modifier refundsGasNoCalldata(IGasRefunder gasRefunder, address payable spender) {
|
29
|
-
uint256 startGasLeft = gasleft();
|
30
|
-
_;
|
31
|
-
if (address(gasRefunder) != address(0)) {
|
32
|
-
gasRefunder.onGasSpent(spender, startGasLeft - gasleft(), 0);
|
33
|
+
gasRefunder.onGasSpent(payable(msg.sender), startGasLeft - gasleft(), calldataSize);
|
33
34
|
}
|
34
35
|
}
|
35
36
|
}
|
@@ -34,10 +34,19 @@ library MerkleLib {
|
|
34
34
|
if (proofItems > 256) revert MerkleProofTooLong(proofItems, 256);
|
35
35
|
bytes32 h = item;
|
36
36
|
for (uint256 i = 0; i < proofItems; i++) {
|
37
|
+
bytes32 node = nodes[i];
|
37
38
|
if (route % 2 == 0) {
|
38
|
-
|
39
|
+
assembly {
|
40
|
+
mstore(0x00, h)
|
41
|
+
mstore(0x20, node)
|
42
|
+
h := keccak256(0x00, 0x40)
|
43
|
+
}
|
39
44
|
} else {
|
40
|
-
|
45
|
+
assembly {
|
46
|
+
mstore(0x00, node)
|
47
|
+
mstore(0x20, h)
|
48
|
+
h := keccak256(0x00, 0x40)
|
49
|
+
}
|
41
50
|
}
|
42
51
|
route /= 2;
|
43
52
|
}
|
@@ -8,6 +8,7 @@ uint8 constant L2_MSG = 3;
|
|
8
8
|
uint8 constant L1MessageType_L2FundedByL1 = 7;
|
9
9
|
uint8 constant L1MessageType_submitRetryableTx = 9;
|
10
10
|
uint8 constant L1MessageType_ethDeposit = 12;
|
11
|
+
uint8 constant L1MessageType_batchPostingReport = 13;
|
11
12
|
uint8 constant L2MessageType_unsignedEOATx = 0;
|
12
13
|
uint8 constant L2MessageType_unsignedContractTx = 1;
|
13
14
|
|