@aztec/ethereum 0.0.1-commit.4d79d1f2d → 0.0.1-commit.4d9804df

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 (176) hide show
  1. package/dest/client.d.ts +25 -3
  2. package/dest/client.d.ts.map +1 -1
  3. package/dest/client.js +60 -8
  4. package/dest/config.d.ts +29 -8
  5. package/dest/config.d.ts.map +1 -1
  6. package/dest/config.js +68 -13
  7. package/dest/contracts/chain_state_override.d.ts +78 -0
  8. package/dest/contracts/chain_state_override.d.ts.map +1 -0
  9. package/dest/contracts/chain_state_override.js +137 -0
  10. package/dest/contracts/fee_asset_price_oracle.d.ts +105 -0
  11. package/dest/contracts/fee_asset_price_oracle.d.ts.map +1 -0
  12. package/dest/contracts/fee_asset_price_oracle.js +656 -0
  13. package/dest/contracts/governance.d.ts +108 -33
  14. package/dest/contracts/governance.d.ts.map +1 -1
  15. package/dest/contracts/governance.js +196 -15
  16. package/dest/contracts/governance_proposer.d.ts +33 -1
  17. package/dest/contracts/governance_proposer.d.ts.map +1 -1
  18. package/dest/contracts/governance_proposer.js +53 -2
  19. package/dest/contracts/gse.d.ts +4 -2
  20. package/dest/contracts/gse.d.ts.map +1 -1
  21. package/dest/contracts/gse.js +2 -2
  22. package/dest/contracts/inbox.d.ts +3 -3
  23. package/dest/contracts/inbox.d.ts.map +1 -1
  24. package/dest/contracts/inbox.js +12 -7
  25. package/dest/contracts/index.d.ts +4 -3
  26. package/dest/contracts/index.d.ts.map +1 -1
  27. package/dest/contracts/index.js +3 -2
  28. package/dest/contracts/multicall.d.ts +130 -13
  29. package/dest/contracts/multicall.d.ts.map +1 -1
  30. package/dest/contracts/multicall.js +203 -94
  31. package/dest/contracts/outbox.d.ts +27 -4
  32. package/dest/contracts/outbox.d.ts.map +1 -1
  33. package/dest/contracts/outbox.js +34 -7
  34. package/dest/contracts/registry.d.ts +3 -1
  35. package/dest/contracts/registry.d.ts.map +1 -1
  36. package/dest/contracts/registry.js +30 -1
  37. package/dest/contracts/rollup.d.ts +5419 -31
  38. package/dest/contracts/rollup.d.ts.map +1 -1
  39. package/dest/contracts/rollup.js +400 -75
  40. package/dest/contracts/{tally_slashing_proposer.d.ts → slashing_proposer.d.ts} +3 -4
  41. package/dest/contracts/slashing_proposer.d.ts.map +1 -0
  42. package/dest/contracts/{tally_slashing_proposer.js → slashing_proposer.js} +13 -15
  43. package/dest/deploy_aztec_l1_contracts.d.ts +19 -12
  44. package/dest/deploy_aztec_l1_contracts.d.ts.map +1 -1
  45. package/dest/deploy_aztec_l1_contracts.js +61 -36
  46. package/dest/deploy_l1_contract.js +3 -3
  47. package/dest/foundry_binary.d.ts +13 -0
  48. package/dest/foundry_binary.d.ts.map +1 -0
  49. package/dest/foundry_binary.js +52 -0
  50. package/dest/l1_artifacts.d.ts +15524 -15847
  51. package/dest/l1_artifacts.d.ts.map +1 -1
  52. package/dest/l1_artifacts.js +9 -24
  53. package/dest/l1_contract_addresses.d.ts +61 -65
  54. package/dest/l1_contract_addresses.d.ts.map +1 -1
  55. package/dest/l1_contract_addresses.js +101 -82
  56. package/dest/l1_reader.d.ts +5 -5
  57. package/dest/l1_reader.d.ts.map +1 -1
  58. package/dest/l1_reader.js +9 -7
  59. package/dest/l1_tx_utils/config.d.ts +7 -1
  60. package/dest/l1_tx_utils/config.d.ts.map +1 -1
  61. package/dest/l1_tx_utils/config.js +17 -4
  62. package/dest/l1_tx_utils/factory.d.ts +18 -10
  63. package/dest/l1_tx_utils/factory.d.ts.map +1 -1
  64. package/dest/l1_tx_utils/factory.js +17 -7
  65. package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts +15 -15
  66. package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts.map +1 -1
  67. package/dest/l1_tx_utils/forwarder_l1_tx_utils.js +9 -15
  68. package/dest/l1_tx_utils/index-blobs.d.ts +3 -3
  69. package/dest/l1_tx_utils/index-blobs.d.ts.map +1 -1
  70. package/dest/l1_tx_utils/index-blobs.js +2 -2
  71. package/dest/l1_tx_utils/index.d.ts +2 -1
  72. package/dest/l1_tx_utils/index.d.ts.map +1 -1
  73. package/dest/l1_tx_utils/index.js +1 -0
  74. package/dest/l1_tx_utils/l1_fee_analyzer.d.ts +23 -4
  75. package/dest/l1_tx_utils/l1_fee_analyzer.d.ts.map +1 -1
  76. package/dest/l1_tx_utils/l1_fee_analyzer.js +65 -3
  77. package/dest/l1_tx_utils/l1_tx_utils.d.ts +26 -7
  78. package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -1
  79. package/dest/l1_tx_utils/l1_tx_utils.js +179 -82
  80. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +1 -1
  81. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -1
  82. package/dest/l1_tx_utils/readonly_l1_tx_utils.js +10 -5
  83. package/dest/l1_tx_utils/tx_delayer.d.ts +58 -0
  84. package/dest/l1_tx_utils/tx_delayer.d.ts.map +1 -0
  85. package/dest/{test → l1_tx_utils}/tx_delayer.js +67 -37
  86. package/dest/l1_tx_utils/types.d.ts +27 -1
  87. package/dest/l1_tx_utils/types.d.ts.map +1 -1
  88. package/dest/l1_tx_utils/types.js +10 -0
  89. package/dest/publisher_manager.d.ts +34 -8
  90. package/dest/publisher_manager.d.ts.map +1 -1
  91. package/dest/publisher_manager.js +119 -8
  92. package/dest/queries.d.ts +13 -2
  93. package/dest/queries.d.ts.map +1 -1
  94. package/dest/queries.js +69 -4
  95. package/dest/test/blob_kzg_warmup.d.ts +19 -0
  96. package/dest/test/blob_kzg_warmup.d.ts.map +1 -0
  97. package/dest/test/blob_kzg_warmup.js +64 -0
  98. package/dest/test/chain_monitor.d.ts +55 -4
  99. package/dest/test/chain_monitor.d.ts.map +1 -1
  100. package/dest/test/chain_monitor.js +104 -3
  101. package/dest/test/eth_cheat_codes.d.ts +37 -6
  102. package/dest/test/eth_cheat_codes.d.ts.map +1 -1
  103. package/dest/test/eth_cheat_codes.js +89 -41
  104. package/dest/test/index.d.ts +2 -3
  105. package/dest/test/index.d.ts.map +1 -1
  106. package/dest/test/index.js +1 -2
  107. package/dest/test/rollup_cheat_codes.d.ts +60 -3
  108. package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
  109. package/dest/test/rollup_cheat_codes.js +86 -7
  110. package/dest/test/start_anvil.d.ts +23 -3
  111. package/dest/test/start_anvil.d.ts.map +1 -1
  112. package/dest/test/start_anvil.js +182 -32
  113. package/dest/test/upgrade_utils.js +2 -2
  114. package/dest/utils.d.ts +9 -2
  115. package/dest/utils.d.ts.map +1 -1
  116. package/dest/utils.js +48 -16
  117. package/package.json +6 -9
  118. package/src/client.ts +66 -2
  119. package/src/config.ts +96 -17
  120. package/src/contracts/chain_state_override.ts +200 -0
  121. package/src/contracts/fee_asset_price_oracle.ts +285 -0
  122. package/src/contracts/governance.ts +269 -12
  123. package/src/contracts/governance_proposer.ts +54 -1
  124. package/src/contracts/gse.ts +7 -2
  125. package/src/contracts/inbox.ts +13 -5
  126. package/src/contracts/index.ts +3 -2
  127. package/src/contracts/multicall.ts +247 -106
  128. package/src/contracts/outbox.ts +42 -8
  129. package/src/contracts/registry.ts +31 -1
  130. package/src/contracts/rollup.ts +457 -86
  131. package/src/contracts/{tally_slashing_proposer.ts → slashing_proposer.ts} +14 -16
  132. package/src/deploy_aztec_l1_contracts.ts +88 -47
  133. package/src/deploy_l1_contract.ts +3 -3
  134. package/src/foundry_binary.ts +57 -0
  135. package/src/l1_artifacts.ts +12 -35
  136. package/src/l1_contract_addresses.ts +120 -94
  137. package/src/l1_reader.ts +17 -10
  138. package/src/l1_tx_utils/config.ts +23 -3
  139. package/src/l1_tx_utils/factory.ts +31 -31
  140. package/src/l1_tx_utils/forwarder_l1_tx_utils.ts +43 -54
  141. package/src/l1_tx_utils/index-blobs.ts +2 -2
  142. package/src/l1_tx_utils/index.ts +1 -0
  143. package/src/l1_tx_utils/l1_fee_analyzer.ts +75 -3
  144. package/src/l1_tx_utils/l1_tx_utils.ts +164 -62
  145. package/src/l1_tx_utils/readonly_l1_tx_utils.ts +10 -5
  146. package/src/{test → l1_tx_utils}/tx_delayer.ts +93 -56
  147. package/src/l1_tx_utils/types.ts +32 -0
  148. package/src/publisher_manager.ts +143 -12
  149. package/src/queries.ts +76 -4
  150. package/src/test/blob_kzg_warmup.ts +65 -0
  151. package/src/test/chain_monitor.ts +148 -3
  152. package/src/test/eth_cheat_codes.ts +82 -45
  153. package/src/test/index.ts +1 -2
  154. package/src/test/rollup_cheat_codes.ts +115 -6
  155. package/src/test/start_anvil.ts +212 -32
  156. package/src/test/upgrade_utils.ts +2 -2
  157. package/src/utils.ts +45 -18
  158. package/dest/contracts/empire_slashing_proposer.d.ts +0 -67
  159. package/dest/contracts/empire_slashing_proposer.d.ts.map +0 -1
  160. package/dest/contracts/empire_slashing_proposer.js +0 -207
  161. package/dest/contracts/tally_slashing_proposer.d.ts.map +0 -1
  162. package/dest/generated/l1-contracts-defaults.d.ts +0 -30
  163. package/dest/generated/l1-contracts-defaults.d.ts.map +0 -1
  164. package/dest/generated/l1-contracts-defaults.js +0 -30
  165. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts +0 -26
  166. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts.map +0 -1
  167. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.js +0 -26
  168. package/dest/test/delayed_tx_utils.d.ts +0 -13
  169. package/dest/test/delayed_tx_utils.d.ts.map +0 -1
  170. package/dest/test/delayed_tx_utils.js +0 -28
  171. package/dest/test/tx_delayer.d.ts +0 -36
  172. package/dest/test/tx_delayer.d.ts.map +0 -1
  173. package/src/contracts/empire_slashing_proposer.ts +0 -259
  174. package/src/generated/l1-contracts-defaults.ts +0 -32
  175. package/src/l1_tx_utils/l1_tx_utils_with_blobs.ts +0 -77
  176. package/src/test/delayed_tx_utils.ts +0 -52
@@ -7,7 +7,7 @@ import { EthAddress } from '@aztec/foundation/eth-address';
7
7
  import { Signature } from '@aztec/foundation/eth-signature';
8
8
  import { hexToBuffer } from '@aztec/foundation/string';
9
9
  import { SlasherAbi } from '@aztec/l1-artifacts/SlasherAbi';
10
- import { TallySlashingProposerAbi } from '@aztec/l1-artifacts/TallySlashingProposerAbi';
10
+ import { SlashingProposerAbi } from '@aztec/l1-artifacts/SlashingProposerAbi';
11
11
 
12
12
  import {
13
13
  type GetContractReturnType,
@@ -19,13 +19,11 @@ import {
19
19
  } from 'viem';
20
20
 
21
21
  /**
22
- * Wrapper around the TallySlashingProposer contract that provides
22
+ * Wrapper around the SlashingProposer contract that provides
23
23
  * a TypeScript interface for interacting with the consensus-based slashing system.
24
24
  */
25
- export class TallySlashingProposerContract {
26
- private readonly contract: GetContractReturnType<typeof TallySlashingProposerAbi, ViemClient>;
27
-
28
- public readonly type = 'tally' as const;
25
+ export class SlashingProposerContract {
26
+ private readonly contract: GetContractReturnType<typeof SlashingProposerAbi, ViemClient>;
29
27
 
30
28
  constructor(
31
29
  public readonly client: ViemClient,
@@ -33,7 +31,7 @@ export class TallySlashingProposerContract {
33
31
  ) {
34
32
  this.contract = getContract({
35
33
  address: typeof address === 'string' ? address : address.toString(),
36
- abi: TallySlashingProposerAbi,
34
+ abi: SlashingProposerAbi,
37
35
  client,
38
36
  });
39
37
  }
@@ -136,12 +134,12 @@ export class TallySlashingProposerContract {
136
134
 
137
135
  /** Tries to extract a VoteCast event from the given logs. */
138
136
  public tryExtractVoteCastEvent(logs: Log[]) {
139
- return tryExtractEvent(logs, this.address.toString(), TallySlashingProposerAbi, 'VoteCast');
137
+ return tryExtractEvent(logs, this.address.toString(), SlashingProposerAbi, 'VoteCast');
140
138
  }
141
139
 
142
140
  /** Tries to extract a RoundExecuted event from the given logs. */
143
141
  public tryExtractRoundExecutedEvent(logs: Log[]) {
144
- return tryExtractEvent(logs, this.address.toString(), TallySlashingProposerAbi, 'RoundExecuted');
142
+ return tryExtractEvent(logs, this.address.toString(), SlashingProposerAbi, 'RoundExecuted');
145
143
  }
146
144
 
147
145
  /**
@@ -161,9 +159,9 @@ export class TallySlashingProposerContract {
161
159
 
162
160
  return {
163
161
  to: this.contract.address,
164
- abi: TallySlashingProposerAbi,
162
+ abi: SlashingProposerAbi,
165
163
  data: encodeFunctionData({
166
- abi: TallySlashingProposerAbi,
164
+ abi: SlashingProposerAbi,
167
165
  functionName: 'vote',
168
166
  args: [votes, signature.toViemSignature()],
169
167
  }),
@@ -173,7 +171,7 @@ export class TallySlashingProposerContract {
173
171
  /** Returns the typed data definition to EIP712-sign for voting */
174
172
  public buildVoteTypedData(votes: Hex, slot: SlotNumber): TypedDataDefinition {
175
173
  const domain = {
176
- name: 'TallySlashingProposer',
174
+ name: 'SlashingProposer',
177
175
  version: '1',
178
176
  chainId: this.client.chain.id,
179
177
  verifyingContract: this.contract.address,
@@ -209,9 +207,9 @@ export class TallySlashingProposerContract {
209
207
  public buildVoteRequestWithSignature(votes: Hex, signature: { v: number; r: Hex; s: Hex }): L1TxRequest {
210
208
  return {
211
209
  to: this.contract.address,
212
- abi: TallySlashingProposerAbi,
210
+ abi: SlashingProposerAbi,
213
211
  data: encodeFunctionData({
214
- abi: TallySlashingProposerAbi,
212
+ abi: SlashingProposerAbi,
215
213
  functionName: 'vote',
216
214
  args: [votes, signature],
217
215
  }),
@@ -227,9 +225,9 @@ export class TallySlashingProposerContract {
227
225
  public buildExecuteRoundRequest(round: bigint, committees: EthAddress[][]): L1TxRequest {
228
226
  return {
229
227
  to: this.contract.address,
230
- abi: mergeAbis([TallySlashingProposerAbi, SlasherAbi]),
228
+ abi: mergeAbis([SlashingProposerAbi, SlasherAbi]),
231
229
  data: encodeFunctionData({
232
- abi: TallySlashingProposerAbi,
230
+ abi: SlashingProposerAbi,
233
231
  functionName: 'executeRound',
234
232
  args: [round, committees.map(c => c.map(addr => addr.toString()))],
235
233
  }),
@@ -5,12 +5,12 @@ import { jsonStringify } from '@aztec/foundation/json-rpc';
5
5
  import { createLogger } from '@aztec/foundation/log';
6
6
  import { promiseWithResolvers } from '@aztec/foundation/promise';
7
7
  import type { Fr } from '@aztec/foundation/schemas';
8
- import { fileURLToPath } from '@aztec/foundation/url';
9
8
 
10
9
  import { bn254 } from '@noble/curves/bn254';
11
10
  import type { Abi, Narrow } from 'abitype';
12
11
  import { spawn } from 'child_process';
13
12
  import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'fs';
13
+ import { createRequire } from 'node:module';
14
14
  import { tmpdir } from 'os';
15
15
  import { dirname, join, resolve } from 'path';
16
16
  import readline from 'readline';
@@ -19,21 +19,23 @@ import { mainnet, sepolia } from 'viem/chains';
19
19
 
20
20
  import { createEthereumChain, isAnvilTestChain } from './chain.js';
21
21
  import { createExtendedL1Client } from './client.js';
22
- import type { L1ContractsConfig } from './config.js';
22
+ import { type L1ContractsConfig, assertValidSlotDurations } from './config.js';
23
23
  import { deployMulticall3 } from './contracts/multicall.js';
24
24
  import { RollupContract } from './contracts/rollup.js';
25
+ import { resolveFoundryBinary } from './foundry_binary.js';
25
26
  import type { L1ContractAddresses } from './l1_contract_addresses.js';
26
- import type { L1TxUtilsConfig } from './l1_tx_utils/config.js';
27
27
  import type { ExtendedViemWalletClient } from './types.js';
28
28
 
29
29
  const logger = createLogger('ethereum:deploy_aztec_l1_contracts');
30
30
 
31
+ const require = createRequire(import.meta.url);
32
+
31
33
  const JSON_DEPLOY_RESULT_PREFIX = 'JSON DEPLOY RESULT:';
32
34
 
33
35
  /**
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.
36
+ * Runs a process and parses JSON deploy results from stdout.
37
+ * Lines starting with JSON_DEPLOY_RESULT_PREFIX are parsed and returned.
38
+ * All other stdout goes to logger.info, stderr goes to logger.warn.
37
39
  */
38
40
  function runProcess<T>(
39
41
  command: string,
@@ -49,26 +51,41 @@ function runProcess<T>(
49
51
  });
50
52
 
51
53
  let result: T | undefined;
54
+ let parseError: Error | undefined;
55
+ let settled = false;
52
56
 
53
57
  readline.createInterface({ input: proc.stdout }).on('line', line => {
54
58
  const trimmedLine = line.trim();
55
59
  if (trimmedLine.startsWith(JSON_DEPLOY_RESULT_PREFIX)) {
56
60
  const jsonStr = trimmedLine.slice(JSON_DEPLOY_RESULT_PREFIX.length).trim();
57
- // TODO(AD): should this be a zod parse?
58
- result = JSON.parse(jsonStr);
61
+ try {
62
+ result = JSON.parse(jsonStr);
63
+ } catch {
64
+ parseError = new Error(`Failed to parse deploy result JSON: ${jsonStr.slice(0, 200)}`);
65
+ }
59
66
  } else {
60
67
  logger.info(line);
61
68
  }
62
69
  });
63
- readline.createInterface({ input: proc.stderr }).on('line', logger.error.bind(logger));
70
+ readline.createInterface({ input: proc.stderr }).on('line', logger.warn.bind(logger));
64
71
 
65
72
  proc.on('error', error => {
73
+ if (settled) {
74
+ return;
75
+ }
76
+ settled = true;
66
77
  reject(new Error(`Failed to spawn ${command}: ${error.message}`));
67
78
  });
68
79
 
69
80
  proc.on('close', code => {
81
+ if (settled) {
82
+ return;
83
+ }
84
+ settled = true;
70
85
  if (code !== 0) {
71
- reject(new Error(`${command} exited with code ${code}. See logs for details.\n`));
86
+ reject(new Error(`${command} exited with code ${code}`));
87
+ } else if (parseError) {
88
+ reject(parseError);
72
89
  } else {
73
90
  resolve(result);
74
91
  }
@@ -79,11 +96,16 @@ function runProcess<T>(
79
96
 
80
97
  // Covers an edge where where we may have a cached BlobLib that is not meant for production.
81
98
  // Despite the profile apparently sometimes cached code remains (so says Lasse after his ignition-monorepo arc).
82
- async function maybeForgeForceProductionBuild(l1ContractsPath: string, script: string, chainId: number) {
99
+ async function maybeForgeForceProductionBuild(
100
+ forgeBin: string,
101
+ l1ContractsPath: string,
102
+ script: string,
103
+ chainId: number,
104
+ ) {
83
105
  if (chainId === mainnet.id) {
84
106
  logger.info(`Recompiling ${script} with production profile for mainnet deployment`);
85
107
  logger.info('This may take a minute but ensures production BlobLib is used.');
86
- await runProcess('forge', ['build', script, '--force'], { FOUNDRY_PROFILE: 'production' }, l1ContractsPath);
108
+ await runProcess(forgeBin, ['build', script, '--force'], { FOUNDRY_PROFILE: 'production' }, l1ContractsPath);
87
109
  }
88
110
  }
89
111
 
@@ -109,15 +131,13 @@ export interface ValidatorJson {
109
131
  }
110
132
 
111
133
  /**
112
- * Gets the path to the l1-contracts foundry artifacts directory.
113
- * These are copied from l1-contracts to yarn-project/l1-artifacts/l1-contracts
114
- * during build to make yarn-project self-contained.
134
+ * Gets the path to the l1-contracts foundry artifacts directory bundled inside @aztec/l1-artifacts.
135
+ * Resolved through the package (its "." export -> dest/index.js) so it works whether the package is
136
+ * linked via portal (monorepo) or installed under node_modules (published npm) — resolution follows
137
+ * the symlink in the portal case. The bundled foundry subtree sits alongside dest/, at <pkg>/l1-contracts.
115
138
  */
116
139
  export function getL1ContractsPath(): string {
117
- const currentDir = dirname(fileURLToPath(import.meta.url));
118
- // Go up from yarn-project/ethereum/dest to yarn-project, then to l1-artifacts/l1-contracts
119
- const l1ContractsPath = resolve(currentDir, '..', '..', 'l1-artifacts', 'l1-contracts');
120
- return l1ContractsPath;
140
+ return resolve(dirname(require.resolve('@aztec/l1-artifacts')), '..', 'l1-contracts');
121
141
  }
122
142
 
123
143
  // Cached deployment directory
@@ -216,7 +236,6 @@ export function computeValidatorData(operator: Operator): ValidatorJson {
216
236
  export interface RollupUpgradeAddresses {
217
237
  rollupAddress: string;
218
238
  verifierAddress: string;
219
- slashFactoryAddress: string;
220
239
  inboxAddress: string;
221
240
  outboxAddress: string;
222
241
  feeJuicePortalAddress: string;
@@ -229,7 +248,6 @@ export interface RollupUpgradeAddresses {
229
248
  export interface ForgeRollupUpgradeResult {
230
249
  rollupAddress: Hex;
231
250
  verifierAddress: Hex;
232
- slashFactoryAddress: Hex;
233
251
  inboxAddress: Hex;
234
252
  outboxAddress: Hex;
235
253
  feeJuicePortalAddress: Hex;
@@ -270,6 +288,7 @@ export async function deployAztecL1Contracts(
270
288
  args: DeployAztecL1ContractsArgs,
271
289
  ): Promise<DeployAztecL1ContractsReturnType> {
272
290
  logger.info(`Deploying L1 contracts with config: ${jsonStringify(args)}`);
291
+ assertValidSlotDurations(args);
273
292
  if (args.initialValidators && args.initialValidators.length > 0 && args.existingTokenAddress) {
274
293
  throw new Error(
275
294
  'Cannot deploy with both initialValidators and existingTokenAddress. ' +
@@ -307,8 +326,9 @@ export async function deployAztecL1Contracts(
307
326
  // Use foundry-artifacts from l1-artifacts package
308
327
  const l1ContractsPath = prepareL1ContractsForDeployment();
309
328
 
329
+ const forgeBin = resolveFoundryBinary('forge');
310
330
  const FORGE_SCRIPT = 'script/deploy/DeployAztecL1Contracts.s.sol';
311
- await maybeForgeForceProductionBuild(l1ContractsPath, FORGE_SCRIPT, chainId);
331
+ await maybeForgeForceProductionBuild(forgeBin, l1ContractsPath, FORGE_SCRIPT, chainId);
312
332
 
313
333
  // Verify contracts on Etherscan when on mainnet/sepolia and ETHERSCAN_API_KEY is available.
314
334
  const isVerifiableChain = chainId === mainnet.id || chainId === sepolia.id;
@@ -321,11 +341,8 @@ export async function deployAztecL1Contracts(
321
341
  );
322
342
  }
323
343
 
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.
344
+ const scriptPath = join(getL1ContractsPath(), 'scripts', 'forge_broadcast.js');
327
345
  const forgeArgs = [
328
- 'script',
329
346
  FORGE_SCRIPT,
330
347
  '--sig',
331
348
  'run()',
@@ -333,18 +350,22 @@ export async function deployAztecL1Contracts(
333
350
  privateKey,
334
351
  '--rpc-url',
335
352
  rpcUrl,
336
- '--broadcast',
337
- '--batch-size',
338
- MAGIC_ANVIL_BATCH_SIZE.toString(),
339
353
  ...(shouldVerify ? ['--verify'] : []),
340
354
  ];
341
355
  const forgeEnv = {
356
+ // Resolved forge binary picked up by forge_broadcast.js, so it works without forge on PATH.
357
+ FORGE_BIN: forgeBin,
342
358
  // Env vars required by l1-contracts/script/deploy/DeploymentConfiguration.sol.
343
359
  NETWORK: getActiveNetworkName(),
344
360
  FOUNDRY_PROFILE: chainId === mainnet.id ? 'production' : undefined,
345
361
  ...getDeployAztecL1ContractsEnvVars(args),
346
362
  };
347
- const result = await runProcess<ForgeL1ContractsDeployResult>('forge', forgeArgs, forgeEnv, l1ContractsPath);
363
+ const result = await runProcess<ForgeL1ContractsDeployResult>(
364
+ process.execPath,
365
+ [scriptPath, ...forgeArgs],
366
+ forgeEnv,
367
+ l1ContractsPath,
368
+ );
348
369
  if (!result) {
349
370
  throw new Error('Forge script did not output deployment result');
350
371
  }
@@ -390,7 +411,6 @@ export async function deployAztecL1Contracts(
390
411
  governanceProposerAddress: EthAddress.fromString(result.governanceProposerAddress),
391
412
  governanceAddress: EthAddress.fromString(result.governanceAddress),
392
413
  stakingAssetAddress: EthAddress.fromString(result.stakingAssetAddress),
393
- slashFactoryAddress: result.slashFactoryAddress ? EthAddress.fromString(result.slashFactoryAddress) : undefined,
394
414
  feeAssetHandlerAddress: result.feeAssetHandlerAddress
395
415
  ? EthAddress.fromString(result.feeAssetHandlerAddress)
396
416
  : undefined,
@@ -477,7 +497,25 @@ export type VerificationRecord = {
477
497
  libraries: VerificationLibraryEntry[];
478
498
  };
479
499
 
480
- export interface DeployAztecL1ContractsArgs extends Omit<L1ContractsConfig, keyof L1TxUtilsConfig> {
500
+ export interface DeployAztecL1ContractsArgs
501
+ extends Omit<
502
+ L1ContractsConfig,
503
+ | 'gasLimitBufferPercentage'
504
+ | 'maxGwei'
505
+ | 'maxBlobGwei'
506
+ | 'priorityFeeBumpPercentage'
507
+ | 'priorityFeeRetryBumpPercentage'
508
+ | 'minimumPriorityFeePerGas'
509
+ | 'maxSpeedUpAttempts'
510
+ | 'checkIntervalMs'
511
+ | 'stallTimeMs'
512
+ | 'txTimeoutMs'
513
+ | 'cancelTxOnTimeout'
514
+ | 'txCancellationFinalTimeoutMs'
515
+ | 'txUnseenConsideredDroppedMs'
516
+ | 'enableDelayer'
517
+ | 'txDelayerMaxInclusionTimeIntoSlot'
518
+ > {
481
519
  /** The vk tree root. */
482
520
  vkTreeRoot: Fr;
483
521
  /** The hash of the protocol contracts. */
@@ -554,13 +592,18 @@ export function getDeployRollupForUpgradeEnvVars(
554
592
  AZTEC_EXIT_DELAY_SECONDS: args.exitDelaySeconds.toString(),
555
593
  AZTEC_PROVING_COST_PER_MANA: args.provingCostPerMana.toString(),
556
594
  AZTEC_INITIAL_ETH_PER_FEE_ASSET: args.initialEthPerFeeAsset.toString(),
557
- AZTEC_SLASHER_FLAVOR: args.slasherFlavor,
595
+ AZTEC_SLASHER_ENABLED: args.slasherEnabled ? 'true' : 'false',
558
596
  AZTEC_SLASHING_ROUND_SIZE_IN_EPOCHS: args.slashingRoundSizeInEpochs.toString(),
559
597
  AZTEC_SLASHING_QUORUM: args.slashingQuorum?.toString(),
560
598
  AZTEC_SLASHING_OFFSET_IN_ROUNDS: args.slashingOffsetInRounds.toString(),
561
599
  AZTEC_SLASH_AMOUNT_SMALL: args.slashAmountSmall.toString(),
562
600
  AZTEC_SLASH_AMOUNT_MEDIUM: args.slashAmountMedium.toString(),
563
601
  AZTEC_SLASH_AMOUNT_LARGE: args.slashAmountLarge.toString(),
602
+ AZTEC_ENTRY_QUEUE_BOOTSTRAP_VALIDATOR_SET_SIZE: args.entryQueueBootstrapValidatorSetSize.toString(),
603
+ AZTEC_ENTRY_QUEUE_BOOTSTRAP_FLUSH_SIZE: args.entryQueueBootstrapFlushSize.toString(),
604
+ AZTEC_ENTRY_QUEUE_FLUSH_SIZE_MIN: args.entryQueueFlushSizeMin.toString(),
605
+ AZTEC_ENTRY_QUEUE_FLUSH_SIZE_QUOTIENT: args.entryQueueFlushSizeQuotient.toString(),
606
+ AZTEC_ENTRY_QUEUE_MAX_FLUSH_SIZE: args.entryQueueMaxFlushSize.toString(),
564
607
  } as const;
565
608
  }
566
609
 
@@ -584,21 +627,15 @@ export const deployRollupForUpgrade = async (
584
627
  // Use foundry-artifacts from l1-artifacts package
585
628
  const l1ContractsPath = prepareL1ContractsForDeployment();
586
629
 
630
+ const forgeBin = resolveFoundryBinary('forge');
587
631
  const FORGE_SCRIPT = 'script/deploy/DeployRollupForUpgrade.s.sol';
588
- await maybeForgeForceProductionBuild(l1ContractsPath, FORGE_SCRIPT, chainId);
632
+ await maybeForgeForceProductionBuild(forgeBin, l1ContractsPath, FORGE_SCRIPT, chainId);
589
633
 
590
- const forgeArgs = [
591
- 'script',
592
- FORGE_SCRIPT,
593
- '--sig',
594
- 'run()',
595
- '--private-key',
596
- privateKey,
597
- '--rpc-url',
598
- rpcUrl,
599
- '--broadcast',
600
- ];
634
+ const scriptPath = join(getL1ContractsPath(), 'scripts', 'forge_broadcast.js');
635
+ const forgeArgs = [FORGE_SCRIPT, '--sig', 'run()', '--private-key', privateKey, '--rpc-url', rpcUrl];
601
636
  const forgeEnv = {
637
+ // Resolved forge binary picked up by forge_broadcast.js, so it works without forge on PATH.
638
+ FORGE_BIN: forgeBin,
602
639
  FOUNDRY_PROFILE: chainId === mainnet.id ? 'production' : undefined,
603
640
  // Env vars required by l1-contracts/script/deploy/RollupConfiguration.sol.
604
641
  REGISTRY_ADDRESS: registryAddress.toString(),
@@ -606,7 +643,12 @@ export const deployRollupForUpgrade = async (
606
643
  ...getDeployRollupForUpgradeEnvVars(args),
607
644
  };
608
645
 
609
- const result = await runProcess<ForgeRollupUpgradeResult>('forge', forgeArgs, forgeEnv, l1ContractsPath);
646
+ const result = await runProcess<ForgeRollupUpgradeResult>(
647
+ process.execPath,
648
+ [scriptPath, ...forgeArgs],
649
+ forgeEnv,
650
+ l1ContractsPath,
651
+ );
610
652
  if (!result) {
611
653
  throw new Error('Forge script did not output deployment result');
612
654
  }
@@ -618,6 +660,5 @@ export const deployRollupForUpgrade = async (
618
660
 
619
661
  return {
620
662
  rollup,
621
- slashFactoryAddress: result.slashFactoryAddress,
622
663
  };
623
664
  };
@@ -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 },
@@ -0,0 +1,57 @@
1
+ import { spawnSync } from 'child_process';
2
+ import { accessSync, constants } from 'fs';
3
+ import { homedir } from 'os';
4
+ import { join } from 'path';
5
+
6
+ function isExecutable(path: string): boolean {
7
+ try {
8
+ accessSync(path, constants.X_OK);
9
+ return true;
10
+ } catch {
11
+ return false;
12
+ }
13
+ }
14
+
15
+ /**
16
+ * Locate a Foundry binary (`anvil`, `forge`, ...) without relying on the caller's PATH. Order:
17
+ * 1. `$<NAME>_BIN` (e.g. `$ANVIL_BIN`, `$FORGE_BIN`) — explicit override, e.g. for CI with a pinned
18
+ * version. Throws if set but not pointing at an executable, instead of silently falling back.
19
+ * 2. `~/.aztec/current/internal-bin/<name>` — where aztec-up installs it.
20
+ * 3. `~/.aztec/current/bin/aztec-<name>` — the publicly-exposed symlink.
21
+ * 4. `~/.foundry/bin/<name>` — standalone foundryup install.
22
+ * 5. `command -v <name>` — anything else on PATH.
23
+ *
24
+ * Throws with a directive message if none work.
25
+ */
26
+ export function resolveFoundryBinary(name: string): string {
27
+ const envVar = `${name.toUpperCase()}_BIN`;
28
+ const envBin = process.env[envVar];
29
+ if (envBin) {
30
+ if (!isExecutable(envBin)) {
31
+ throw new Error(`$${envVar} is set to ${envBin}, which does not exist or is not executable.`);
32
+ }
33
+ return envBin;
34
+ }
35
+
36
+ const candidates = [
37
+ join(homedir(), '.aztec', 'current', 'internal-bin', name),
38
+ join(homedir(), '.aztec', 'current', 'bin', `aztec-${name}`),
39
+ join(homedir(), '.foundry', 'bin', name),
40
+ ];
41
+ for (const path of candidates) {
42
+ if (isExecutable(path)) {
43
+ return path;
44
+ }
45
+ }
46
+
47
+ const which = spawnSync('sh', ['-c', `command -v ${name}`], { encoding: 'utf8' });
48
+ if (which.status === 0 && which.stdout.trim()) {
49
+ return which.stdout.trim();
50
+ }
51
+
52
+ throw new Error(
53
+ `${name} binary not found. Tried $${envVar}, ~/.aztec/current/internal-bin/${name}, ` +
54
+ `~/.aztec/current/bin/aztec-${name}, ~/.foundry/bin/${name}, and $PATH. ` +
55
+ `Install via \`aztec-up\` or set ${envVar} to a working binary.`,
56
+ );
57
+ }
@@ -3,10 +3,6 @@ import {
3
3
  CoinIssuerBytecode,
4
4
  DateGatedRelayerAbi,
5
5
  DateGatedRelayerBytecode,
6
- EmpireSlasherDeploymentExtLibAbi,
7
- EmpireSlasherDeploymentExtLibBytecode,
8
- EmpireSlashingProposerAbi,
9
- EmpireSlashingProposerBytecode,
10
6
  FeeAssetHandlerAbi,
11
7
  FeeAssetHandlerBytecode,
12
8
  FeeJuicePortalAbi,
@@ -42,16 +38,14 @@ import {
42
38
  RollupLinkReferences,
43
39
  RollupOperationsExtLibAbi,
44
40
  RollupOperationsExtLibBytecode,
45
- SlashFactoryAbi,
46
- SlashFactoryBytecode,
47
41
  SlasherAbi,
48
42
  SlasherBytecode,
43
+ SlasherDeploymentExtLibAbi,
44
+ SlasherDeploymentExtLibBytecode,
45
+ SlashingProposerAbi,
46
+ SlashingProposerBytecode,
49
47
  StakingAssetHandlerAbi,
50
48
  StakingAssetHandlerBytecode,
51
- TallySlasherDeploymentExtLibAbi,
52
- TallySlasherDeploymentExtLibBytecode,
53
- TallySlashingProposerAbi,
54
- TallySlashingProposerBytecode,
55
49
  TestERC20Abi,
56
50
  TestERC20Bytecode,
57
51
  ValidatorOperationsExtLibAbi,
@@ -107,15 +101,10 @@ export const RollupArtifact = {
107
101
  contractAbi: RewardExtLibAbi,
108
102
  contractBytecode: RewardExtLibBytecode as Hex,
109
103
  },
110
- TallySlasherDeploymentExtLib: {
111
- name: 'TallySlasherDeploymentExtLib',
112
- contractAbi: TallySlasherDeploymentExtLibAbi,
113
- contractBytecode: TallySlasherDeploymentExtLibBytecode as Hex,
114
- },
115
- EmpireSlasherDeploymentExtLib: {
116
- name: 'EmpireSlasherDeploymentExtLib',
117
- contractAbi: EmpireSlasherDeploymentExtLibAbi,
118
- contractBytecode: EmpireSlasherDeploymentExtLibBytecode as Hex,
104
+ SlasherDeploymentExtLib: {
105
+ name: 'SlasherDeploymentExtLib',
106
+ contractAbi: SlasherDeploymentExtLibAbi,
107
+ contractBytecode: SlasherDeploymentExtLibBytecode as Hex,
119
108
  },
120
109
  },
121
110
  },
@@ -175,22 +164,10 @@ export const SlasherArtifact = {
175
164
  contractBytecode: SlasherBytecode as Hex,
176
165
  };
177
166
 
178
- export const EmpireSlashingProposerArtifact = {
179
- name: 'EmpireSlashingProposer',
180
- contractAbi: EmpireSlashingProposerAbi,
181
- contractBytecode: EmpireSlashingProposerBytecode as Hex,
182
- };
183
-
184
- export const TallySlashingProposerArtifact = {
185
- name: 'TallySlashingProposer',
186
- contractAbi: TallySlashingProposerAbi,
187
- contractBytecode: TallySlashingProposerBytecode as Hex,
188
- };
189
-
190
- export const SlashFactoryArtifact = {
191
- name: 'SlashFactory',
192
- contractAbi: SlashFactoryAbi,
193
- contractBytecode: SlashFactoryBytecode as Hex,
167
+ export const SlashingProposerArtifact = {
168
+ name: 'SlashingProposer',
169
+ contractAbi: SlashingProposerAbi,
170
+ contractBytecode: SlashingProposerBytecode as Hex,
194
171
  };
195
172
 
196
173
  export const RegisterNewRollupVersionPayloadArtifact = {