@arbitrum/nitro-contracts 1.0.0-beta.7 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +13 -2
- package/src/bridge/Bridge.sol +49 -29
- package/src/bridge/IBridge.sol +58 -45
- package/src/bridge/IDelayedMessageProvider.sol +2 -1
- package/src/bridge/IInbox.sol +133 -50
- package/src/bridge/IOutbox.sol +95 -27
- package/src/bridge/IOwnable.sol +2 -1
- package/src/bridge/ISequencerInbox.sol +79 -31
- package/src/bridge/Inbox.sol +171 -108
- package/src/bridge/Outbox.sol +26 -41
- package/src/bridge/SequencerInbox.sol +152 -62
- package/src/challenge/ChallengeManager.sol +0 -9
- package/src/challenge/IChallengeManager.sol +0 -2
- package/src/libraries/AdminFallbackProxy.sol +4 -4
- package/src/libraries/Constants.sol +3 -0
- package/src/libraries/{SecondaryLogicUUPSUpgradeable.sol → DoubleLogicUUPSUpgradeable.sol} +2 -1
- package/src/libraries/Error.sol +119 -0
- package/src/libraries/IGasRefunder.sol +13 -6
- package/src/libraries/MerkleLib.sol +5 -3
- package/src/mocks/BridgeStub.sol +22 -1
- package/src/mocks/BridgeUnproxied.sol +17 -0
- package/src/mocks/InboxStub.sol +49 -2
- package/src/mocks/SequencerInboxStub.sol +13 -3
- package/src/mocks/Simple.sol +69 -0
- package/src/node-interface/NodeInterface.sol +69 -7
- package/src/precompiles/ArbGasInfo.sol +16 -4
- package/src/precompiles/ArbOwner.sol +18 -0
- package/src/precompiles/ArbOwnerPublic.sol +3 -0
- package/src/precompiles/ArbSys.sol +7 -4
- package/src/rollup/IRollupCore.sol +2 -0
- package/src/rollup/IRollupLogic.sol +10 -0
- package/src/rollup/RollupAdminLogic.sol +69 -3
- package/src/rollup/RollupCore.sol +8 -2
- package/src/rollup/RollupCreator.sol +3 -3
- package/src/rollup/RollupEventInbox.sol +3 -6
- package/src/rollup/RollupLib.sol +1 -0
- package/src/{libraries/ArbitrumProxy.sol → rollup/RollupProxy.sol} +3 -3
- package/src/rollup/RollupUserLogic.sol +47 -10
- package/src/state/GlobalState.sol +7 -0
- package/src/test-helpers/BridgeTester.sol +17 -1
- package/src/test-helpers/InterfaceCompatibilityTester.sol +11 -0
- package/src/test-helpers/OutboxWithoutOptTester.sol +33 -7
@@ -4,6 +4,24 @@
|
|
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
|
+
NotForked
|
24
|
+
} from "../libraries/Error.sol";
|
7
25
|
import "./IBridge.sol";
|
8
26
|
import "./IInbox.sol";
|
9
27
|
import "./ISequencerInbox.sol";
|
@@ -27,20 +45,16 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
27
45
|
|
28
46
|
IBridge public bridge;
|
29
47
|
|
30
|
-
/// @
|
48
|
+
/// @inheritdoc ISequencerInbox
|
31
49
|
uint256 public constant HEADER_LENGTH = 40;
|
32
|
-
|
33
|
-
///
|
50
|
+
|
51
|
+
/// @inheritdoc ISequencerInbox
|
34
52
|
bytes1 public constant DATA_AUTHENTICATED_FLAG = 0x40;
|
35
53
|
|
36
54
|
IOwnable public rollup;
|
37
55
|
mapping(address => bool) public isBatchPoster;
|
38
56
|
ISequencerInbox.MaxTimeVariation public maxTimeVariation;
|
39
57
|
|
40
|
-
struct DasKeySetInfo {
|
41
|
-
bool isValidKeyset;
|
42
|
-
uint64 creationBlock;
|
43
|
-
}
|
44
58
|
mapping(bytes32 => DasKeySetInfo) public dasKeySetInfo;
|
45
59
|
|
46
60
|
modifier onlyRollupOwner() {
|
@@ -48,6 +62,12 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
48
62
|
_;
|
49
63
|
}
|
50
64
|
|
65
|
+
uint256 internal immutable deployTimeChainId = block.chainid;
|
66
|
+
|
67
|
+
function _chainIdChanged() internal view returns (bool) {
|
68
|
+
return deployTimeChainId != block.chainid;
|
69
|
+
}
|
70
|
+
|
51
71
|
function initialize(
|
52
72
|
IBridge bridge_,
|
53
73
|
ISequencerInbox.MaxTimeVariation calldata maxTimeVariation_
|
@@ -72,17 +92,18 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
72
92
|
return bounds;
|
73
93
|
}
|
74
94
|
|
75
|
-
/// @
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
95
|
+
/// @inheritdoc ISequencerInbox
|
96
|
+
function removeDelayAfterFork() external {
|
97
|
+
if (!_chainIdChanged()) revert NotForked();
|
98
|
+
maxTimeVariation = ISequencerInbox.MaxTimeVariation({
|
99
|
+
delayBlocks: 1,
|
100
|
+
futureBlocks: 1,
|
101
|
+
delaySeconds: 1,
|
102
|
+
futureSeconds: 1
|
103
|
+
});
|
104
|
+
}
|
105
|
+
|
106
|
+
/// @inheritdoc ISequencerInbox
|
86
107
|
function forceInclusion(
|
87
108
|
uint256 _totalDelayedMessagesRead,
|
88
109
|
uint8 kind,
|
@@ -120,12 +141,23 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
120
141
|
(bytes32 dataHash, TimeBounds memory timeBounds) = formEmptyDataHash(
|
121
142
|
_totalDelayedMessagesRead
|
122
143
|
);
|
144
|
+
uint256 __totalDelayedMessagesRead = _totalDelayedMessagesRead;
|
145
|
+
uint256 prevSeqMsgCount = bridge.sequencerReportedSubMessageCount();
|
146
|
+
uint256 newSeqMsgCount = prevSeqMsgCount +
|
147
|
+
_totalDelayedMessagesRead -
|
148
|
+
totalDelayedMessagesRead;
|
123
149
|
(
|
124
150
|
uint256 seqMessageIndex,
|
125
151
|
bytes32 beforeAcc,
|
126
152
|
bytes32 delayedAcc,
|
127
153
|
bytes32 afterAcc
|
128
|
-
) = addSequencerL2BatchImpl(
|
154
|
+
) = addSequencerL2BatchImpl(
|
155
|
+
dataHash,
|
156
|
+
__totalDelayedMessagesRead,
|
157
|
+
0,
|
158
|
+
prevSeqMsgCount,
|
159
|
+
newSeqMsgCount
|
160
|
+
);
|
129
161
|
emit SequencerBatchDelivered(
|
130
162
|
seqMessageIndex,
|
131
163
|
beforeAcc,
|
@@ -137,6 +169,7 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
137
169
|
);
|
138
170
|
}
|
139
171
|
|
172
|
+
/// @dev Deprecated in favor of the variant specifying message counts for consistency
|
140
173
|
function addSequencerL2BatchFromOrigin(
|
141
174
|
uint256 sequenceNumber,
|
142
175
|
bytes calldata data,
|
@@ -146,6 +179,7 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
146
179
|
// solhint-disable-next-line avoid-tx-origin
|
147
180
|
if (msg.sender != tx.origin) revert NotOrigin();
|
148
181
|
if (!isBatchPoster[msg.sender]) revert NotBatchPoster();
|
182
|
+
|
149
183
|
(bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
|
150
184
|
data,
|
151
185
|
afterDelayedMessagesRead
|
@@ -155,7 +189,7 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
155
189
|
bytes32 beforeAcc,
|
156
190
|
bytes32 delayedAcc,
|
157
191
|
bytes32 afterAcc
|
158
|
-
) = addSequencerL2BatchImpl(dataHash, afterDelayedMessagesRead, data.length);
|
192
|
+
) = addSequencerL2BatchImpl(dataHash, afterDelayedMessagesRead, data.length, 0, 0);
|
159
193
|
if (seqMessageIndex != sequenceNumber)
|
160
194
|
revert BadSequencerNumber(seqMessageIndex, sequenceNumber);
|
161
195
|
emit SequencerBatchDelivered(
|
@@ -169,38 +203,101 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
169
203
|
);
|
170
204
|
}
|
171
205
|
|
172
|
-
function
|
206
|
+
function addSequencerL2BatchFromOrigin(
|
173
207
|
uint256 sequenceNumber,
|
174
208
|
bytes calldata data,
|
175
209
|
uint256 afterDelayedMessagesRead,
|
176
|
-
IGasRefunder gasRefunder
|
177
|
-
|
178
|
-
|
179
|
-
|
210
|
+
IGasRefunder gasRefunder,
|
211
|
+
uint256 prevMessageCount,
|
212
|
+
uint256 newMessageCount
|
213
|
+
) external refundsGas(gasRefunder) {
|
214
|
+
// solhint-disable-next-line avoid-tx-origin
|
215
|
+
if (msg.sender != tx.origin) revert NotOrigin();
|
216
|
+
if (!isBatchPoster[msg.sender]) revert NotBatchPoster();
|
180
217
|
(bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
|
181
218
|
data,
|
182
219
|
afterDelayedMessagesRead
|
183
220
|
);
|
184
|
-
//
|
185
|
-
|
221
|
+
// Reformat the stack to prevent "Stack too deep"
|
222
|
+
uint256 sequenceNumber_ = sequenceNumber;
|
223
|
+
TimeBounds memory timeBounds_ = timeBounds;
|
224
|
+
bytes32 dataHash_ = dataHash;
|
225
|
+
uint256 dataLength = data.length;
|
226
|
+
uint256 afterDelayedMessagesRead_ = afterDelayedMessagesRead;
|
227
|
+
uint256 prevMessageCount_ = prevMessageCount;
|
228
|
+
uint256 newMessageCount_ = newMessageCount;
|
186
229
|
(
|
187
230
|
uint256 seqMessageIndex,
|
188
231
|
bytes32 beforeAcc,
|
189
232
|
bytes32 delayedAcc,
|
190
233
|
bytes32 afterAcc
|
191
|
-
) = addSequencerL2BatchImpl(
|
192
|
-
|
193
|
-
|
234
|
+
) = addSequencerL2BatchImpl(
|
235
|
+
dataHash_,
|
236
|
+
afterDelayedMessagesRead_,
|
237
|
+
dataLength,
|
238
|
+
prevMessageCount_,
|
239
|
+
newMessageCount_
|
240
|
+
);
|
241
|
+
if (seqMessageIndex != sequenceNumber_ && sequenceNumber_ != ~uint256(0))
|
242
|
+
revert BadSequencerNumber(seqMessageIndex, sequenceNumber_);
|
194
243
|
emit SequencerBatchDelivered(
|
195
|
-
|
244
|
+
seqMessageIndex,
|
196
245
|
beforeAcc,
|
197
246
|
afterAcc,
|
198
247
|
delayedAcc,
|
199
|
-
|
200
|
-
|
201
|
-
BatchDataLocation.
|
248
|
+
totalDelayedMessagesRead,
|
249
|
+
timeBounds_,
|
250
|
+
BatchDataLocation.TxInput
|
251
|
+
);
|
252
|
+
}
|
253
|
+
|
254
|
+
function addSequencerL2Batch(
|
255
|
+
uint256 sequenceNumber,
|
256
|
+
bytes calldata data,
|
257
|
+
uint256 afterDelayedMessagesRead,
|
258
|
+
IGasRefunder gasRefunder,
|
259
|
+
uint256 prevMessageCount,
|
260
|
+
uint256 newMessageCount
|
261
|
+
) external override refundsGas(gasRefunder) {
|
262
|
+
if (!isBatchPoster[msg.sender] && msg.sender != address(rollup)) revert NotBatchPoster();
|
263
|
+
(bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
|
264
|
+
data,
|
265
|
+
afterDelayedMessagesRead
|
202
266
|
);
|
203
|
-
|
267
|
+
uint256 seqMessageIndex;
|
268
|
+
{
|
269
|
+
// Reformat the stack to prevent "Stack too deep"
|
270
|
+
uint256 sequenceNumber_ = sequenceNumber;
|
271
|
+
TimeBounds memory timeBounds_ = timeBounds;
|
272
|
+
bytes32 dataHash_ = dataHash;
|
273
|
+
uint256 afterDelayedMessagesRead_ = afterDelayedMessagesRead;
|
274
|
+
uint256 prevMessageCount_ = prevMessageCount;
|
275
|
+
uint256 newMessageCount_ = newMessageCount;
|
276
|
+
// we set the calldata length posted to 0 here since the caller isn't the origin
|
277
|
+
// of the tx, so they might have not paid tx input cost for the calldata
|
278
|
+
bytes32 beforeAcc;
|
279
|
+
bytes32 delayedAcc;
|
280
|
+
bytes32 afterAcc;
|
281
|
+
(seqMessageIndex, beforeAcc, delayedAcc, afterAcc) = addSequencerL2BatchImpl(
|
282
|
+
dataHash_,
|
283
|
+
afterDelayedMessagesRead_,
|
284
|
+
0,
|
285
|
+
prevMessageCount_,
|
286
|
+
newMessageCount_
|
287
|
+
);
|
288
|
+
if (seqMessageIndex != sequenceNumber_ && sequenceNumber_ != ~uint256(0))
|
289
|
+
revert BadSequencerNumber(seqMessageIndex, sequenceNumber_);
|
290
|
+
emit SequencerBatchDelivered(
|
291
|
+
seqMessageIndex,
|
292
|
+
beforeAcc,
|
293
|
+
afterAcc,
|
294
|
+
delayedAcc,
|
295
|
+
totalDelayedMessagesRead,
|
296
|
+
timeBounds_,
|
297
|
+
BatchDataLocation.SeparateBatchEvent
|
298
|
+
);
|
299
|
+
}
|
300
|
+
emit SequencerBatchData(seqMessageIndex, data);
|
204
301
|
}
|
205
302
|
|
206
303
|
modifier validateBatchData(bytes calldata data) {
|
@@ -260,7 +357,9 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
260
357
|
function addSequencerL2BatchImpl(
|
261
358
|
bytes32 dataHash,
|
262
359
|
uint256 afterDelayedMessagesRead,
|
263
|
-
uint256 calldataLengthPosted
|
360
|
+
uint256 calldataLengthPosted,
|
361
|
+
uint256 prevMessageCount,
|
362
|
+
uint256 newMessageCount
|
264
363
|
)
|
265
364
|
internal
|
266
365
|
returns (
|
@@ -275,7 +374,9 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
275
374
|
|
276
375
|
(seqMessageIndex, beforeAcc, delayedAcc, acc) = bridge.enqueueSequencerMessage(
|
277
376
|
dataHash,
|
278
|
-
afterDelayedMessagesRead
|
377
|
+
afterDelayedMessagesRead,
|
378
|
+
prevMessageCount,
|
379
|
+
newMessageCount
|
279
380
|
);
|
280
381
|
|
281
382
|
totalDelayedMessagesRead = afterDelayedMessagesRead;
|
@@ -300,43 +401,35 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
300
401
|
}
|
301
402
|
}
|
302
403
|
|
303
|
-
function inboxAccs(uint256 index) external view
|
404
|
+
function inboxAccs(uint256 index) external view returns (bytes32) {
|
304
405
|
return bridge.sequencerInboxAccs(index);
|
305
406
|
}
|
306
407
|
|
307
|
-
function batchCount() external view
|
408
|
+
function batchCount() external view returns (uint256) {
|
308
409
|
return bridge.sequencerMessageCount();
|
309
410
|
}
|
310
411
|
|
311
|
-
|
312
|
-
* @notice Set max delay for sequencer inbox
|
313
|
-
* @param maxTimeVariation_ the maximum time variation parameters
|
314
|
-
*/
|
412
|
+
/// @inheritdoc ISequencerInbox
|
315
413
|
function setMaxTimeVariation(ISequencerInbox.MaxTimeVariation memory maxTimeVariation_)
|
316
414
|
external
|
317
|
-
override
|
318
415
|
onlyRollupOwner
|
319
416
|
{
|
320
417
|
maxTimeVariation = maxTimeVariation_;
|
321
418
|
emit OwnerFunctionCalled(0);
|
322
419
|
}
|
323
420
|
|
324
|
-
|
325
|
-
|
326
|
-
* @param addr the address
|
327
|
-
* @param isBatchPoster_ if the specified address should be authorized as a batch poster
|
328
|
-
*/
|
329
|
-
function setIsBatchPoster(address addr, bool isBatchPoster_) external override onlyRollupOwner {
|
421
|
+
/// @inheritdoc ISequencerInbox
|
422
|
+
function setIsBatchPoster(address addr, bool isBatchPoster_) external onlyRollupOwner {
|
330
423
|
isBatchPoster[addr] = isBatchPoster_;
|
331
424
|
emit OwnerFunctionCalled(1);
|
332
425
|
}
|
333
426
|
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
427
|
+
/// @inheritdoc ISequencerInbox
|
428
|
+
function setValidKeyset(bytes calldata keysetBytes) external onlyRollupOwner {
|
429
|
+
uint256 ksWord = uint256(keccak256(bytes.concat(hex"fe", keccak256(keysetBytes))));
|
430
|
+
bytes32 ksHash = bytes32(ksWord ^ (1 << 255));
|
431
|
+
require(keysetBytes.length < 64 * 1024, "keyset is too large");
|
432
|
+
|
340
433
|
if (dasKeySetInfo[ksHash].isValidKeyset) revert AlreadyValidDASKeyset(ksHash);
|
341
434
|
dasKeySetInfo[ksHash] = DasKeySetInfo({
|
342
435
|
isValidKeyset: true,
|
@@ -346,11 +439,8 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
346
439
|
emit OwnerFunctionCalled(2);
|
347
440
|
}
|
348
441
|
|
349
|
-
|
350
|
-
|
351
|
-
* @param ksHash hash of the keyset
|
352
|
-
*/
|
353
|
-
function invalidateKeysetHash(bytes32 ksHash) external override onlyRollupOwner {
|
442
|
+
/// @inheritdoc ISequencerInbox
|
443
|
+
function invalidateKeysetHash(bytes32 ksHash) external onlyRollupOwner {
|
354
444
|
if (!dasKeySetInfo[ksHash].isValidKeyset) revert NoSuchKeyset(ksHash);
|
355
445
|
// we don't delete the block creation value since its used to fetch the SetValidKeyset
|
356
446
|
// event efficiently. The event provides the hash preimage of the key.
|
@@ -364,7 +454,7 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
364
454
|
return dasKeySetInfo[ksHash].isValidKeyset;
|
365
455
|
}
|
366
456
|
|
367
|
-
/// @
|
457
|
+
/// @inheritdoc ISequencerInbox
|
368
458
|
function getKeysetCreationBlock(bytes32 ksHash) external view returns (uint256) {
|
369
459
|
DasKeySetInfo memory ksInfo = dasKeySetInfo[ksHash];
|
370
460
|
if (ksInfo.creationBlock == 0) revert NoSuchKeyset(ksHash);
|
@@ -285,15 +285,6 @@ contract ChallengeManager is DelegateCallAware, IChallengeManager {
|
|
285
285
|
return challenges[challengeIndex].current.addr;
|
286
286
|
}
|
287
287
|
|
288
|
-
function currentResponderTimeLeft(uint64 challengeIndex)
|
289
|
-
public
|
290
|
-
view
|
291
|
-
override
|
292
|
-
returns (uint256)
|
293
|
-
{
|
294
|
-
return challenges[challengeIndex].current.timeLeft;
|
295
|
-
}
|
296
|
-
|
297
288
|
function isTimedOut(uint64 challengeIndex) public view override returns (bool) {
|
298
289
|
return challenges[challengeIndex].isTimedOut();
|
299
290
|
}
|
@@ -67,8 +67,6 @@ interface IChallengeManager {
|
|
67
67
|
|
68
68
|
function isTimedOut(uint64 challengeIndex) external view returns (bool);
|
69
69
|
|
70
|
-
function currentResponderTimeLeft(uint64 challengeIndex_) external view returns (uint256);
|
71
|
-
|
72
70
|
function clearChallenge(uint64 challengeIndex_) external;
|
73
71
|
|
74
72
|
function timeout(uint64 challengeIndex_) external;
|
@@ -87,7 +87,7 @@ abstract contract DoubleLogicERC1967Upgrade is ERC1967Upgrade {
|
|
87
87
|
try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
|
88
88
|
require(
|
89
89
|
slot == _IMPLEMENTATION_SECONDARY_SLOT,
|
90
|
-
"ERC1967Upgrade: unsupported proxiableUUID"
|
90
|
+
"ERC1967Upgrade: unsupported secondary proxiableUUID"
|
91
91
|
);
|
92
92
|
} catch {
|
93
93
|
revert("ERC1967Upgrade: new secondary implementation is not UUPS");
|
@@ -132,8 +132,8 @@ contract AdminFallbackProxy is Proxy, DoubleLogicERC1967Upgrade {
|
|
132
132
|
require(msg.data.length >= 4, "NO_FUNC_SIG");
|
133
133
|
// if the sender is the proxy's admin, delegate to admin logic
|
134
134
|
// if the admin is disabled, all calls will be forwarded to user logic
|
135
|
-
// admin affordances can be disabled by setting to
|
136
|
-
//
|
135
|
+
// admin affordances can be disabled by setting to a no-op smart contract
|
136
|
+
// since there is a check for contract code before updating the value
|
137
137
|
address target = _getAdmin() != msg.sender
|
138
138
|
? DoubleLogicERC1967Upgrade._getSecondaryImplementation()
|
139
139
|
: ERC1967Upgrade._getImplementation();
|
@@ -144,7 +144,7 @@ contract AdminFallbackProxy is Proxy, DoubleLogicERC1967Upgrade {
|
|
144
144
|
|
145
145
|
/**
|
146
146
|
* @dev unlike transparent upgradeable proxies, this does allow the admin to fallback to a logic contract
|
147
|
-
* the admin is expected to interact only with the
|
147
|
+
* the admin is expected to interact only with the primary logic contract, which handles contract
|
148
148
|
* upgrades using the UUPS approach
|
149
149
|
*/
|
150
150
|
function _beforeFallback() internal override {
|
@@ -8,8 +8,9 @@ import {DoubleLogicERC1967Upgrade} from "./AdminFallbackProxy.sol";
|
|
8
8
|
import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
|
9
9
|
|
10
10
|
/// @notice An extension to OZ's UUPSUpgradeable contract to be used for handling UUPS upgrades with a DoubleLogicERC1967Upgrade proxy
|
11
|
+
/// The should be used in the primary implementation slot of the DoubleLogicUUPS proxy
|
11
12
|
/// @dev upgrades should be handles by the primary logic contract in order to pass the `onlyProxy` check
|
12
|
-
abstract contract
|
13
|
+
abstract contract DoubleLogicUUPSUpgradeable is UUPSUpgradeable, DoubleLogicERC1967Upgrade {
|
13
14
|
/// @inheritdoc UUPSUpgradeable
|
14
15
|
function proxiableUUID() external view override notDelegated returns (bytes32) {
|
15
16
|
return _IMPLEMENTATION_SLOT;
|
package/src/libraries/Error.sol
CHANGED
@@ -42,3 +42,122 @@ 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
|
+
/// @dev Thrown when a L1 chainId fork is detected
|
100
|
+
error L1Forked();
|
101
|
+
|
102
|
+
/// @dev Thrown when a L1 chainId fork is not detected
|
103
|
+
error NotForked();
|
104
|
+
|
105
|
+
/// @dev The provided gasLimit is larger than uint64
|
106
|
+
error GasLimitTooLarge();
|
107
|
+
|
108
|
+
// Outbox Errors
|
109
|
+
|
110
|
+
/// @dev The provided proof was too long
|
111
|
+
/// @param proofLength The length of the too-long proof
|
112
|
+
error ProofTooLong(uint256 proofLength);
|
113
|
+
|
114
|
+
/// @dev The output index was greater than the maximum
|
115
|
+
/// @param index The output index
|
116
|
+
/// @param maxIndex The max the index could be
|
117
|
+
error PathNotMinimal(uint256 index, uint256 maxIndex);
|
118
|
+
|
119
|
+
/// @dev The calculated root does not exist
|
120
|
+
/// @param root The calculated root
|
121
|
+
error UnknownRoot(bytes32 root);
|
122
|
+
|
123
|
+
/// @dev The record has already been spent
|
124
|
+
/// @param index The index of the spent record
|
125
|
+
error AlreadySpent(uint256 index);
|
126
|
+
|
127
|
+
/// @dev A call to the bridge failed with no return data
|
128
|
+
error BridgeCallFailed();
|
129
|
+
|
130
|
+
// Sequencer Inbox Errors
|
131
|
+
|
132
|
+
/// @dev Thrown when someone attempts to read fewer messages than have already been read
|
133
|
+
error DelayedBackwards();
|
134
|
+
|
135
|
+
/// @dev Thrown when someone attempts to read more messages than exist
|
136
|
+
error DelayedTooFar();
|
137
|
+
|
138
|
+
/// @dev Force include can only read messages more blocks old than the delay period
|
139
|
+
error ForceIncludeBlockTooSoon();
|
140
|
+
|
141
|
+
/// @dev Force include can only read messages more seconds old than the delay period
|
142
|
+
error ForceIncludeTimeTooSoon();
|
143
|
+
|
144
|
+
/// @dev The message provided did not match the hash in the delayed inbox
|
145
|
+
error IncorrectMessagePreimage();
|
146
|
+
|
147
|
+
/// @dev This can only be called by the batch poster
|
148
|
+
error NotBatchPoster();
|
149
|
+
|
150
|
+
/// @dev The sequence number provided to this message was inconsistent with the number of batches already included
|
151
|
+
error BadSequencerNumber(uint256 stored, uint256 received);
|
152
|
+
|
153
|
+
/// @dev The sequence message number provided to this message was inconsistent with the previous one
|
154
|
+
error BadSequencerMessageNumber(uint256 stored, uint256 received);
|
155
|
+
|
156
|
+
/// @dev The batch data has the inbox authenticated bit set, but the batch data was not authenticated by the inbox
|
157
|
+
error DataNotAuthenticated();
|
158
|
+
|
159
|
+
/// @dev Tried to create an already valid Data Availability Service keyset
|
160
|
+
error AlreadyValidDASKeyset(bytes32);
|
161
|
+
|
162
|
+
/// @dev Tried to use or invalidate an already invalid Data Availability Service keyset
|
163
|
+
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(
|
@@ -20,14 +21,20 @@ abstract contract GasRefundEnabled {
|
|
20
21
|
uint256 startGasLeft = gasleft();
|
21
22
|
_;
|
22
23
|
if (address(gasRefunder) != address(0)) {
|
23
|
-
uint256 calldataSize
|
24
|
+
uint256 calldataSize;
|
25
|
+
assembly {
|
26
|
+
calldataSize := calldatasize()
|
27
|
+
}
|
28
|
+
uint256 calldataWords = (calldataSize + 31) / 32;
|
29
|
+
// account for the CALLDATACOPY cost of the proxy contract, including the memory expansion cost
|
30
|
+
startGasLeft += calldataWords * 6 + (calldataWords**2) / 512;
|
24
31
|
// if triggered in a contract call, the spender may be overrefunded by appending dummy data to the call
|
25
32
|
// so we check if it is a top level call, which would mean the sender paid calldata as part of tx.input
|
26
33
|
// solhint-disable-next-line avoid-tx-origin
|
27
|
-
if (msg.sender
|
28
|
-
|
29
|
-
|
30
|
-
|
34
|
+
if (msg.sender != tx.origin) {
|
35
|
+
// We can't be sure if this calldata came from the top level tx,
|
36
|
+
// so to be safe we tell the gas refunder there was no calldata.
|
37
|
+
calldataSize = 0;
|
31
38
|
}
|
32
39
|
gasRefunder.onGasSpent(payable(msg.sender), startGasLeft - gasleft(), calldataSize);
|
33
40
|
}
|
@@ -33,9 +33,9 @@ library MerkleLib {
|
|
33
33
|
uint256 proofItems = nodes.length;
|
34
34
|
if (proofItems > 256) revert MerkleProofTooLong(proofItems, 256);
|
35
35
|
bytes32 h = item;
|
36
|
-
for (uint256 i = 0; i < proofItems;
|
36
|
+
for (uint256 i = 0; i < proofItems; ) {
|
37
37
|
bytes32 node = nodes[i];
|
38
|
-
if (route
|
38
|
+
if ((route & (1 << i)) == 0) {
|
39
39
|
assembly {
|
40
40
|
mstore(0x00, h)
|
41
41
|
mstore(0x20, node)
|
@@ -48,7 +48,9 @@ library MerkleLib {
|
|
48
48
|
h := keccak256(0x00, 0x40)
|
49
49
|
}
|
50
50
|
}
|
51
|
-
|
51
|
+
unchecked {
|
52
|
+
++i;
|
53
|
+
}
|
52
54
|
}
|
53
55
|
return h;
|
54
56
|
}
|
package/src/mocks/BridgeStub.sol
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
pragma solidity ^0.8.0;
|
6
6
|
|
7
7
|
import "./InboxStub.sol";
|
8
|
+
import {BadSequencerMessageNumber} from "../libraries/Error.sol";
|
8
9
|
|
9
10
|
import "../bridge/IBridge.sol";
|
10
11
|
|
@@ -28,6 +29,7 @@ contract BridgeStub is IBridge {
|
|
28
29
|
bytes32[] public override sequencerInboxAccs;
|
29
30
|
|
30
31
|
address public sequencerInbox;
|
32
|
+
uint256 public override sequencerReportedSubMessageCount;
|
31
33
|
|
32
34
|
function setSequencerInbox(address _sequencerInbox) external override {
|
33
35
|
sequencerInbox = _sequencerInbox;
|
@@ -59,7 +61,12 @@ contract BridgeStub is IBridge {
|
|
59
61
|
);
|
60
62
|
}
|
61
63
|
|
62
|
-
function enqueueSequencerMessage(
|
64
|
+
function enqueueSequencerMessage(
|
65
|
+
bytes32 dataHash,
|
66
|
+
uint256 afterDelayedMessagesRead,
|
67
|
+
uint256 prevMessageCount,
|
68
|
+
uint256 newMessageCount
|
69
|
+
)
|
63
70
|
external
|
64
71
|
returns (
|
65
72
|
uint256 seqMessageIndex,
|
@@ -68,6 +75,14 @@ contract BridgeStub is IBridge {
|
|
68
75
|
bytes32 acc
|
69
76
|
)
|
70
77
|
{
|
78
|
+
if (
|
79
|
+
sequencerReportedSubMessageCount != prevMessageCount &&
|
80
|
+
prevMessageCount != 0 &&
|
81
|
+
sequencerReportedSubMessageCount != 0
|
82
|
+
) {
|
83
|
+
revert BadSequencerMessageNumber(sequencerReportedSubMessageCount, prevMessageCount);
|
84
|
+
}
|
85
|
+
sequencerReportedSubMessageCount = newMessageCount;
|
71
86
|
seqMessageIndex = sequencerInboxAccs.length;
|
72
87
|
if (sequencerInboxAccs.length > 0) {
|
73
88
|
beforeAcc = sequencerInboxAccs[sequencerInboxAccs.length - 1];
|
@@ -158,4 +173,10 @@ contract BridgeStub is IBridge {
|
|
158
173
|
function rollup() external pure override returns (IOwnable) {
|
159
174
|
revert("NOT_IMPLEMENTED");
|
160
175
|
}
|
176
|
+
|
177
|
+
function acceptFundsFromOldBridge() external payable {}
|
178
|
+
|
179
|
+
function initialize(IOwnable) external pure {
|
180
|
+
revert("NOT_IMPLEMENTED");
|
181
|
+
}
|
161
182
|
}
|