@arbitrum/nitro-contracts 1.0.0-beta.1 → 1.0.0-beta.4
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/README.md +15 -0
- package/package.json +12 -8
- package/src/bridge/IInbox.sol +9 -0
- package/src/bridge/Inbox.sol +19 -39
- package/src/libraries/AdminFallbackProxy.sol +5 -5
- package/src/libraries/MessageTypes.sol +1 -0
- package/src/mocks/InboxStub.sol +4 -0
- package/src/mocks/Simple.sol +30 -0
- package/src/node-interface/NodeInterface.sol +18 -1
- package/src/node-interface/NodeInterfaceDebug.sol +30 -0
- package/src/osp/OneStepProver0.sol +14 -0
- package/src/osp/OneStepProverMath.sol +2 -2
- package/src/precompiles/ArbOwner.sol +3 -0
- package/src/rollup/IRollupCore.sol +26 -2
- package/src/rollup/IRollupEventBridge.sol +17 -0
- package/src/rollup/IRollupLogic.sol +34 -2
- package/src/rollup/RollupCore.sol +2 -2
- package/src/rollup/RollupCreator.sol +5 -15
- package/src/rollup/RollupEventBridge.sol +2 -3
- package/src/rollup/RollupLib.sol +2 -2
- package/src/rollup/RollupUserLogic.sol +7 -3
- package/src/rollup/ValidatorUtils.sol +0 -1
- package/src/rollup/ValidatorWallet.sol +0 -1
- package/src/state/Instructions.sol +2 -0
- package/.prettierrc +0 -5
- package/.solhint.json +0 -18
- package/deploy/BridgeStubCreator.js +0 -10
- package/deploy/HashProofHelper.js +0 -13
- package/deploy/InboxStubCreator.js +0 -17
- package/deploy/OneStepProofEntryCreator.js +0 -19
- package/deploy/OneStepProver0Creator.js +0 -14
- package/deploy/OneStepProverHostIoCreator.js +0 -14
- package/deploy/OneStepProverMathCreator.js +0 -14
- package/deploy/OneStepProverMemoryCreator.js +0 -14
- package/deploy/SequencerInboxStubCreator.js +0 -13
- package/deploy/ValueArrayTesterCreator.js +0 -13
- package/hardhat.config.ts +0 -47
- package/src/mocks/Counter.sol +0 -13
- package/test/contract/arbRollup.spec.ts +0 -869
- package/test/contract/common/challengeLib.ts +0 -43
- package/test/contract/common/globalStateLib.ts +0 -17
- package/test/contract/common/rolluplib.ts +0 -259
- package/test/contract/cryptographyPrimitives.spec.ts +0 -82
- package/test/contract/sequencerInboxForceInclude.spec.ts +0 -516
- package/test/contract/utils.ts +0 -40
- package/test/prover/hash-proofs.ts +0 -75
- package/test/prover/one-step-proof.ts +0 -93
- package/test/prover/proofs/.gitkeep +0 -0
- package/test/prover/value-arrays.ts +0 -11
- package/tsconfig.json +0 -13
@@ -1,516 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* Copyright 2019-2020, Offchain Labs, Inc.
|
3
|
-
*
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
-
* you may not use this file except in compliance with the License.
|
6
|
-
* You may obtain a copy of the License at
|
7
|
-
*
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
-
*
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
-
* See the License for the specific language governing permissions and
|
14
|
-
* limitations under the License.
|
15
|
-
*/
|
16
|
-
|
17
|
-
/* eslint-env node, mocha */
|
18
|
-
|
19
|
-
import { ethers, network } from 'hardhat'
|
20
|
-
import { BigNumber } from '@ethersproject/bignumber'
|
21
|
-
import { Block, TransactionReceipt } from '@ethersproject/providers'
|
22
|
-
import { expect } from 'chai'
|
23
|
-
import {
|
24
|
-
Bridge,
|
25
|
-
Bridge__factory,
|
26
|
-
Inbox,
|
27
|
-
Inbox__factory,
|
28
|
-
MessageTester,
|
29
|
-
SequencerInbox,
|
30
|
-
SequencerInbox__factory,
|
31
|
-
TransparentUpgradeableProxy__factory,
|
32
|
-
} from '../../build/types'
|
33
|
-
import { initializeAccounts } from './utils'
|
34
|
-
import { Event } from '@ethersproject/contracts'
|
35
|
-
import { Interface } from '@ethersproject/abi'
|
36
|
-
import {
|
37
|
-
BridgeInterface,
|
38
|
-
MessageDeliveredEvent,
|
39
|
-
} from '../../build/types/Bridge'
|
40
|
-
import { Signer } from 'ethers'
|
41
|
-
|
42
|
-
const mineBlocks = async (count: number, timeDiffPerBlock = 14) => {
|
43
|
-
const block = (await network.provider.send('eth_getBlockByNumber', [
|
44
|
-
'latest',
|
45
|
-
false,
|
46
|
-
])) as Block
|
47
|
-
let timestamp = BigNumber.from(block.timestamp).toNumber()
|
48
|
-
for (let i = 0; i < count; i++) {
|
49
|
-
timestamp = timestamp + timeDiffPerBlock
|
50
|
-
await network.provider.send('evm_mine', [timestamp])
|
51
|
-
}
|
52
|
-
}
|
53
|
-
|
54
|
-
describe('SequencerInboxForceInclude', async () => {
|
55
|
-
const findMatchingLogs = <TInterface extends Interface, TEvent extends Event>(
|
56
|
-
receipt: TransactionReceipt,
|
57
|
-
iFace: TInterface,
|
58
|
-
eventTopicGen: (i: TInterface) => string,
|
59
|
-
): TEvent['args'][] => {
|
60
|
-
const logs = receipt.logs.filter(
|
61
|
-
(log) => log.topics[0] === eventTopicGen(iFace),
|
62
|
-
)
|
63
|
-
return logs.map((l) => iFace.parseLog(l).args as TEvent['args'])
|
64
|
-
}
|
65
|
-
|
66
|
-
const getMessageDeliveredEvents = (receipt: TransactionReceipt) => {
|
67
|
-
const bridgeInterface = Bridge__factory.createInterface()
|
68
|
-
return findMatchingLogs<BridgeInterface, MessageDeliveredEvent>(
|
69
|
-
receipt,
|
70
|
-
bridgeInterface,
|
71
|
-
(i) => i.getEventTopic(i.getEvent('MessageDelivered')),
|
72
|
-
)
|
73
|
-
}
|
74
|
-
|
75
|
-
const sendDelayedTx = async (
|
76
|
-
sender: Signer,
|
77
|
-
inbox: Inbox,
|
78
|
-
bridge: Bridge,
|
79
|
-
messageTester: MessageTester,
|
80
|
-
l2Gas: number,
|
81
|
-
l2GasPrice: number,
|
82
|
-
nonce: number,
|
83
|
-
destAddr: string,
|
84
|
-
amount: BigNumber,
|
85
|
-
data: string,
|
86
|
-
) => {
|
87
|
-
const countBefore = (await bridge.functions.messageCount())[0].toNumber()
|
88
|
-
const sendUnsignedTx = await inbox
|
89
|
-
.connect(sender)
|
90
|
-
.sendUnsignedTransaction(l2Gas, l2GasPrice, nonce, destAddr, amount, data)
|
91
|
-
const sendUnsignedTxReceipt = await sendUnsignedTx.wait()
|
92
|
-
|
93
|
-
const countAfter = (await bridge.functions.messageCount())[0].toNumber()
|
94
|
-
expect(countAfter, 'Unexpected inbox count').to.eq(countBefore + 1)
|
95
|
-
|
96
|
-
const senderAddr = await sender.getAddress()
|
97
|
-
|
98
|
-
const messageDeliveredEvent = getMessageDeliveredEvents(
|
99
|
-
sendUnsignedTxReceipt,
|
100
|
-
)[0]
|
101
|
-
const l1BlockNumber = sendUnsignedTxReceipt.blockNumber
|
102
|
-
const blockL1 = await sender.provider!.getBlock(l1BlockNumber)
|
103
|
-
const baseFeeL1 = blockL1.baseFeePerGas!.toNumber()
|
104
|
-
const l1BlockTimestamp = blockL1.timestamp
|
105
|
-
const delayedAcc = await bridge.inboxAccs(countBefore)
|
106
|
-
|
107
|
-
// need to hex pad the address
|
108
|
-
const messageDataHash = ethers.utils.solidityKeccak256(
|
109
|
-
['uint8', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'bytes'],
|
110
|
-
[
|
111
|
-
0,
|
112
|
-
l2Gas,
|
113
|
-
l2GasPrice,
|
114
|
-
nonce,
|
115
|
-
ethers.utils.hexZeroPad(destAddr, 32),
|
116
|
-
amount,
|
117
|
-
data,
|
118
|
-
],
|
119
|
-
)
|
120
|
-
expect(
|
121
|
-
messageDeliveredEvent.messageDataHash,
|
122
|
-
'Incorrect messageDataHash',
|
123
|
-
).to.eq(messageDataHash)
|
124
|
-
|
125
|
-
const messageHash = (
|
126
|
-
await messageTester.functions.messageHash(
|
127
|
-
3,
|
128
|
-
senderAddr,
|
129
|
-
l1BlockNumber,
|
130
|
-
l1BlockTimestamp,
|
131
|
-
countBefore,
|
132
|
-
baseFeeL1,
|
133
|
-
messageDataHash,
|
134
|
-
)
|
135
|
-
)[0]
|
136
|
-
|
137
|
-
const prevAccumulator = messageDeliveredEvent.beforeInboxAcc
|
138
|
-
expect(prevAccumulator, 'Incorrect prev accumulator').to.eq(
|
139
|
-
countBefore === 0
|
140
|
-
? ethers.utils.hexZeroPad('0x', 32)
|
141
|
-
: await bridge.inboxAccs(countBefore - 1),
|
142
|
-
)
|
143
|
-
|
144
|
-
const nextAcc = (
|
145
|
-
await messageTester.functions.accumulateInboxMessage(
|
146
|
-
prevAccumulator,
|
147
|
-
messageHash,
|
148
|
-
)
|
149
|
-
)[0]
|
150
|
-
|
151
|
-
expect(delayedAcc, 'Incorrect delayed acc').to.eq(nextAcc)
|
152
|
-
|
153
|
-
return {
|
154
|
-
baseFeeL1: baseFeeL1,
|
155
|
-
deliveredMessageEvent: messageDeliveredEvent,
|
156
|
-
l1BlockNumber,
|
157
|
-
l1BlockTimestamp,
|
158
|
-
delayedAcc,
|
159
|
-
l2Gas,
|
160
|
-
l2GasPrice,
|
161
|
-
nonce,
|
162
|
-
destAddr,
|
163
|
-
amount,
|
164
|
-
data,
|
165
|
-
senderAddr,
|
166
|
-
inboxAccountLength: countAfter,
|
167
|
-
}
|
168
|
-
}
|
169
|
-
|
170
|
-
const forceIncludeMessages = async (
|
171
|
-
sequencerInbox: SequencerInbox,
|
172
|
-
newTotalDelayedMessagesRead: number,
|
173
|
-
kind: number,
|
174
|
-
l1blockNumber: number,
|
175
|
-
l1Timestamp: number,
|
176
|
-
l1BaseFee: number,
|
177
|
-
senderAddr: string,
|
178
|
-
messageDataHash: string,
|
179
|
-
expectedErrorType?: string,
|
180
|
-
) => {
|
181
|
-
const inboxLengthBefore = (await sequencerInbox.batchCount()).toNumber()
|
182
|
-
|
183
|
-
const forceInclusionTx = sequencerInbox.forceInclusion(
|
184
|
-
newTotalDelayedMessagesRead,
|
185
|
-
kind,
|
186
|
-
[l1blockNumber, l1Timestamp],
|
187
|
-
l1BaseFee,
|
188
|
-
senderAddr,
|
189
|
-
messageDataHash,
|
190
|
-
)
|
191
|
-
if (expectedErrorType) {
|
192
|
-
await expect(forceInclusionTx).to.be.revertedWith(`reverted with custom error '${expectedErrorType}()'`)
|
193
|
-
} else {
|
194
|
-
await (await forceInclusionTx).wait()
|
195
|
-
|
196
|
-
const totalDelayedMessagsReadAfter = (
|
197
|
-
await sequencerInbox.totalDelayedMessagesRead()
|
198
|
-
).toNumber()
|
199
|
-
expect(
|
200
|
-
totalDelayedMessagsReadAfter,
|
201
|
-
'Incorrect totalDelayedMessagesRead after.',
|
202
|
-
).to.eq(newTotalDelayedMessagesRead)
|
203
|
-
const inboxLengthAfter = (await sequencerInbox.batchCount()).toNumber()
|
204
|
-
expect(
|
205
|
-
inboxLengthAfter - inboxLengthBefore,
|
206
|
-
'Inbox not incremented',
|
207
|
-
).to.eq(1)
|
208
|
-
}
|
209
|
-
}
|
210
|
-
|
211
|
-
const setupSequencerInbox = async (maxDelayBlocks = 10, maxDelayTime = 0) => {
|
212
|
-
const accounts = await initializeAccounts()
|
213
|
-
const admin = accounts[0]
|
214
|
-
const adminAddr = await admin.getAddress()
|
215
|
-
const user = accounts[1]
|
216
|
-
const dummyRollup = accounts[2]
|
217
|
-
|
218
|
-
const sequencerInboxFac = (await ethers.getContractFactory(
|
219
|
-
'SequencerInbox',
|
220
|
-
)) as SequencerInbox__factory
|
221
|
-
const seqInboxTemplate = await sequencerInboxFac.deploy()
|
222
|
-
const inboxFac = (await ethers.getContractFactory(
|
223
|
-
'Inbox',
|
224
|
-
)) as Inbox__factory
|
225
|
-
const inboxTemplate = await inboxFac.deploy()
|
226
|
-
const bridgeFac = (await ethers.getContractFactory(
|
227
|
-
'Bridge',
|
228
|
-
)) as Bridge__factory
|
229
|
-
const bridgeTemplate = await bridgeFac.deploy()
|
230
|
-
const transparentUpgradeableProxyFac = (await ethers.getContractFactory(
|
231
|
-
'TransparentUpgradeableProxy',
|
232
|
-
)) as TransparentUpgradeableProxy__factory
|
233
|
-
|
234
|
-
const bridgeProxy = await transparentUpgradeableProxyFac.deploy(
|
235
|
-
bridgeTemplate.address,
|
236
|
-
adminAddr,
|
237
|
-
'0x',
|
238
|
-
)
|
239
|
-
const sequencerInboxProxy = await transparentUpgradeableProxyFac.deploy(
|
240
|
-
seqInboxTemplate.address,
|
241
|
-
adminAddr,
|
242
|
-
'0x',
|
243
|
-
)
|
244
|
-
const inboxProxy = await transparentUpgradeableProxyFac.deploy(
|
245
|
-
inboxTemplate.address,
|
246
|
-
adminAddr,
|
247
|
-
'0x',
|
248
|
-
)
|
249
|
-
|
250
|
-
const bridge = await bridgeFac.attach(bridgeProxy.address).connect(user)
|
251
|
-
const sequencerInbox = await sequencerInboxFac
|
252
|
-
.attach(sequencerInboxProxy.address)
|
253
|
-
.connect(user)
|
254
|
-
const inbox = await inboxFac.attach(inboxProxy.address).connect(user)
|
255
|
-
|
256
|
-
await bridge.initialize()
|
257
|
-
|
258
|
-
await sequencerInbox.initialize(
|
259
|
-
bridgeProxy.address,
|
260
|
-
await dummyRollup.getAddress(),
|
261
|
-
{
|
262
|
-
delayBlocks: maxDelayBlocks,
|
263
|
-
delaySeconds: maxDelayTime,
|
264
|
-
futureBlocks: 10,
|
265
|
-
futureSeconds: 3000,
|
266
|
-
},
|
267
|
-
)
|
268
|
-
await inbox.initialize(bridgeProxy.address)
|
269
|
-
|
270
|
-
await bridge.setInbox(inbox.address, true)
|
271
|
-
|
272
|
-
const messageTester = (await (
|
273
|
-
await ethers.getContractFactory('MessageTester')
|
274
|
-
).deploy()) as MessageTester
|
275
|
-
|
276
|
-
return {
|
277
|
-
user,
|
278
|
-
bridge: bridge,
|
279
|
-
inbox: inbox,
|
280
|
-
sequencerInbox: sequencerInbox,
|
281
|
-
messageTester,
|
282
|
-
}
|
283
|
-
}
|
284
|
-
|
285
|
-
it('can force-include', async () => {
|
286
|
-
const {
|
287
|
-
user,
|
288
|
-
inbox,
|
289
|
-
bridge,
|
290
|
-
messageTester,
|
291
|
-
sequencerInbox,
|
292
|
-
} = await setupSequencerInbox()
|
293
|
-
|
294
|
-
const delayedTx = await sendDelayedTx(
|
295
|
-
user,
|
296
|
-
inbox,
|
297
|
-
bridge,
|
298
|
-
messageTester,
|
299
|
-
1000000,
|
300
|
-
21000000000,
|
301
|
-
0,
|
302
|
-
await user.getAddress(),
|
303
|
-
BigNumber.from(10),
|
304
|
-
'0x1010',
|
305
|
-
)
|
306
|
-
const maxTimeVariation = await sequencerInbox.maxTimeVariation()
|
307
|
-
|
308
|
-
await mineBlocks(maxTimeVariation.delayBlocks.toNumber())
|
309
|
-
|
310
|
-
await forceIncludeMessages(
|
311
|
-
sequencerInbox,
|
312
|
-
delayedTx.inboxAccountLength,
|
313
|
-
delayedTx.deliveredMessageEvent.kind,
|
314
|
-
delayedTx.l1BlockNumber,
|
315
|
-
delayedTx.l1BlockTimestamp,
|
316
|
-
delayedTx.baseFeeL1,
|
317
|
-
delayedTx.senderAddr,
|
318
|
-
delayedTx.deliveredMessageEvent.messageDataHash,
|
319
|
-
)
|
320
|
-
})
|
321
|
-
|
322
|
-
it('can force-include one after another', async () => {
|
323
|
-
const {
|
324
|
-
user,
|
325
|
-
inbox,
|
326
|
-
bridge,
|
327
|
-
messageTester,
|
328
|
-
sequencerInbox,
|
329
|
-
} = await setupSequencerInbox()
|
330
|
-
const delayedTx = await sendDelayedTx(
|
331
|
-
user,
|
332
|
-
inbox,
|
333
|
-
bridge,
|
334
|
-
messageTester,
|
335
|
-
1000000,
|
336
|
-
21000000000,
|
337
|
-
0,
|
338
|
-
await user.getAddress(),
|
339
|
-
BigNumber.from(10),
|
340
|
-
'0x1010',
|
341
|
-
)
|
342
|
-
|
343
|
-
const delayedTx2 = await sendDelayedTx(
|
344
|
-
user,
|
345
|
-
inbox,
|
346
|
-
bridge,
|
347
|
-
messageTester,
|
348
|
-
1000000,
|
349
|
-
21000000000,
|
350
|
-
1,
|
351
|
-
await user.getAddress(),
|
352
|
-
BigNumber.from(10),
|
353
|
-
'0xdeadface',
|
354
|
-
)
|
355
|
-
|
356
|
-
const maxTimeVariation = await sequencerInbox.maxTimeVariation()
|
357
|
-
await mineBlocks(maxTimeVariation.delayBlocks.toNumber())
|
358
|
-
|
359
|
-
await forceIncludeMessages(
|
360
|
-
sequencerInbox,
|
361
|
-
delayedTx.inboxAccountLength,
|
362
|
-
delayedTx.deliveredMessageEvent.kind,
|
363
|
-
delayedTx.l1BlockNumber,
|
364
|
-
delayedTx.l1BlockTimestamp,
|
365
|
-
delayedTx.baseFeeL1,
|
366
|
-
delayedTx.senderAddr,
|
367
|
-
delayedTx.deliveredMessageEvent.messageDataHash,
|
368
|
-
)
|
369
|
-
await forceIncludeMessages(
|
370
|
-
sequencerInbox,
|
371
|
-
delayedTx2.inboxAccountLength,
|
372
|
-
delayedTx2.deliveredMessageEvent.kind,
|
373
|
-
delayedTx2.l1BlockNumber,
|
374
|
-
delayedTx2.l1BlockTimestamp,
|
375
|
-
delayedTx2.baseFeeL1,
|
376
|
-
delayedTx2.senderAddr,
|
377
|
-
delayedTx2.deliveredMessageEvent.messageDataHash,
|
378
|
-
)
|
379
|
-
})
|
380
|
-
|
381
|
-
it('can force-include three at once', async () => {
|
382
|
-
const {
|
383
|
-
user,
|
384
|
-
inbox,
|
385
|
-
bridge,
|
386
|
-
messageTester,
|
387
|
-
sequencerInbox,
|
388
|
-
} = await setupSequencerInbox()
|
389
|
-
await sendDelayedTx(
|
390
|
-
user,
|
391
|
-
inbox,
|
392
|
-
bridge,
|
393
|
-
messageTester,
|
394
|
-
1000000,
|
395
|
-
21000000000,
|
396
|
-
0,
|
397
|
-
await user.getAddress(),
|
398
|
-
BigNumber.from(10),
|
399
|
-
'0x1010',
|
400
|
-
)
|
401
|
-
await sendDelayedTx(
|
402
|
-
user,
|
403
|
-
inbox,
|
404
|
-
bridge,
|
405
|
-
messageTester,
|
406
|
-
1000000,
|
407
|
-
21000000000,
|
408
|
-
1,
|
409
|
-
await user.getAddress(),
|
410
|
-
BigNumber.from(10),
|
411
|
-
'0x101010',
|
412
|
-
)
|
413
|
-
const delayedTx3 = await sendDelayedTx(
|
414
|
-
user,
|
415
|
-
inbox,
|
416
|
-
bridge,
|
417
|
-
messageTester,
|
418
|
-
1000000,
|
419
|
-
21000000000,
|
420
|
-
10,
|
421
|
-
await user.getAddress(),
|
422
|
-
BigNumber.from(10),
|
423
|
-
'0x10101010',
|
424
|
-
)
|
425
|
-
|
426
|
-
const maxTimeVariation = await sequencerInbox.maxTimeVariation()
|
427
|
-
await mineBlocks(maxTimeVariation.delayBlocks.toNumber())
|
428
|
-
|
429
|
-
await forceIncludeMessages(
|
430
|
-
sequencerInbox,
|
431
|
-
delayedTx3.inboxAccountLength,
|
432
|
-
delayedTx3.deliveredMessageEvent.kind,
|
433
|
-
delayedTx3.l1BlockNumber,
|
434
|
-
delayedTx3.l1BlockTimestamp,
|
435
|
-
delayedTx3.baseFeeL1,
|
436
|
-
delayedTx3.senderAddr,
|
437
|
-
delayedTx3.deliveredMessageEvent.messageDataHash,
|
438
|
-
)
|
439
|
-
})
|
440
|
-
|
441
|
-
it('cannot include before max block delay', async () => {
|
442
|
-
const {
|
443
|
-
user,
|
444
|
-
inbox,
|
445
|
-
bridge,
|
446
|
-
messageTester,
|
447
|
-
sequencerInbox,
|
448
|
-
} = await setupSequencerInbox(10, 100)
|
449
|
-
const delayedTx = await sendDelayedTx(
|
450
|
-
user,
|
451
|
-
inbox,
|
452
|
-
bridge,
|
453
|
-
messageTester,
|
454
|
-
1000000,
|
455
|
-
21000000000,
|
456
|
-
0,
|
457
|
-
await user.getAddress(),
|
458
|
-
BigNumber.from(10),
|
459
|
-
'0x1010',
|
460
|
-
)
|
461
|
-
|
462
|
-
const maxTimeVariation = await sequencerInbox.maxTimeVariation()
|
463
|
-
await mineBlocks(maxTimeVariation.delayBlocks.toNumber() - 1, 5)
|
464
|
-
|
465
|
-
await forceIncludeMessages(
|
466
|
-
sequencerInbox,
|
467
|
-
delayedTx.inboxAccountLength,
|
468
|
-
delayedTx.deliveredMessageEvent.kind,
|
469
|
-
delayedTx.l1BlockNumber,
|
470
|
-
delayedTx.l1BlockTimestamp,
|
471
|
-
delayedTx.baseFeeL1,
|
472
|
-
delayedTx.senderAddr,
|
473
|
-
delayedTx.deliveredMessageEvent.messageDataHash,
|
474
|
-
'ForceIncludeBlockTooSoon',
|
475
|
-
)
|
476
|
-
})
|
477
|
-
|
478
|
-
it('cannot include before max time delay', async () => {
|
479
|
-
const {
|
480
|
-
user,
|
481
|
-
inbox,
|
482
|
-
bridge,
|
483
|
-
messageTester,
|
484
|
-
sequencerInbox,
|
485
|
-
} = await setupSequencerInbox(10, 100)
|
486
|
-
const delayedTx = await sendDelayedTx(
|
487
|
-
user,
|
488
|
-
inbox,
|
489
|
-
bridge,
|
490
|
-
messageTester,
|
491
|
-
1000000,
|
492
|
-
21000000000,
|
493
|
-
0,
|
494
|
-
await user.getAddress(),
|
495
|
-
BigNumber.from(10),
|
496
|
-
'0x1010',
|
497
|
-
)
|
498
|
-
|
499
|
-
const maxTimeVariation = await sequencerInbox.maxTimeVariation()
|
500
|
-
// mine a lot of blocks - but use a short time per block
|
501
|
-
// this should mean enough blocks have passed, but not enough time
|
502
|
-
await mineBlocks(maxTimeVariation.delayBlocks.toNumber() + 1, 5)
|
503
|
-
|
504
|
-
await forceIncludeMessages(
|
505
|
-
sequencerInbox,
|
506
|
-
delayedTx.inboxAccountLength,
|
507
|
-
delayedTx.deliveredMessageEvent.kind,
|
508
|
-
delayedTx.l1BlockNumber,
|
509
|
-
delayedTx.l1BlockTimestamp,
|
510
|
-
delayedTx.baseFeeL1,
|
511
|
-
delayedTx.senderAddr,
|
512
|
-
delayedTx.deliveredMessageEvent.messageDataHash,
|
513
|
-
'ForceIncludeTimeTooSoon',
|
514
|
-
)
|
515
|
-
})
|
516
|
-
})
|
package/test/contract/utils.ts
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
import { ethers } from 'hardhat'
|
2
|
-
import { Signer } from '@ethersproject/abstract-signer'
|
3
|
-
|
4
|
-
export async function initializeAccounts(): Promise<Signer[]> {
|
5
|
-
const [account0] = await ethers.getSigners()
|
6
|
-
const provider = account0.provider!
|
7
|
-
|
8
|
-
const accounts: Signer[] = [account0]
|
9
|
-
for (let i = 0; i < 9; i++) {
|
10
|
-
const account = ethers.Wallet.createRandom().connect(provider)
|
11
|
-
accounts.push(account)
|
12
|
-
const tx = await account0.sendTransaction({
|
13
|
-
value: ethers.utils.parseEther('10000.0'),
|
14
|
-
to: await account.getAddress(),
|
15
|
-
})
|
16
|
-
await tx.wait()
|
17
|
-
}
|
18
|
-
return accounts
|
19
|
-
}
|
20
|
-
|
21
|
-
export async function tryAdvanceChain(
|
22
|
-
account: Signer,
|
23
|
-
blocks: number
|
24
|
-
): Promise<void> {
|
25
|
-
try {
|
26
|
-
for (let i = 0; i < blocks; i++) {
|
27
|
-
await ethers.provider.send('evm_mine', [])
|
28
|
-
}
|
29
|
-
} catch (e) {
|
30
|
-
// EVM mine failed. Try advancing the chain by sending txes if the node
|
31
|
-
// is in dev mode and mints blocks when txes are sent
|
32
|
-
for (let i = 0; i < blocks; i++) {
|
33
|
-
const tx = await account.sendTransaction({
|
34
|
-
value: 0,
|
35
|
-
to: await account.getAddress(),
|
36
|
-
})
|
37
|
-
await tx.wait()
|
38
|
-
}
|
39
|
-
}
|
40
|
-
}
|
@@ -1,75 +0,0 @@
|
|
1
|
-
import { assert } from "chai";
|
2
|
-
import { ethers, run } from "hardhat";
|
3
|
-
|
4
|
-
describe("HashProofHelper", function () {
|
5
|
-
it("Should produce valid proofs from full preimages", async function () {
|
6
|
-
await run("deploy", { tags: "HashProofHelper" });
|
7
|
-
|
8
|
-
const hashProofHelper = await ethers.getContract("HashProofHelper");
|
9
|
-
|
10
|
-
for (let i = 0; i < 16; i += 1) {
|
11
|
-
const len = Math.floor(Math.random() * 256);
|
12
|
-
const data = Math.floor(Math.random() * 256);
|
13
|
-
const offset = Math.floor(Math.random() * 256);
|
14
|
-
const bytes = Array(len).fill(data);
|
15
|
-
const hash = ethers.utils.keccak256(bytes);
|
16
|
-
|
17
|
-
const proofTx = await hashProofHelper.proveWithFullPreimage(bytes, offset);
|
18
|
-
const receipt = await proofTx.wait();
|
19
|
-
const log = hashProofHelper.interface.parseLog(receipt.logs[0]);
|
20
|
-
const provenPart = await hashProofHelper.getPreimagePart(hash, offset);
|
21
|
-
|
22
|
-
let dataHex = data.toString(16);
|
23
|
-
dataHex = "00".slice(dataHex.length) + dataHex;
|
24
|
-
const partLen = Math.min(32, Math.max(0, len - offset));
|
25
|
-
const partString = "0x" + dataHex.repeat(partLen);
|
26
|
-
assert.equal(log.args["fullHash"], hash);
|
27
|
-
assert.equal(log.args["offset"], offset);
|
28
|
-
assert.equal(log.args["part"], partString);
|
29
|
-
assert.equal(provenPart, partString);
|
30
|
-
}
|
31
|
-
});
|
32
|
-
|
33
|
-
it("Should produce valid proofs from split preimages", async function () {
|
34
|
-
await run("deploy", { tags: "HashProofHelper" });
|
35
|
-
|
36
|
-
const hashProofHelper = await ethers.getContract("HashProofHelper");
|
37
|
-
|
38
|
-
for (let i = 0; i < 16; i += 1) {
|
39
|
-
const len = Math.floor(Math.random() * 1024);
|
40
|
-
const data = Math.floor(Math.random() * 256);
|
41
|
-
const offset = Math.floor(Math.random() * 256);
|
42
|
-
const bytes = Array(len).fill(data);
|
43
|
-
const hash = ethers.utils.keccak256(bytes);
|
44
|
-
|
45
|
-
let provenLen = 0;
|
46
|
-
let provenPart = null;
|
47
|
-
let log = null;
|
48
|
-
while (provenPart === null) {
|
49
|
-
let nextPartialLen = 136 * (1 + Math.floor(Math.random() * 2));
|
50
|
-
if (nextPartialLen > len - provenLen) {
|
51
|
-
nextPartialLen = len - provenLen;
|
52
|
-
}
|
53
|
-
const newProvenLen = provenLen + nextPartialLen;
|
54
|
-
const isFinal = newProvenLen == len;
|
55
|
-
const proofTx = await hashProofHelper.proveWithSplitPreimage(bytes.slice(provenLen, newProvenLen), offset, isFinal ? 1 : 0);
|
56
|
-
const receipt = await proofTx.wait();
|
57
|
-
if (receipt.logs.length > 0) {
|
58
|
-
log = hashProofHelper.interface.parseLog(receipt.logs[0]);
|
59
|
-
provenPart = await hashProofHelper.getPreimagePart(hash, offset);
|
60
|
-
}
|
61
|
-
provenLen = newProvenLen;
|
62
|
-
}
|
63
|
-
|
64
|
-
let dataHex = data.toString(16);
|
65
|
-
dataHex = "00".slice(dataHex.length) + dataHex;
|
66
|
-
const partLen = Math.min(32, Math.max(0, len - offset));
|
67
|
-
const partString = "0x" + dataHex.repeat(partLen);
|
68
|
-
assert.isNotNull(log);
|
69
|
-
assert.equal(log!.args["fullHash"], hash);
|
70
|
-
assert.equal(log!.args["offset"], offset);
|
71
|
-
assert.equal(log!.args["part"], partString);
|
72
|
-
assert.equal(provenPart, partString);
|
73
|
-
}
|
74
|
-
});
|
75
|
-
});
|