@arbitrum/nitro-contracts 1.0.0-beta.8 → 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 +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
|
}
|