@aztec/ethereum 3.0.0-canary.a9708bd → 3.0.0-devnet.3

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.
Files changed (144) hide show
  1. package/dest/client.d.ts +1 -1
  2. package/dest/client.d.ts.map +1 -1
  3. package/dest/config.d.ts +11 -6
  4. package/dest/config.d.ts.map +1 -1
  5. package/dest/config.js +124 -64
  6. package/dest/contracts/empire_base.d.ts +1 -1
  7. package/dest/contracts/empire_base.d.ts.map +1 -1
  8. package/dest/contracts/empire_slashing_proposer.d.ts +2 -2
  9. package/dest/contracts/empire_slashing_proposer.d.ts.map +1 -1
  10. package/dest/contracts/empire_slashing_proposer.js +1 -1
  11. package/dest/contracts/fee_asset_handler.d.ts +3 -3
  12. package/dest/contracts/fee_asset_handler.d.ts.map +1 -1
  13. package/dest/contracts/governance.js +7 -3
  14. package/dest/contracts/governance_proposer.d.ts +1 -2
  15. package/dest/contracts/governance_proposer.d.ts.map +1 -1
  16. package/dest/contracts/governance_proposer.js +1 -2
  17. package/dest/contracts/multicall.d.ts +3 -5
  18. package/dest/contracts/multicall.d.ts.map +1 -1
  19. package/dest/contracts/multicall.js +6 -4
  20. package/dest/contracts/rollup.d.ts +39 -19
  21. package/dest/contracts/rollup.d.ts.map +1 -1
  22. package/dest/contracts/rollup.js +84 -88
  23. package/dest/contracts/slasher_contract.d.ts +10 -0
  24. package/dest/contracts/slasher_contract.d.ts.map +1 -1
  25. package/dest/contracts/slasher_contract.js +18 -0
  26. package/dest/contracts/tally_slashing_proposer.d.ts +22 -3
  27. package/dest/contracts/tally_slashing_proposer.d.ts.map +1 -1
  28. package/dest/contracts/tally_slashing_proposer.js +55 -5
  29. package/dest/deploy_l1_contracts.d.ts +22 -7
  30. package/dest/deploy_l1_contracts.d.ts.map +1 -1
  31. package/dest/deploy_l1_contracts.js +555 -362
  32. package/dest/index.d.ts +1 -1
  33. package/dest/index.d.ts.map +1 -1
  34. package/dest/index.js +1 -1
  35. package/dest/l1_artifacts.d.ts +8729 -6014
  36. package/dest/l1_artifacts.d.ts.map +1 -1
  37. package/dest/l1_artifacts.js +10 -5
  38. package/dest/l1_contract_addresses.d.ts +5 -1
  39. package/dest/l1_contract_addresses.d.ts.map +1 -1
  40. package/dest/l1_contract_addresses.js +16 -26
  41. package/dest/l1_reader.d.ts +1 -1
  42. package/dest/l1_reader.d.ts.map +1 -1
  43. package/dest/l1_reader.js +8 -8
  44. package/dest/l1_tx_utils/config.d.ts +59 -0
  45. package/dest/l1_tx_utils/config.d.ts.map +1 -0
  46. package/dest/l1_tx_utils/config.js +73 -0
  47. package/dest/l1_tx_utils/constants.d.ts +6 -0
  48. package/dest/l1_tx_utils/constants.d.ts.map +1 -0
  49. package/dest/l1_tx_utils/constants.js +14 -0
  50. package/dest/l1_tx_utils/factory.d.ts +24 -0
  51. package/dest/l1_tx_utils/factory.d.ts.map +1 -0
  52. package/dest/l1_tx_utils/factory.js +12 -0
  53. package/dest/l1_tx_utils/index.d.ts +10 -0
  54. package/dest/l1_tx_utils/index.d.ts.map +1 -0
  55. package/dest/l1_tx_utils/index.js +10 -0
  56. package/dest/l1_tx_utils/interfaces.d.ts +76 -0
  57. package/dest/l1_tx_utils/interfaces.d.ts.map +1 -0
  58. package/dest/l1_tx_utils/interfaces.js +4 -0
  59. package/dest/l1_tx_utils/l1_tx_utils.d.ts +95 -0
  60. package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -0
  61. package/dest/l1_tx_utils/l1_tx_utils.js +610 -0
  62. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts +26 -0
  63. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts.map +1 -0
  64. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.js +26 -0
  65. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +81 -0
  66. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -0
  67. package/dest/l1_tx_utils/readonly_l1_tx_utils.js +294 -0
  68. package/dest/l1_tx_utils/signer.d.ts +4 -0
  69. package/dest/l1_tx_utils/signer.d.ts.map +1 -0
  70. package/dest/l1_tx_utils/signer.js +16 -0
  71. package/dest/l1_tx_utils/types.d.ts +67 -0
  72. package/dest/l1_tx_utils/types.d.ts.map +1 -0
  73. package/dest/l1_tx_utils/types.js +26 -0
  74. package/dest/l1_tx_utils/utils.d.ts +4 -0
  75. package/dest/l1_tx_utils/utils.d.ts.map +1 -0
  76. package/dest/l1_tx_utils/utils.js +14 -0
  77. package/dest/publisher_manager.d.ts +7 -2
  78. package/dest/publisher_manager.d.ts.map +1 -1
  79. package/dest/publisher_manager.js +36 -8
  80. package/dest/queries.d.ts.map +1 -1
  81. package/dest/queries.js +11 -12
  82. package/dest/test/chain_monitor.d.ts +11 -0
  83. package/dest/test/chain_monitor.d.ts.map +1 -1
  84. package/dest/test/chain_monitor.js +81 -12
  85. package/dest/test/delayed_tx_utils.d.ts +2 -2
  86. package/dest/test/delayed_tx_utils.d.ts.map +1 -1
  87. package/dest/test/delayed_tx_utils.js +2 -2
  88. package/dest/test/eth_cheat_codes.d.ts +32 -6
  89. package/dest/test/eth_cheat_codes.d.ts.map +1 -1
  90. package/dest/test/eth_cheat_codes.js +115 -28
  91. package/dest/test/rollup_cheat_codes.d.ts +11 -9
  92. package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
  93. package/dest/test/rollup_cheat_codes.js +38 -6
  94. package/dest/test/upgrade_utils.d.ts.map +1 -1
  95. package/dest/test/upgrade_utils.js +3 -2
  96. package/dest/utils.d.ts.map +1 -1
  97. package/dest/utils.js +10 -161
  98. package/dest/zkPassportVerifierAddress.js +1 -1
  99. package/package.json +7 -7
  100. package/src/client.ts +1 -1
  101. package/src/config.ts +136 -68
  102. package/src/contracts/empire_base.ts +1 -1
  103. package/src/contracts/empire_slashing_proposer.ts +7 -3
  104. package/src/contracts/fee_asset_handler.ts +1 -1
  105. package/src/contracts/governance.ts +3 -3
  106. package/src/contracts/governance_proposer.ts +3 -4
  107. package/src/contracts/multicall.ts +12 -10
  108. package/src/contracts/rollup.ts +104 -106
  109. package/src/contracts/slasher_contract.ts +22 -0
  110. package/src/contracts/tally_slashing_proposer.ts +54 -6
  111. package/src/deploy_l1_contracts.ts +570 -328
  112. package/src/index.ts +1 -1
  113. package/src/l1_artifacts.ts +14 -6
  114. package/src/l1_contract_addresses.ts +17 -26
  115. package/src/l1_reader.ts +9 -9
  116. package/src/l1_tx_utils/README.md +177 -0
  117. package/src/l1_tx_utils/config.ts +140 -0
  118. package/src/l1_tx_utils/constants.ts +18 -0
  119. package/src/l1_tx_utils/factory.ts +64 -0
  120. package/src/l1_tx_utils/index.ts +12 -0
  121. package/src/l1_tx_utils/interfaces.ts +86 -0
  122. package/src/l1_tx_utils/l1_tx_utils.ts +718 -0
  123. package/src/l1_tx_utils/l1_tx_utils_with_blobs.ts +77 -0
  124. package/src/l1_tx_utils/readonly_l1_tx_utils.ts +372 -0
  125. package/src/l1_tx_utils/signer.ts +28 -0
  126. package/src/l1_tx_utils/types.ts +85 -0
  127. package/src/l1_tx_utils/utils.ts +16 -0
  128. package/src/publisher_manager.ts +51 -9
  129. package/src/queries.ts +13 -8
  130. package/src/test/chain_monitor.ts +89 -9
  131. package/src/test/delayed_tx_utils.ts +2 -2
  132. package/src/test/eth_cheat_codes.ts +142 -29
  133. package/src/test/rollup_cheat_codes.ts +54 -14
  134. package/src/test/upgrade_utils.ts +3 -2
  135. package/src/utils.ts +13 -185
  136. package/src/zkPassportVerifierAddress.ts +1 -1
  137. package/dest/l1_tx_utils.d.ts +0 -250
  138. package/dest/l1_tx_utils.d.ts.map +0 -1
  139. package/dest/l1_tx_utils.js +0 -826
  140. package/dest/l1_tx_utils_with_blobs.d.ts +0 -19
  141. package/dest/l1_tx_utils_with_blobs.d.ts.map +0 -1
  142. package/dest/l1_tx_utils_with_blobs.js +0 -85
  143. package/src/l1_tx_utils.ts +0 -1105
  144. package/src/l1_tx_utils_with_blobs.ts +0 -144
@@ -2,27 +2,34 @@ import { toBigIntBE, toHex } from '@aztec/foundation/bigint-buffer';
2
2
  import { keccak256 } from '@aztec/foundation/crypto';
3
3
  import { jsonStringify } from '@aztec/foundation/json-rpc';
4
4
  import { createLogger } from '@aztec/foundation/log';
5
- import { createPublicClient, fallback, http } from 'viem';
5
+ import { pluralize } from '@aztec/foundation/string';
6
+ import { createPublicClient, fallback, hexToNumber, http } from 'viem';
6
7
  /**
7
8
  * A class that provides utility functions for interacting with ethereum (L1).
8
9
  */ export class EthCheatCodes {
9
10
  rpcUrls;
11
+ dateProvider;
10
12
  logger;
11
13
  publicClient;
12
14
  constructor(/**
13
15
  * The RPC URL to use for interacting with the chain
14
16
  */ rpcUrls, /**
17
+ * The date provider to use for time operations
18
+ */ dateProvider, /**
15
19
  * The logger to use for the eth cheatcodes
16
20
  */ logger = createLogger('ethereum:cheat_codes')){
17
21
  this.rpcUrls = rpcUrls;
22
+ this.dateProvider = dateProvider;
18
23
  this.logger = logger;
19
24
  this.publicClient = createPublicClient({
20
25
  transport: fallback(this.rpcUrls.map((url)=>http(url)))
21
26
  });
22
27
  }
23
- async rpcCall(method, params) {
24
- const paramsString = jsonStringify(params);
25
- this.logger.debug(`Calling ${method} with params: ${paramsString} on ${this.rpcUrls.join(', ')}`);
28
+ rpcCall(method, params) {
29
+ this.logger.debug(`Calling ${method} with params: ${jsonStringify(params)} on ${this.rpcUrls.join(', ')}`);
30
+ return this.doRpcCall(method, params);
31
+ }
32
+ async doRpcCall(method, params) {
26
33
  return await this.publicClient.transport.request({
27
34
  method,
28
35
  params
@@ -33,7 +40,7 @@ import { createPublicClient, fallback, http } from 'viem';
33
40
  * @returns True if automine is on, false otherwise
34
41
  */ async isAutoMining() {
35
42
  try {
36
- const res = await this.rpcCall('anvil_getAutomine', []);
43
+ const res = await this.doRpcCall('anvil_getAutomine', []);
37
44
  return res;
38
45
  } catch (err) {
39
46
  this.logger.error(`Calling "anvil_getAutomine" failed with:`, err);
@@ -44,21 +51,21 @@ import { createPublicClient, fallback, http } from 'viem';
44
51
  * Get the current blocknumber
45
52
  * @returns The current block number
46
53
  */ async blockNumber() {
47
- const res = await this.rpcCall('eth_blockNumber', []);
54
+ const res = await this.doRpcCall('eth_blockNumber', []);
48
55
  return parseInt(res, 16);
49
56
  }
50
57
  /**
51
58
  * Get the current chainId
52
59
  * @returns The current chainId
53
60
  */ async chainId() {
54
- const res = await this.rpcCall('eth_chainId', []);
61
+ const res = await this.doRpcCall('eth_chainId', []);
55
62
  return parseInt(res, 16);
56
63
  }
57
64
  /**
58
65
  * Get the current timestamp
59
66
  * @returns The current timestamp
60
67
  */ async timestamp() {
61
- const res = await this.rpcCall('eth_getBlockByNumber', [
68
+ const res = await this.doRpcCall('eth_getBlockByNumber', [
62
69
  'latest',
63
70
  true
64
71
  ]);
@@ -73,7 +80,7 @@ import { createPublicClient, fallback, http } from 'viem';
73
80
  }
74
81
  async doMine(numberOfBlocks = 1) {
75
82
  try {
76
- await this.rpcCall('hardhat_mine', [
83
+ await this.doRpcCall('hardhat_mine', [
77
84
  numberOfBlocks
78
85
  ]);
79
86
  } catch (err) {
@@ -84,7 +91,8 @@ import { createPublicClient, fallback, http } from 'viem';
84
91
  * Mines a single block with evm_mine
85
92
  */ async evmMine() {
86
93
  try {
87
- await this.rpcCall('evm_mine', []);
94
+ await this.doRpcCall('evm_mine', []);
95
+ this.logger.warn(`Mined 1 L1 block with evm_mine`);
88
96
  } catch (err) {
89
97
  throw new Error(`Error mining: ${err}`);
90
98
  }
@@ -105,7 +113,7 @@ import { createPublicClient, fallback, http } from 'viem';
105
113
  this.logger.warn(`Set balance for ${account} to ${balance}`);
106
114
  }
107
115
  async getBalance(account) {
108
- const res = await this.rpcCall('eth_getBalance', [
116
+ const res = await this.doRpcCall('eth_getBalance', [
109
117
  account.toString(),
110
118
  'latest'
111
119
  ]);
@@ -142,7 +150,7 @@ import { createPublicClient, fallback, http } from 'viem';
142
150
  * @param seconds - The interval to use between blocks
143
151
  */ getIntervalMining() {
144
152
  try {
145
- return this.rpcCall('anvil_getIntervalMining', []);
153
+ return this.doRpcCall('anvil_getIntervalMining', []);
146
154
  } catch (err) {
147
155
  throw new Error(`Error getting interval mining: ${err}`);
148
156
  }
@@ -206,7 +214,7 @@ import { createPublicClient, fallback, http } from 'viem';
206
214
  /**
207
215
  * Set the next block timestamp and mines the block.
208
216
  * Optionally resets interval mining so the next block is mined in `blockInterval` seconds from now.
209
- * Optionally updates a provided date provider to follow L1 time.
217
+ * Always updates the injected date provider to follow L1 time.
210
218
  * @param timestamp - The timestamp to set the next block to
211
219
  */ async warp(timestamp, opts = {}) {
212
220
  let blockInterval = null;
@@ -226,8 +234,10 @@ import { createPublicClient, fallback, http } from 'viem';
226
234
  ]);
227
235
  // And mine a block so the timestamp goes into effect now
228
236
  await this.doMine();
229
- // Update the date provider if provided so it follows L1 time
230
- opts.updateDateProvider?.setTime(Number(timestamp) * 1000);
237
+ // Update the injected date provider so it follows L1 time
238
+ if ('setTime' in this.dateProvider) {
239
+ this.dateProvider.setTime(Number(timestamp) * 1000);
240
+ }
231
241
  } catch (err) {
232
242
  throw new Error(`Error warping: ${err}`);
233
243
  } finally{
@@ -260,7 +270,7 @@ import { createPublicClient, fallback, http } from 'viem';
260
270
  * @param contract - The contract address
261
271
  * @param slot - The storage slot
262
272
  * @param value - The value to set the storage slot to
263
- */ async store(contract, slot, value) {
273
+ */ async store(contract, slot, value, opts = {}) {
264
274
  // for the rpc call, we need to change value to be a 32 byte hex string.
265
275
  try {
266
276
  await this.rpcCall('hardhat_setStorageAt', [
@@ -271,7 +281,9 @@ import { createPublicClient, fallback, http } from 'viem';
271
281
  } catch (err) {
272
282
  throw new Error(`Error setting storage for contract ${contract} at ${slot}: ${err}`);
273
283
  }
274
- this.logger.warn(`Set L1 storage for contract ${contract} at ${slot} to ${value}`);
284
+ if (!opts.silent) {
285
+ this.logger.warn(`Set L1 storage for contract ${contract} at ${slot} to ${value}`);
286
+ }
275
287
  }
276
288
  /**
277
289
  * Computes the slot value for a given map and key.
@@ -333,31 +345,28 @@ import { createPublicClient, fallback, http } from 'viem';
333
345
  * @param contract - The contract address
334
346
  * @returns The bytecode for the contract
335
347
  */ async getBytecode(contract) {
336
- const res = await this.rpcCall('eth_getCode', [
348
+ return await this.doRpcCall('eth_getCode', [
337
349
  contract.toString(),
338
350
  'latest'
339
351
  ]);
340
- return res;
341
352
  }
342
353
  /**
343
354
  * Get the raw transaction object for a given transaction hash
344
355
  * @param txHash - The transaction hash
345
356
  * @returns The raw transaction
346
357
  */ async getRawTransaction(txHash) {
347
- const res = await this.rpcCall('debug_getRawTransaction', [
358
+ return await this.doRpcCall('debug_getRawTransaction', [
348
359
  txHash
349
360
  ]);
350
- return res;
351
361
  }
352
362
  /**
353
363
  * Get the trace for a given transaction hash
354
364
  * @param txHash - The transaction hash
355
365
  * @returns The trace
356
366
  */ async debugTraceTransaction(txHash) {
357
- const res = await this.rpcCall('debug_traceTransaction', [
367
+ return await this.doRpcCall('debug_traceTransaction', [
358
368
  txHash
359
369
  ]);
360
- return res;
361
370
  }
362
371
  /**
363
372
  * Triggers a reorg of the given depth, removing those blocks from the chain.
@@ -373,9 +382,6 @@ import { createPublicClient, fallback, http } from 'viem';
373
382
  * Causes Anvil to reorg until the given block number is the new tip
374
383
  * @param blockNumber - The block number that's going to be the new tip
375
384
  */ reorgTo(blockNumber) {
376
- this.logger.info('reorgTo', {
377
- blockNumber
378
- });
379
385
  if (blockNumber <= 0) {
380
386
  throw new Error(`Can't reorg to block before genesis: ${blockNumber}`);
381
387
  }
@@ -389,6 +395,7 @@ import { createPublicClient, fallback, http } from 'viem';
389
395
  await this.rpcCall('anvil_rollback', [
390
396
  depth
391
397
  ]);
398
+ this.logger.warn(`Reorged L1 chain to block number ${blockNumber} (depth ${depth})`);
392
399
  });
393
400
  }
394
401
  /**
@@ -418,10 +425,68 @@ import { createPublicClient, fallback, http } from 'viem';
418
425
  });
419
426
  }
420
427
  traceTransaction(txHash) {
421
- return this.rpcCall('trace_transaction', [
428
+ return this.doRpcCall('trace_transaction', [
422
429
  txHash
423
430
  ]);
424
431
  }
432
+ async getTxPoolStatus() {
433
+ const { pending, queued } = await this.doRpcCall('txpool_status', []);
434
+ return {
435
+ pending: hexToNumber(pending),
436
+ queued: hexToNumber(queued)
437
+ };
438
+ }
439
+ async getTxPoolContents() {
440
+ const txpoolContent = await this.doRpcCall('txpool_content', []);
441
+ return mapTxPoolContent(txpoolContent);
442
+ }
443
+ /**
444
+ * Mines an empty block by temporarily removing all pending transactions from the mempool,
445
+ * mining a block, and then re-adding the transactions back to the pool.
446
+ */ async mineEmptyBlock(blockCount = 1) {
447
+ await this.execWithPausedAnvil(async ()=>{
448
+ // Get all pending and queued transactions from the pool
449
+ const txs = await this.getTxPoolContents();
450
+ this.logger.debug(`Found ${txs.length} transactions in pool`);
451
+ // Get raw transactions before dropping them
452
+ const rawTxs = [];
453
+ for (const tx of txs){
454
+ try {
455
+ const rawTx = await this.doRpcCall('debug_getRawTransaction', [
456
+ tx.hash
457
+ ]);
458
+ if (rawTx) {
459
+ rawTxs.push(rawTx);
460
+ this.logger.debug(`Got raw tx for ${tx.hash}`);
461
+ } else {
462
+ this.logger.warn(`No raw tx found for ${tx.hash}`);
463
+ }
464
+ } catch {
465
+ this.logger.warn(`Failed to get raw transaction for ${tx.hash}`);
466
+ }
467
+ }
468
+ this.logger.debug(`Retrieved ${rawTxs.length} raw transactions`);
469
+ // Drop all transactions from the mempool
470
+ await this.doRpcCall('anvil_dropAllTransactions', []);
471
+ // Mine an empty block
472
+ await this.doMine(blockCount);
473
+ // Re-add the transactions to the pool
474
+ for (const rawTx of rawTxs){
475
+ try {
476
+ const txHash = await this.doRpcCall('eth_sendRawTransaction', [
477
+ rawTx
478
+ ]);
479
+ this.logger.debug(`Re-added transaction ${txHash}`);
480
+ } catch (err) {
481
+ this.logger.warn(`Failed to re-add transaction: ${err}`);
482
+ }
483
+ }
484
+ if (rawTxs.length !== txs.length) {
485
+ this.logger.warn(`Failed to add all txs back: had ${txs.length} but re-added ${rawTxs.length}`);
486
+ }
487
+ });
488
+ this.logger.warn(`Mined ${blockCount} empty L1 ${pluralize('block', blockCount)}`);
489
+ }
425
490
  async execWithPausedAnvil(fn) {
426
491
  const [blockInterval, wasAutoMining] = await Promise.all([
427
492
  this.getIntervalMining(),
@@ -438,7 +503,7 @@ import { createPublicClient, fallback, http } from 'viem';
438
503
  silent: true
439
504
  });
440
505
  }
441
- await fn();
506
+ return await fn();
442
507
  } finally{
443
508
  try {
444
509
  // restore automine if necessary
@@ -462,4 +527,26 @@ import { createPublicClient, fallback, http } from 'viem';
462
527
  }
463
528
  }
464
529
  }
530
+ async syncDateProvider() {
531
+ const timestamp = await this.timestamp();
532
+ if ('setTime' in this.dateProvider) {
533
+ this.dateProvider.setTime(timestamp * 1000);
534
+ }
535
+ }
536
+ }
537
+ function mapTxPoolContent(content) {
538
+ const result = [];
539
+ const processPool = (pool, poolState)=>{
540
+ for (const txsByNonce of Object.values(pool)){
541
+ for (const tx of Object.values(txsByNonce)){
542
+ result.push({
543
+ ...tx,
544
+ poolState
545
+ });
546
+ }
547
+ }
548
+ };
549
+ processPool(content.pending, 'pending');
550
+ processPool(content.queued, 'queued');
551
+ return result;
465
552
  }
@@ -1,6 +1,6 @@
1
1
  import { type ViemPublicClient } from '@aztec/ethereum';
2
2
  import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
3
- import type { TestDateProvider } from '@aztec/foundation/timer';
3
+ import type { DateProvider } from '@aztec/foundation/timer';
4
4
  import { RollupAbi } from '@aztec/l1-artifacts/RollupAbi';
5
5
  import { type GetContractReturnType, type Hex } from 'viem';
6
6
  import { EthCheatCodes } from './eth_cheat_codes.js';
@@ -11,7 +11,7 @@ export declare class RollupCheatCodes {
11
11
  private rollup;
12
12
  private logger;
13
13
  constructor(ethCheatCodes: EthCheatCodes, addresses: Pick<L1ContractAddresses, 'rollupAddress'>);
14
- static create(rpcUrls: string[], addresses: Pick<L1ContractAddresses, 'rollupAddress'>): RollupCheatCodes;
14
+ static create(rpcUrls: string[], addresses: Pick<L1ContractAddresses, 'rollupAddress'>, dateProvider: DateProvider): RollupCheatCodes;
15
15
  /** Returns the current slot */
16
16
  getSlot(): Promise<bigint>;
17
17
  /** Returns the current epoch */
@@ -38,15 +38,12 @@ export declare class RollupCheatCodes {
38
38
  * @param epoch - The epoch to advance to
39
39
  * @param opts - Options
40
40
  */
41
- advanceToEpoch(epoch: bigint, opts?: {
42
- /** Optional test date provider to update with the epoch timestamp */
43
- updateDateProvider?: TestDateProvider;
41
+ advanceToEpoch(epoch: bigint | number, opts?: {
42
+ /** Offset in seconds */
43
+ offset?: number;
44
44
  }): Promise<bigint>;
45
45
  /** Warps time in L1 until the next epoch */
46
- advanceToNextEpoch(opts?: {
47
- /** Optional test date provider to update with the epoch timestamp */
48
- updateDateProvider?: TestDateProvider;
49
- }): Promise<void>;
46
+ advanceToNextEpoch(): Promise<void>;
50
47
  /** Warps time in L1 until the beginning of the next slot. */
51
48
  advanceToNextSlot(): Promise<bigint[]>;
52
49
  /**
@@ -59,6 +56,11 @@ export declare class RollupCheatCodes {
59
56
  * @param maybeBlockNumber - The block number to mark as proven (defaults to latest pending)
60
57
  */
61
58
  markAsProven(maybeBlockNumber?: number | bigint): Promise<void>;
59
+ /**
60
+ * Overrides the inProgress field of the Inbox contract state
61
+ * @param howMuch - How many blocks to move it forward
62
+ */
63
+ advanceInboxInProgress(howMuch: number | bigint): Promise<bigint>;
62
64
  /**
63
65
  * Executes an action impersonated as the owner of the Rollup contract.
64
66
  * @param action - The action to execute
@@ -1 +1 @@
1
- {"version":3,"file":"rollup_cheat_codes.d.ts","sourceRoot":"","sources":["../../src/test/rollup_cheat_codes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAGjF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE1D,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,GAAG,EAMT,MAAM,MAAM,CAAC;AAGd,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,8CAA8C;AAC9C,qBAAa,gBAAgB;IAOzB,OAAO,CAAC,aAAa;IANvB,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,MAAM,CAA4D;IAE1E,OAAO,CAAC,MAAM,CAAuC;gBAG3C,aAAa,EAAE,aAAa,EACpC,SAAS,EAAE,IAAI,CAAC,mBAAmB,EAAE,eAAe,CAAC;IAavD,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,mBAAmB,EAAE,eAAe,CAAC,GAAG,gBAAgB;IAKzG,+BAA+B;IAClB,OAAO;IAKpB,gCAAgC;IACnB,QAAQ;IAKrB;;;OAGG;IACU,OAAO,IAAI,OAAO,CAAC;QAC9B,4BAA4B,CAAC,OAAO,EAAE,MAAM,CAAC;QAC7C,2BAA2B,CAAC,MAAM,EAAE,MAAM,CAAC;KAC5C,CAAC;IAQF;;OAEG;IACU,WAAW;IAmBxB,0EAA0E;IAC7D,SAAS,IAAI,OAAO,CAAC;QAChC,qBAAqB,CAAC,aAAa,EAAE,MAAM,CAAC;QAC5C,oBAAoB,CAAC,YAAY,EAAE,MAAM,CAAC;KAC3C,CAAC;IAQF;;;;OAIG;IACU,cAAc,CACzB,KAAK,EAAE,MAAM,EACb,IAAI,GAAE;QACJ,qEAAqE;QACrE,kBAAkB,CAAC,EAAE,gBAAgB,CAAC;KAClC;IAaR,4CAA4C;IAC/B,kBAAkB,CAC7B,IAAI,GAAE;QACJ,qEAAqE;QACrE,kBAAkB,CAAC,EAAE,gBAAgB,CAAC;KAClC;IAeR,6DAA6D;IAChD,iBAAiB;IAQ9B;;;OAGG;IACU,YAAY,CAAC,OAAO,EAAE,MAAM;IASzC;;;OAGG;IACI,YAAY,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM;IAiCtD;;;OAGG;IACU,OAAO,CAClB,MAAM,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,qBAAqB,CAAC,OAAO,SAAS,EAAE,gBAAgB,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC;IAQ1G;;OAEG;IACU,UAAU;IASvB,4CAA4C;IAC/B,oBAAoB;IAQjC;;;OAGG;IACU,sBAAsB,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM;IAMtE;;;OAGG;IACU,qBAAqB,CAAC,QAAQ,EAAE,MAAM;CAWpD"}
1
+ {"version":3,"file":"rollup_cheat_codes.d.ts","sourceRoot":"","sources":["../../src/test/rollup_cheat_codes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAGjF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE1D,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,GAAG,EAMT,MAAM,MAAM,CAAC;AAGd,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,8CAA8C;AAC9C,qBAAa,gBAAgB;IAOzB,OAAO,CAAC,aAAa;IANvB,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,MAAM,CAA4D;IAE1E,OAAO,CAAC,MAAM,CAAuC;gBAG3C,aAAa,EAAE,aAAa,EACpC,SAAS,EAAE,IAAI,CAAC,mBAAmB,EAAE,eAAe,CAAC;IAavD,MAAM,CAAC,MAAM,CACX,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,EAAE,IAAI,CAAC,mBAAmB,EAAE,eAAe,CAAC,EACrD,YAAY,EAAE,YAAY,GACzB,gBAAgB;IAKnB,+BAA+B;IAClB,OAAO;IAKpB,gCAAgC;IACnB,QAAQ;IAKrB;;;OAGG;IACU,OAAO,IAAI,OAAO,CAAC;QAC9B,4BAA4B,CAAC,OAAO,EAAE,MAAM,CAAC;QAC7C,2BAA2B,CAAC,MAAM,EAAE,MAAM,CAAC;KAC5C,CAAC;IAQF;;OAEG;IACU,WAAW;IAmBxB,0EAA0E;IAC7D,SAAS,IAAI,OAAO,CAAC;QAChC,qBAAqB,CAAC,aAAa,EAAE,MAAM,CAAC;QAC5C,oBAAoB,CAAC,YAAY,EAAE,MAAM,CAAC;KAC3C,CAAC;IAQF;;;;OAIG;IACU,cAAc,CACzB,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,IAAI,GAAE;QACJ,wBAAwB;QACxB,MAAM,CAAC,EAAE,MAAM,CAAC;KACZ;IAcR,4CAA4C;IAC/B,kBAAkB;IAa/B,6DAA6D;IAChD,iBAAiB;IAQ9B;;;OAGG;IACU,YAAY,CAAC,OAAO,EAAE,MAAM;IASzC;;;OAGG;IACI,YAAY,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM;IAiCtD;;;OAGG;IACI,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAqCxE;;;OAGG;IACU,OAAO,CAClB,MAAM,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,qBAAqB,CAAC,OAAO,SAAS,EAAE,gBAAgB,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC;IAQ1G;;OAEG;IACU,UAAU;IASvB,4CAA4C;IAC/B,oBAAoB;IAQjC;;;OAGG;IACU,sBAAsB,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM;IAMtE;;;OAGG;IACU,qBAAqB,CAAC,QAAQ,EAAE,MAAM;CAWpD"}
@@ -23,8 +23,8 @@ import { EthCheatCodes } from './eth_cheat_codes.js';
23
23
  client: this.client
24
24
  });
25
25
  }
26
- static create(rpcUrls, addresses) {
27
- const ethCheatCodes = new EthCheatCodes(rpcUrls);
26
+ static create(rpcUrls, addresses, dateProvider) {
27
+ const ethCheatCodes = new EthCheatCodes(rpcUrls, dateProvider);
28
28
  return new RollupCheatCodes(ethCheatCodes, addresses);
29
29
  }
30
30
  /** Returns the current slot */ async getSlot() {
@@ -85,8 +85,8 @@ import { EthCheatCodes } from './eth_cheat_codes.js';
85
85
  */ async advanceToEpoch(epoch, opts = {}) {
86
86
  const { epochDuration: slotsInEpoch } = await this.getConfig();
87
87
  const timestamp = await this.rollup.read.getTimestampForSlot([
88
- epoch * slotsInEpoch
89
- ]);
88
+ BigInt(epoch) * slotsInEpoch
89
+ ]) + BigInt(opts.offset ?? 0);
90
90
  try {
91
91
  await this.ethCheatCodes.warp(Number(timestamp), {
92
92
  ...opts,
@@ -99,14 +99,13 @@ import { EthCheatCodes } from './eth_cheat_codes.js';
99
99
  }
100
100
  return timestamp;
101
101
  }
102
- /** Warps time in L1 until the next epoch */ async advanceToNextEpoch(opts = {}) {
102
+ /** Warps time in L1 until the next epoch */ async advanceToNextEpoch() {
103
103
  const slot = await this.getSlot();
104
104
  const { epochDuration, slotDuration } = await this.getConfig();
105
105
  const slotsUntilNextEpoch = epochDuration - slot % epochDuration + 1n;
106
106
  const timeToNextEpoch = slotsUntilNextEpoch * slotDuration;
107
107
  const l1Timestamp = BigInt((await this.client.getBlock()).timestamp);
108
108
  await this.ethCheatCodes.warp(Number(l1Timestamp + timeToNextEpoch), {
109
- ...opts,
110
109
  silent: true,
111
110
  resetBlockInterval: true
112
111
  });
@@ -173,6 +172,39 @@ import { EthCheatCodes } from './eth_cheat_codes.js';
173
172
  });
174
173
  }
175
174
  /**
175
+ * Overrides the inProgress field of the Inbox contract state
176
+ * @param howMuch - How many blocks to move it forward
177
+ */ advanceInboxInProgress(howMuch) {
178
+ return this.ethCheatCodes.execWithPausedAnvil(async ()=>{
179
+ // Storage slot 2 contains the InboxState struct
180
+ const inboxStateSlot = 2n;
181
+ // Get inbox and its current state values
182
+ const inboxAddress = await this.rollup.read.getInbox();
183
+ const currentStateValue = await this.ethCheatCodes.load(EthAddress.fromString(inboxAddress), inboxStateSlot);
184
+ // Extract current values from the packed storage slot
185
+ // Storage layout: rollingHash (128 bits) | totalMessagesInserted (64 bits) | inProgress (64 bits)
186
+ const currentRollingHash = currentStateValue & (1n << 128n) - 1n;
187
+ const currentTotalMessages = currentStateValue >> 128n & (1n << 64n) - 1n;
188
+ const currentInProgress = currentStateValue >> 192n;
189
+ const newInProgress = currentInProgress + BigInt(howMuch);
190
+ // Pack new values: rollingHash (low 128 bits) | totalMessages (middle 64 bits) | inProgress (high 64 bits)
191
+ const newValue = BigInt(newInProgress) << 192n | currentTotalMessages << 128n | currentRollingHash;
192
+ await this.ethCheatCodes.store(EthAddress.fromString(inboxAddress), inboxStateSlot, newValue, {
193
+ silent: true
194
+ });
195
+ this.logger.warn(`Inbox inProgress advanced from ${currentInProgress} to ${newInProgress}`, {
196
+ inbox: inboxAddress,
197
+ oldValue: '0x' + currentStateValue.toString(16),
198
+ newValue: '0x' + newValue.toString(16),
199
+ rollingHash: currentRollingHash,
200
+ totalMessages: currentTotalMessages,
201
+ oldInProgress: currentInProgress,
202
+ newInProgress
203
+ });
204
+ return newInProgress;
205
+ });
206
+ }
207
+ /**
176
208
  * Executes an action impersonated as the owner of the Rollup contract.
177
209
  * @param action - The action to execute
178
210
  */ async asOwner(action) {
@@ -1 +1 @@
1
- {"version":3,"file":"upgrade_utils.d.ts","sourceRoot":"","sources":["../../src/test/upgrade_utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAGlE,OAAO,EAAE,KAAK,qBAAqB,EAAE,KAAK,iBAAiB,EAAe,MAAM,MAAM,CAAC;AAGvF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAEvE,OAAO,KAAK,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG9E,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,qBAAqB,CAAC,OAAO,aAAa,EAAE,gBAAgB,CAAC,EACzE,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,iBAAiB,EAC7B,QAAQ,EAAE,wBAAwB,EAClC,OAAO,EAAE,MAAM,EAAE,EACjB,MAAM,EAAE,MAAM,iBAmCf;AAED,wBAAsB,wBAAwB,CAC5C,cAAc,EAAE,KAAK,MAAM,EAAE,EAC7B,SAAS,EAAE,mBAAmB,EAC9B,UAAU,EAAE,iBAAiB,EAC7B,YAAY,EAAE,gBAAgB,EAC9B,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IACT,UAAU,EAAE,qBAAqB,CAAC,OAAO,aAAa,EAAE,gBAAgB,CAAC,CAAC;IAC1E,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC,CAyCD"}
1
+ {"version":3,"file":"upgrade_utils.d.ts","sourceRoot":"","sources":["../../src/test/upgrade_utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAEpD,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAGlE,OAAO,EAAE,KAAK,qBAAqB,EAAE,KAAK,iBAAiB,EAAe,MAAM,MAAM,CAAC;AAGvF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAEvE,OAAO,KAAK,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG9E,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,qBAAqB,CAAC,OAAO,aAAa,EAAE,gBAAgB,CAAC,EACzE,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,iBAAiB,EAC7B,QAAQ,EAAE,wBAAwB,EAClC,OAAO,EAAE,MAAM,EAAE,EACjB,MAAM,EAAE,MAAM,iBAmCf;AAED,wBAAsB,wBAAwB,CAC5C,cAAc,EAAE,KAAK,MAAM,EAAE,EAC7B,SAAS,EAAE,mBAAmB,EAC9B,UAAU,EAAE,iBAAiB,EAC7B,YAAY,EAAE,gBAAgB,EAC9B,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IACT,UAAU,EAAE,qBAAqB,CAAC,OAAO,aAAa,EAAE,gBAAgB,CAAC,CAAC;IAC1E,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC,CAyCD"}
@@ -1,8 +1,9 @@
1
+ import { DateProvider } from '@aztec/foundation/timer';
1
2
  import { GovernanceAbi } from '@aztec/l1-artifacts/GovernanceAbi';
2
3
  import { TestERC20Abi as StakingAssetAbi } from '@aztec/l1-artifacts/TestERC20Abi';
3
4
  import { getContract } from 'viem';
4
5
  import { extractProposalIdFromLogs } from '../contracts/governance.js';
5
- import { createL1TxUtilsFromViemWallet } from '../l1_tx_utils.js';
6
+ import { createL1TxUtilsFromViemWallet } from '../l1_tx_utils/index.js';
6
7
  import { EthCheatCodes } from './eth_cheat_codes.js';
7
8
  export async function executeGovernanceProposal(proposalId, governance, voteAmount, privateKey, l1Client, rpcUrls, logger) {
8
9
  const proposal = await governance.read.getProposal([
@@ -15,7 +16,7 @@ export async function executeGovernanceProposal(proposalId, governance, voteAmou
15
16
  value: 1n
16
17
  });
17
18
  };
18
- const cheatCodes = new EthCheatCodes(rpcUrls, logger);
19
+ const cheatCodes = new EthCheatCodes(rpcUrls, new DateProvider(), logger);
19
20
  const timeToActive = proposal.creation + proposal.config.votingDelay;
20
21
  logger.info(`Warping to ${timeToActive + 1n}`);
21
22
  await cheatCodes.warp(Number(timeToActive + 1n));
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAGpD,OAAO,EACL,KAAK,GAAG,EAER,KAAK,iBAAiB,EAEtB,KAAK,wBAAwB,EAC7B,KAAK,GAAG,EACR,KAAK,GAAG,EAGT,MAAM,MAAM,CAAC;AAEd,MAAM,WAAW,OAAO;IACtB,WAAW,EAAE,EAAE,CAAC;IAChB,WAAW,EAAE,EAAE,CAAC;IAChB,WAAW,EAAE,GAAG,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,CAAC,EAAE,GAAG,EAAE,CAAC;gBAET,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,GAAG,EAAE;CAKlD;AAED,wBAAgB,YAAY,CAC1B,KAAK,CAAC,IAAI,SAAS,GAAG,GAAG,SAAS,OAAO,EAAE,EAC3C,UAAU,SAAS,iBAAiB,CAAC,IAAI,CAAC,EAC1C,UAAU,GAAG,wBAAwB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,EAE/E,IAAI,EAAE,GAAG,EAAE,EACX,OAAO,EAAE,GAAG,EACZ,GAAG,EAAE,IAAI,EACT,SAAS,EAAE,UAAU,EACrB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,EACrC,MAAM,CAAC,EAAE,MAAM,GACd,UAAU,CAMZ;AAED,wBAAgB,eAAe,CAC7B,KAAK,CAAC,IAAI,SAAS,GAAG,GAAG,SAAS,OAAO,EAAE,EAC3C,UAAU,SAAS,iBAAiB,CAAC,IAAI,CAAC,EAC1C,UAAU,GAAG,wBAAwB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,EAE/E,IAAI,EAAE,GAAG,EAAE,EACX,OAAO,EAAE,GAAG,EACZ,GAAG,EAAE,IAAI,EACT,SAAS,EAAE,UAAU,EACrB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,EACrC,MAAM,CAAC,EAAE,MAAM,GACd,UAAU,GAAG,SAAS,CAgBxB;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,GAAG,OAW7C;AA0BD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,GAAE,GAAe,GAAG,kBAAkB,CA8FpF;AA+KD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,GAAG,sBAa7C"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAGpD,OAAO,EACL,KAAK,GAAG,EAER,KAAK,iBAAiB,EAEtB,KAAK,wBAAwB,EAC7B,KAAK,GAAG,EACR,KAAK,GAAG,EAGT,MAAM,MAAM,CAAC;AAEd,MAAM,WAAW,OAAO;IACtB,WAAW,EAAE,EAAE,CAAC;IAChB,WAAW,EAAE,EAAE,CAAC;IAChB,WAAW,EAAE,GAAG,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,CAAC,EAAE,GAAG,EAAE,CAAC;gBAET,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,GAAG,EAAE;CAKlD;AAED,wBAAgB,YAAY,CAC1B,KAAK,CAAC,IAAI,SAAS,GAAG,GAAG,SAAS,OAAO,EAAE,EAC3C,UAAU,SAAS,iBAAiB,CAAC,IAAI,CAAC,EAC1C,UAAU,GAAG,wBAAwB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,EAE/E,IAAI,EAAE,GAAG,EAAE,EACX,OAAO,EAAE,GAAG,EACZ,GAAG,EAAE,IAAI,EACT,SAAS,EAAE,UAAU,EACrB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,EACrC,MAAM,CAAC,EAAE,MAAM,GACd,UAAU,CAMZ;AAED,wBAAgB,eAAe,CAC7B,KAAK,CAAC,IAAI,SAAS,GAAG,GAAG,SAAS,OAAO,EAAE,EAC3C,UAAU,SAAS,iBAAiB,CAAC,IAAI,CAAC,EAC1C,UAAU,GAAG,wBAAwB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,EAE/E,IAAI,EAAE,GAAG,EAAE,EACX,OAAO,EAAE,GAAG,EACZ,GAAG,EAAE,IAAI,EACT,SAAS,EAAE,UAAU,EACrB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,EACrC,MAAM,CAAC,EAAE,MAAM,GACd,UAAU,GAAG,SAAS,CAgBxB;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,GAAG,OAW7C;AA0BD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,GAAE,GAAe,GAAG,kBAAkB,CAwEpF;AAyBD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,GAAG,sBAa7C"}
package/dest/utils.js CHANGED
@@ -118,34 +118,16 @@ function getNestedErrorData(error) {
118
118
  if (error instanceof Error) {
119
119
  return new FormattedViemError(error.message, error?.metaMessages);
120
120
  }
121
- // Extract the actual error message and highlight it for clarity
122
- let formattedRes = extractAndFormatRequestBody(error?.message || String(error));
123
- let errorDetail = '';
124
- // Look for specific details in known locations
125
- if (error) {
126
- // Check for details property which often has the most specific error message
127
- if (typeof error.details === 'string' && error.details) {
128
- errorDetail = error.details;
129
- } else if (typeof error.shortMessage === 'string' && error.shortMessage) {
130
- errorDetail = error.shortMessage;
131
- }
132
- }
133
- // If we found a specific error detail, format it clearly
134
- if (errorDetail) {
135
- // Look for key sections of the formatted result to replace with highlighted error
136
- let replaced = false;
137
- // Try to find the Details: section
138
- const detailsMatch = formattedRes.match(/Details: ([^\n]+)/);
139
- if (detailsMatch) {
140
- formattedRes = formattedRes.replace(detailsMatch[0], `Details: *${errorDetail}*`);
141
- replaced = true;
142
- }
143
- // If we didn't find a Details section, add the error at the beginning
144
- if (!replaced) {
145
- formattedRes = `Error: *${errorDetail}*\n\n${formattedRes}`;
146
- }
147
- }
148
- return new FormattedViemError(formattedRes.replace(/\\n/g, '\n'), error?.metaMessages);
121
+ const body = String(error);
122
+ const length = body.length;
123
+ // LogExplorer can only render up to 2500 characters in it's summary view. Try to keep the whole message below this number
124
+ // Limit the error to 2000 chacaters in order to allow code higher up to decorate this error with extra details (up to 500 characters)
125
+ if (length > 2000) {
126
+ const chunk = 950;
127
+ const truncated = length - 2 * chunk;
128
+ return new FormattedViemError(body.slice(0, chunk) + `...${truncated} characters truncated...` + body.slice(-1 * chunk));
129
+ }
130
+ return new FormattedViemError(body);
149
131
  }
150
132
  function stripAbis(obj) {
151
133
  if (!obj || typeof obj !== 'object') {
@@ -166,139 +148,6 @@ function stripAbis(obj) {
166
148
  }
167
149
  });
168
150
  }
169
- function extractAndFormatRequestBody(message) {
170
- // First check if message is extremely large and contains very large hex strings
171
- if (message.length > 50000) {
172
- message = replaceHexStrings(message, {
173
- minLength: 10000,
174
- truncateLength: 200
175
- });
176
- }
177
- // Add a specific check for RPC calls with large params
178
- if (message.includes('"method":"eth_sendRawTransaction"')) {
179
- message = replaceHexStrings(message, {
180
- pattern: /"params":\s*\[\s*"(0x[a-fA-F0-9]{1000,})"\s*\]/g,
181
- transform: (hex)=>`"params":["${truncateHex(hex, 200)}"]`
182
- });
183
- }
184
- // First handle Request body JSON
185
- const requestBodyRegex = /Request body: ({[\s\S]*?})\n/g;
186
- let result = message.replace(requestBodyRegex, (match, body)=>{
187
- return `Request body: ${formatRequestBody(body)}\n`;
188
- });
189
- // Then handle Arguments section
190
- const argsRegex = /((?:Request |Estimate Gas )?Arguments:[\s\S]*?(?=\n\n|$))/g;
191
- result = result.replace(argsRegex, (section)=>{
192
- const lines = section.split('\n');
193
- const processedLines = lines.map((line)=>{
194
- // Check if line contains a colon followed by content
195
- const colonIndex = line.indexOf(':');
196
- if (colonIndex !== -1) {
197
- const [prefix, content] = [
198
- line.slice(0, colonIndex + 1),
199
- line.slice(colonIndex + 1).trim()
200
- ];
201
- // If content contains a hex string, truncate it
202
- if (content.includes('0x')) {
203
- const processedContent = replaceHexStrings(content);
204
- return `${prefix} ${processedContent}`;
205
- }
206
- }
207
- return line;
208
- });
209
- return processedLines.join('\n');
210
- });
211
- // Finally, catch any remaining hex strings in the message
212
- result = replaceHexStrings(result);
213
- return result;
214
- }
215
- function truncateHex(hex, length = 100) {
216
- if (!hex || typeof hex !== 'string') {
217
- return hex;
218
- }
219
- if (!hex.startsWith('0x')) {
220
- return hex;
221
- }
222
- if (hex.length <= length * 2) {
223
- return hex;
224
- }
225
- // For extremely large hex strings, use more aggressive truncation
226
- if (hex.length > 10000) {
227
- return `${hex.slice(0, length)}...<${hex.length - length * 2} chars omitted>...${hex.slice(-length)}`;
228
- }
229
- return `${hex.slice(0, length)}...${hex.slice(-length)}`;
230
- }
231
- function replaceHexStrings(text, options = {}) {
232
- const { minLength = 10, maxLength = Infinity, truncateLength = 100, pattern, transform = (hex)=>truncateHex(hex, truncateLength) } = options;
233
- const hexRegex = pattern ?? new RegExp(`(0x[a-fA-F0-9]{${minLength},${maxLength}})`, 'g');
234
- return text.replace(hexRegex, (match)=>transform(match));
235
- }
236
- function formatRequestBody(body) {
237
- try {
238
- // Special handling for eth_sendRawTransaction
239
- if (body.includes('"method":"eth_sendRawTransaction"')) {
240
- try {
241
- const parsed = JSON.parse(body);
242
- if (parsed.params && Array.isArray(parsed.params) && parsed.params.length > 0) {
243
- // These are likely large transaction hex strings
244
- parsed.params = parsed.params.map((param)=>{
245
- if (typeof param === 'string' && param.startsWith('0x') && param.length > 1000) {
246
- return truncateHex(param, 200);
247
- }
248
- return param;
249
- });
250
- }
251
- return JSON.stringify(parsed, null, 2);
252
- } catch {
253
- // If specific parsing fails, fall back to regex-based truncation
254
- return replaceHexStrings(body, {
255
- pattern: /"params":\s*\[\s*"(0x[a-fA-F0-9]{1000,})"\s*\]/g,
256
- transform: (hex)=>`"params":["${truncateHex(hex, 200)}"]`
257
- });
258
- }
259
- }
260
- // For extremely large request bodies, use simple truncation instead of parsing
261
- if (body.length > 50000) {
262
- const jsonStart = body.indexOf('{');
263
- const jsonEnd = body.lastIndexOf('}');
264
- if (jsonStart >= 0 && jsonEnd > jsonStart) {
265
- return replaceHexStrings(body, {
266
- minLength: 10000,
267
- truncateLength: 200
268
- });
269
- }
270
- }
271
- const parsed = JSON.parse(body);
272
- // Process the entire request body
273
- const processed = processParams(parsed);
274
- return JSON.stringify(processed, null, 2);
275
- } catch {
276
- // If JSON parsing fails, do a simple truncation of any large hex strings
277
- return replaceHexStrings(body, {
278
- minLength: 1000,
279
- truncateLength: 150
280
- });
281
- }
282
- }
283
- // Recursively process all parameters that might contain hex strings
284
- function processParams(obj) {
285
- if (Array.isArray(obj)) {
286
- return obj.map((item)=>processParams(item));
287
- }
288
- if (typeof obj === 'object' && obj !== null) {
289
- const result = {};
290
- for (const [key, value] of Object.entries(obj)){
291
- result[key] = processParams(value);
292
- }
293
- return result;
294
- }
295
- if (typeof obj === 'string') {
296
- if (obj.startsWith('0x')) {
297
- return truncateHex(obj);
298
- }
299
- }
300
- return obj;
301
- }
302
151
  export function tryGetCustomErrorName(err) {
303
152
  try {
304
153
  // See https://viem.sh/docs/contract/simulateContract#handling-custom-errors