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

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 (195) hide show
  1. package/dest/account.d.ts +1 -1
  2. package/dest/chain.d.ts +1 -1
  3. package/dest/client.d.ts +2 -2
  4. package/dest/client.d.ts.map +1 -1
  5. package/dest/config.d.ts +16 -8
  6. package/dest/config.d.ts.map +1 -1
  7. package/dest/config.js +160 -62
  8. package/dest/constants.d.ts +1 -1
  9. package/dest/contracts/empire_base.d.ts +7 -6
  10. package/dest/contracts/empire_base.d.ts.map +1 -1
  11. package/dest/contracts/empire_base.js +1 -1
  12. package/dest/contracts/empire_slashing_proposer.d.ts +7 -6
  13. package/dest/contracts/empire_slashing_proposer.d.ts.map +1 -1
  14. package/dest/contracts/empire_slashing_proposer.js +9 -3
  15. package/dest/contracts/errors.d.ts +1 -1
  16. package/dest/contracts/errors.d.ts.map +1 -1
  17. package/dest/contracts/fee_asset_handler.d.ts +4 -4
  18. package/dest/contracts/fee_asset_handler.d.ts.map +1 -1
  19. package/dest/contracts/fee_juice.d.ts +1 -1
  20. package/dest/contracts/fee_juice.d.ts.map +1 -1
  21. package/dest/contracts/governance.d.ts +16 -16
  22. package/dest/contracts/governance.d.ts.map +1 -1
  23. package/dest/contracts/governance.js +7 -3
  24. package/dest/contracts/governance_proposer.d.ts +6 -6
  25. package/dest/contracts/governance_proposer.d.ts.map +1 -1
  26. package/dest/contracts/governance_proposer.js +9 -4
  27. package/dest/contracts/gse.d.ts +1 -1
  28. package/dest/contracts/gse.d.ts.map +1 -1
  29. package/dest/contracts/inbox.d.ts +1 -1
  30. package/dest/contracts/inbox.d.ts.map +1 -1
  31. package/dest/contracts/index.d.ts +1 -1
  32. package/dest/contracts/multicall.d.ts +5 -7
  33. package/dest/contracts/multicall.d.ts.map +1 -1
  34. package/dest/contracts/multicall.js +6 -4
  35. package/dest/contracts/registry.d.ts +1 -1
  36. package/dest/contracts/registry.d.ts.map +1 -1
  37. package/dest/contracts/rollup.d.ts +83 -72
  38. package/dest/contracts/rollup.d.ts.map +1 -1
  39. package/dest/contracts/rollup.js +144 -139
  40. package/dest/contracts/slasher_contract.d.ts +11 -1
  41. package/dest/contracts/slasher_contract.d.ts.map +1 -1
  42. package/dest/contracts/slasher_contract.js +18 -0
  43. package/dest/contracts/tally_slashing_proposer.d.ts +30 -9
  44. package/dest/contracts/tally_slashing_proposer.d.ts.map +1 -1
  45. package/dest/contracts/tally_slashing_proposer.js +58 -8
  46. package/dest/contracts/utils.d.ts +1 -1
  47. package/dest/deploy_l1_contracts.d.ts +477 -15
  48. package/dest/deploy_l1_contracts.d.ts.map +1 -1
  49. package/dest/deploy_l1_contracts.js +610 -386
  50. package/dest/eth-signer/eth-signer.d.ts +1 -1
  51. package/dest/eth-signer/index.d.ts +1 -1
  52. package/dest/forwarder_proxy.d.ts +32 -0
  53. package/dest/forwarder_proxy.d.ts.map +1 -0
  54. package/dest/forwarder_proxy.js +93 -0
  55. package/dest/l1_artifacts.d.ts +14258 -6015
  56. package/dest/l1_artifacts.d.ts.map +1 -1
  57. package/dest/l1_artifacts.js +10 -5
  58. package/dest/l1_contract_addresses.d.ts +8 -4
  59. package/dest/l1_contract_addresses.d.ts.map +1 -1
  60. package/dest/l1_contract_addresses.js +16 -26
  61. package/dest/l1_reader.d.ts +4 -2
  62. package/dest/l1_reader.d.ts.map +1 -1
  63. package/dest/l1_reader.js +14 -8
  64. package/dest/l1_tx_utils/config.d.ts +59 -0
  65. package/dest/l1_tx_utils/config.d.ts.map +1 -0
  66. package/dest/l1_tx_utils/config.js +96 -0
  67. package/dest/l1_tx_utils/constants.d.ts +6 -0
  68. package/dest/l1_tx_utils/constants.d.ts.map +1 -0
  69. package/dest/l1_tx_utils/constants.js +14 -0
  70. package/dest/l1_tx_utils/factory.d.ts +24 -0
  71. package/dest/l1_tx_utils/factory.d.ts.map +1 -0
  72. package/dest/l1_tx_utils/factory.js +12 -0
  73. package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts +41 -0
  74. package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts.map +1 -0
  75. package/dest/l1_tx_utils/forwarder_l1_tx_utils.js +48 -0
  76. package/dest/l1_tx_utils/index-blobs.d.ts +3 -0
  77. package/dest/l1_tx_utils/index-blobs.d.ts.map +1 -0
  78. package/dest/l1_tx_utils/index-blobs.js +2 -0
  79. package/dest/l1_tx_utils/index.d.ts +10 -0
  80. package/dest/l1_tx_utils/index.d.ts.map +1 -0
  81. package/dest/l1_tx_utils/index.js +10 -0
  82. package/dest/l1_tx_utils/interfaces.d.ts +76 -0
  83. package/dest/l1_tx_utils/interfaces.d.ts.map +1 -0
  84. package/dest/l1_tx_utils/interfaces.js +4 -0
  85. package/dest/l1_tx_utils/l1_tx_utils.d.ts +94 -0
  86. package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -0
  87. package/dest/l1_tx_utils/l1_tx_utils.js +623 -0
  88. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts +26 -0
  89. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts.map +1 -0
  90. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.js +26 -0
  91. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +94 -0
  92. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -0
  93. package/dest/l1_tx_utils/readonly_l1_tx_utils.js +431 -0
  94. package/dest/l1_tx_utils/signer.d.ts +4 -0
  95. package/dest/l1_tx_utils/signer.d.ts.map +1 -0
  96. package/dest/l1_tx_utils/signer.js +16 -0
  97. package/dest/l1_tx_utils/types.d.ts +67 -0
  98. package/dest/l1_tx_utils/types.d.ts.map +1 -0
  99. package/dest/l1_tx_utils/types.js +26 -0
  100. package/dest/l1_tx_utils/utils.d.ts +4 -0
  101. package/dest/l1_tx_utils/utils.d.ts.map +1 -0
  102. package/dest/l1_tx_utils/utils.js +14 -0
  103. package/dest/l1_types.d.ts +1 -1
  104. package/dest/publisher_manager.d.ts +8 -3
  105. package/dest/publisher_manager.d.ts.map +1 -1
  106. package/dest/publisher_manager.js +36 -8
  107. package/dest/queries.d.ts +1 -1
  108. package/dest/queries.d.ts.map +1 -1
  109. package/dest/queries.js +13 -12
  110. package/dest/test/chain_monitor.d.ts +33 -19
  111. package/dest/test/chain_monitor.d.ts.map +1 -1
  112. package/dest/test/chain_monitor.js +100 -33
  113. package/dest/test/delayed_tx_utils.d.ts +3 -3
  114. package/dest/test/delayed_tx_utils.d.ts.map +1 -1
  115. package/dest/test/delayed_tx_utils.js +2 -2
  116. package/dest/test/eth_cheat_codes.d.ts +36 -14
  117. package/dest/test/eth_cheat_codes.d.ts.map +1 -1
  118. package/dest/test/eth_cheat_codes.js +124 -31
  119. package/dest/test/eth_cheat_codes_with_state.d.ts +1 -1
  120. package/dest/test/eth_cheat_codes_with_state.d.ts.map +1 -1
  121. package/dest/test/index.d.ts +1 -1
  122. package/dest/test/rollup_cheat_codes.d.ts +23 -20
  123. package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
  124. package/dest/test/rollup_cheat_codes.js +79 -42
  125. package/dest/test/start_anvil.d.ts +2 -1
  126. package/dest/test/start_anvil.d.ts.map +1 -1
  127. package/dest/test/start_anvil.js +2 -1
  128. package/dest/test/tx_delayer.d.ts +1 -1
  129. package/dest/test/tx_delayer.d.ts.map +1 -1
  130. package/dest/test/tx_delayer.js +3 -2
  131. package/dest/test/upgrade_utils.d.ts +1 -1
  132. package/dest/test/upgrade_utils.d.ts.map +1 -1
  133. package/dest/test/upgrade_utils.js +3 -2
  134. package/dest/types.d.ts +57 -2
  135. package/dest/types.d.ts.map +1 -1
  136. package/dest/utils.d.ts +2 -2
  137. package/dest/utils.d.ts.map +1 -1
  138. package/dest/utils.js +10 -161
  139. package/dest/zkPassportVerifierAddress.d.ts +1 -1
  140. package/dest/zkPassportVerifierAddress.js +1 -1
  141. package/package.json +27 -13
  142. package/src/client.ts +1 -1
  143. package/src/config.ts +177 -65
  144. package/src/contracts/empire_base.ts +7 -6
  145. package/src/contracts/empire_slashing_proposer.ts +18 -8
  146. package/src/contracts/fee_asset_handler.ts +1 -1
  147. package/src/contracts/governance.ts +3 -3
  148. package/src/contracts/governance_proposer.ts +14 -9
  149. package/src/contracts/multicall.ts +12 -10
  150. package/src/contracts/rollup.ts +170 -171
  151. package/src/contracts/slasher_contract.ts +22 -0
  152. package/src/contracts/tally_slashing_proposer.ts +63 -12
  153. package/src/deploy_l1_contracts.ts +610 -337
  154. package/src/forwarder_proxy.ts +108 -0
  155. package/src/l1_artifacts.ts +14 -6
  156. package/src/l1_contract_addresses.ts +17 -26
  157. package/src/l1_reader.ts +17 -9
  158. package/src/l1_tx_utils/README.md +177 -0
  159. package/src/l1_tx_utils/config.ts +161 -0
  160. package/src/l1_tx_utils/constants.ts +18 -0
  161. package/src/l1_tx_utils/factory.ts +64 -0
  162. package/src/l1_tx_utils/forwarder_l1_tx_utils.ts +119 -0
  163. package/src/l1_tx_utils/index-blobs.ts +2 -0
  164. package/src/l1_tx_utils/index.ts +12 -0
  165. package/src/l1_tx_utils/interfaces.ts +86 -0
  166. package/src/l1_tx_utils/l1_tx_utils.ts +738 -0
  167. package/src/l1_tx_utils/l1_tx_utils_with_blobs.ts +77 -0
  168. package/src/l1_tx_utils/readonly_l1_tx_utils.ts +557 -0
  169. package/src/l1_tx_utils/signer.ts +28 -0
  170. package/src/l1_tx_utils/types.ts +85 -0
  171. package/src/l1_tx_utils/utils.ts +16 -0
  172. package/src/publisher_manager.ts +51 -9
  173. package/src/queries.ts +16 -8
  174. package/src/test/chain_monitor.ts +118 -36
  175. package/src/test/delayed_tx_utils.ts +2 -2
  176. package/src/test/eth_cheat_codes.ts +149 -30
  177. package/src/test/rollup_cheat_codes.ts +94 -52
  178. package/src/test/start_anvil.ts +2 -0
  179. package/src/test/tx_delayer.ts +4 -2
  180. package/src/test/upgrade_utils.ts +3 -2
  181. package/src/types.ts +62 -0
  182. package/src/utils.ts +12 -184
  183. package/src/zkPassportVerifierAddress.ts +1 -1
  184. package/dest/index.d.ts +0 -18
  185. package/dest/index.d.ts.map +0 -1
  186. package/dest/index.js +0 -17
  187. package/dest/l1_tx_utils.d.ts +0 -250
  188. package/dest/l1_tx_utils.d.ts.map +0 -1
  189. package/dest/l1_tx_utils.js +0 -826
  190. package/dest/l1_tx_utils_with_blobs.d.ts +0 -19
  191. package/dest/l1_tx_utils_with_blobs.d.ts.map +0 -1
  192. package/dest/l1_tx_utils_with_blobs.js +0 -85
  193. package/src/index.ts +0 -17
  194. package/src/l1_tx_utils.ts +0 -1105
  195. package/src/l1_tx_utils_with_blobs.ts +0 -144
@@ -1,11 +1,13 @@
1
1
  import { toBigIntBE, toHex } from '@aztec/foundation/bigint-buffer';
2
- import { keccak256 } from '@aztec/foundation/crypto';
2
+ import { keccak256 } from '@aztec/foundation/crypto/keccak';
3
3
  import { EthAddress } from '@aztec/foundation/eth-address';
4
4
  import { jsonStringify } from '@aztec/foundation/json-rpc';
5
5
  import { createLogger } from '@aztec/foundation/log';
6
- import type { TestDateProvider } from '@aztec/foundation/timer';
6
+ import { pluralize } from '@aztec/foundation/string';
7
+ import type { DateProvider, TestDateProvider } from '@aztec/foundation/timer';
7
8
 
8
- import { type Hex, createPublicClient, fallback, http } from 'viem';
9
+ import { type Chain, type Hex, type Transaction, createPublicClient, fallback, hexToNumber, http } from 'viem';
10
+ import { foundry } from 'viem/chains';
9
11
 
10
12
  import type { ViemPublicClient } from '../types.js';
11
13
 
@@ -19,19 +21,31 @@ export class EthCheatCodes {
19
21
  * The RPC URL to use for interacting with the chain
20
22
  */
21
23
  public rpcUrls: string[],
24
+ /**
25
+ * The date provider to use for time operations
26
+ */
27
+ public dateProvider: DateProvider | TestDateProvider,
22
28
  /**
23
29
  * The logger to use for the eth cheatcodes
24
30
  */
25
31
  public logger = createLogger('ethereum:cheat_codes'),
32
+ /**
33
+ * The chain configuration provided to Anvil
34
+ */
35
+ public chain: Chain = foundry,
26
36
  ) {
27
37
  this.publicClient = createPublicClient({
28
38
  transport: fallback(this.rpcUrls.map(url => http(url))),
39
+ chain: chain,
29
40
  });
30
41
  }
31
42
 
32
- async rpcCall(method: string, params: any[]) {
33
- const paramsString = jsonStringify(params);
34
- this.logger.debug(`Calling ${method} with params: ${paramsString} on ${this.rpcUrls.join(', ')}`);
43
+ public rpcCall(method: string, params: any[]) {
44
+ this.logger.debug(`Calling ${method} with params: ${jsonStringify(params)} on ${this.rpcUrls.join(', ')}`);
45
+ return this.doRpcCall(method, params);
46
+ }
47
+
48
+ private async doRpcCall(method: string, params: any[]) {
35
49
  return (await this.publicClient.transport.request({
36
50
  method,
37
51
  params,
@@ -44,7 +58,7 @@ export class EthCheatCodes {
44
58
  */
45
59
  public async isAutoMining(): Promise<boolean> {
46
60
  try {
47
- const res = await this.rpcCall('anvil_getAutomine', []);
61
+ const res = await this.doRpcCall('anvil_getAutomine', []);
48
62
  return res;
49
63
  } catch (err) {
50
64
  this.logger.error(`Calling "anvil_getAutomine" failed with:`, err);
@@ -57,7 +71,7 @@ export class EthCheatCodes {
57
71
  * @returns The current block number
58
72
  */
59
73
  public async blockNumber(): Promise<number> {
60
- const res = await this.rpcCall('eth_blockNumber', []);
74
+ const res = await this.doRpcCall('eth_blockNumber', []);
61
75
  return parseInt(res, 16);
62
76
  }
63
77
 
@@ -66,7 +80,7 @@ export class EthCheatCodes {
66
80
  * @returns The current chainId
67
81
  */
68
82
  public async chainId(): Promise<number> {
69
- const res = await this.rpcCall('eth_chainId', []);
83
+ const res = await this.doRpcCall('eth_chainId', []);
70
84
  return parseInt(res, 16);
71
85
  }
72
86
 
@@ -75,7 +89,7 @@ export class EthCheatCodes {
75
89
  * @returns The current timestamp
76
90
  */
77
91
  public async timestamp(): Promise<number> {
78
- const res = await this.rpcCall('eth_getBlockByNumber', ['latest', true]);
92
+ const res = await this.doRpcCall('eth_getBlockByNumber', ['latest', true]);
79
93
  return parseInt(res.timestamp, 16);
80
94
  }
81
95
 
@@ -90,7 +104,7 @@ export class EthCheatCodes {
90
104
 
91
105
  private async doMine(numberOfBlocks = 1): Promise<void> {
92
106
  try {
93
- await this.rpcCall('hardhat_mine', [numberOfBlocks]);
107
+ await this.doRpcCall('hardhat_mine', [numberOfBlocks]);
94
108
  } catch (err) {
95
109
  throw new Error(`Error mining: ${err}`);
96
110
  }
@@ -101,7 +115,8 @@ export class EthCheatCodes {
101
115
  */
102
116
  public async evmMine(): Promise<void> {
103
117
  try {
104
- await this.rpcCall('evm_mine', []);
118
+ await this.doRpcCall('evm_mine', []);
119
+ this.logger.warn(`Mined 1 L1 block with evm_mine`);
105
120
  } catch (err) {
106
121
  throw new Error(`Error mining: ${err}`);
107
122
  }
@@ -122,7 +137,7 @@ export class EthCheatCodes {
122
137
  }
123
138
 
124
139
  public async getBalance(account: EthAddress | Hex): Promise<bigint> {
125
- const res = await this.rpcCall('eth_getBalance', [account.toString(), 'latest']);
140
+ const res = await this.doRpcCall('eth_getBalance', [account.toString(), 'latest']);
126
141
  return BigInt(res);
127
142
  }
128
143
 
@@ -158,7 +173,7 @@ export class EthCheatCodes {
158
173
  */
159
174
  public getIntervalMining(): Promise<number | null> {
160
175
  try {
161
- return this.rpcCall('anvil_getIntervalMining', []);
176
+ return this.doRpcCall('anvil_getIntervalMining', []);
162
177
  } catch (err) {
163
178
  throw new Error(`Error getting interval mining: ${err}`);
164
179
  }
@@ -225,12 +240,12 @@ export class EthCheatCodes {
225
240
  /**
226
241
  * Set the next block timestamp and mines the block.
227
242
  * Optionally resets interval mining so the next block is mined in `blockInterval` seconds from now.
228
- * Optionally updates a provided date provider to follow L1 time.
243
+ * Always updates the injected date provider to follow L1 time.
229
244
  * @param timestamp - The timestamp to set the next block to
230
245
  */
231
246
  public async warp(
232
247
  timestamp: number | bigint,
233
- opts: { silent?: boolean; resetBlockInterval?: boolean; updateDateProvider?: TestDateProvider } = {},
248
+ opts: { silent?: boolean; resetBlockInterval?: boolean } = {},
234
249
  ): Promise<void> {
235
250
  let blockInterval: number | null = null;
236
251
  try {
@@ -245,8 +260,10 @@ export class EthCheatCodes {
245
260
  await this.rpcCall('evm_setNextBlockTimestamp', [Number(timestamp)]);
246
261
  // And mine a block so the timestamp goes into effect now
247
262
  await this.doMine();
248
- // Update the date provider if provided so it follows L1 time
249
- opts.updateDateProvider?.setTime(Number(timestamp) * 1000);
263
+ // Update the injected date provider so it follows L1 time
264
+ if ('setTime' in this.dateProvider) {
265
+ this.dateProvider.setTime(Number(timestamp) * 1000);
266
+ }
250
267
  } catch (err) {
251
268
  throw new Error(`Error warping: ${err}`);
252
269
  } finally {
@@ -277,14 +294,21 @@ export class EthCheatCodes {
277
294
  * @param slot - The storage slot
278
295
  * @param value - The value to set the storage slot to
279
296
  */
280
- public async store(contract: EthAddress, slot: bigint, value: bigint): Promise<void> {
297
+ public async store(
298
+ contract: EthAddress,
299
+ slot: bigint,
300
+ value: bigint,
301
+ opts: { silent?: boolean } = {},
302
+ ): Promise<void> {
281
303
  // for the rpc call, we need to change value to be a 32 byte hex string.
282
304
  try {
283
305
  await this.rpcCall('hardhat_setStorageAt', [contract.toString(), toHex(slot), toHex(value, true)]);
284
306
  } catch (err) {
285
307
  throw new Error(`Error setting storage for contract ${contract} at ${slot}: ${err}`);
286
308
  }
287
- this.logger.warn(`Set L1 storage for contract ${contract} at ${slot} to ${value}`);
309
+ if (!opts.silent) {
310
+ this.logger.warn(`Set L1 storage for contract ${contract} at ${slot} to ${value}`);
311
+ }
288
312
  }
289
313
 
290
314
  /**
@@ -350,8 +374,7 @@ export class EthCheatCodes {
350
374
  * @returns The bytecode for the contract
351
375
  */
352
376
  public async getBytecode(contract: EthAddress): Promise<`0x${string}`> {
353
- const res = await this.rpcCall('eth_getCode', [contract.toString(), 'latest']);
354
- return res;
377
+ return await this.doRpcCall('eth_getCode', [contract.toString(), 'latest']);
355
378
  }
356
379
 
357
380
  /**
@@ -360,8 +383,7 @@ export class EthCheatCodes {
360
383
  * @returns The raw transaction
361
384
  */
362
385
  public async getRawTransaction(txHash: Hex): Promise<`0x${string}`> {
363
- const res = await this.rpcCall('debug_getRawTransaction', [txHash]);
364
- return res;
386
+ return await this.doRpcCall('debug_getRawTransaction', [txHash]);
365
387
  }
366
388
 
367
389
  /**
@@ -370,8 +392,7 @@ export class EthCheatCodes {
370
392
  * @returns The trace
371
393
  */
372
394
  public async debugTraceTransaction(txHash: Hex): Promise<any> {
373
- const res = await this.rpcCall('debug_traceTransaction', [txHash]);
374
- return res;
395
+ return await this.doRpcCall('debug_traceTransaction', [txHash]);
375
396
  }
376
397
 
377
398
  /**
@@ -389,7 +410,6 @@ export class EthCheatCodes {
389
410
  * @param blockNumber - The block number that's going to be the new tip
390
411
  */
391
412
  public reorgTo(blockNumber: number): Promise<void> {
392
- this.logger.info('reorgTo', { blockNumber });
393
413
  if (blockNumber <= 0) {
394
414
  throw new Error(`Can't reorg to block before genesis: ${blockNumber}`);
395
415
  }
@@ -405,6 +425,7 @@ export class EthCheatCodes {
405
425
 
406
426
  const depth = Number(currentTip - BigInt(blockNumber) + 1n);
407
427
  await this.rpcCall('anvil_rollback', [depth]);
428
+ this.logger.warn(`Reorged L1 chain to block number ${blockNumber} (depth ${depth})`);
408
429
  });
409
430
  }
410
431
 
@@ -431,10 +452,73 @@ export class EthCheatCodes {
431
452
  }
432
453
 
433
454
  public traceTransaction(txHash: Hex): Promise<any> {
434
- return this.rpcCall('trace_transaction', [txHash]);
455
+ return this.doRpcCall('trace_transaction', [txHash]);
456
+ }
457
+
458
+ public async getTxPoolStatus(): Promise<{ pending: number; queued: number }> {
459
+ const { pending, queued } = await this.doRpcCall('txpool_status', []);
460
+ return { pending: hexToNumber(pending), queued: hexToNumber(queued) };
461
+ }
462
+
463
+ public async getTxPoolContents(): Promise<TxPoolTransaction[]> {
464
+ const txpoolContent = await this.doRpcCall('txpool_content', []);
465
+ return mapTxPoolContent(txpoolContent);
466
+ }
467
+
468
+ /**
469
+ * Mines an empty block by temporarily removing all pending transactions from the mempool,
470
+ * mining a block, and then re-adding the transactions back to the pool.
471
+ */
472
+ public async mineEmptyBlock(blockCount: number = 1): Promise<void> {
473
+ await this.execWithPausedAnvil(async () => {
474
+ // Get all pending and queued transactions from the pool
475
+ const txs = await this.getTxPoolContents();
476
+
477
+ this.logger.debug(`Found ${txs.length} transactions in pool`);
478
+
479
+ // Get raw transactions before dropping them
480
+ const rawTxs: Hex[] = [];
481
+ for (const tx of txs) {
482
+ try {
483
+ const rawTx = await this.doRpcCall('debug_getRawTransaction', [tx.hash]);
484
+ if (rawTx) {
485
+ rawTxs.push(rawTx);
486
+ this.logger.debug(`Got raw tx for ${tx.hash}`);
487
+ } else {
488
+ this.logger.warn(`No raw tx found for ${tx.hash}`);
489
+ }
490
+ } catch {
491
+ this.logger.warn(`Failed to get raw transaction for ${tx.hash}`);
492
+ }
493
+ }
494
+
495
+ this.logger.debug(`Retrieved ${rawTxs.length} raw transactions`);
496
+
497
+ // Drop all transactions from the mempool
498
+ await this.doRpcCall('anvil_dropAllTransactions', []);
499
+
500
+ // Mine an empty block
501
+ await this.doMine(blockCount);
502
+
503
+ // Re-add the transactions to the pool
504
+ for (const rawTx of rawTxs) {
505
+ try {
506
+ const txHash = await this.doRpcCall('eth_sendRawTransaction', [rawTx]);
507
+ this.logger.debug(`Re-added transaction ${txHash}`);
508
+ } catch (err) {
509
+ this.logger.warn(`Failed to re-add transaction: ${err}`);
510
+ }
511
+ }
512
+
513
+ if (rawTxs.length !== txs.length) {
514
+ this.logger.warn(`Failed to add all txs back: had ${txs.length} but re-added ${rawTxs.length}`);
515
+ }
516
+ });
517
+
518
+ this.logger.warn(`Mined ${blockCount} empty L1 ${pluralize('block', blockCount)}`);
435
519
  }
436
520
 
437
- public async execWithPausedAnvil(fn: () => Promise<void>): Promise<void> {
521
+ public async execWithPausedAnvil<T>(fn: () => Promise<T>): Promise<T> {
438
522
  const [blockInterval, wasAutoMining] = await Promise.all([this.getIntervalMining(), this.isAutoMining()]);
439
523
  try {
440
524
  if (blockInterval !== null) {
@@ -445,7 +529,7 @@ export class EthCheatCodes {
445
529
  await this.setAutomine(false, { silent: true });
446
530
  }
447
531
 
448
- await fn();
532
+ return await fn();
449
533
  } finally {
450
534
  try {
451
535
  // restore automine if necessary
@@ -466,4 +550,39 @@ export class EthCheatCodes {
466
550
  }
467
551
  }
468
552
  }
553
+
554
+ public async syncDateProvider() {
555
+ const timestamp = await this.timestamp();
556
+ if ('setTime' in this.dateProvider) {
557
+ this.dateProvider.setTime(timestamp * 1000);
558
+ }
559
+ }
560
+ }
561
+
562
+ type TxPoolState = 'pending' | 'queued';
563
+
564
+ interface TxPoolContent {
565
+ pending: Record<Hex, Record<string, Transaction>>;
566
+ queued: Record<Hex, Record<string, Transaction>>;
567
+ }
568
+
569
+ export type TxPoolTransaction = Transaction & {
570
+ poolState: TxPoolState;
571
+ };
572
+
573
+ function mapTxPoolContent(content: TxPoolContent): TxPoolTransaction[] {
574
+ const result: TxPoolTransaction[] = [];
575
+
576
+ const processPool = (pool: Record<Hex, Record<string, Transaction>>, poolState: TxPoolState) => {
577
+ for (const txsByNonce of Object.values(pool)) {
578
+ for (const tx of Object.values(txsByNonce)) {
579
+ result.push({ ...tx, poolState });
580
+ }
581
+ }
582
+ };
583
+
584
+ processPool(content.pending, 'pending');
585
+ processPool(content.queued, 'queued');
586
+
587
+ return result;
469
588
  }
@@ -1,8 +1,10 @@
1
- import { RollupContract, type ViemPublicClient } from '@aztec/ethereum';
1
+ import { RollupContract } from '@aztec/ethereum/contracts';
2
2
  import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
3
+ import type { ViemPublicClient } from '@aztec/ethereum/types';
4
+ import { CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
3
5
  import { EthAddress } from '@aztec/foundation/eth-address';
4
6
  import { createLogger } from '@aztec/foundation/log';
5
- import type { TestDateProvider } from '@aztec/foundation/timer';
7
+ import type { DateProvider } from '@aztec/foundation/timer';
6
8
  import { RollupAbi } from '@aztec/l1-artifacts/RollupAbi';
7
9
 
8
10
  import {
@@ -14,7 +16,6 @@ import {
14
16
  hexToBigInt,
15
17
  http,
16
18
  } from 'viem';
17
- import { foundry } from 'viem/chains';
18
19
 
19
20
  import { EthCheatCodes } from './eth_cheat_codes.js';
20
21
 
@@ -30,7 +31,7 @@ export class RollupCheatCodes {
30
31
  addresses: Pick<L1ContractAddresses, 'rollupAddress'>,
31
32
  ) {
32
33
  this.client = createPublicClient({
33
- chain: foundry,
34
+ chain: ethCheatCodes.chain,
34
35
  transport: fallback(ethCheatCodes.rpcUrls.map(url => http(url))),
35
36
  });
36
37
  this.rollup = getContract({
@@ -40,21 +41,25 @@ export class RollupCheatCodes {
40
41
  });
41
42
  }
42
43
 
43
- static create(rpcUrls: string[], addresses: Pick<L1ContractAddresses, 'rollupAddress'>): RollupCheatCodes {
44
- const ethCheatCodes = new EthCheatCodes(rpcUrls);
44
+ static create(
45
+ rpcUrls: string[],
46
+ addresses: Pick<L1ContractAddresses, 'rollupAddress'>,
47
+ dateProvider: DateProvider,
48
+ ): RollupCheatCodes {
49
+ const ethCheatCodes = new EthCheatCodes(rpcUrls, dateProvider);
45
50
  return new RollupCheatCodes(ethCheatCodes, addresses);
46
51
  }
47
52
 
48
53
  /** Returns the current slot */
49
- public async getSlot() {
54
+ public async getSlot(): Promise<SlotNumber> {
50
55
  const ts = BigInt((await this.client.getBlock()).timestamp);
51
- return await this.rollup.read.getSlotAt([ts]);
56
+ return SlotNumber.fromBigInt(await this.rollup.read.getSlotAt([ts]));
52
57
  }
53
58
 
54
59
  /** Returns the current epoch */
55
- public async getEpoch() {
60
+ public async getEpoch(): Promise<EpochNumber> {
56
61
  const slotNumber = await this.getSlot();
57
- return await this.rollup.read.getEpochAtSlot([slotNumber]);
62
+ return EpochNumber.fromBigInt(await this.rollup.read.getEpochAtSlot([BigInt(slotNumber)]));
58
63
  }
59
64
 
60
65
  /**
@@ -62,13 +67,13 @@ export class RollupCheatCodes {
62
67
  * @returns The pending and proven chain tips
63
68
  */
64
69
  public async getTips(): Promise<{
65
- /** The pending chain tip */ pending: bigint;
66
- /** The proven chain tip */ proven: bigint;
70
+ /** The pending chain tip */ pending: CheckpointNumber;
71
+ /** The proven chain tip */ proven: CheckpointNumber;
67
72
  }> {
68
- const res = await this.rollup.read.getTips();
73
+ const { pending, proven } = await this.rollup.read.getTips();
69
74
  return {
70
- pending: res.pendingBlockNumber,
71
- proven: res.provenBlockNumber,
75
+ pending: CheckpointNumber.fromBigInt(pending),
76
+ proven: CheckpointNumber.fromBigInt(proven),
72
77
  };
73
78
  }
74
79
 
@@ -77,16 +82,16 @@ export class RollupCheatCodes {
77
82
  */
78
83
  public async debugRollup() {
79
84
  const rollup = new RollupContract(this.client, this.rollup.address);
80
- const pendingNum = await rollup.getBlockNumber();
81
- const provenNum = await rollup.getProvenBlockNumber();
85
+ const pendingNum = await rollup.getCheckpointNumber();
86
+ const provenNum = await rollup.getProvenCheckpointNumber();
82
87
  const validators = await rollup.getAttesters();
83
88
  const committee = await rollup.getCurrentEpochCommittee();
84
89
  const archive = await rollup.archive();
85
90
  const slot = await this.getSlot();
86
91
  const epochNum = await rollup.getEpochNumberForSlotNumber(slot);
87
92
 
88
- this.logger.info(`Pending block num: ${pendingNum}`);
89
- this.logger.info(`Proven block num: ${provenNum}`);
93
+ this.logger.info(`Pending checkpoint num: ${pendingNum}`);
94
+ this.logger.info(`Proven checkpoint num: ${provenNum}`);
90
95
  this.logger.info(`Validators: ${validators.map(v => v.toString()).join(', ')}`);
91
96
  this.logger.info(`Committee: ${committee?.map(v => v.toString()).join(', ')}`);
92
97
  this.logger.info(`Archive: ${archive}`);
@@ -97,13 +102,13 @@ export class RollupCheatCodes {
97
102
  /** Fetches the epoch and slot duration config from the rollup contract */
98
103
  public async getConfig(): Promise<{
99
104
  /** Epoch duration */ epochDuration: bigint;
100
- /** Slot duration */ slotDuration: bigint;
105
+ /** Slot duration */ slotDuration: number;
101
106
  }> {
102
107
  const [epochDuration, slotDuration] = await Promise.all([
103
108
  this.rollup.read.getEpochDuration(),
104
109
  this.rollup.read.getSlotDuration(),
105
110
  ]);
106
- return { epochDuration, slotDuration };
111
+ return { epochDuration, slotDuration: Number(slotDuration) };
107
112
  }
108
113
 
109
114
  /**
@@ -112,17 +117,18 @@ export class RollupCheatCodes {
112
117
  * @param opts - Options
113
118
  */
114
119
  public async advanceToEpoch(
115
- epoch: bigint,
120
+ epoch: EpochNumber,
116
121
  opts: {
117
- /** Optional test date provider to update with the epoch timestamp */
118
- updateDateProvider?: TestDateProvider;
122
+ /** Offset in seconds */
123
+ offset?: number;
119
124
  } = {},
120
125
  ) {
121
126
  const { epochDuration: slotsInEpoch } = await this.getConfig();
122
- const timestamp = await this.rollup.read.getTimestampForSlot([epoch * slotsInEpoch]);
127
+ const slotNumber = SlotNumber(epoch * Number(slotsInEpoch));
128
+ const timestamp = (await this.rollup.read.getTimestampForSlot([BigInt(slotNumber)])) + BigInt(opts.offset ?? 0);
123
129
  try {
124
130
  await this.ethCheatCodes.warp(Number(timestamp), { ...opts, silent: true, resetBlockInterval: true });
125
- this.logger.warn(`Warped to epoch ${epoch}`);
131
+ this.logger.warn(`Warped to epoch ${epoch}`, { offset: opts.offset, timestamp });
126
132
  } catch (err) {
127
133
  this.logger.warn(`Warp to epoch ${epoch} failed: ${err}`);
128
134
  }
@@ -130,19 +136,13 @@ export class RollupCheatCodes {
130
136
  }
131
137
 
132
138
  /** Warps time in L1 until the next epoch */
133
- public async advanceToNextEpoch(
134
- opts: {
135
- /** Optional test date provider to update with the epoch timestamp */
136
- updateDateProvider?: TestDateProvider;
137
- } = {},
138
- ) {
139
+ public async advanceToNextEpoch() {
139
140
  const slot = await this.getSlot();
140
141
  const { epochDuration, slotDuration } = await this.getConfig();
141
- const slotsUntilNextEpoch = epochDuration - (slot % epochDuration) + 1n;
142
- const timeToNextEpoch = slotsUntilNextEpoch * slotDuration;
142
+ const slotsUntilNextEpoch = epochDuration - (BigInt(slot) % epochDuration) + 1n;
143
+ const timeToNextEpoch = slotsUntilNextEpoch * BigInt(slotDuration);
143
144
  const l1Timestamp = BigInt((await this.client.getBlock()).timestamp);
144
145
  await this.ethCheatCodes.warp(Number(l1Timestamp + timeToNextEpoch), {
145
- ...opts,
146
146
  silent: true,
147
147
  resetBlockInterval: true,
148
148
  });
@@ -152,10 +152,11 @@ export class RollupCheatCodes {
152
152
  /** Warps time in L1 until the beginning of the next slot. */
153
153
  public async advanceToNextSlot() {
154
154
  const currentSlot = await this.getSlot();
155
- const timestamp = await this.rollup.read.getTimestampForSlot([currentSlot + 1n]);
155
+ const nextSlot = SlotNumber(currentSlot + 1);
156
+ const timestamp = await this.rollup.read.getTimestampForSlot([BigInt(nextSlot)]);
156
157
  await this.ethCheatCodes.warp(Number(timestamp), { silent: true, resetBlockInterval: true });
157
- this.logger.warn(`Advanced to slot ${currentSlot + 1n}`);
158
- return [timestamp, currentSlot + 1n];
158
+ this.logger.warn(`Advanced to slot ${nextSlot}`);
159
+ return [timestamp, nextSlot];
159
160
  }
160
161
 
161
162
  /**
@@ -164,42 +165,42 @@ export class RollupCheatCodes {
164
165
  */
165
166
  public async advanceSlots(howMany: number) {
166
167
  const l1Timestamp = (await this.client.getBlock()).timestamp;
167
- const slotDuration = await this.rollup.read.getSlotDuration();
168
- const timeToWarp = BigInt(howMany) * slotDuration;
168
+ const slotDuration = Number(await this.rollup.read.getSlotDuration());
169
+ const timeToWarp = BigInt(howMany) * BigInt(slotDuration);
169
170
  await this.ethCheatCodes.warp(l1Timestamp + timeToWarp, { silent: true, resetBlockInterval: true });
170
171
  const [slot, epoch] = await Promise.all([this.getSlot(), this.getEpoch()]);
171
172
  this.logger.warn(`Advanced ${howMany} slots up to slot ${slot} in epoch ${epoch}`);
172
173
  }
173
174
 
174
175
  /**
175
- * Marks the specified block (or latest if none) as proven
176
- * @param maybeBlockNumber - The block number to mark as proven (defaults to latest pending)
176
+ * Marks the specified checkpoint (or latest if none) as proven
177
+ * @param maybeCheckpointNumber - The checkpoint number to mark as proven (defaults to latest pending)
177
178
  */
178
- public markAsProven(maybeBlockNumber?: number | bigint) {
179
+ public markAsProven(maybeCheckpointNumber?: number | bigint) {
179
180
  return this.ethCheatCodes.execWithPausedAnvil(async () => {
180
181
  const tipsBefore = await this.getTips();
181
182
  const { pending, proven } = tipsBefore;
182
183
 
183
- let blockNumber = maybeBlockNumber;
184
- if (blockNumber === undefined || blockNumber > pending) {
185
- blockNumber = pending;
184
+ let checkpointNumber = maybeCheckpointNumber;
185
+ if (checkpointNumber === undefined || checkpointNumber > pending) {
186
+ checkpointNumber = pending;
186
187
  }
187
- if (blockNumber <= proven) {
188
- this.logger.debug(`Block ${blockNumber} is already proven`);
188
+ if (checkpointNumber <= proven) {
189
+ this.logger.debug(`Checkpoint ${checkpointNumber} is already proven`);
189
190
  return;
190
191
  }
191
192
 
192
193
  // @note @LHerskind this is heavily dependent on the storage layout and size of values
193
194
  // The rollupStore is a struct and if the size of elements or the struct changes, this can break
194
- const provenBlockNumberSlot = hexToBigInt(RollupContract.stfStorageSlot);
195
+ const provenCheckpointNumberSlot = hexToBigInt(RollupContract.stfStorageSlot);
195
196
 
196
197
  // Need to pack it as a single 32 byte word
197
- const newValue = (BigInt(tipsBefore.pending) << 128n) | BigInt(blockNumber);
198
- await this.ethCheatCodes.store(EthAddress.fromString(this.rollup.address), provenBlockNumberSlot, newValue);
198
+ const newValue = (BigInt(tipsBefore.pending) << 128n) | BigInt(checkpointNumber);
199
+ await this.ethCheatCodes.store(EthAddress.fromString(this.rollup.address), provenCheckpointNumberSlot, newValue);
199
200
 
200
201
  const tipsAfter = await this.getTips();
201
202
  if (tipsAfter.pending < tipsAfter.proven) {
202
- throw new Error('Overwrote pending tip to a block in the past');
203
+ throw new Error('Overwrote pending tip to a checkpoint in the past');
203
204
  }
204
205
 
205
206
  this.logger.info(
@@ -208,6 +209,47 @@ export class RollupCheatCodes {
208
209
  });
209
210
  }
210
211
 
212
+ /**
213
+ * Overrides the inProgress field of the Inbox contract state
214
+ * @param howMuch - How many checkpoints to move it forward
215
+ */
216
+ public advanceInboxInProgress(howMuch: number | bigint): Promise<bigint> {
217
+ return this.ethCheatCodes.execWithPausedAnvil(async () => {
218
+ // Storage slot 2 contains the InboxState struct
219
+ const inboxStateSlot = 2n;
220
+
221
+ // Get inbox and its current state values
222
+ const inboxAddress = await this.rollup.read.getInbox();
223
+ const currentStateValue = await this.ethCheatCodes.load(EthAddress.fromString(inboxAddress), inboxStateSlot);
224
+
225
+ // Extract current values from the packed storage slot
226
+ // Storage layout: rollingHash (128 bits) | totalMessagesInserted (64 bits) | inProgress (64 bits)
227
+ const currentRollingHash = currentStateValue & ((1n << 128n) - 1n);
228
+ const currentTotalMessages = (currentStateValue >> 128n) & ((1n << 64n) - 1n);
229
+ const currentInProgress = currentStateValue >> 192n;
230
+ const newInProgress = currentInProgress + BigInt(howMuch);
231
+
232
+ // Pack new values: rollingHash (low 128 bits) | totalMessages (middle 64 bits) | inProgress (high 64 bits)
233
+ const newValue = (BigInt(newInProgress) << 192n) | (currentTotalMessages << 128n) | currentRollingHash;
234
+
235
+ await this.ethCheatCodes.store(EthAddress.fromString(inboxAddress), inboxStateSlot, newValue, {
236
+ silent: true,
237
+ });
238
+
239
+ this.logger.warn(`Inbox inProgress advanced from ${currentInProgress} to ${newInProgress}`, {
240
+ inbox: inboxAddress,
241
+ oldValue: '0x' + currentStateValue.toString(16),
242
+ newValue: '0x' + newValue.toString(16),
243
+ rollingHash: currentRollingHash,
244
+ totalMessages: currentTotalMessages,
245
+ oldInProgress: currentInProgress,
246
+ newInProgress,
247
+ });
248
+
249
+ return newInProgress;
250
+ });
251
+ }
252
+
211
253
  /**
212
254
  * Executes an action impersonated as the owner of the Rollup contract.
213
255
  * @param action - The action to execute
@@ -15,6 +15,7 @@ export async function startAnvil(
15
15
  log?: boolean;
16
16
  captureMethodCalls?: boolean;
17
17
  accounts?: number;
18
+ chainId?: number;
18
19
  } = {},
19
20
  ): Promise<{ anvil: Anvil; methodCalls?: string[]; rpcUrl: string; stop: () => Promise<void> }> {
20
21
  const anvilBinary = resolve(dirname(fileURLToPath(import.meta.url)), '../../', 'scripts/anvil_kill_wrapper.sh');
@@ -35,6 +36,7 @@ export async function startAnvil(
35
36
  stopTimeout: 1000,
36
37
  accounts: opts.accounts ?? 20,
37
38
  gasLimit: 45_000_000n,
39
+ chainId: opts.chainId ?? 31337,
38
40
  });
39
41
 
40
42
  // Listen to the anvil output to get the port.
@@ -18,6 +18,8 @@ import {
18
18
 
19
19
  import { type ViemClient, isExtendedClient } from '../types.js';
20
20
 
21
+ const MAX_WAIT_TIME_SECONDS = 180;
22
+
21
23
  export function waitUntilBlock<T extends Client>(
22
24
  client: T,
23
25
  blockNumber: number | bigint,
@@ -36,7 +38,7 @@ export function waitUntilBlock<T extends Client>(
36
38
  return currentBlockNumber >= BigInt(blockNumber);
37
39
  },
38
40
  `Wait until L1 block ${blockNumber}`,
39
- timeout ?? 120,
41
+ timeout ?? MAX_WAIT_TIME_SECONDS,
40
42
  0.1,
41
43
  );
42
44
  }
@@ -66,7 +68,7 @@ export function waitUntilL1Timestamp<T extends Client>(
66
68
  return currentTs >= BigInt(timestamp);
67
69
  },
68
70
  `Wait until L1 timestamp ${timestamp}`,
69
- timeout ?? 120,
71
+ timeout ?? MAX_WAIT_TIME_SECONDS,
70
72
  0.1,
71
73
  );
72
74
  }