@arbitrum/nitro-contracts 1.0.0-beta.5 → 1.0.0-beta.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|