@aztec/ethereum 0.0.1-commit.86469d5 → 0.0.1-commit.88c5703d4

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 (117) hide show
  1. package/dest/client.d.ts +10 -2
  2. package/dest/client.d.ts.map +1 -1
  3. package/dest/client.js +13 -7
  4. package/dest/config.d.ts +3 -1
  5. package/dest/config.d.ts.map +1 -1
  6. package/dest/config.js +11 -3
  7. package/dest/contracts/empire_base.d.ts +3 -1
  8. package/dest/contracts/empire_base.d.ts.map +1 -1
  9. package/dest/contracts/empire_slashing_proposer.d.ts +3 -1
  10. package/dest/contracts/empire_slashing_proposer.d.ts.map +1 -1
  11. package/dest/contracts/empire_slashing_proposer.js +9 -0
  12. package/dest/contracts/fee_asset_price_oracle.d.ts +101 -0
  13. package/dest/contracts/fee_asset_price_oracle.d.ts.map +1 -0
  14. package/dest/contracts/fee_asset_price_oracle.js +651 -0
  15. package/dest/contracts/governance.js +3 -3
  16. package/dest/contracts/governance_proposer.d.ts +3 -1
  17. package/dest/contracts/governance_proposer.d.ts.map +1 -1
  18. package/dest/contracts/governance_proposer.js +9 -0
  19. package/dest/contracts/index.d.ts +2 -1
  20. package/dest/contracts/index.d.ts.map +1 -1
  21. package/dest/contracts/index.js +1 -0
  22. package/dest/contracts/registry.d.ts +3 -1
  23. package/dest/contracts/registry.d.ts.map +1 -1
  24. package/dest/contracts/registry.js +30 -1
  25. package/dest/contracts/rollup.d.ts +20 -6
  26. package/dest/contracts/rollup.d.ts.map +1 -1
  27. package/dest/contracts/rollup.js +60 -7
  28. package/dest/deploy_aztec_l1_contracts.d.ts +2 -3
  29. package/dest/deploy_aztec_l1_contracts.d.ts.map +1 -1
  30. package/dest/deploy_aztec_l1_contracts.js +34 -22
  31. package/dest/deploy_l1_contract.js +3 -3
  32. package/dest/generated/l1-contracts-defaults.d.ts +1 -1
  33. package/dest/generated/l1-contracts-defaults.js +1 -1
  34. package/dest/l1_artifacts.d.ts +1051 -42
  35. package/dest/l1_artifacts.d.ts.map +1 -1
  36. package/dest/l1_reader.d.ts +3 -1
  37. package/dest/l1_reader.d.ts.map +1 -1
  38. package/dest/l1_reader.js +6 -1
  39. package/dest/l1_tx_utils/config.d.ts +7 -1
  40. package/dest/l1_tx_utils/config.d.ts.map +1 -1
  41. package/dest/l1_tx_utils/config.js +14 -1
  42. package/dest/l1_tx_utils/factory.d.ts +18 -10
  43. package/dest/l1_tx_utils/factory.d.ts.map +1 -1
  44. package/dest/l1_tx_utils/factory.js +17 -7
  45. package/dest/l1_tx_utils/fee-strategies/p75_competitive.js +1 -1
  46. package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.js +1 -1
  47. package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts +15 -15
  48. package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts.map +1 -1
  49. package/dest/l1_tx_utils/forwarder_l1_tx_utils.js +9 -15
  50. package/dest/l1_tx_utils/index-blobs.d.ts +3 -3
  51. package/dest/l1_tx_utils/index-blobs.d.ts.map +1 -1
  52. package/dest/l1_tx_utils/index-blobs.js +2 -2
  53. package/dest/l1_tx_utils/index.d.ts +2 -1
  54. package/dest/l1_tx_utils/index.d.ts.map +1 -1
  55. package/dest/l1_tx_utils/index.js +1 -0
  56. package/dest/l1_tx_utils/l1_tx_utils.d.ts +18 -7
  57. package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -1
  58. package/dest/l1_tx_utils/l1_tx_utils.js +52 -36
  59. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +1 -1
  60. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -1
  61. package/dest/l1_tx_utils/readonly_l1_tx_utils.js +8 -4
  62. package/dest/l1_tx_utils/tx_delayer.d.ts +56 -0
  63. package/dest/l1_tx_utils/tx_delayer.d.ts.map +1 -0
  64. package/dest/{test → l1_tx_utils}/tx_delayer.js +62 -34
  65. package/dest/test/chain_monitor.d.ts +22 -3
  66. package/dest/test/chain_monitor.d.ts.map +1 -1
  67. package/dest/test/chain_monitor.js +33 -2
  68. package/dest/test/index.d.ts +1 -3
  69. package/dest/test/index.d.ts.map +1 -1
  70. package/dest/test/index.js +0 -2
  71. package/dest/test/start_anvil.d.ts +16 -3
  72. package/dest/test/start_anvil.d.ts.map +1 -1
  73. package/dest/test/start_anvil.js +129 -29
  74. package/dest/test/upgrade_utils.js +2 -2
  75. package/dest/utils.d.ts +1 -1
  76. package/dest/utils.d.ts.map +1 -1
  77. package/dest/utils.js +16 -12
  78. package/package.json +5 -7
  79. package/src/client.ts +10 -2
  80. package/src/config.ts +15 -2
  81. package/src/contracts/empire_base.ts +2 -0
  82. package/src/contracts/empire_slashing_proposer.ts +6 -0
  83. package/src/contracts/fee_asset_price_oracle.ts +280 -0
  84. package/src/contracts/governance.ts +3 -3
  85. package/src/contracts/governance_proposer.ts +6 -0
  86. package/src/contracts/index.ts +1 -0
  87. package/src/contracts/registry.ts +31 -1
  88. package/src/contracts/rollup.ts +70 -9
  89. package/src/deploy_aztec_l1_contracts.ts +57 -29
  90. package/src/deploy_l1_contract.ts +3 -3
  91. package/src/generated/l1-contracts-defaults.ts +1 -1
  92. package/src/l1_reader.ts +13 -1
  93. package/src/l1_tx_utils/config.ts +20 -0
  94. package/src/l1_tx_utils/factory.ts +31 -31
  95. package/src/l1_tx_utils/fee-strategies/p75_competitive.ts +1 -1
  96. package/src/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.ts +1 -1
  97. package/src/l1_tx_utils/forwarder_l1_tx_utils.ts +43 -54
  98. package/src/l1_tx_utils/index-blobs.ts +2 -2
  99. package/src/l1_tx_utils/index.ts +1 -0
  100. package/src/l1_tx_utils/l1_tx_utils.ts +54 -26
  101. package/src/l1_tx_utils/readonly_l1_tx_utils.ts +8 -4
  102. package/src/{test → l1_tx_utils}/tx_delayer.ts +78 -50
  103. package/src/test/chain_monitor.ts +60 -3
  104. package/src/test/index.ts +0 -2
  105. package/src/test/start_anvil.ts +154 -29
  106. package/src/test/upgrade_utils.ts +2 -2
  107. package/src/utils.ts +17 -14
  108. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts +0 -26
  109. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts.map +0 -1
  110. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.js +0 -26
  111. package/dest/test/delayed_tx_utils.d.ts +0 -13
  112. package/dest/test/delayed_tx_utils.d.ts.map +0 -1
  113. package/dest/test/delayed_tx_utils.js +0 -28
  114. package/dest/test/tx_delayer.d.ts +0 -36
  115. package/dest/test/tx_delayer.d.ts.map +0 -1
  116. package/src/l1_tx_utils/l1_tx_utils_with_blobs.ts +0 -77
  117. package/src/test/delayed_tx_utils.ts +0 -52
@@ -134,6 +134,14 @@ export type L1FeeData = {
134
134
  blobFee: bigint;
135
135
  };
136
136
 
137
+ /** Components of the minimum fee per mana, as returned by the L1 rollup contract. */
138
+ export type ManaMinFeeComponents = {
139
+ sequencerCost: bigint;
140
+ proverCost: bigint;
141
+ congestionCost: bigint;
142
+ congestionMultiplier: bigint;
143
+ };
144
+
137
145
  /**
138
146
  * Reward configuration for the rollup
139
147
  */
@@ -193,10 +201,10 @@ export type CheckpointProposedArgs = {
193
201
  checkpointNumber: CheckpointNumber;
194
202
  archive: Fr;
195
203
  versionedBlobHashes: Buffer[];
196
- /** Hash of attestations. Undefined for older events (backwards compatibility). */
197
- attestationsHash?: Buffer32;
198
- /** Digest of the payload. Undefined for older events (backwards compatibility). */
199
- payloadDigest?: Buffer32;
204
+ /** Hash of attestations emitted in the CheckpointProposed event. */
205
+ attestationsHash: Buffer32;
206
+ /** Digest of the payload emitted in the CheckpointProposed event. */
207
+ payloadDigest: Buffer32;
200
208
  };
201
209
 
202
210
  /** Log type for CheckpointProposed events. */
@@ -379,6 +387,20 @@ export class RollupContract {
379
387
  return Fr.fromString(await this.rollup.read.archiveAt([0n]));
380
388
  }
381
389
 
390
+ @memoize
391
+ async getVkTreeRoot(): Promise<Fr> {
392
+ const slot = BigInt(RollupContract.stfStorageSlot) + 3n;
393
+ const value = await this.client.getStorageAt({ address: this.address, slot: `0x${slot.toString(16)}` });
394
+ return Fr.fromString(value ?? '0x0');
395
+ }
396
+
397
+ @memoize
398
+ async getProtocolContractsHash(): Promise<Fr> {
399
+ const slot = BigInt(RollupContract.stfStorageSlot) + 4n;
400
+ const value = await this.client.getStorageAt({ address: this.address, slot: `0x${slot.toString(16)}` });
401
+ return Fr.fromString(value ?? '0x0');
402
+ }
403
+
382
404
  /**
383
405
  * Returns rollup constants used for epoch queries.
384
406
  * Return type is `L1RollupConstants` which is defined in stdlib,
@@ -391,13 +413,25 @@ export class RollupContract {
391
413
  slotDuration: number;
392
414
  epochDuration: number;
393
415
  proofSubmissionEpochs: number;
416
+ targetCommitteeSize: number;
417
+ rollupManaLimit: number;
394
418
  }> {
395
- const [l1StartBlock, l1GenesisTime, slotDuration, epochDuration, proofSubmissionEpochs] = await Promise.all([
419
+ const [
420
+ l1StartBlock,
421
+ l1GenesisTime,
422
+ slotDuration,
423
+ epochDuration,
424
+ proofSubmissionEpochs,
425
+ targetCommitteeSize,
426
+ rollupManaLimit,
427
+ ] = await Promise.all([
396
428
  this.getL1StartBlock(),
397
429
  this.getL1GenesisTime(),
398
430
  this.getSlotDuration(),
399
431
  this.getEpochDuration(),
400
432
  this.getProofSubmissionEpochs(),
433
+ this.getTargetCommitteeSize(),
434
+ this.getManaLimit(),
401
435
  ]);
402
436
  return {
403
437
  l1StartBlock,
@@ -405,6 +439,8 @@ export class RollupContract {
405
439
  slotDuration,
406
440
  epochDuration: Number(epochDuration),
407
441
  proofSubmissionEpochs: Number(proofSubmissionEpochs),
442
+ targetCommitteeSize,
443
+ rollupManaLimit: Number(rollupManaLimit),
408
444
  };
409
445
  }
410
446
 
@@ -499,8 +535,9 @@ export class RollupContract {
499
535
  return CheckpointNumber.fromBigInt(await this.rollup.read.getPendingCheckpointNumber());
500
536
  }
501
537
 
502
- async getProvenCheckpointNumber(): Promise<CheckpointNumber> {
503
- return CheckpointNumber.fromBigInt(await this.rollup.read.getProvenCheckpointNumber());
538
+ async getProvenCheckpointNumber(options?: { blockNumber?: bigint }): Promise<CheckpointNumber> {
539
+ await checkBlockTag(options?.blockNumber, this.client);
540
+ return CheckpointNumber.fromBigInt(await this.rollup.read.getProvenCheckpointNumber(options));
504
541
  }
505
542
 
506
543
  async getSlotNumber(): Promise<SlotNumber> {
@@ -848,6 +885,16 @@ export class RollupContract {
848
885
  return this.rollup.read.getManaMinFeeAt([timestamp, inFeeAsset]);
849
886
  }
850
887
 
888
+ async getManaMinFeeComponentsAt(timestamp: bigint, inFeeAsset: boolean): Promise<ManaMinFeeComponents> {
889
+ const result = await this.rollup.read.getManaMinFeeComponentsAt([timestamp, inFeeAsset]);
890
+ return {
891
+ sequencerCost: result.sequencerCost,
892
+ proverCost: result.proverCost,
893
+ congestionCost: result.congestionCost,
894
+ congestionMultiplier: result.congestionMultiplier,
895
+ };
896
+ }
897
+
851
898
  async getSlotAt(timestamp: bigint): Promise<SlotNumber> {
852
899
  return SlotNumber.fromBigInt(await this.rollup.read.getSlotAt([timestamp]));
853
900
  }
@@ -1056,8 +1103,22 @@ export class RollupContract {
1056
1103
  checkpointNumber: CheckpointNumber.fromBigInt(log.args.checkpointNumber!),
1057
1104
  archive: Fr.fromString(log.args.archive!),
1058
1105
  versionedBlobHashes: log.args.versionedBlobHashes!.map(h => Buffer.from(h.slice(2), 'hex')),
1059
- attestationsHash: log.args.attestationsHash ? Buffer32.fromString(log.args.attestationsHash) : undefined,
1060
- payloadDigest: log.args.payloadDigest ? Buffer32.fromString(log.args.payloadDigest) : undefined,
1106
+ attestationsHash: (() => {
1107
+ if (!log.args.attestationsHash) {
1108
+ throw new Error(
1109
+ `CheckpointProposed event missing attestationsHash for checkpoint ${log.args.checkpointNumber}`,
1110
+ );
1111
+ }
1112
+ return Buffer32.fromString(log.args.attestationsHash);
1113
+ })(),
1114
+ payloadDigest: (() => {
1115
+ if (!log.args.payloadDigest) {
1116
+ throw new Error(
1117
+ `CheckpointProposed event missing payloadDigest for checkpoint ${log.args.checkpointNumber}`,
1118
+ );
1119
+ }
1120
+ return Buffer32.fromString(log.args.payloadDigest);
1121
+ })(),
1061
1122
  },
1062
1123
  }));
1063
1124
  }
@@ -15,7 +15,7 @@ import { tmpdir } from 'os';
15
15
  import { dirname, join, resolve } from 'path';
16
16
  import readline from 'readline';
17
17
  import type { Hex } from 'viem';
18
- import { foundry, mainnet, sepolia } from 'viem/chains';
18
+ import { mainnet, sepolia } from 'viem/chains';
19
19
 
20
20
  import { createEthereumChain, isAnvilTestChain } from './chain.js';
21
21
  import { createExtendedL1Client } from './client.js';
@@ -23,7 +23,6 @@ import type { L1ContractsConfig } from './config.js';
23
23
  import { deployMulticall3 } from './contracts/multicall.js';
24
24
  import { RollupContract } from './contracts/rollup.js';
25
25
  import type { L1ContractAddresses } from './l1_contract_addresses.js';
26
- import type { L1TxUtilsConfig } from './l1_tx_utils/config.js';
27
26
  import type { ExtendedViemWalletClient } from './types.js';
28
27
 
29
28
  const logger = createLogger('ethereum:deploy_aztec_l1_contracts');
@@ -31,9 +30,9 @@ const logger = createLogger('ethereum:deploy_aztec_l1_contracts');
31
30
  const JSON_DEPLOY_RESULT_PREFIX = 'JSON DEPLOY RESULT:';
32
31
 
33
32
  /**
34
- * Runs a process with the given command, arguments, and environment.
35
- * If the process outputs a line starting with JSON_DEPLOY_RESULT_PREFIX,
36
- * the JSON is parsed and returned.
33
+ * Runs a process and parses JSON deploy results from stdout.
34
+ * Lines starting with JSON_DEPLOY_RESULT_PREFIX are parsed and returned.
35
+ * All other stdout goes to logger.info, stderr goes to logger.warn.
37
36
  */
38
37
  function runProcess<T>(
39
38
  command: string,
@@ -49,26 +48,41 @@ function runProcess<T>(
49
48
  });
50
49
 
51
50
  let result: T | undefined;
51
+ let parseError: Error | undefined;
52
+ let settled = false;
52
53
 
53
54
  readline.createInterface({ input: proc.stdout }).on('line', line => {
54
55
  const trimmedLine = line.trim();
55
56
  if (trimmedLine.startsWith(JSON_DEPLOY_RESULT_PREFIX)) {
56
57
  const jsonStr = trimmedLine.slice(JSON_DEPLOY_RESULT_PREFIX.length).trim();
57
- // TODO(AD): should this be a zod parse?
58
- result = JSON.parse(jsonStr);
58
+ try {
59
+ result = JSON.parse(jsonStr);
60
+ } catch {
61
+ parseError = new Error(`Failed to parse deploy result JSON: ${jsonStr.slice(0, 200)}`);
62
+ }
59
63
  } else {
60
64
  logger.info(line);
61
65
  }
62
66
  });
63
- readline.createInterface({ input: proc.stderr }).on('line', logger.error.bind(logger));
67
+ readline.createInterface({ input: proc.stderr }).on('line', logger.warn.bind(logger));
64
68
 
65
69
  proc.on('error', error => {
70
+ if (settled) {
71
+ return;
72
+ }
73
+ settled = true;
66
74
  reject(new Error(`Failed to spawn ${command}: ${error.message}`));
67
75
  });
68
76
 
69
77
  proc.on('close', code => {
78
+ if (settled) {
79
+ return;
80
+ }
81
+ settled = true;
70
82
  if (code !== 0) {
71
- reject(new Error(`${command} exited with code ${code}. See logs for details.\n`));
83
+ reject(new Error(`${command} exited with code ${code}`));
84
+ } else if (parseError) {
85
+ reject(parseError);
72
86
  } else {
73
87
  resolve(result);
74
88
  }
@@ -321,11 +335,8 @@ export async function deployAztecL1Contracts(
321
335
  );
322
336
  }
323
337
 
324
- // From heuristic testing. More caused issues with anvil.
325
- const MAGIC_ANVIL_BATCH_SIZE = 8;
326
- // Anvil seems to stall with unbounded batch size. Otherwise no max batch size is desirable.
338
+ const scriptPath = join(getL1ContractsPath(), 'scripts', 'forge_broadcast.js');
327
339
  const forgeArgs = [
328
- 'script',
329
340
  FORGE_SCRIPT,
330
341
  '--sig',
331
342
  'run()',
@@ -333,8 +344,6 @@ export async function deployAztecL1Contracts(
333
344
  privateKey,
334
345
  '--rpc-url',
335
346
  rpcUrl,
336
- '--broadcast',
337
- ...(chainId === foundry.id ? ['--batch-size', MAGIC_ANVIL_BATCH_SIZE.toString()] : []),
338
347
  ...(shouldVerify ? ['--verify'] : []),
339
348
  ];
340
349
  const forgeEnv = {
@@ -343,7 +352,12 @@ export async function deployAztecL1Contracts(
343
352
  FOUNDRY_PROFILE: chainId === mainnet.id ? 'production' : undefined,
344
353
  ...getDeployAztecL1ContractsEnvVars(args),
345
354
  };
346
- const result = await runProcess<ForgeL1ContractsDeployResult>('forge', forgeArgs, forgeEnv, l1ContractsPath);
355
+ const result = await runProcess<ForgeL1ContractsDeployResult>(
356
+ process.execPath,
357
+ [scriptPath, ...forgeArgs],
358
+ forgeEnv,
359
+ l1ContractsPath,
360
+ );
347
361
  if (!result) {
348
362
  throw new Error('Forge script did not output deployment result');
349
363
  }
@@ -476,7 +490,25 @@ export type VerificationRecord = {
476
490
  libraries: VerificationLibraryEntry[];
477
491
  };
478
492
 
479
- export interface DeployAztecL1ContractsArgs extends Omit<L1ContractsConfig, keyof L1TxUtilsConfig> {
493
+ export interface DeployAztecL1ContractsArgs
494
+ extends Omit<
495
+ L1ContractsConfig,
496
+ | 'gasLimitBufferPercentage'
497
+ | 'maxGwei'
498
+ | 'maxBlobGwei'
499
+ | 'priorityFeeBumpPercentage'
500
+ | 'priorityFeeRetryBumpPercentage'
501
+ | 'minimumPriorityFeePerGas'
502
+ | 'maxSpeedUpAttempts'
503
+ | 'checkIntervalMs'
504
+ | 'stallTimeMs'
505
+ | 'txTimeoutMs'
506
+ | 'cancelTxOnTimeout'
507
+ | 'txCancellationFinalTimeoutMs'
508
+ | 'txUnseenConsideredDroppedMs'
509
+ | 'enableDelayer'
510
+ | 'txDelayerMaxInclusionTimeIntoSlot'
511
+ > {
480
512
  /** The vk tree root. */
481
513
  vkTreeRoot: Fr;
482
514
  /** The hash of the protocol contracts. */
@@ -586,17 +618,8 @@ export const deployRollupForUpgrade = async (
586
618
  const FORGE_SCRIPT = 'script/deploy/DeployRollupForUpgrade.s.sol';
587
619
  await maybeForgeForceProductionBuild(l1ContractsPath, FORGE_SCRIPT, chainId);
588
620
 
589
- const forgeArgs = [
590
- 'script',
591
- FORGE_SCRIPT,
592
- '--sig',
593
- 'run()',
594
- '--private-key',
595
- privateKey,
596
- '--rpc-url',
597
- rpcUrl,
598
- '--broadcast',
599
- ];
621
+ const scriptPath = join(getL1ContractsPath(), 'scripts', 'forge_broadcast.js');
622
+ const forgeArgs = [FORGE_SCRIPT, '--sig', 'run()', '--private-key', privateKey, '--rpc-url', rpcUrl];
600
623
  const forgeEnv = {
601
624
  FOUNDRY_PROFILE: chainId === mainnet.id ? 'production' : undefined,
602
625
  // Env vars required by l1-contracts/script/deploy/RollupConfiguration.sol.
@@ -605,7 +628,12 @@ export const deployRollupForUpgrade = async (
605
628
  ...getDeployRollupForUpgradeEnvVars(args),
606
629
  };
607
630
 
608
- const result = await runProcess<ForgeRollupUpgradeResult>('forge', forgeArgs, forgeEnv, l1ContractsPath);
631
+ const result = await runProcess<ForgeRollupUpgradeResult>(
632
+ process.execPath,
633
+ [scriptPath, ...forgeArgs],
634
+ forgeEnv,
635
+ l1ContractsPath,
636
+ );
609
637
  if (!result) {
610
638
  throw new Error('Forge script did not output deployment result');
611
639
  }
@@ -24,7 +24,7 @@ import {
24
24
  } from './deploy_aztec_l1_contracts.js';
25
25
  import { RegisterNewRollupVersionPayloadArtifact } from './l1_artifacts.js';
26
26
  import { type L1TxUtilsConfig, getL1TxUtilsConfigEnvVars } from './l1_tx_utils/config.js';
27
- import { createL1TxUtilsFromViemWallet } from './l1_tx_utils/factory.js';
27
+ import { createL1TxUtils } from './l1_tx_utils/factory.js';
28
28
  import type { L1TxUtils } from './l1_tx_utils/l1_tx_utils.js';
29
29
  import type { GasPrice, L1TxConfig, L1TxRequest } from './l1_tx_utils/types.js';
30
30
  import type { ExtendedViemWalletClient } from './types.js';
@@ -46,7 +46,7 @@ export class L1Deployer {
46
46
  private createVerificationJson: boolean = false,
47
47
  ) {
48
48
  this.salt = maybeSalt ? padHex(numberToHex(maybeSalt), { size: 32 }) : undefined;
49
- this.l1TxUtils = createL1TxUtilsFromViemWallet(
49
+ this.l1TxUtils = createL1TxUtils(
50
50
  this.client,
51
51
  { logger: this.logger, dateProvider },
52
52
  { ...this.txUtilsConfig, debugMaxGasLimit: acceleratedTestDeployments },
@@ -179,7 +179,7 @@ export async function deployL1Contract(
179
179
 
180
180
  if (!l1TxUtils) {
181
181
  const config = getL1TxUtilsConfigEnvVars();
182
- l1TxUtils = createL1TxUtilsFromViemWallet(
182
+ l1TxUtils = createL1TxUtils(
183
183
  extendedClient,
184
184
  { logger },
185
185
  { ...config, debugMaxGasLimit: acceleratedTestDeployments },
@@ -4,7 +4,7 @@
4
4
  /** Default L1 contracts configuration values from network-defaults.yml */
5
5
  export const l1ContractsDefaultEnv = {
6
6
  ETHEREUM_SLOT_DURATION: 12,
7
- AZTEC_SLOT_DURATION: 36,
7
+ AZTEC_SLOT_DURATION: 72,
8
8
  AZTEC_EPOCH_DURATION: 32,
9
9
  AZTEC_TARGET_COMMITTEE_SIZE: 48,
10
10
  AZTEC_LAG_IN_EPOCHS_FOR_VALIDATOR_SET: 2,
package/src/l1_reader.ts CHANGED
@@ -1,4 +1,9 @@
1
- import { type ConfigMappingsType, getConfigFromMappings, numberConfigHelper } from '@aztec/foundation/config';
1
+ import {
2
+ type ConfigMappingsType,
3
+ getConfigFromMappings,
4
+ numberConfigHelper,
5
+ optionalNumberConfigHelper,
6
+ } from '@aztec/foundation/config';
2
7
 
3
8
  import { type L1ContractAddresses, l1ContractAddressesMapping } from './l1_contract_addresses.js';
4
9
 
@@ -14,6 +19,8 @@ export interface L1ReaderConfig {
14
19
  l1Contracts: L1ContractAddresses;
15
20
  /** The polling interval viem uses in ms */
16
21
  viemPollingIntervalMS: number;
22
+ /** Timeout for HTTP requests to the L1 RPC node in ms. */
23
+ l1HttpTimeoutMS?: number;
17
24
  }
18
25
 
19
26
  export const l1ReaderConfigMappings: ConfigMappingsType<L1ReaderConfig> = {
@@ -43,6 +50,11 @@ export const l1ReaderConfigMappings: ConfigMappingsType<L1ReaderConfig> = {
43
50
  description: 'The polling interval viem uses in ms',
44
51
  ...numberConfigHelper(1_000),
45
52
  },
53
+ l1HttpTimeoutMS: {
54
+ env: 'ETHEREUM_HTTP_TIMEOUT_MS',
55
+ description: 'Timeout for HTTP requests to the L1 RPC node in ms.',
56
+ ...optionalNumberConfigHelper(),
57
+ },
46
58
  };
47
59
 
48
60
  export function getL1ReaderConfigFromEnv(): L1ReaderConfig {
@@ -5,6 +5,7 @@ import {
5
5
  getConfigFromMappings,
6
6
  getDefaultConfig,
7
7
  numberConfigHelper,
8
+ optionalNumberConfigHelper,
8
9
  } from '@aztec/foundation/config';
9
10
 
10
11
  export interface L1TxUtilsConfig {
@@ -60,6 +61,12 @@ export interface L1TxUtilsConfig {
60
61
  * How long a tx nonce can be unseen in the mempool before considering it dropped
61
62
  */
62
63
  txUnseenConsideredDroppedMs?: number;
64
+ /** Enable tx delayer. When true, wraps the viem client to intercept and delay txs. Test-only. */
65
+ enableDelayer?: boolean;
66
+ /** Max seconds into an L1 slot for tx inclusion. Txs sent later are deferred to next slot. Only used when enableDelayer is true. */
67
+ txDelayerMaxInclusionTimeIntoSlot?: number;
68
+ /** How many seconds an L1 slot lasts. */
69
+ ethereumSlotDuration?: number;
63
70
  }
64
71
 
65
72
  export const l1TxUtilsConfigMappings: ConfigMappingsType<L1TxUtilsConfig> = {
@@ -142,6 +149,19 @@ export const l1TxUtilsConfigMappings: ConfigMappingsType<L1TxUtilsConfig> = {
142
149
  env: 'L1_TX_MONITOR_TX_UNSEEN_CONSIDERED_DROPPED_MS',
143
150
  ...numberConfigHelper(6 * 12 * 1000), // 6 L1 blocks
144
151
  },
152
+ enableDelayer: {
153
+ description: 'Enable tx delayer for testing.',
154
+ ...booleanConfigHelper(false),
155
+ },
156
+ txDelayerMaxInclusionTimeIntoSlot: {
157
+ description: 'Max seconds into L1 slot for tx inclusion when delayer is enabled.',
158
+ ...optionalNumberConfigHelper(),
159
+ },
160
+ ethereumSlotDuration: {
161
+ env: 'ETHEREUM_SLOT_DURATION',
162
+ description: 'How many seconds an L1 slot lasts.',
163
+ ...numberConfigHelper(12),
164
+ },
145
165
  };
146
166
 
147
167
  // We abuse the fact that all mappings above have a non null default value and force-type this to Required
@@ -1,64 +1,64 @@
1
+ import type { BlobKzgInstance } from '@aztec/blob-lib/types';
1
2
  import { EthAddress } from '@aztec/foundation/eth-address';
2
3
  import type { Logger } from '@aztec/foundation/log';
3
4
  import { DateProvider } from '@aztec/foundation/timer';
4
5
 
5
- import type { TransactionSerializable } from 'viem';
6
-
7
6
  import type { EthSigner } from '../eth-signer/eth-signer.js';
8
7
  import type { ExtendedViemWalletClient, ViemClient } from '../types.js';
9
8
  import type { L1TxUtilsConfig } from './config.js';
10
9
  import type { IL1TxMetrics, IL1TxStore } from './interfaces.js';
11
10
  import { L1TxUtils } from './l1_tx_utils.js';
12
11
  import { createViemSigner } from './signer.js';
12
+ import { Delayer } from './tx_delayer.js';
13
13
  import type { SigningCallback } from './types.js';
14
14
 
15
- export function createL1TxUtilsFromViemWallet(
16
- client: ExtendedViemWalletClient,
17
- deps?: {
18
- logger?: Logger;
19
- dateProvider?: DateProvider;
20
- store?: IL1TxStore;
21
- metrics?: IL1TxMetrics;
22
- },
23
- config?: Partial<L1TxUtilsConfig> & { debugMaxGasLimit?: boolean },
24
- ): L1TxUtils {
25
- return new L1TxUtils(
15
+ /** Source of signing capability: either a wallet client or a separate client + signer. */
16
+ export type L1SignerSource = ExtendedViemWalletClient | { client: ViemClient; signer: EthSigner };
17
+
18
+ export function resolveSignerSource(source: L1SignerSource): {
19
+ client: ViemClient;
20
+ address: EthAddress;
21
+ signingCallback: SigningCallback;
22
+ } {
23
+ if ('account' in source && source.account) {
24
+ return {
25
+ client: source as ExtendedViemWalletClient,
26
+ address: EthAddress.fromString((source as ExtendedViemWalletClient).account.address),
27
+ signingCallback: createViemSigner(source as ExtendedViemWalletClient),
28
+ };
29
+ }
30
+ const { client, signer } = source as { client: ViemClient; signer: EthSigner };
31
+ return {
26
32
  client,
27
- EthAddress.fromString(client.account.address),
28
- createViemSigner(client),
29
- deps?.logger,
30
- deps?.dateProvider,
31
- config,
32
- config?.debugMaxGasLimit ?? false,
33
- deps?.store,
34
- deps?.metrics,
35
- );
33
+ address: signer.address,
34
+ signingCallback: async (tx, _addr) => (await signer.signTransaction(tx)).toViemTransactionSignature(),
35
+ };
36
36
  }
37
37
 
38
- export function createL1TxUtilsFromEthSigner(
39
- client: ViemClient,
40
- signer: EthSigner,
38
+ export function createL1TxUtils(
39
+ source: L1SignerSource,
41
40
  deps?: {
42
41
  logger?: Logger;
43
42
  dateProvider?: DateProvider;
44
43
  store?: IL1TxStore;
45
44
  metrics?: IL1TxMetrics;
45
+ kzg?: BlobKzgInstance;
46
+ delayer?: Delayer;
46
47
  },
47
48
  config?: Partial<L1TxUtilsConfig> & { debugMaxGasLimit?: boolean },
48
49
  ): L1TxUtils {
49
- const callback: SigningCallback = async (transaction: TransactionSerializable, _signingAddress) => {
50
- return (await signer.signTransaction(transaction)).toViemTransactionSignature();
51
- };
52
-
50
+ const { client, address, signingCallback } = resolveSignerSource(source);
53
51
  return new L1TxUtils(
54
52
  client,
55
- signer.address,
56
- callback,
53
+ address,
54
+ signingCallback,
57
55
  deps?.logger,
58
56
  deps?.dateProvider,
59
57
  config,
60
58
  config?.debugMaxGasLimit ?? false,
61
59
  deps?.store,
62
60
  deps?.metrics,
61
+ deps?.kzg,
62
+ deps?.delayer,
63
63
  );
64
64
  }
@@ -134,7 +134,7 @@ export const P75AllTxsPriorityFeeStrategy: PriorityFeeStrategy = {
134
134
  // Sanity check: cap competitive fee at 100x network estimate to avoid using unrealistic fees
135
135
  const maxReasonableFee = networkEstimate * 100n;
136
136
  if (competitiveFee > maxReasonableFee && networkEstimate > 0n) {
137
- logger?.warn('Competitive fee exceeds sanity cap, using capped value', {
137
+ logger?.debug('Competitive fee exceeds sanity cap, using capped value', {
138
138
  competitiveFee: formatGwei(competitiveFee),
139
139
  networkEstimate: formatGwei(networkEstimate),
140
140
  cappedTo: formatGwei(maxReasonableFee),
@@ -207,7 +207,7 @@ export const P75BlobTxsOnlyPriorityFeeStrategy: PriorityFeeStrategy = {
207
207
 
208
208
  // Debug: Log suspicious fees from history
209
209
  if (medianHistoricalFee > 100n * WEI_CONST) {
210
- logger?.warn('Suspicious high fee in history', {
210
+ logger?.debug('Suspicious high fee in history', {
211
211
  historicalMedian: formatGwei(medianHistoricalFee),
212
212
  allP75Fees: percentile75Fees.map(f => formatGwei(f)),
213
213
  });
@@ -1,25 +1,27 @@
1
+ import type { BlobKzgInstance } from '@aztec/blob-lib/types';
1
2
  import { EthAddress } from '@aztec/foundation/eth-address';
2
3
  import type { Logger } from '@aztec/foundation/log';
3
4
  import type { DateProvider } from '@aztec/foundation/timer';
4
5
 
5
6
  import { type Hex, encodeFunctionData } from 'viem';
6
7
 
7
- import type { EthSigner } from '../eth-signer/eth-signer.js';
8
8
  import { FORWARDER_ABI } from '../forwarder_proxy.js';
9
- import type { ExtendedViemWalletClient, ViemClient } from '../types.js';
9
+ import type { ViemClient } from '../types.js';
10
10
  import type { L1TxUtilsConfig } from './config.js';
11
+ import type { L1SignerSource } from './factory.js';
12
+ import { resolveSignerSource } from './factory.js';
11
13
  import type { IL1TxMetrics, IL1TxStore } from './interfaces.js';
12
- import { L1TxUtilsWithBlobs } from './l1_tx_utils_with_blobs.js';
13
- import { createViemSigner } from './signer.js';
14
+ import { L1TxUtils } from './l1_tx_utils.js';
15
+ import { Delayer } from './tx_delayer.js';
14
16
  import type { L1BlobInputs, L1TxConfig, L1TxRequest, SigningCallback } from './types.js';
15
17
 
16
18
  /**
17
- * Extends L1TxUtilsWithBlobs to wrap all transactions through a forwarder contract.
19
+ * Extends L1TxUtils to wrap all transactions through a forwarder contract.
18
20
  * This is mainly used for testing the archiver's ability to decode transactions that go through proxies.
19
21
  */
20
- export class ForwarderL1TxUtils extends L1TxUtilsWithBlobs {
22
+ export class ForwarderL1TxUtils extends L1TxUtils {
21
23
  constructor(
22
- client: ViemClient | ExtendedViemWalletClient,
24
+ client: ViemClient,
23
25
  senderAddress: EthAddress,
24
26
  signingCallback: SigningCallback,
25
27
  logger: Logger | undefined,
@@ -28,9 +30,23 @@ export class ForwarderL1TxUtils extends L1TxUtilsWithBlobs {
28
30
  debugMaxGasLimit: boolean,
29
31
  store: IL1TxStore | undefined,
30
32
  metrics: IL1TxMetrics | undefined,
33
+ kzg: BlobKzgInstance | undefined,
34
+ delayer: Delayer | undefined,
31
35
  private readonly forwarderAddress: EthAddress,
32
36
  ) {
33
- super(client, senderAddress, signingCallback, logger, dateProvider, config, debugMaxGasLimit, store, metrics);
37
+ super(
38
+ client,
39
+ senderAddress,
40
+ signingCallback,
41
+ logger,
42
+ dateProvider,
43
+ config,
44
+ debugMaxGasLimit,
45
+ store,
46
+ metrics,
47
+ kzg,
48
+ delayer,
49
+ );
34
50
  }
35
51
 
36
52
  /**
@@ -61,59 +77,32 @@ export class ForwarderL1TxUtils extends L1TxUtilsWithBlobs {
61
77
  }
62
78
  }
63
79
 
64
- export function createForwarderL1TxUtilsFromViemWallet(
65
- client: ExtendedViemWalletClient,
80
+ export function createForwarderL1TxUtils(
81
+ source: L1SignerSource,
66
82
  forwarderAddress: EthAddress,
67
- deps: {
83
+ deps?: {
68
84
  logger?: Logger;
69
85
  dateProvider?: DateProvider;
70
86
  store?: IL1TxStore;
71
87
  metrics?: IL1TxMetrics;
72
- } = {},
73
- config: Partial<L1TxUtilsConfig> = {},
74
- debugMaxGasLimit: boolean = false,
75
- ) {
88
+ kzg?: BlobKzgInstance;
89
+ delayer?: Delayer;
90
+ },
91
+ config?: Partial<L1TxUtilsConfig> & { debugMaxGasLimit?: boolean },
92
+ ): ForwarderL1TxUtils {
93
+ const { client, address, signingCallback } = resolveSignerSource(source);
76
94
  return new ForwarderL1TxUtils(
77
95
  client,
78
- EthAddress.fromString(client.account.address),
79
- createViemSigner(client),
80
- deps.logger,
81
- deps.dateProvider,
82
- config,
83
- debugMaxGasLimit,
84
- deps.store,
85
- deps.metrics,
86
- forwarderAddress,
87
- );
88
- }
89
-
90
- export function createForwarderL1TxUtilsFromEthSigner(
91
- client: ViemClient,
92
- signer: EthSigner,
93
- forwarderAddress: EthAddress,
94
- deps: {
95
- logger?: Logger;
96
- dateProvider?: DateProvider;
97
- store?: IL1TxStore;
98
- metrics?: IL1TxMetrics;
99
- } = {},
100
- config: Partial<L1TxUtilsConfig> = {},
101
- debugMaxGasLimit: boolean = false,
102
- ) {
103
- const callback: SigningCallback = async (transaction, _signingAddress) => {
104
- return (await signer.signTransaction(transaction)).toViemTransactionSignature();
105
- };
106
-
107
- return new ForwarderL1TxUtils(
108
- client,
109
- signer.address,
110
- callback,
111
- deps.logger,
112
- deps.dateProvider,
113
- config,
114
- debugMaxGasLimit,
115
- deps.store,
116
- deps.metrics,
96
+ address,
97
+ signingCallback,
98
+ deps?.logger,
99
+ deps?.dateProvider,
100
+ config ?? {},
101
+ config?.debugMaxGasLimit ?? false,
102
+ deps?.store,
103
+ deps?.metrics,
104
+ deps?.kzg,
105
+ deps?.delayer,
117
106
  forwarderAddress,
118
107
  );
119
108
  }