@aztec/ethereum 0.0.1-commit.fce3e4f → 0.0.1-commit.ff7989d6c

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 (199) hide show
  1. package/dest/client.js +6 -2
  2. package/dest/config.d.ts +19 -68
  3. package/dest/config.d.ts.map +1 -1
  4. package/dest/config.js +55 -380
  5. package/dest/contracts/empire_base.d.ts +4 -1
  6. package/dest/contracts/empire_base.d.ts.map +1 -1
  7. package/dest/contracts/empire_slashing_proposer.d.ts +4 -1
  8. package/dest/contracts/empire_slashing_proposer.d.ts.map +1 -1
  9. package/dest/contracts/empire_slashing_proposer.js +31 -15
  10. package/dest/contracts/fee_asset_handler.d.ts +6 -5
  11. package/dest/contracts/fee_asset_handler.d.ts.map +1 -1
  12. package/dest/contracts/fee_asset_handler.js +11 -9
  13. package/dest/contracts/fee_asset_price_oracle.d.ts +101 -0
  14. package/dest/contracts/fee_asset_price_oracle.d.ts.map +1 -0
  15. package/dest/contracts/fee_asset_price_oracle.js +651 -0
  16. package/dest/contracts/governance.d.ts +3 -1
  17. package/dest/contracts/governance.d.ts.map +1 -1
  18. package/dest/contracts/governance.js +14 -4
  19. package/dest/contracts/governance_proposer.d.ts +4 -1
  20. package/dest/contracts/governance_proposer.d.ts.map +1 -1
  21. package/dest/contracts/governance_proposer.js +404 -9
  22. package/dest/contracts/inbox.d.ts +24 -3
  23. package/dest/contracts/inbox.d.ts.map +1 -1
  24. package/dest/contracts/inbox.js +36 -1
  25. package/dest/contracts/index.d.ts +4 -1
  26. package/dest/contracts/index.d.ts.map +1 -1
  27. package/dest/contracts/index.js +3 -0
  28. package/dest/contracts/log.d.ts +13 -0
  29. package/dest/contracts/log.d.ts.map +1 -0
  30. package/dest/contracts/log.js +1 -0
  31. package/dest/contracts/multicall.d.ts +1 -1
  32. package/dest/contracts/multicall.d.ts.map +1 -1
  33. package/dest/contracts/multicall.js +2 -1
  34. package/dest/contracts/outbox.d.ts +41 -0
  35. package/dest/contracts/outbox.d.ts.map +1 -0
  36. package/dest/contracts/outbox.js +86 -0
  37. package/dest/contracts/rollup.d.ts +177 -96
  38. package/dest/contracts/rollup.d.ts.map +1 -1
  39. package/dest/contracts/rollup.js +707 -144
  40. package/dest/contracts/tally_slashing_proposer.d.ts +3 -2
  41. package/dest/contracts/tally_slashing_proposer.d.ts.map +1 -1
  42. package/dest/contracts/tally_slashing_proposer.js +8 -1
  43. package/dest/deploy_aztec_l1_contracts.d.ts +259 -0
  44. package/dest/deploy_aztec_l1_contracts.d.ts.map +1 -0
  45. package/dest/deploy_aztec_l1_contracts.js +413 -0
  46. package/dest/deploy_l1_contract.d.ts +68 -0
  47. package/dest/deploy_l1_contract.d.ts.map +1 -0
  48. package/dest/deploy_l1_contract.js +312 -0
  49. package/dest/forwarder_proxy.d.ts +32 -0
  50. package/dest/forwarder_proxy.d.ts.map +1 -0
  51. package/dest/forwarder_proxy.js +93 -0
  52. package/dest/generated/l1-contracts-defaults.d.ts +30 -0
  53. package/dest/generated/l1-contracts-defaults.d.ts.map +1 -0
  54. package/dest/generated/l1-contracts-defaults.js +30 -0
  55. package/dest/l1_artifacts.d.ts +5975 -1575
  56. package/dest/l1_artifacts.d.ts.map +1 -1
  57. package/dest/l1_contract_addresses.d.ts +1 -1
  58. package/dest/l1_contract_addresses.d.ts.map +1 -1
  59. package/dest/l1_contract_addresses.js +3 -3
  60. package/dest/l1_reader.d.ts +3 -1
  61. package/dest/l1_reader.d.ts.map +1 -1
  62. package/dest/l1_reader.js +6 -0
  63. package/dest/l1_tx_utils/config.d.ts +9 -3
  64. package/dest/l1_tx_utils/config.d.ts.map +1 -1
  65. package/dest/l1_tx_utils/config.js +31 -4
  66. package/dest/l1_tx_utils/constants.d.ts +8 -2
  67. package/dest/l1_tx_utils/constants.d.ts.map +1 -1
  68. package/dest/l1_tx_utils/constants.js +27 -2
  69. package/dest/l1_tx_utils/factory.d.ts +18 -10
  70. package/dest/l1_tx_utils/factory.d.ts.map +1 -1
  71. package/dest/l1_tx_utils/factory.js +17 -7
  72. package/dest/l1_tx_utils/fee-strategies/index.d.ts +10 -0
  73. package/dest/l1_tx_utils/fee-strategies/index.d.ts.map +1 -0
  74. package/dest/l1_tx_utils/fee-strategies/index.js +12 -0
  75. package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts +8 -0
  76. package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts.map +1 -0
  77. package/dest/l1_tx_utils/fee-strategies/p75_competitive.js +129 -0
  78. package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.d.ts +23 -0
  79. package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.d.ts.map +1 -0
  80. package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.js +191 -0
  81. package/dest/l1_tx_utils/fee-strategies/types.d.ts +51 -0
  82. package/dest/l1_tx_utils/fee-strategies/types.d.ts.map +1 -0
  83. package/dest/l1_tx_utils/fee-strategies/types.js +3 -0
  84. package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts +41 -0
  85. package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts.map +1 -0
  86. package/dest/l1_tx_utils/forwarder_l1_tx_utils.js +42 -0
  87. package/dest/l1_tx_utils/index-blobs.d.ts +3 -0
  88. package/dest/l1_tx_utils/index-blobs.d.ts.map +1 -0
  89. package/dest/l1_tx_utils/index-blobs.js +2 -0
  90. package/dest/l1_tx_utils/index.d.ts +4 -1
  91. package/dest/l1_tx_utils/index.d.ts.map +1 -1
  92. package/dest/l1_tx_utils/index.js +3 -0
  93. package/dest/l1_tx_utils/interfaces.d.ts +2 -2
  94. package/dest/l1_tx_utils/interfaces.d.ts.map +1 -1
  95. package/dest/l1_tx_utils/l1_fee_analyzer.d.ts +233 -0
  96. package/dest/l1_tx_utils/l1_fee_analyzer.d.ts.map +1 -0
  97. package/dest/l1_tx_utils/l1_fee_analyzer.js +506 -0
  98. package/dest/l1_tx_utils/l1_tx_utils.d.ts +15 -5
  99. package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -1
  100. package/dest/l1_tx_utils/l1_tx_utils.js +64 -17
  101. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +4 -15
  102. package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -1
  103. package/dest/l1_tx_utils/readonly_l1_tx_utils.js +53 -160
  104. package/dest/l1_tx_utils/tx_delayer.d.ts +56 -0
  105. package/dest/l1_tx_utils/tx_delayer.d.ts.map +1 -0
  106. package/dest/{test → l1_tx_utils}/tx_delayer.js +65 -36
  107. package/dest/publisher_manager.d.ts +3 -2
  108. package/dest/publisher_manager.d.ts.map +1 -1
  109. package/dest/publisher_manager.js +2 -2
  110. package/dest/queries.d.ts +2 -2
  111. package/dest/queries.d.ts.map +1 -1
  112. package/dest/queries.js +12 -4
  113. package/dest/test/chain_monitor.d.ts +15 -13
  114. package/dest/test/chain_monitor.d.ts.map +1 -1
  115. package/dest/test/chain_monitor.js +7 -9
  116. package/dest/test/eth_cheat_codes.d.ts +13 -1
  117. package/dest/test/eth_cheat_codes.d.ts.map +1 -1
  118. package/dest/test/eth_cheat_codes.js +4 -2
  119. package/dest/test/index.d.ts +1 -3
  120. package/dest/test/index.d.ts.map +1 -1
  121. package/dest/test/index.js +0 -2
  122. package/dest/test/rollup_cheat_codes.d.ts +9 -6
  123. package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
  124. package/dest/test/rollup_cheat_codes.js +32 -6
  125. package/dest/test/start_anvil.d.ts +3 -1
  126. package/dest/test/start_anvil.d.ts.map +1 -1
  127. package/dest/test/start_anvil.js +1 -1
  128. package/dest/test/upgrade_utils.js +2 -2
  129. package/dest/types.d.ts +57 -2
  130. package/dest/types.d.ts.map +1 -1
  131. package/dest/utils.d.ts +16 -3
  132. package/dest/utils.d.ts.map +1 -1
  133. package/dest/utils.js +64 -0
  134. package/package.json +33 -14
  135. package/src/client.ts +2 -2
  136. package/src/config.ts +65 -459
  137. package/src/contracts/README.md +157 -0
  138. package/src/contracts/empire_base.ts +3 -1
  139. package/src/contracts/empire_slashing_proposer.ts +28 -28
  140. package/src/contracts/fee_asset_handler.ts +10 -7
  141. package/src/contracts/fee_asset_price_oracle.ts +280 -0
  142. package/src/contracts/governance.ts +13 -4
  143. package/src/contracts/governance_proposer.ts +16 -2
  144. package/src/contracts/inbox.ts +55 -3
  145. package/src/contracts/index.ts +3 -0
  146. package/src/contracts/log.ts +13 -0
  147. package/src/contracts/multicall.ts +5 -2
  148. package/src/contracts/outbox.ts +98 -0
  149. package/src/contracts/rollup.ts +390 -118
  150. package/src/contracts/tally_slashing_proposer.ts +7 -1
  151. package/src/deploy_aztec_l1_contracts.ts +650 -0
  152. package/src/deploy_l1_contract.ts +362 -0
  153. package/src/forwarder_proxy.ts +108 -0
  154. package/src/generated/l1-contracts-defaults.ts +32 -0
  155. package/src/l1_contract_addresses.ts +22 -20
  156. package/src/l1_reader.ts +8 -0
  157. package/src/l1_tx_utils/config.ts +44 -6
  158. package/src/l1_tx_utils/constants.ts +13 -2
  159. package/src/l1_tx_utils/factory.ts +31 -31
  160. package/src/l1_tx_utils/fee-strategies/index.ts +22 -0
  161. package/src/l1_tx_utils/fee-strategies/p75_competitive.ts +163 -0
  162. package/src/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.ts +245 -0
  163. package/src/l1_tx_utils/fee-strategies/types.ts +56 -0
  164. package/src/l1_tx_utils/forwarder_l1_tx_utils.ts +108 -0
  165. package/src/l1_tx_utils/index-blobs.ts +2 -0
  166. package/src/l1_tx_utils/index.ts +3 -0
  167. package/src/l1_tx_utils/interfaces.ts +1 -1
  168. package/src/l1_tx_utils/l1_fee_analyzer.ts +803 -0
  169. package/src/l1_tx_utils/l1_tx_utils.ts +76 -21
  170. package/src/l1_tx_utils/readonly_l1_tx_utils.ts +67 -206
  171. package/src/{test → l1_tx_utils}/tx_delayer.ts +82 -52
  172. package/src/publisher_manager.ts +4 -2
  173. package/src/queries.ts +11 -3
  174. package/src/test/chain_monitor.ts +18 -16
  175. package/src/test/eth_cheat_codes.ts +2 -2
  176. package/src/test/index.ts +0 -2
  177. package/src/test/rollup_cheat_codes.ts +32 -9
  178. package/src/test/start_anvil.ts +3 -1
  179. package/src/test/upgrade_utils.ts +2 -2
  180. package/src/types.ts +62 -0
  181. package/src/utils.ts +83 -1
  182. package/dest/deploy_l1_contracts.d.ts +0 -673
  183. package/dest/deploy_l1_contracts.d.ts.map +0 -1
  184. package/dest/deploy_l1_contracts.js +0 -1491
  185. package/dest/index.d.ts +0 -18
  186. package/dest/index.d.ts.map +0 -1
  187. package/dest/index.js +0 -17
  188. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts +0 -26
  189. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts.map +0 -1
  190. package/dest/l1_tx_utils/l1_tx_utils_with_blobs.js +0 -26
  191. package/dest/test/delayed_tx_utils.d.ts +0 -13
  192. package/dest/test/delayed_tx_utils.d.ts.map +0 -1
  193. package/dest/test/delayed_tx_utils.js +0 -28
  194. package/dest/test/tx_delayer.d.ts +0 -36
  195. package/dest/test/tx_delayer.d.ts.map +0 -1
  196. package/src/deploy_l1_contracts.ts +0 -1869
  197. package/src/index.ts +0 -17
  198. package/src/l1_tx_utils/l1_tx_utils_with_blobs.ts +0 -77
  199. package/src/test/delayed_tx_utils.ts +0 -52
@@ -0,0 +1,362 @@
1
+ import { EthAddress } from '@aztec/foundation/eth-address';
2
+ import { type Logger, createLogger } from '@aztec/foundation/log';
3
+ import { DateProvider } from '@aztec/foundation/timer';
4
+
5
+ import {
6
+ type Abi,
7
+ type ContractConstructorArgs,
8
+ type Hex,
9
+ type Narrow,
10
+ concatHex,
11
+ encodeAbiParameters,
12
+ encodeDeployData,
13
+ getContractAddress,
14
+ numberToHex,
15
+ padHex,
16
+ } from 'viem';
17
+
18
+ import {
19
+ type ContractArtifacts,
20
+ DEPLOYER_ADDRESS,
21
+ type Libraries,
22
+ type VerificationLibraryEntry,
23
+ type VerificationRecord,
24
+ } from './deploy_aztec_l1_contracts.js';
25
+ import { RegisterNewRollupVersionPayloadArtifact } from './l1_artifacts.js';
26
+ import { type L1TxUtilsConfig, getL1TxUtilsConfigEnvVars } from './l1_tx_utils/config.js';
27
+ import { createL1TxUtils } from './l1_tx_utils/factory.js';
28
+ import type { L1TxUtils } from './l1_tx_utils/l1_tx_utils.js';
29
+ import type { GasPrice, L1TxConfig, L1TxRequest } from './l1_tx_utils/types.js';
30
+ import type { ExtendedViemWalletClient } from './types.js';
31
+ import { formatViemError } from './utils.js';
32
+
33
+ export class L1Deployer {
34
+ private salt: Hex | undefined;
35
+ private txHashes: Hex[] = [];
36
+ public readonly l1TxUtils: L1TxUtils;
37
+ public readonly verificationRecords: VerificationRecord[] = [];
38
+
39
+ constructor(
40
+ public readonly client: ExtendedViemWalletClient,
41
+ maybeSalt: number | undefined,
42
+ dateProvider: DateProvider = new DateProvider(),
43
+ private acceleratedTestDeployments: boolean = false,
44
+ private logger: Logger = createLogger('L1Deployer'),
45
+ private txUtilsConfig?: L1TxUtilsConfig,
46
+ private createVerificationJson: boolean = false,
47
+ ) {
48
+ this.salt = maybeSalt ? padHex(numberToHex(maybeSalt), { size: 32 }) : undefined;
49
+ this.l1TxUtils = createL1TxUtils(
50
+ this.client,
51
+ { logger: this.logger, dateProvider },
52
+ { ...this.txUtilsConfig, debugMaxGasLimit: acceleratedTestDeployments },
53
+ );
54
+ }
55
+
56
+ async deploy<const TAbi extends Abi>(
57
+ params: ContractArtifacts<TAbi>,
58
+ args?: ContractConstructorArgs<TAbi>,
59
+ opts: { gasLimit?: bigint; noSimulation?: boolean } = {},
60
+ ): Promise<{ address: EthAddress; existed: boolean }> {
61
+ this.logger.debug(`Deploying ${params.name} contract`, { args });
62
+ try {
63
+ const { txHash, address, deployedLibraries, existed } = await deployL1Contract(
64
+ this.client,
65
+ params.contractAbi,
66
+ params.contractBytecode,
67
+ (args ?? []) as readonly unknown[],
68
+ {
69
+ salt: this.salt,
70
+ libraries: params.libraries,
71
+ logger: this.logger,
72
+ l1TxUtils: this.l1TxUtils,
73
+ acceleratedTestDeployments: this.acceleratedTestDeployments,
74
+ gasLimit: opts.gasLimit,
75
+ noSimulation: opts.noSimulation,
76
+ },
77
+ );
78
+ if (txHash) {
79
+ this.txHashes.push(txHash);
80
+ }
81
+ this.logger.debug(`Deployed ${params.name} at ${address}`, { args });
82
+
83
+ if (this.createVerificationJson) {
84
+ // Encode constructor args for verification
85
+ let constructorArgsHex: Hex = '0x';
86
+ try {
87
+ const abiItem: any = (params.contractAbi as any[]).find((x: any) => x && x.type === 'constructor');
88
+ const inputDefs: any[] = abiItem && Array.isArray(abiItem.inputs) ? abiItem.inputs : [];
89
+ constructorArgsHex =
90
+ inputDefs.length > 0 ? (encodeAbiParameters(inputDefs as any, (args ?? []) as any) as Hex) : ('0x' as Hex);
91
+ } catch {
92
+ constructorArgsHex = '0x' as Hex;
93
+ }
94
+
95
+ this.verificationRecords.push({
96
+ name: params.name,
97
+ address: address.toString(),
98
+ constructorArgsHex,
99
+ libraries: deployedLibraries ?? [],
100
+ });
101
+ }
102
+ return {
103
+ address,
104
+ existed,
105
+ };
106
+ } catch (error) {
107
+ throw new Error(`Failed to deploy ${params.name}`, { cause: formatViemError(error) });
108
+ }
109
+ }
110
+
111
+ async waitForDeployments(): Promise<void> {
112
+ if (this.acceleratedTestDeployments) {
113
+ this.logger.info('Accelerated test deployments - skipping waiting for deployments');
114
+ return;
115
+ }
116
+ if (this.txHashes.length === 0) {
117
+ return;
118
+ }
119
+
120
+ this.logger.verbose(`Waiting for ${this.txHashes.length} transactions to be mined`, { txHashes: this.txHashes });
121
+ const receipts = await Promise.all(
122
+ this.txHashes.map(txHash => this.client.waitForTransactionReceipt({ hash: txHash })),
123
+ );
124
+ const failed = receipts.filter(r => r.status !== 'success');
125
+ if (failed.length > 0) {
126
+ throw new Error(`Some deployment txs have failed: ${failed.map(f => f.transactionHash).join(', ')}`);
127
+ }
128
+ this.logger.info('All transactions mined successfully', { txHashes: this.txHashes });
129
+ }
130
+
131
+ sendTransaction(
132
+ tx: L1TxRequest,
133
+ options?: L1TxConfig,
134
+ ): Promise<{ txHash: Hex; gasLimit: bigint; gasPrice: GasPrice }> {
135
+ return this.l1TxUtils.sendTransaction(tx, options).then(({ txHash, state }) => ({
136
+ txHash,
137
+ gasLimit: state.gasLimit,
138
+ gasPrice: state.gasPrice,
139
+ }));
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Helper function to deploy ETH contracts.
145
+ * @param walletClient - A viem WalletClient.
146
+ * @param publicClient - A viem PublicClient.
147
+ * @param abi - The ETH contract's ABI (as abitype's Abi).
148
+ * @param bytecode - The ETH contract's bytecode.
149
+ * @param args - Constructor arguments for the contract.
150
+ * @param salt - Optional salt for CREATE2 deployment (does not wait for deployment tx to be mined if set, does not send tx if contract already exists).
151
+ * @returns The ETH address the contract was deployed to.
152
+ */
153
+ export async function deployL1Contract(
154
+ extendedClient: ExtendedViemWalletClient,
155
+ abi: Narrow<Abi | readonly unknown[]>,
156
+ bytecode: Hex,
157
+ args: readonly unknown[] = [],
158
+ opts: {
159
+ salt?: Hex;
160
+ libraries?: Libraries;
161
+ logger?: Logger;
162
+ l1TxUtils?: L1TxUtils;
163
+ gasLimit?: bigint;
164
+ acceleratedTestDeployments?: boolean;
165
+ noSimulation?: boolean;
166
+ } = {},
167
+ ): Promise<{
168
+ address: EthAddress;
169
+ txHash: Hex | undefined;
170
+ deployedLibraries?: VerificationLibraryEntry[];
171
+ existed: boolean;
172
+ }> {
173
+ let txHash: Hex | undefined = undefined;
174
+ let resultingAddress: Hex | null | undefined = undefined;
175
+ const deployedLibraries: VerificationLibraryEntry[] = [];
176
+
177
+ const { salt: saltFromOpts, libraries, logger, gasLimit, acceleratedTestDeployments, noSimulation } = opts;
178
+ let { l1TxUtils } = opts;
179
+
180
+ if (!l1TxUtils) {
181
+ const config = getL1TxUtilsConfigEnvVars();
182
+ l1TxUtils = createL1TxUtils(
183
+ extendedClient,
184
+ { logger },
185
+ { ...config, debugMaxGasLimit: acceleratedTestDeployments },
186
+ );
187
+ }
188
+
189
+ if (libraries) {
190
+ // Note that this does NOT work well for linked libraries having linked libraries.
191
+
192
+ // Verify that all link references have corresponding code
193
+ for (const linkRef in libraries.linkReferences) {
194
+ for (const contractName in libraries.linkReferences[linkRef]) {
195
+ if (!libraries.libraryCode[contractName]) {
196
+ throw new Error(`Missing library code for ${contractName}`);
197
+ }
198
+ }
199
+ }
200
+
201
+ const replacements: Record<string, EthAddress> = {};
202
+ const libraryTxs: Hex[] = [];
203
+ for (const libraryName in libraries?.libraryCode) {
204
+ const lib = libraries.libraryCode[libraryName];
205
+ const { libraries: _libraries, ...optsWithoutLibraries } = opts;
206
+ const { address, txHash } = await deployL1Contract(
207
+ extendedClient,
208
+ lib.contractAbi,
209
+ lib.contractBytecode,
210
+ [],
211
+ optsWithoutLibraries,
212
+ );
213
+
214
+ // Log deployed library name and address for easier verification/triage
215
+ logger?.verbose(`Linked library deployed`, { library: libraryName, address: address.toString(), txHash });
216
+
217
+ if (txHash) {
218
+ libraryTxs.push(txHash);
219
+ }
220
+
221
+ // Try to find the source file for this library from linkReferences
222
+ let fileNameForLibrary: string | undefined = undefined;
223
+ for (const fileName in libraries.linkReferences) {
224
+ if (libraries.linkReferences[fileName] && libraries.linkReferences[fileName][libraryName]) {
225
+ fileNameForLibrary = fileName;
226
+ break;
227
+ }
228
+ }
229
+ if (fileNameForLibrary) {
230
+ deployedLibraries.push({
231
+ file: fileNameForLibrary,
232
+ contract: libraryName,
233
+ address: address.toString(),
234
+ });
235
+ }
236
+
237
+ for (const linkRef in libraries.linkReferences) {
238
+ for (const contractName in libraries.linkReferences[linkRef]) {
239
+ // If the library name matches the one we just deployed, we replace it.
240
+ if (contractName !== libraryName) {
241
+ continue;
242
+ }
243
+
244
+ // We read the first instance to figure out what we are to replace.
245
+ const start = 2 + 2 * libraries.linkReferences[linkRef][contractName][0].start;
246
+ const length = 2 * libraries.linkReferences[linkRef][contractName][0].length;
247
+
248
+ const toReplace = bytecode.slice(start, start + length);
249
+ replacements[toReplace] = address;
250
+ }
251
+ }
252
+ }
253
+
254
+ const escapeRegExp = (s: string) => {
255
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // Escape special characters
256
+ };
257
+
258
+ for (const toReplace in replacements) {
259
+ const replacement = replacements[toReplace].toString().slice(2);
260
+ bytecode = bytecode.replace(new RegExp(escapeRegExp(toReplace), 'g'), replacement) as Hex;
261
+ }
262
+
263
+ // Reth fails gas estimation if the deployed contract attempts to call a library that is not yet deployed,
264
+ // so we wait for all library deployments to be mined before deploying the contract.
265
+ // However, if we are in fast mode or using debugMaxGasLimit, we will skip simulation, so we can skip waiting.
266
+ if (libraryTxs.length > 0 && !acceleratedTestDeployments) {
267
+ logger?.verbose(`Awaiting for linked libraries to be deployed`);
268
+ await Promise.all(libraryTxs.map(txHash => extendedClient.waitForTransactionReceipt({ hash: txHash })));
269
+ } else {
270
+ logger?.verbose(
271
+ `Skipping waiting for linked libraries to be deployed ${
272
+ acceleratedTestDeployments ? '(accelerated test deployments)' : ''
273
+ }`,
274
+ );
275
+ }
276
+ }
277
+
278
+ let existed = false;
279
+
280
+ if (saltFromOpts) {
281
+ logger?.info(`Deploying contract with salt ${saltFromOpts}`);
282
+ const { address, paddedSalt: salt, calldata } = getExpectedAddress(abi, bytecode, args, saltFromOpts);
283
+ resultingAddress = address;
284
+ const existing = await extendedClient.getCode({ address: resultingAddress });
285
+ if (existing === undefined || existing === '0x') {
286
+ if (!noSimulation) {
287
+ try {
288
+ await l1TxUtils.simulate({ to: DEPLOYER_ADDRESS, data: concatHex([salt, calldata]), gas: gasLimit });
289
+ } catch (err) {
290
+ logger?.error(`Failed to simulate deployment tx using universal deployer`, err);
291
+ await l1TxUtils.simulate({ to: null, data: encodeDeployData({ abi, bytecode, args }), gas: gasLimit });
292
+ }
293
+ }
294
+ const res = await l1TxUtils.sendTransaction(
295
+ { to: DEPLOYER_ADDRESS, data: concatHex([salt, calldata]) },
296
+ { gasLimit },
297
+ );
298
+ txHash = res.txHash;
299
+
300
+ logger?.verbose(`Deployed contract with salt ${salt} to address ${resultingAddress} in tx ${txHash}.`);
301
+ } else {
302
+ logger?.verbose(`Skipping existing deployment of contract with salt ${salt} to address ${resultingAddress}`);
303
+ existed = true;
304
+ }
305
+ } else {
306
+ const deployData = encodeDeployData({ abi, bytecode, args });
307
+ const { receipt } = await l1TxUtils.sendAndMonitorTransaction(
308
+ {
309
+ to: null,
310
+ data: deployData,
311
+ },
312
+ { gasLimit },
313
+ );
314
+
315
+ txHash = receipt.transactionHash;
316
+ resultingAddress = receipt.contractAddress;
317
+ if (!resultingAddress) {
318
+ throw new Error(
319
+ `No contract address found in receipt: ${JSON.stringify(receipt, (_, val) =>
320
+ typeof val === 'bigint' ? String(val) : val,
321
+ )}`,
322
+ );
323
+ }
324
+ }
325
+
326
+ return { address: EthAddress.fromString(resultingAddress!), txHash, deployedLibraries, existed };
327
+ }
328
+
329
+ export function getExpectedAddress(
330
+ abi: Narrow<Abi | readonly unknown[]>,
331
+ bytecode: Hex,
332
+ args: readonly unknown[],
333
+ salt: Hex,
334
+ ) {
335
+ const paddedSalt = padHex(salt, { size: 32 });
336
+ const calldata = encodeDeployData({ abi, bytecode, args });
337
+ const address = getContractAddress({
338
+ from: DEPLOYER_ADDRESS,
339
+ salt: paddedSalt,
340
+ bytecode: calldata,
341
+ opcode: 'CREATE2',
342
+ });
343
+ return {
344
+ address,
345
+ paddedSalt,
346
+ calldata,
347
+ };
348
+ }
349
+
350
+ export const deployUpgradePayload = async (
351
+ deployer: L1Deployer,
352
+ addresses: { registryAddress: EthAddress; rollupAddress: EthAddress },
353
+ ) => {
354
+ const payloadAddress = (
355
+ await deployer.deploy(RegisterNewRollupVersionPayloadArtifact, [
356
+ addresses.registryAddress.toString(),
357
+ addresses.rollupAddress.toString(),
358
+ ])
359
+ ).address;
360
+
361
+ return payloadAddress;
362
+ };
@@ -0,0 +1,108 @@
1
+ /* eslint-disable no-console */
2
+ import { EthAddress } from '@aztec/foundation/eth-address';
3
+ import type { Logger } from '@aztec/foundation/log';
4
+ import { createLogger } from '@aztec/foundation/log';
5
+ import { DateProvider } from '@aztec/foundation/timer';
6
+
7
+ import { type Hex, extractChain } from 'viem';
8
+ import { anvil, mainnet, sepolia } from 'viem/chains';
9
+
10
+ import { L1Deployer } from './deploy_l1_contract.js';
11
+ import type { ExtendedViemWalletClient } from './types.js';
12
+
13
+ export const FORWARDER_SOLIDITY_SOURCE = `
14
+ contract ForwarderProxy {
15
+ function forward(address target, bytes calldata data) external payable returns (bytes memory) {
16
+ (bool success, bytes memory result) = target.call{value: msg.value}(data);
17
+ require(success, "call failed");
18
+ return result;
19
+ }
20
+ }`;
21
+
22
+ export const FORWARDER_ABI = [
23
+ {
24
+ inputs: [
25
+ {
26
+ internalType: 'address',
27
+ name: 'target',
28
+ type: 'address',
29
+ },
30
+ {
31
+ internalType: 'bytes',
32
+ name: 'data',
33
+ type: 'bytes',
34
+ },
35
+ ],
36
+ name: 'forward',
37
+ outputs: [
38
+ {
39
+ internalType: 'bytes',
40
+ name: '',
41
+ type: 'bytes',
42
+ },
43
+ ],
44
+ stateMutability: 'payable',
45
+ type: 'function',
46
+ },
47
+ ] as const;
48
+
49
+ export const FORWARDER_BYTECODE =
50
+ '0x6080604052348015600e575f5ffd5b506103bf8061001c5f395ff3fe60806040526004361061001d575f3560e01c80636fadcf7214610021575b5f5ffd5b61003b600480360381019061003691906101d0565b610051565b604051610048919061029d565b60405180910390f35b60605f5f8573ffffffffffffffffffffffffffffffffffffffff1634868660405161007d9291906102f9565b5f6040518083038185875af1925050503d805f81146100b7576040519150601f19603f3d011682016040523d82523d5f602084013e6100bc565b606091505b509150915081610101576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100f89061036b565b60405180910390fd5b80925050509392505050565b5f5ffd5b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61013e82610115565b9050919050565b61014e81610134565b8114610158575f5ffd5b50565b5f8135905061016981610145565b92915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f8401126101905761018f61016f565b5b8235905067ffffffffffffffff8111156101ad576101ac610173565b5b6020830191508360018202830111156101c9576101c8610177565b5b9250929050565b5f5f5f604084860312156101e7576101e661010d565b5b5f6101f48682870161015b565b935050602084013567ffffffffffffffff81111561021557610214610111565b5b6102218682870161017b565b92509250509250925092565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61026f8261022d565b6102798185610237565b9350610289818560208601610247565b61029281610255565b840191505092915050565b5f6020820190508181035f8301526102b58184610265565b905092915050565b5f81905092915050565b828183375f83830152505050565b5f6102e083856102bd565b93506102ed8385846102c7565b82840190509392505050565b5f6103058284866102d5565b91508190509392505050565b5f82825260208201905092915050565b7f63616c6c206661696c65640000000000000000000000000000000000000000005f82015250565b5f610355600b83610311565b915061036082610321565b602082019050919050565b5f6020820190508181035f83015261038281610349565b905091905056fea26469706673582212209a1c8cf638cf1569450a731ef9457b862f9e153b0a46e5555429bcf4dffd999564736f6c634300081e0033' as Hex;
51
+
52
+ const FORWARDER_ARTIFACT = {
53
+ name: 'Forwarder',
54
+ contractAbi: FORWARDER_ABI,
55
+ contractBytecode: FORWARDER_BYTECODE,
56
+ };
57
+
58
+ /**
59
+ * Deploys the forwarder proxy contract to L1.
60
+ * @param client - The L1 client to use for deployment
61
+ * @param logger - Optional logger
62
+ * @returns The deployed forwarder contract address
63
+ */
64
+ export async function deployForwarderProxy(client: ExtendedViemWalletClient, logger?: Logger): Promise<EthAddress> {
65
+ const log = logger ?? createLogger('ethereum:forwarder');
66
+ const nonce = await client.getTransactionCount({ address: client.account.address });
67
+ const deployer = new L1Deployer(client, nonce, new DateProvider(), false, log, undefined, false);
68
+
69
+ log.info('Deploying forwarder proxy contract');
70
+ const deployment = await deployer.deploy(FORWARDER_ARTIFACT, []);
71
+ log.info(`Forwarder proxy deployed at ${deployment.address.toString()}`);
72
+
73
+ return deployment.address;
74
+ }
75
+
76
+ /**
77
+ * Main function for deploying the forwarder proxy from command line.
78
+ * Usage: node forwarder_proxy.js <private_key> <rpc_url>
79
+ */
80
+ async function main() {
81
+ const args = process.argv.slice(2);
82
+ if (args.length < 3) {
83
+ console.error('Usage: node forwarder_proxy.js <private_key> <rpc_url> <chain_id>');
84
+ process.exit(1);
85
+ }
86
+
87
+ const [privateKey, rpcUrl, chainId] = args;
88
+
89
+ // Dynamic import to avoid pulling in dependencies at module load time
90
+ const { createExtendedL1Client } = await import('./client.js');
91
+
92
+ const client = createExtendedL1Client(
93
+ [rpcUrl],
94
+ privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`,
95
+ extractChain({ chains: [mainnet, sepolia, anvil], id: parseInt(chainId) as any }),
96
+ );
97
+ const address = await deployForwarderProxy(client);
98
+
99
+ console.log(`Forwarder proxy deployed at: ${address.toString()}`);
100
+ }
101
+
102
+ // Only run main if this is the entry point
103
+ if (import.meta.url === `file://${process.argv[1]}`) {
104
+ main().catch(err => {
105
+ console.error('Failed to deploy forwarder proxy:', err);
106
+ process.exit(1);
107
+ });
108
+ }
@@ -0,0 +1,32 @@
1
+ // Auto-generated from spartan/environments/network-defaults.yml
2
+ // Do not edit manually - run yarn generate to regenerate
3
+
4
+ /** Default L1 contracts configuration values from network-defaults.yml */
5
+ export const l1ContractsDefaultEnv = {
6
+ ETHEREUM_SLOT_DURATION: 12,
7
+ AZTEC_SLOT_DURATION: 36,
8
+ AZTEC_EPOCH_DURATION: 32,
9
+ AZTEC_TARGET_COMMITTEE_SIZE: 48,
10
+ AZTEC_LAG_IN_EPOCHS_FOR_VALIDATOR_SET: 2,
11
+ AZTEC_LAG_IN_EPOCHS_FOR_RANDAO: 2,
12
+ AZTEC_ACTIVATION_THRESHOLD: 100000000000000000000,
13
+ AZTEC_EJECTION_THRESHOLD: 50000000000000000000,
14
+ AZTEC_LOCAL_EJECTION_THRESHOLD: 98000000000000000000,
15
+ AZTEC_EXIT_DELAY_SECONDS: 172800,
16
+ AZTEC_INBOX_LAG: 1,
17
+ AZTEC_PROOF_SUBMISSION_EPOCHS: 1,
18
+ AZTEC_MANA_TARGET: 100000000,
19
+ AZTEC_PROVING_COST_PER_MANA: 100,
20
+ AZTEC_INITIAL_ETH_PER_FEE_ASSET: 10000000,
21
+ AZTEC_SLASHER_FLAVOR: 'tally',
22
+ AZTEC_SLASHING_ROUND_SIZE_IN_EPOCHS: 4,
23
+ AZTEC_SLASHING_LIFETIME_IN_ROUNDS: 5,
24
+ AZTEC_SLASHING_EXECUTION_DELAY_IN_ROUNDS: 0,
25
+ AZTEC_SLASHING_OFFSET_IN_ROUNDS: 2,
26
+ AZTEC_SLASHING_VETOER: '0x0000000000000000000000000000000000000000',
27
+ AZTEC_SLASHING_DISABLE_DURATION: 432000,
28
+ AZTEC_SLASH_AMOUNT_SMALL: 10000000000000000000,
29
+ AZTEC_SLASH_AMOUNT_MEDIUM: 20000000000000000000,
30
+ AZTEC_SLASH_AMOUNT_LARGE: 50000000000000000000,
31
+ AZTEC_GOVERNANCE_PROPOSER_ROUND_SIZE: 300,
32
+ } as const;
@@ -1,6 +1,6 @@
1
1
  import type { ConfigMappingsType } from '@aztec/foundation/config';
2
2
  import { EthAddress } from '@aztec/foundation/eth-address';
3
- import { type ZodFor, schemas } from '@aztec/foundation/schemas';
3
+ import { schemas, zodFor } from '@aztec/foundation/schemas';
4
4
 
5
5
  import { z } from 'zod';
6
6
 
@@ -35,25 +35,27 @@ export type L1ContractAddresses = {
35
35
  dateGatedRelayerAddress?: EthAddress | undefined;
36
36
  };
37
37
 
38
- export const L1ContractAddressesSchema = z.object({
39
- rollupAddress: schemas.EthAddress,
40
- registryAddress: schemas.EthAddress,
41
- inboxAddress: schemas.EthAddress,
42
- outboxAddress: schemas.EthAddress,
43
- feeJuiceAddress: schemas.EthAddress,
44
- stakingAssetAddress: schemas.EthAddress,
45
- feeJuicePortalAddress: schemas.EthAddress,
46
- coinIssuerAddress: schemas.EthAddress,
47
- rewardDistributorAddress: schemas.EthAddress,
48
- governanceProposerAddress: schemas.EthAddress,
49
- governanceAddress: schemas.EthAddress,
50
- slashFactoryAddress: schemas.EthAddress.optional(),
51
- feeAssetHandlerAddress: schemas.EthAddress.optional(),
52
- stakingAssetHandlerAddress: schemas.EthAddress.optional(),
53
- zkPassportVerifierAddress: schemas.EthAddress.optional(),
54
- gseAddress: schemas.EthAddress.optional(),
55
- dateGatedRelayerAddress: schemas.EthAddress.optional(),
56
- }) satisfies ZodFor<L1ContractAddresses>;
38
+ export const L1ContractAddressesSchema = zodFor<L1ContractAddresses>()(
39
+ z.object({
40
+ rollupAddress: schemas.EthAddress,
41
+ registryAddress: schemas.EthAddress,
42
+ inboxAddress: schemas.EthAddress,
43
+ outboxAddress: schemas.EthAddress,
44
+ feeJuiceAddress: schemas.EthAddress,
45
+ stakingAssetAddress: schemas.EthAddress,
46
+ feeJuicePortalAddress: schemas.EthAddress,
47
+ coinIssuerAddress: schemas.EthAddress,
48
+ rewardDistributorAddress: schemas.EthAddress,
49
+ governanceProposerAddress: schemas.EthAddress,
50
+ governanceAddress: schemas.EthAddress,
51
+ slashFactoryAddress: schemas.EthAddress.optional(),
52
+ feeAssetHandlerAddress: schemas.EthAddress.optional(),
53
+ stakingAssetHandlerAddress: schemas.EthAddress.optional(),
54
+ zkPassportVerifierAddress: schemas.EthAddress.optional(),
55
+ gseAddress: schemas.EthAddress.optional(),
56
+ dateGatedRelayerAddress: schemas.EthAddress.optional(),
57
+ }),
58
+ );
57
59
 
58
60
  const parseEnv = (val: string) => EthAddress.fromString(val);
59
61
 
package/src/l1_reader.ts CHANGED
@@ -6,6 +6,8 @@ import { type L1ContractAddresses, l1ContractAddressesMapping } from './l1_contr
6
6
  export interface L1ReaderConfig {
7
7
  /** List of URLs of Ethereum RPC nodes that services will connect to (comma separated). */
8
8
  l1RpcUrls: string[];
9
+ /** The RPC Url of the ethereum debug host for trace and debug methods. */
10
+ l1DebugRpcUrls: string[];
9
11
  /** The chain ID of the ethereum host. */
10
12
  l1ChainId: number;
11
13
  /** The deployed l1 contract addresses */
@@ -30,6 +32,12 @@ export const l1ReaderConfigMappings: ConfigMappingsType<L1ReaderConfig> = {
30
32
  parseEnv: (val: string) => val.split(',').map(url => url.trim()),
31
33
  defaultValue: [],
32
34
  },
35
+ l1DebugRpcUrls: {
36
+ env: 'ETHEREUM_DEBUG_HOSTS',
37
+ description: 'The RPC Url of the ethereum debug host for trace and debug methods.',
38
+ parseEnv: (val: string) => val.split(',').map(url => url.trim()),
39
+ defaultValue: [],
40
+ },
33
41
  viemPollingIntervalMS: {
34
42
  env: 'L1_READER_VIEM_POLLING_INTERVAL_MS',
35
43
  description: 'The polling interval viem uses in ms',
@@ -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 {
@@ -29,9 +30,9 @@ export interface L1TxUtilsConfig {
29
30
  */
30
31
  priorityFeeRetryBumpPercentage?: number;
31
32
  /**
32
- * Fixed priority fee per gas in Gwei. Overrides any priority fee bump percentage config
33
+ * Minimum priority fee per gas in Gwei. Acts as a floor for the computed priority fee.
33
34
  */
34
- fixedPriorityFeePerGas?: number;
35
+ minimumPriorityFeePerGas?: number;
35
36
  /**
36
37
  * Maximum number of speed-up attempts
37
38
  */
@@ -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> = {
@@ -90,10 +97,21 @@ export const l1TxUtilsConfigMappings: ConfigMappingsType<L1TxUtilsConfig> = {
90
97
  env: 'L1_PRIORITY_FEE_RETRY_BUMP_PERCENTAGE',
91
98
  ...numberConfigHelper(50),
92
99
  },
93
- fixedPriorityFeePerGas: {
94
- description: 'Fixed priority fee per gas in Gwei. Overrides any priority fee bump percentage',
95
- env: 'L1_FIXED_PRIORITY_FEE_PER_GAS',
96
- fallback: ['L1_FIXED_PRIORITY_FEE_PER_GAS_GWEI'],
100
+ minimumPriorityFeePerGas: {
101
+ description:
102
+ 'Minimum priority fee per gas in Gwei. Acts as a floor for the computed priority fee. If network conditions require a higher fee, the higher fee will be used.',
103
+ env: 'L1_MINIMUM_PRIORITY_FEE_PER_GAS_GWEI',
104
+ fallback: ['L1_FIXED_PRIORITY_FEE_PER_GAS', 'L1_FIXED_PRIORITY_FEE_PER_GAS_GWEI'],
105
+ deprecatedFallback: [
106
+ {
107
+ env: 'L1_FIXED_PRIORITY_FEE_PER_GAS',
108
+ message: deprecatedFixedFeeMessage('L1_FIXED_PRIORITY_FEE_PER_GAS'),
109
+ },
110
+ {
111
+ env: 'L1_FIXED_PRIORITY_FEE_PER_GAS_GWEI',
112
+ message: deprecatedFixedFeeMessage('L1_FIXED_PRIORITY_FEE_PER_GAS_GWEI'),
113
+ },
114
+ ],
97
115
  ...floatConfigHelper(0),
98
116
  },
99
117
  maxSpeedUpAttempts: {
@@ -131,6 +149,19 @@ export const l1TxUtilsConfigMappings: ConfigMappingsType<L1TxUtilsConfig> = {
131
149
  env: 'L1_TX_MONITOR_TX_UNSEEN_CONSIDERED_DROPPED_MS',
132
150
  ...numberConfigHelper(6 * 12 * 1000), // 6 L1 blocks
133
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
+ },
134
165
  };
135
166
 
136
167
  // We abuse the fact that all mappings above have a non null default value and force-type this to Required
@@ -141,3 +172,10 @@ export const defaultL1TxUtilsConfig = getDefaultConfig<L1TxUtilsConfig>(
141
172
  export function getL1TxUtilsConfigEnvVars(): L1TxUtilsConfig {
142
173
  return getConfigFromMappings(l1TxUtilsConfigMappings);
143
174
  }
175
+
176
+ function deprecatedFixedFeeMessage(envVar: string): string {
177
+ return (
178
+ `Environment variable ${envVar} is deprecated. It is now used as a MINIMUM priority fee rather than a fixed value. ` +
179
+ 'Please use L1_MINIMUM_PRIORITY_FEE_PER_GAS_GWEI instead. If network conditions require a higher fee, the higher fee will be used.'
180
+ );
181
+ }