@arbitrum/nitro-contracts 1.0.0-beta.8 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- package/package.json +10 -2
- package/src/bridge/Bridge.sol +39 -30
- package/src/bridge/IBridge.sol +56 -29
- package/src/bridge/IInbox.sol +130 -15
- package/src/bridge/IOutbox.sol +55 -7
- package/src/bridge/ISequencerInbox.sol +84 -7
- package/src/bridge/Inbox.sol +154 -92
- package/src/bridge/Outbox.sol +23 -47
- package/src/bridge/SequencerInbox.sol +132 -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 +12 -0
- package/src/libraries/IGasRefunder.sol +11 -5
- package/src/libraries/MerkleLib.sol +5 -3
- package/src/mocks/BridgeStub.sol +20 -1
- package/src/mocks/BridgeUnproxied.sol +17 -0
- package/src/mocks/InboxStub.sol +48 -3
- package/src/mocks/SequencerInboxStub.sol +13 -3
- package/src/mocks/Simple.sol +69 -0
- package/src/node-interface/NodeInterface.sol +35 -4
- package/src/precompiles/ArbGasInfo.sol +7 -4
- package/src/precompiles/ArbOwner.sol +9 -0
- package/src/precompiles/ArbOwnerPublic.sol +3 -0
- package/src/precompiles/ArbSys.sol +5 -2
- package/src/rollup/IRollupCore.sol +2 -0
- package/src/rollup/IRollupLogic.sol +10 -0
- package/src/rollup/RollupAdminLogic.sol +27 -3
- package/src/rollup/RollupCore.sol +3 -0
- package/src/rollup/RollupCreator.sol +3 -3
- package/src/rollup/RollupEventInbox.sol +3 -6
- package/src/{libraries/ArbitrumProxy.sol → rollup/RollupProxy.sol} +3 -3
- package/src/rollup/RollupUserLogic.sol +47 -10
- package/src/test-helpers/BridgeTester.sol +7 -1
- package/src/test-helpers/OutboxWithoutOptTester.sol +8 -8
package/src/bridge/Outbox.sol
CHANGED
@@ -11,7 +11,8 @@ import {
|
|
11
11
|
PathNotMinimal,
|
12
12
|
UnknownRoot,
|
13
13
|
AlreadySpent,
|
14
|
-
BridgeCallFailed
|
14
|
+
BridgeCallFailed,
|
15
|
+
HadZeroInit
|
15
16
|
} from "../libraries/Error.sol";
|
16
17
|
import "./IBridge.sol";
|
17
18
|
import "./IOutbox.sol";
|
@@ -51,6 +52,7 @@ contract Outbox is DelegateCallAware, IOutbox {
|
|
51
52
|
uint128 public constant OUTBOX_VERSION = 2;
|
52
53
|
|
53
54
|
function initialize(IBridge _bridge) external onlyDelegated {
|
55
|
+
if (address(_bridge) == address(0)) revert HadZeroInit();
|
54
56
|
if (address(bridge) != address(0)) revert AlreadyInit();
|
55
57
|
// address zero is returned if no context is set, but the values used in storage
|
56
58
|
// are non-zero to save users some gas (as storage refunds are usually maxed out)
|
@@ -66,43 +68,38 @@ contract Outbox is DelegateCallAware, IOutbox {
|
|
66
68
|
rollup = address(_bridge.rollup());
|
67
69
|
}
|
68
70
|
|
69
|
-
function updateSendRoot(bytes32 root, bytes32 l2BlockHash) external
|
71
|
+
function updateSendRoot(bytes32 root, bytes32 l2BlockHash) external {
|
70
72
|
if (msg.sender != rollup) revert NotRollup(msg.sender, rollup);
|
71
73
|
roots[root] = l2BlockHash;
|
72
74
|
emit SendRootUpdated(root, l2BlockHash);
|
73
75
|
}
|
74
76
|
|
75
|
-
/// @
|
76
|
-
|
77
|
-
/// @dev the l2ToL1Sender behaves as the tx.origin, the msg.sender should be validated to protect against reentrancies
|
78
|
-
function l2ToL1Sender() external view override returns (address) {
|
77
|
+
/// @inheritdoc IOutbox
|
78
|
+
function l2ToL1Sender() external view returns (address) {
|
79
79
|
address sender = context.sender;
|
80
80
|
// we don't return the default context value to avoid a breaking change in the API
|
81
81
|
if (sender == SENDER_DEFAULT_CONTEXT) return address(0);
|
82
82
|
return sender;
|
83
83
|
}
|
84
84
|
|
85
|
-
/// @
|
86
|
-
|
87
|
-
function l2ToL1Block() external view override returns (uint256) {
|
85
|
+
/// @inheritdoc IOutbox
|
86
|
+
function l2ToL1Block() external view returns (uint256) {
|
88
87
|
uint128 l2Block = context.l2Block;
|
89
88
|
// we don't return the default context value to avoid a breaking change in the API
|
90
89
|
if (l2Block == L1BLOCK_DEFAULT_CONTEXT) return uint256(0);
|
91
90
|
return uint256(l2Block);
|
92
91
|
}
|
93
92
|
|
94
|
-
/// @
|
95
|
-
|
96
|
-
function l2ToL1EthBlock() external view override returns (uint256) {
|
93
|
+
/// @inheritdoc IOutbox
|
94
|
+
function l2ToL1EthBlock() external view returns (uint256) {
|
97
95
|
uint128 l1Block = context.l1Block;
|
98
96
|
// we don't return the default context value to avoid a breaking change in the API
|
99
97
|
if (l1Block == L1BLOCK_DEFAULT_CONTEXT) return uint256(0);
|
100
98
|
return uint256(l1Block);
|
101
99
|
}
|
102
100
|
|
103
|
-
/// @
|
104
|
-
|
105
|
-
function l2ToL1Timestamp() external view override returns (uint256) {
|
101
|
+
/// @inheritdoc IOutbox
|
102
|
+
function l2ToL1Timestamp() external view returns (uint256) {
|
106
103
|
uint128 timestamp = context.timestamp;
|
107
104
|
// we don't return the default context value to avoid a breaking change in the API
|
108
105
|
if (timestamp == TIMESTAMP_DEFAULT_CONTEXT) return uint256(0);
|
@@ -110,33 +107,19 @@ contract Outbox is DelegateCallAware, IOutbox {
|
|
110
107
|
}
|
111
108
|
|
112
109
|
/// @notice batch number is deprecated and now always returns 0
|
113
|
-
function l2ToL1BatchNum() external pure
|
110
|
+
function l2ToL1BatchNum() external pure returns (uint256) {
|
114
111
|
return 0;
|
115
112
|
}
|
116
113
|
|
117
|
-
/// @
|
118
|
-
|
119
|
-
function l2ToL1OutputId() external view override returns (bytes32) {
|
114
|
+
/// @inheritdoc IOutbox
|
115
|
+
function l2ToL1OutputId() external view returns (bytes32) {
|
120
116
|
bytes32 outputId = context.outputId;
|
121
117
|
// we don't return the default context value to avoid a breaking change in the API
|
122
118
|
if (outputId == OUTPUTID_DEFAULT_CONTEXT) return bytes32(0);
|
123
119
|
return outputId;
|
124
120
|
}
|
125
121
|
|
126
|
-
|
127
|
-
* @notice Executes a messages in an Outbox entry.
|
128
|
-
* @dev Reverts if dispute period hasn't expired, since the outbox entry
|
129
|
-
* is only created once the rollup confirms the respective assertion.
|
130
|
-
* @param proof Merkle proof of message inclusion in send root
|
131
|
-
* @param index Merkle path to message
|
132
|
-
* @param l2Sender sender if original message (i.e., caller of ArbSys.sendTxToL1)
|
133
|
-
* @param to destination address for L1 contract call
|
134
|
-
* @param l2Block l2 block number at which sendTxToL1 call was made
|
135
|
-
* @param l1Block l1 block number at which sendTxToL1 call was made
|
136
|
-
* @param l2Timestamp l2 Timestamp at which sendTxToL1 call was made
|
137
|
-
* @param value wei in L1 message
|
138
|
-
* @param data abi-encoded L1 message data
|
139
|
-
*/
|
122
|
+
/// @inheritdoc IOutbox
|
140
123
|
function executeTransaction(
|
141
124
|
bytes32[] calldata proof,
|
142
125
|
uint256 index,
|
@@ -147,7 +130,7 @@ contract Outbox is DelegateCallAware, IOutbox {
|
|
147
130
|
uint256 l2Timestamp,
|
148
131
|
uint256 value,
|
149
132
|
bytes calldata data
|
150
|
-
) external
|
133
|
+
) external {
|
151
134
|
bytes32 userTx = calculateItemHash(
|
152
135
|
l2Sender,
|
153
136
|
to,
|
@@ -163,15 +146,7 @@ contract Outbox is DelegateCallAware, IOutbox {
|
|
163
146
|
executeTransactionImpl(index, l2Sender, to, l2Block, l1Block, l2Timestamp, value, data);
|
164
147
|
}
|
165
148
|
|
166
|
-
/// @
|
167
|
-
/// it is useful for things such as gas estimates. This function includes all costs except for
|
168
|
-
/// proof validation (which can be considered offchain as a somewhat of a fixed cost - it's
|
169
|
-
/// not really a fixed cost, but can be treated as so with a fixed overhead for gas estimation).
|
170
|
-
/// We can't include the cost of proof validation since this is intended to be used to simulate txs
|
171
|
-
/// that are included in yet-to-be confirmed merkle roots. The simulation entrypoint could instead pretend
|
172
|
-
/// to confirm a pending merkle root, but that would be less pratical for integrating with tooling.
|
173
|
-
/// It is only possible to trigger it when the msg sender is address zero, which should be impossible
|
174
|
-
/// unless under simulation in an eth_call or eth_estimateGas
|
149
|
+
/// @inheritdoc IOutbox
|
175
150
|
function executeTransactionSimulation(
|
176
151
|
uint256 index,
|
177
152
|
address l2Sender,
|
@@ -181,7 +156,7 @@ contract Outbox is DelegateCallAware, IOutbox {
|
|
181
156
|
uint256 l2Timestamp,
|
182
157
|
uint256 value,
|
183
158
|
bytes calldata data
|
184
|
-
) external
|
159
|
+
) external {
|
185
160
|
if (msg.sender != address(0)) revert SimulationOnlyEntrypoint();
|
186
161
|
executeTransactionImpl(index, l2Sender, to, l2Block, l1Block, l2Timestamp, value, data);
|
187
162
|
}
|
@@ -235,7 +210,8 @@ contract Outbox is DelegateCallAware, IOutbox {
|
|
235
210
|
return ((replay >> bitOffset) & bytes32(uint256(1))) != bytes32(0);
|
236
211
|
}
|
237
212
|
|
238
|
-
|
213
|
+
/// @inheritdoc IOutbox
|
214
|
+
function isSpent(uint256 index) external view returns (bool) {
|
239
215
|
(, uint256 bitOffset, bytes32 replay) = _calcSpentIndexOffset(index);
|
240
216
|
return _isSpent(bitOffset, replay);
|
241
217
|
}
|
@@ -285,7 +261,7 @@ contract Outbox is DelegateCallAware, IOutbox {
|
|
285
261
|
uint256 l2Timestamp,
|
286
262
|
uint256 value,
|
287
263
|
bytes calldata data
|
288
|
-
) public pure
|
264
|
+
) public pure returns (bytes32) {
|
289
265
|
return
|
290
266
|
keccak256(abi.encodePacked(l2Sender, to, l2Block, l1Block, l2Timestamp, value, data));
|
291
267
|
}
|
@@ -294,7 +270,7 @@ contract Outbox is DelegateCallAware, IOutbox {
|
|
294
270
|
bytes32[] memory proof,
|
295
271
|
uint256 path,
|
296
272
|
bytes32 item
|
297
|
-
) public pure
|
273
|
+
) public pure returns (bytes32) {
|
298
274
|
return MerkleLib.calculateRoot(proof, path, keccak256(abi.encodePacked(item)));
|
299
275
|
}
|
300
276
|
}
|
@@ -19,7 +19,8 @@ import {
|
|
19
19
|
BadSequencerNumber,
|
20
20
|
DataNotAuthenticated,
|
21
21
|
AlreadyValidDASKeyset,
|
22
|
-
NoSuchKeyset
|
22
|
+
NoSuchKeyset,
|
23
|
+
NotForked
|
23
24
|
} from "../libraries/Error.sol";
|
24
25
|
import "./IBridge.sol";
|
25
26
|
import "./IInbox.sol";
|
@@ -44,20 +45,16 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
44
45
|
|
45
46
|
IBridge public bridge;
|
46
47
|
|
47
|
-
/// @
|
48
|
+
/// @inheritdoc ISequencerInbox
|
48
49
|
uint256 public constant HEADER_LENGTH = 40;
|
49
|
-
|
50
|
-
///
|
50
|
+
|
51
|
+
/// @inheritdoc ISequencerInbox
|
51
52
|
bytes1 public constant DATA_AUTHENTICATED_FLAG = 0x40;
|
52
53
|
|
53
54
|
IOwnable public rollup;
|
54
55
|
mapping(address => bool) public isBatchPoster;
|
55
56
|
ISequencerInbox.MaxTimeVariation public maxTimeVariation;
|
56
57
|
|
57
|
-
struct DasKeySetInfo {
|
58
|
-
bool isValidKeyset;
|
59
|
-
uint64 creationBlock;
|
60
|
-
}
|
61
58
|
mapping(bytes32 => DasKeySetInfo) public dasKeySetInfo;
|
62
59
|
|
63
60
|
modifier onlyRollupOwner() {
|
@@ -65,6 +62,12 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
65
62
|
_;
|
66
63
|
}
|
67
64
|
|
65
|
+
uint256 internal immutable deployTimeChainId = block.chainid;
|
66
|
+
|
67
|
+
function _chainIdChanged() internal view returns (bool) {
|
68
|
+
return deployTimeChainId != block.chainid;
|
69
|
+
}
|
70
|
+
|
68
71
|
function initialize(
|
69
72
|
IBridge bridge_,
|
70
73
|
ISequencerInbox.MaxTimeVariation calldata maxTimeVariation_
|
@@ -89,17 +92,18 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
89
92
|
return bounds;
|
90
93
|
}
|
91
94
|
|
92
|
-
/// @
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
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
|
103
107
|
function forceInclusion(
|
104
108
|
uint256 _totalDelayedMessagesRead,
|
105
109
|
uint8 kind,
|
@@ -137,12 +141,23 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
137
141
|
(bytes32 dataHash, TimeBounds memory timeBounds) = formEmptyDataHash(
|
138
142
|
_totalDelayedMessagesRead
|
139
143
|
);
|
144
|
+
uint256 __totalDelayedMessagesRead = _totalDelayedMessagesRead;
|
145
|
+
uint256 prevSeqMsgCount = bridge.sequencerReportedSubMessageCount();
|
146
|
+
uint256 newSeqMsgCount = prevSeqMsgCount +
|
147
|
+
_totalDelayedMessagesRead -
|
148
|
+
totalDelayedMessagesRead;
|
140
149
|
(
|
141
150
|
uint256 seqMessageIndex,
|
142
151
|
bytes32 beforeAcc,
|
143
152
|
bytes32 delayedAcc,
|
144
153
|
bytes32 afterAcc
|
145
|
-
) = addSequencerL2BatchImpl(
|
154
|
+
) = addSequencerL2BatchImpl(
|
155
|
+
dataHash,
|
156
|
+
__totalDelayedMessagesRead,
|
157
|
+
0,
|
158
|
+
prevSeqMsgCount,
|
159
|
+
newSeqMsgCount
|
160
|
+
);
|
146
161
|
emit SequencerBatchDelivered(
|
147
162
|
seqMessageIndex,
|
148
163
|
beforeAcc,
|
@@ -154,6 +169,7 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
154
169
|
);
|
155
170
|
}
|
156
171
|
|
172
|
+
/// @dev Deprecated in favor of the variant specifying message counts for consistency
|
157
173
|
function addSequencerL2BatchFromOrigin(
|
158
174
|
uint256 sequenceNumber,
|
159
175
|
bytes calldata data,
|
@@ -163,6 +179,7 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
163
179
|
// solhint-disable-next-line avoid-tx-origin
|
164
180
|
if (msg.sender != tx.origin) revert NotOrigin();
|
165
181
|
if (!isBatchPoster[msg.sender]) revert NotBatchPoster();
|
182
|
+
|
166
183
|
(bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
|
167
184
|
data,
|
168
185
|
afterDelayedMessagesRead
|
@@ -172,7 +189,7 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
172
189
|
bytes32 beforeAcc,
|
173
190
|
bytes32 delayedAcc,
|
174
191
|
bytes32 afterAcc
|
175
|
-
) = addSequencerL2BatchImpl(dataHash, afterDelayedMessagesRead, data.length);
|
192
|
+
) = addSequencerL2BatchImpl(dataHash, afterDelayedMessagesRead, data.length, 0, 0);
|
176
193
|
if (seqMessageIndex != sequenceNumber)
|
177
194
|
revert BadSequencerNumber(seqMessageIndex, sequenceNumber);
|
178
195
|
emit SequencerBatchDelivered(
|
@@ -186,38 +203,101 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
186
203
|
);
|
187
204
|
}
|
188
205
|
|
189
|
-
function
|
206
|
+
function addSequencerL2BatchFromOrigin(
|
190
207
|
uint256 sequenceNumber,
|
191
208
|
bytes calldata data,
|
192
209
|
uint256 afterDelayedMessagesRead,
|
193
|
-
IGasRefunder gasRefunder
|
194
|
-
|
195
|
-
|
196
|
-
|
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();
|
197
217
|
(bytes32 dataHash, TimeBounds memory timeBounds) = formDataHash(
|
198
218
|
data,
|
199
219
|
afterDelayedMessagesRead
|
200
220
|
);
|
201
|
-
//
|
202
|
-
|
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;
|
203
229
|
(
|
204
230
|
uint256 seqMessageIndex,
|
205
231
|
bytes32 beforeAcc,
|
206
232
|
bytes32 delayedAcc,
|
207
233
|
bytes32 afterAcc
|
208
|
-
) = addSequencerL2BatchImpl(
|
209
|
-
|
210
|
-
|
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_);
|
211
243
|
emit SequencerBatchDelivered(
|
212
|
-
|
244
|
+
seqMessageIndex,
|
213
245
|
beforeAcc,
|
214
246
|
afterAcc,
|
215
247
|
delayedAcc,
|
216
|
-
|
217
|
-
|
218
|
-
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
|
219
266
|
);
|
220
|
-
|
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);
|
221
301
|
}
|
222
302
|
|
223
303
|
modifier validateBatchData(bytes calldata data) {
|
@@ -277,7 +357,9 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
277
357
|
function addSequencerL2BatchImpl(
|
278
358
|
bytes32 dataHash,
|
279
359
|
uint256 afterDelayedMessagesRead,
|
280
|
-
uint256 calldataLengthPosted
|
360
|
+
uint256 calldataLengthPosted,
|
361
|
+
uint256 prevMessageCount,
|
362
|
+
uint256 newMessageCount
|
281
363
|
)
|
282
364
|
internal
|
283
365
|
returns (
|
@@ -292,7 +374,9 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
292
374
|
|
293
375
|
(seqMessageIndex, beforeAcc, delayedAcc, acc) = bridge.enqueueSequencerMessage(
|
294
376
|
dataHash,
|
295
|
-
afterDelayedMessagesRead
|
377
|
+
afterDelayedMessagesRead,
|
378
|
+
prevMessageCount,
|
379
|
+
newMessageCount
|
296
380
|
);
|
297
381
|
|
298
382
|
totalDelayedMessagesRead = afterDelayedMessagesRead;
|
@@ -317,42 +401,31 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
317
401
|
}
|
318
402
|
}
|
319
403
|
|
320
|
-
function inboxAccs(uint256 index) external view
|
404
|
+
function inboxAccs(uint256 index) external view returns (bytes32) {
|
321
405
|
return bridge.sequencerInboxAccs(index);
|
322
406
|
}
|
323
407
|
|
324
|
-
function batchCount() external view
|
408
|
+
function batchCount() external view returns (uint256) {
|
325
409
|
return bridge.sequencerMessageCount();
|
326
410
|
}
|
327
411
|
|
328
|
-
|
329
|
-
* @notice Set max delay for sequencer inbox
|
330
|
-
* @param maxTimeVariation_ the maximum time variation parameters
|
331
|
-
*/
|
412
|
+
/// @inheritdoc ISequencerInbox
|
332
413
|
function setMaxTimeVariation(ISequencerInbox.MaxTimeVariation memory maxTimeVariation_)
|
333
414
|
external
|
334
|
-
override
|
335
415
|
onlyRollupOwner
|
336
416
|
{
|
337
417
|
maxTimeVariation = maxTimeVariation_;
|
338
418
|
emit OwnerFunctionCalled(0);
|
339
419
|
}
|
340
420
|
|
341
|
-
|
342
|
-
|
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 {
|
421
|
+
/// @inheritdoc ISequencerInbox
|
422
|
+
function setIsBatchPoster(address addr, bool isBatchPoster_) external onlyRollupOwner {
|
347
423
|
isBatchPoster[addr] = isBatchPoster_;
|
348
424
|
emit OwnerFunctionCalled(1);
|
349
425
|
}
|
350
426
|
|
351
|
-
|
352
|
-
|
353
|
-
* @param keysetBytes bytes of the serialized keyset
|
354
|
-
*/
|
355
|
-
function setValidKeyset(bytes calldata keysetBytes) external override onlyRollupOwner {
|
427
|
+
/// @inheritdoc ISequencerInbox
|
428
|
+
function setValidKeyset(bytes calldata keysetBytes) external onlyRollupOwner {
|
356
429
|
uint256 ksWord = uint256(keccak256(bytes.concat(hex"fe", keccak256(keysetBytes))));
|
357
430
|
bytes32 ksHash = bytes32(ksWord ^ (1 << 255));
|
358
431
|
require(keysetBytes.length < 64 * 1024, "keyset is too large");
|
@@ -366,11 +439,8 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
366
439
|
emit OwnerFunctionCalled(2);
|
367
440
|
}
|
368
441
|
|
369
|
-
|
370
|
-
|
371
|
-
* @param ksHash hash of the keyset
|
372
|
-
*/
|
373
|
-
function invalidateKeysetHash(bytes32 ksHash) external override onlyRollupOwner {
|
442
|
+
/// @inheritdoc ISequencerInbox
|
443
|
+
function invalidateKeysetHash(bytes32 ksHash) external onlyRollupOwner {
|
374
444
|
if (!dasKeySetInfo[ksHash].isValidKeyset) revert NoSuchKeyset(ksHash);
|
375
445
|
// we don't delete the block creation value since its used to fetch the SetValidKeyset
|
376
446
|
// event efficiently. The event provides the hash preimage of the key.
|
@@ -384,7 +454,7 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
|
|
384
454
|
return dasKeySetInfo[ksHash].isValidKeyset;
|
385
455
|
}
|
386
456
|
|
387
|
-
/// @
|
457
|
+
/// @inheritdoc ISequencerInbox
|
388
458
|
function getKeysetCreationBlock(bytes32 ksHash) external view returns (uint256) {
|
389
459
|
DasKeySetInfo memory ksInfo = dasKeySetInfo[ksHash];
|
390
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
@@ -96,6 +96,15 @@ error RetryableData(
|
|
96
96
|
bytes data
|
97
97
|
);
|
98
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
|
+
|
99
108
|
// Outbox Errors
|
100
109
|
|
101
110
|
/// @dev The provided proof was too long
|
@@ -141,6 +150,9 @@ error NotBatchPoster();
|
|
141
150
|
/// @dev The sequence number provided to this message was inconsistent with the number of batches already included
|
142
151
|
error BadSequencerNumber(uint256 stored, uint256 received);
|
143
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
|
+
|
144
156
|
/// @dev The batch data has the inbox authenticated bit set, but the batch data was not authenticated by the inbox
|
145
157
|
error DataNotAuthenticated();
|
146
158
|
|
@@ -21,14 +21,20 @@ abstract contract GasRefundEnabled {
|
|
21
21
|
uint256 startGasLeft = gasleft();
|
22
22
|
_;
|
23
23
|
if (address(gasRefunder) != address(0)) {
|
24
|
-
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;
|
25
31
|
// if triggered in a contract call, the spender may be overrefunded by appending dummy data to the call
|
26
32
|
// so we check if it is a top level call, which would mean the sender paid calldata as part of tx.input
|
27
33
|
// solhint-disable-next-line avoid-tx-origin
|
28
|
-
if (msg.sender
|
29
|
-
|
30
|
-
|
31
|
-
|
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;
|
32
38
|
}
|
33
39
|
gasRefunder.onGasSpent(payable(msg.sender), startGasLeft - gasleft(), calldataSize);
|
34
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
|
}
|