@aztec/ethereum 0.50.1 → 0.51.1

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.
@@ -65,7 +65,7 @@ export interface L1ContractArtifactsForDeployment {
65
65
  */
66
66
  feeJuice: ContractArtifacts;
67
67
  /**
68
- * Gas portal contract artifacts. Optional for now as gas is not strictly enforced
68
+ * Fee juice portal contract artifacts. Optional for now as gas is not strictly enforced
69
69
  */
70
70
  feeJuicePortal: ContractArtifacts;
71
71
  }
@@ -96,6 +96,7 @@ export declare const deployL1Contracts: (rpcUrl: string, account: HDAccount | Pr
96
96
  vkTreeRoot: Fr;
97
97
  assumeProvenUntil?: number;
98
98
  salt: number | undefined;
99
+ initialValidators?: EthAddress[];
99
100
  }) => Promise<DeployL1Contracts>;
100
101
  /**
101
102
  * Helper function to deploy ETH contracts.
@@ -104,7 +105,11 @@ export declare const deployL1Contracts: (rpcUrl: string, account: HDAccount | Pr
104
105
  * @param abi - The ETH contract's ABI (as abitype's Abi).
105
106
  * @param bytecode - The ETH contract's bytecode.
106
107
  * @param args - Constructor arguments for the contract.
108
+ * @param maybeSalt - Optional salt for CREATE2 deployment (does not wait for deployment tx to be mined if set, does not send tx if contract already exists).
107
109
  * @returns The ETH address the contract was deployed to.
108
110
  */
109
- export declare function deployL1Contract(walletClient: WalletClient<HttpTransport, Chain, Account>, publicClient: PublicClient<HttpTransport, Chain>, abi: Narrow<Abi | readonly unknown[]>, bytecode: Hex, args?: readonly unknown[], maybeSalt?: Hex, logger?: DebugLogger): Promise<EthAddress>;
111
+ export declare function deployL1Contract(walletClient: WalletClient<HttpTransport, Chain, Account>, publicClient: PublicClient<HttpTransport, Chain>, abi: Narrow<Abi | readonly unknown[]>, bytecode: Hex, args?: readonly unknown[], maybeSalt?: Hex, logger?: DebugLogger): Promise<{
112
+ address: EthAddress;
113
+ txHash: Hex | undefined;
114
+ }>;
110
115
  //# sourceMappingURL=deploy_l1_contracts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"deploy_l1_contracts.d.ts","sourceRoot":"","sources":["../src/deploy_l1_contracts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"deploy_l1_contracts.d.ts","sourceRoot":"","sources":["../src/deploy_l1_contracts.ts"],"names":[],"mappings":"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"}
@@ -40,7 +40,7 @@ export const deployL1Contracts = async (rpcUrl, account, chain, logger, contract
40
40
  // We are assuming that you are running this on a local anvil node which have 1s block times
41
41
  // To align better with actual deployment, we update the block interval to 12s
42
42
  // The code is same as `setBlockInterval` in `cheat_codes.ts`
43
- const rpcCall = async (rpcUrl, method, params) => {
43
+ const rpcCall = async (method, params) => {
44
44
  const paramsString = JSON.stringify(params);
45
45
  const content = {
46
46
  body: `{"jsonrpc":"2.0", "method": "${method}", "params": ${paramsString}, "id": 1}`,
@@ -49,12 +49,14 @@ export const deployL1Contracts = async (rpcUrl, account, chain, logger, contract
49
49
  };
50
50
  return await (await fetch(rpcUrl, content)).json();
51
51
  };
52
- const interval = 12;
53
- const res = await rpcCall(rpcUrl, 'anvil_setBlockTimestampInterval', [interval]);
54
- if (res.error) {
55
- throw new Error(`Error setting block interval: ${res.error.message}`);
52
+ if (chain.id == foundry.id) {
53
+ const interval = 12;
54
+ const res = await rpcCall('anvil_setBlockTimestampInterval', [interval]);
55
+ if (res.error) {
56
+ throw new Error(`Error setting block interval: ${res.error.message}`);
57
+ }
58
+ logger.info(`Set block interval to ${interval}`);
56
59
  }
57
- logger.info(`Set block interval to ${interval}`);
58
60
  logger.info(`Deploying contracts from ${account.address.toString()}...`);
59
61
  const walletClient = createWalletClient({ account, chain, transport: http(rpcUrl) });
60
62
  const publicClient = createPublicClient({ chain, transport: http(rpcUrl) });
@@ -67,75 +69,85 @@ export const deployL1Contracts = async (rpcUrl, account, chain, logger, contract
67
69
  logger.info(`Deployed Fee Juice at ${feeJuiceAddress}`);
68
70
  const feeJuicePortalAddress = await deployer.deploy(contractsToDeploy.feeJuicePortal, [account.address.toString()]);
69
71
  logger.info(`Deployed Gas Portal at ${feeJuicePortalAddress}`);
72
+ const rollupAddress = await deployer.deploy(contractsToDeploy.rollup, [
73
+ getAddress(registryAddress.toString()),
74
+ getAddress(availabilityOracleAddress.toString()),
75
+ getAddress(feeJuicePortalAddress.toString()),
76
+ args.vkTreeRoot.toString(),
77
+ account.address.toString(),
78
+ args.initialValidators?.map(v => v.toString()) ?? [],
79
+ ]);
80
+ logger.info(`Deployed Rollup at ${rollupAddress}`);
81
+ await deployer.waitForDeployments();
82
+ logger.info(`All contracts deployed`);
70
83
  const feeJuicePortal = getContract({
71
84
  address: feeJuicePortalAddress.toString(),
72
85
  abi: contractsToDeploy.feeJuicePortal.contractAbi,
73
86
  client: walletClient,
74
87
  });
75
- // fund the portal contract with Fee Juice
76
88
  const feeJuice = getContract({
77
89
  address: feeJuiceAddress.toString(),
78
90
  abi: contractsToDeploy.feeJuice.contractAbi,
79
91
  client: walletClient,
80
92
  });
93
+ const rollup = getContract({
94
+ address: getAddress(rollupAddress.toString()),
95
+ abi: contractsToDeploy.rollup.contractAbi,
96
+ client: walletClient,
97
+ });
98
+ // Transaction hashes to await
99
+ const txHashes = [];
81
100
  // @note This value MUST match what is in `constants.nr`. It is currently specified here instead of just importing
82
101
  // because there is circular dependency hell. This is a temporary solution. #3342
102
+ // @todo #8084
103
+ // fund the portal contract with Fee Juice
83
104
  const FEE_JUICE_INITIAL_MINT = 20000000000;
84
- const receipt = await feeJuice.write.mint([feeJuicePortalAddress.toString(), FEE_JUICE_INITIAL_MINT], {});
85
- await publicClient.waitForTransactionReceipt({ hash: receipt });
86
- logger.info(`Funded fee juice portal contract with Fee Juice`);
105
+ const mintTxHash = await feeJuice.write.mint([feeJuicePortalAddress.toString(), FEE_JUICE_INITIAL_MINT], {});
106
+ txHashes.push(mintTxHash);
107
+ logger.info(`Funding fee juice portal contract with fee juice in ${mintTxHash}`);
87
108
  if ((await feeJuicePortal.read.registry([])) === zeroAddress) {
88
- await publicClient.waitForTransactionReceipt({
89
- hash: await feeJuicePortal.write.initialize([
90
- registryAddress.toString(),
91
- feeJuiceAddress.toString(),
92
- args.l2FeeJuiceAddress.toString(),
93
- ]),
94
- });
95
- logger.verbose(`Fee juice portal initialized with registry ${registryAddress.toString()}`);
109
+ const initPortalTxHash = await feeJuicePortal.write.initialize([
110
+ registryAddress.toString(),
111
+ feeJuiceAddress.toString(),
112
+ args.l2FeeJuiceAddress.toString(),
113
+ ]);
114
+ txHashes.push(initPortalTxHash);
115
+ logger.verbose(`Fee juice portal initializing with registry ${registryAddress.toString()} in tx ${initPortalTxHash}`);
96
116
  }
97
117
  else {
98
118
  logger.verbose(`Fee juice portal is already initialized`);
99
119
  }
100
120
  logger.info(`Initialized Gas Portal at ${feeJuicePortalAddress} to bridge between L1 ${feeJuiceAddress} to L2 ${args.l2FeeJuiceAddress}`);
101
- const rollupAddress = await deployer.deploy(contractsToDeploy.rollup, [
102
- getAddress(registryAddress.toString()),
103
- getAddress(availabilityOracleAddress.toString()),
104
- getAddress(feeJuicePortalAddress.toString()),
105
- args.vkTreeRoot.toString(),
106
- account.address.toString(),
107
- ]);
108
- logger.info(`Deployed Rollup at ${rollupAddress}`);
121
+ if (chain.id == foundry.id) {
122
+ // @note We make a time jump PAST the very first slot to not have to deal with the edge case of the first slot.
123
+ // The edge case being that the genesis block is already occupying slot 0, so we cannot have another block.
124
+ try {
125
+ // Need to get the time
126
+ const currentSlot = (await rollup.read.getCurrentSlot([]));
127
+ if (BigInt(currentSlot) === 0n) {
128
+ const ts = Number(await rollup.read.getTimestampForSlot([1]));
129
+ await rpcCall('evm_setNextBlockTimestamp', [ts]);
130
+ await rpcCall('hardhat_mine', [1]);
131
+ const currentSlot = (await rollup.read.getCurrentSlot([]));
132
+ if (BigInt(currentSlot) !== 1n) {
133
+ throw new Error(`Error jumping time: current slot is ${currentSlot}`);
134
+ }
135
+ logger.info(`Jumped to slot 1`);
136
+ }
137
+ }
138
+ catch (e) {
139
+ throw new Error(`Error jumping time: ${e}`);
140
+ }
141
+ }
109
142
  // Set initial blocks as proven if requested
110
143
  if (args.assumeProvenUntil && args.assumeProvenUntil > 0) {
111
- const rollup = getContract({
112
- address: getAddress(rollupAddress.toString()),
113
- abi: contractsToDeploy.rollup.contractAbi,
114
- client: walletClient,
115
- });
116
144
  await rollup.write.setAssumeProvenUntilBlockNumber([BigInt(args.assumeProvenUntil)], { account });
117
145
  logger.info(`Set Rollup assumedProvenUntil to ${args.assumeProvenUntil}`);
118
146
  }
119
147
  // Inbox and Outbox are immutable and are deployed from Rollup's constructor so we just fetch them from the contract.
120
- let inboxAddress;
121
- {
122
- const rollup = getContract({
123
- address: getAddress(rollupAddress.toString()),
124
- abi: contractsToDeploy.rollup.contractAbi,
125
- client: publicClient,
126
- });
127
- inboxAddress = EthAddress.fromString((await rollup.read.INBOX([])));
128
- }
148
+ const inboxAddress = EthAddress.fromString((await rollup.read.INBOX([])));
129
149
  logger.info(`Inbox available at ${inboxAddress}`);
130
- let outboxAddress;
131
- {
132
- const rollup = getContract({
133
- address: getAddress(rollupAddress.toString()),
134
- abi: contractsToDeploy.rollup.contractAbi,
135
- client: publicClient,
136
- });
137
- outboxAddress = EthAddress.fromString((await rollup.read.OUTBOX([])));
138
- }
150
+ const outboxAddress = EthAddress.fromString((await rollup.read.OUTBOX([])));
139
151
  logger.info(`Outbox available at ${outboxAddress}`);
140
152
  // We need to call a function on the registry to set the various contract addresses.
141
153
  const registryContract = getContract({
@@ -144,12 +156,16 @@ export const deployL1Contracts = async (rpcUrl, account, chain, logger, contract
144
156
  client: walletClient,
145
157
  });
146
158
  if (!(await registryContract.read.isRollupRegistered([getAddress(rollupAddress.toString())]))) {
147
- await registryContract.write.upgrade([getAddress(rollupAddress.toString())], { account });
148
- logger.verbose(`Upgraded registry contract at ${registryAddress} to rollup ${rollupAddress}`);
159
+ const upgradeTxHash = await registryContract.write.upgrade([getAddress(rollupAddress.toString())], { account });
160
+ logger.verbose(`Upgrading registry contract at ${registryAddress} to rollup ${rollupAddress} in tx ${upgradeTxHash}`);
161
+ txHashes.push(upgradeTxHash);
149
162
  }
150
163
  else {
151
164
  logger.verbose(`Registry ${registryAddress} has already registered rollup ${rollupAddress}`);
152
165
  }
166
+ // Wait for all actions to be mined
167
+ await Promise.all(txHashes.map(txHash => publicClient.waitForTransactionReceipt({ hash: txHash })));
168
+ logger.verbose(`All transactions for L1 deployment have been mined`);
153
169
  const l1Contracts = {
154
170
  availabilityOracleAddress,
155
171
  rollupAddress,
@@ -170,10 +186,18 @@ class L1Deployer {
170
186
  this.walletClient = walletClient;
171
187
  this.publicClient = publicClient;
172
188
  this.logger = logger;
189
+ this.txHashes = [];
173
190
  this.salt = maybeSalt ? padHex(numberToHex(maybeSalt), { size: 32 }) : undefined;
174
191
  }
175
- deploy(params, args = []) {
176
- return deployL1Contract(this.walletClient, this.publicClient, params.contractAbi, params.contractBytecode, args, this.salt, this.logger);
192
+ async deploy(params, args = []) {
193
+ const { txHash, address } = await deployL1Contract(this.walletClient, this.publicClient, params.contractAbi, params.contractBytecode, args, this.salt, this.logger);
194
+ if (txHash) {
195
+ this.txHashes.push(txHash);
196
+ }
197
+ return address;
198
+ }
199
+ async waitForDeployments() {
200
+ await Promise.all(this.txHashes.map(txHash => this.publicClient.waitForTransactionReceipt({ hash: txHash })));
177
201
  }
178
202
  }
179
203
  // docs:start:deployL1Contract
@@ -184,38 +208,36 @@ class L1Deployer {
184
208
  * @param abi - The ETH contract's ABI (as abitype's Abi).
185
209
  * @param bytecode - The ETH contract's bytecode.
186
210
  * @param args - Constructor arguments for the contract.
211
+ * @param maybeSalt - Optional salt for CREATE2 deployment (does not wait for deployment tx to be mined if set, does not send tx if contract already exists).
187
212
  * @returns The ETH address the contract was deployed to.
188
213
  */
189
214
  export async function deployL1Contract(walletClient, publicClient, abi, bytecode, args = [], maybeSalt, logger) {
215
+ let txHash = undefined;
216
+ let address = undefined;
190
217
  if (maybeSalt) {
191
218
  const salt = padHex(maybeSalt, { size: 32 });
192
219
  const deployer = '0x4e59b44847b379578588920cA78FbF26c0B4956C';
193
220
  const calldata = encodeDeployData({ abi, bytecode, args });
194
- const address = getContractAddress({ from: deployer, salt, bytecode: calldata, opcode: 'CREATE2' });
221
+ address = getContractAddress({ from: deployer, salt, bytecode: calldata, opcode: 'CREATE2' });
195
222
  const existing = await publicClient.getBytecode({ address });
196
223
  if (existing === undefined || existing === '0x') {
197
- const hash = await walletClient.sendTransaction({
198
- to: deployer,
199
- data: concatHex([salt, calldata]),
200
- });
201
- logger?.verbose(`Deploying contract with salt ${salt} to address ${address} in tx ${hash}`);
202
- await publicClient.waitForTransactionReceipt({ hash, pollingInterval: 100 });
224
+ txHash = await walletClient.sendTransaction({ to: deployer, data: concatHex([salt, calldata]) });
225
+ logger?.verbose(`Deploying contract with salt ${salt} to address ${address} in tx ${txHash}`);
203
226
  }
204
227
  else {
205
228
  logger?.verbose(`Skipping existing deployment of contract with salt ${salt} to address ${address}`);
206
229
  }
207
- return EthAddress.fromString(address);
208
230
  }
209
231
  else {
210
- const hash = await walletClient.deployContract({ abi, bytecode, args });
211
- logger?.verbose(`Deploying contract in tx ${hash}`);
212
- const receipt = await publicClient.waitForTransactionReceipt({ hash, pollingInterval: 100 });
213
- const contractAddress = receipt.contractAddress;
214
- if (!contractAddress) {
232
+ txHash = await walletClient.deployContract({ abi, bytecode, args });
233
+ logger?.verbose(`Deploying contract in tx ${txHash}`);
234
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash, pollingInterval: 100 });
235
+ address = receipt.contractAddress;
236
+ if (!address) {
215
237
  throw new Error(`No contract address found in receipt: ${JSON.stringify(receipt, (_, val) => typeof val === 'bigint' ? String(val) : val)}`);
216
238
  }
217
- return EthAddress.fromString(contractAddress);
218
239
  }
240
+ return { address: EthAddress.fromString(address), txHash };
219
241
  }
220
242
  // docs:end:deployL1Contract
221
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95X2wxX2NvbnRyYWN0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9kZXBsb3lfbDFfY29udHJhY3RzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUszRCxPQUFPLEVBT0wsU0FBUyxFQUNULGtCQUFrQixFQUNsQixrQkFBa0IsRUFDbEIsZ0JBQWdCLEVBQ2hCLFVBQVUsRUFDVixXQUFXLEVBQ1gsa0JBQWtCLEVBQ2xCLElBQUksRUFDSixXQUFXLEVBQ1gsTUFBTSxFQUNOLFdBQVcsR0FDWixNQUFNLE1BQU0sQ0FBQztBQUNkLE9BQU8sRUFBMEMsaUJBQWlCLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDL0csT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLGFBQWEsQ0FBQztBQTJFdEM7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLGVBQWUsQ0FDN0IsTUFBYyxFQUNkLCtCQUF1RixFQUN2RixRQUFlLE9BQU87SUFFdEIsTUFBTSxTQUFTLEdBQ2IsT0FBTywrQkFBK0IsS0FBSyxRQUFRO1FBQ2pELENBQUMsQ0FBQywrQkFBK0IsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDO1lBQ2hELENBQUMsQ0FBQyxtQkFBbUIsQ0FBQywrQkFBZ0QsQ0FBQztZQUN2RSxDQUFDLENBQUMsaUJBQWlCLENBQUMsK0JBQStCLENBQUM7UUFDdEQsQ0FBQyxDQUFDLCtCQUErQixDQUFDO0lBRXRDLE1BQU0sWUFBWSxHQUFHLGtCQUFrQixDQUFDO1FBQ3RDLE9BQU8sRUFBRSxTQUFTO1FBQ2xCLEtBQUs7UUFDTCxTQUFTLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQztLQUN4QixDQUFDLENBQUM7SUFDSCxNQUFNLFlBQVksR0FBRyxrQkFBa0IsQ0FBQztRQUN0QyxLQUFLO1FBQ0wsU0FBUyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUM7S0FDeEIsQ0FBQyxD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
243
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95X2wxX2NvbnRyYWN0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9kZXBsb3lfbDFfY29udHJhY3RzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUszRCxPQUFPLEVBT0wsU0FBUyxFQUNULGtCQUFrQixFQUNsQixrQkFBa0IsRUFDbEIsZ0JBQWdCLEVBQ2hCLFVBQVUsRUFDVixXQUFXLEVBQ1gsa0JBQWtCLEVBQ2xCLElBQUksRUFDSixXQUFXLEVBQ1gsTUFBTSxFQUNOLFdBQVcsR0FDWixNQUFNLE1BQU0sQ0FBQztBQUNkLE9BQU8sRUFBMEMsaUJBQWlCLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDL0csT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLGFBQWEsQ0FBQztBQTJFdEM7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLGVBQWUsQ0FDN0IsTUFBYyxFQUNkLCtCQUF1RixFQUN2RixRQUFlLE9BQU87SUFFdEIsTUFBTSxTQUFTLEdBQ2IsT0FBTywrQkFBK0IsS0FBSyxRQUFRO1FBQ2pELENBQUMsQ0FBQywrQkFBK0IsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDO1lBQ2hELENBQUMsQ0FBQyxtQkFBbUIsQ0FBQywrQkFBZ0QsQ0FBQztZQUN2RSxDQUFDLENBQUMsaUJBQWlCLENBQUMsK0JBQStCLENBQUM7UUFDdEQsQ0FBQyxDQUFDLCtCQUErQixDQUFDO0lBRXRDLE1BQU0sWUFBWSxHQUFHLGtCQUFrQixDQUFDO1FBQ3RDLE9BQU8sRUFBRSxTQUFTO1FBQ2xCLEtBQUs7UUFDTCxTQUFTLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQztLQUN4QixDQUFDLENBQUM7SUFDSCxNQUFNLFlBQVksR0FBRyxrQkFBa0IsQ0FBQztRQUN0QyxLQUFLO1FBQ0wsU0FBUyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUM7S0FDeEIsQ0FBQyxD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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/ethereum",
3
- "version": "0.50.1",
3
+ "version": "0.51.1",
4
4
  "type": "module",
5
5
  "exports": "./dest/index.js",
6
6
  "typedocOptions": {
@@ -24,7 +24,7 @@
24
24
  "../package.common.json"
25
25
  ],
26
26
  "dependencies": {
27
- "@aztec/foundation": "0.50.1",
27
+ "@aztec/foundation": "0.51.1",
28
28
  "dotenv": "^16.0.3",
29
29
  "tslib": "^2.4.0",
30
30
  "viem": "^2.7.15"
@@ -89,7 +89,7 @@ export interface L1ContractArtifactsForDeployment {
89
89
  */
90
90
  feeJuice: ContractArtifacts;
91
91
  /**
92
- * Gas portal contract artifacts. Optional for now as gas is not strictly enforced
92
+ * Fee juice portal contract artifacts. Optional for now as gas is not strictly enforced
93
93
  */
94
94
  feeJuicePortal: ContractArtifacts;
95
95
  }
@@ -147,12 +147,18 @@ export const deployL1Contracts = async (
147
147
  chain: Chain,
148
148
  logger: DebugLogger,
149
149
  contractsToDeploy: L1ContractArtifactsForDeployment,
150
- args: { l2FeeJuiceAddress: AztecAddress; vkTreeRoot: Fr; assumeProvenUntil?: number; salt: number | undefined },
150
+ args: {
151
+ l2FeeJuiceAddress: AztecAddress;
152
+ vkTreeRoot: Fr;
153
+ assumeProvenUntil?: number;
154
+ salt: number | undefined;
155
+ initialValidators?: EthAddress[];
156
+ },
151
157
  ): Promise<DeployL1Contracts> => {
152
158
  // We are assuming that you are running this on a local anvil node which have 1s block times
153
159
  // To align better with actual deployment, we update the block interval to 12s
154
160
  // The code is same as `setBlockInterval` in `cheat_codes.ts`
155
- const rpcCall = async (rpcUrl: string, method: string, params: any[]) => {
161
+ const rpcCall = async (method: string, params: any[]) => {
156
162
  const paramsString = JSON.stringify(params);
157
163
  const content = {
158
164
  body: `{"jsonrpc":"2.0", "method": "${method}", "params": ${paramsString}, "id": 1}`,
@@ -161,12 +167,14 @@ export const deployL1Contracts = async (
161
167
  };
162
168
  return await (await fetch(rpcUrl, content)).json();
163
169
  };
164
- const interval = 12;
165
- const res = await rpcCall(rpcUrl, 'anvil_setBlockTimestampInterval', [interval]);
166
- if (res.error) {
167
- throw new Error(`Error setting block interval: ${res.error.message}`);
170
+ if (chain.id == foundry.id) {
171
+ const interval = 12;
172
+ const res = await rpcCall('anvil_setBlockTimestampInterval', [interval]);
173
+ if (res.error) {
174
+ throw new Error(`Error setting block interval: ${res.error.message}`);
175
+ }
176
+ logger.info(`Set block interval to ${interval}`);
168
177
  }
169
- logger.info(`Set block interval to ${interval}`);
170
178
 
171
179
  logger.info(`Deploying contracts from ${account.address.toString()}...`);
172
180
 
@@ -188,35 +196,59 @@ export const deployL1Contracts = async (
188
196
 
189
197
  logger.info(`Deployed Gas Portal at ${feeJuicePortalAddress}`);
190
198
 
199
+ const rollupAddress = await deployer.deploy(contractsToDeploy.rollup, [
200
+ getAddress(registryAddress.toString()),
201
+ getAddress(availabilityOracleAddress.toString()),
202
+ getAddress(feeJuicePortalAddress.toString()),
203
+ args.vkTreeRoot.toString(),
204
+ account.address.toString(),
205
+ args.initialValidators?.map(v => v.toString()) ?? [],
206
+ ]);
207
+ logger.info(`Deployed Rollup at ${rollupAddress}`);
208
+
209
+ await deployer.waitForDeployments();
210
+ logger.info(`All contracts deployed`);
211
+
191
212
  const feeJuicePortal = getContract({
192
213
  address: feeJuicePortalAddress.toString(),
193
214
  abi: contractsToDeploy.feeJuicePortal.contractAbi,
194
215
  client: walletClient,
195
216
  });
196
217
 
197
- // fund the portal contract with Fee Juice
198
218
  const feeJuice = getContract({
199
219
  address: feeJuiceAddress.toString(),
200
220
  abi: contractsToDeploy.feeJuice.contractAbi,
201
221
  client: walletClient,
202
222
  });
203
223
 
224
+ const rollup = getContract({
225
+ address: getAddress(rollupAddress.toString()),
226
+ abi: contractsToDeploy.rollup.contractAbi,
227
+ client: walletClient,
228
+ });
229
+
230
+ // Transaction hashes to await
231
+ const txHashes: Hex[] = [];
232
+
204
233
  // @note This value MUST match what is in `constants.nr`. It is currently specified here instead of just importing
205
234
  // because there is circular dependency hell. This is a temporary solution. #3342
235
+ // @todo #8084
236
+ // fund the portal contract with Fee Juice
206
237
  const FEE_JUICE_INITIAL_MINT = 20000000000;
207
- const receipt = await feeJuice.write.mint([feeJuicePortalAddress.toString(), FEE_JUICE_INITIAL_MINT], {} as any);
208
- await publicClient.waitForTransactionReceipt({ hash: receipt });
209
- logger.info(`Funded fee juice portal contract with Fee Juice`);
238
+ const mintTxHash = await feeJuice.write.mint([feeJuicePortalAddress.toString(), FEE_JUICE_INITIAL_MINT], {} as any);
239
+ txHashes.push(mintTxHash);
240
+ logger.info(`Funding fee juice portal contract with fee juice in ${mintTxHash}`);
210
241
 
211
242
  if ((await feeJuicePortal.read.registry([])) === zeroAddress) {
212
- await publicClient.waitForTransactionReceipt({
213
- hash: await feeJuicePortal.write.initialize([
214
- registryAddress.toString(),
215
- feeJuiceAddress.toString(),
216
- args.l2FeeJuiceAddress.toString(),
217
- ]),
218
- });
219
- logger.verbose(`Fee juice portal initialized with registry ${registryAddress.toString()}`);
243
+ const initPortalTxHash = await feeJuicePortal.write.initialize([
244
+ registryAddress.toString(),
245
+ feeJuiceAddress.toString(),
246
+ args.l2FeeJuiceAddress.toString(),
247
+ ]);
248
+ txHashes.push(initPortalTxHash);
249
+ logger.verbose(
250
+ `Fee juice portal initializing with registry ${registryAddress.toString()} in tx ${initPortalTxHash}`,
251
+ );
220
252
  } else {
221
253
  logger.verbose(`Fee juice portal is already initialized`);
222
254
  }
@@ -225,47 +257,40 @@ export const deployL1Contracts = async (
225
257
  `Initialized Gas Portal at ${feeJuicePortalAddress} to bridge between L1 ${feeJuiceAddress} to L2 ${args.l2FeeJuiceAddress}`,
226
258
  );
227
259
 
228
- const rollupAddress = await deployer.deploy(contractsToDeploy.rollup, [
229
- getAddress(registryAddress.toString()),
230
- getAddress(availabilityOracleAddress.toString()),
231
- getAddress(feeJuicePortalAddress.toString()),
232
- args.vkTreeRoot.toString(),
233
- account.address.toString(),
234
- ]);
235
- logger.info(`Deployed Rollup at ${rollupAddress}`);
260
+ if (chain.id == foundry.id) {
261
+ // @note We make a time jump PAST the very first slot to not have to deal with the edge case of the first slot.
262
+ // The edge case being that the genesis block is already occupying slot 0, so we cannot have another block.
263
+ try {
264
+ // Need to get the time
265
+ const currentSlot = (await rollup.read.getCurrentSlot([])) as bigint;
266
+
267
+ if (BigInt(currentSlot) === 0n) {
268
+ const ts = Number(await rollup.read.getTimestampForSlot([1]));
269
+ await rpcCall('evm_setNextBlockTimestamp', [ts]);
270
+ await rpcCall('hardhat_mine', [1]);
271
+ const currentSlot = (await rollup.read.getCurrentSlot([])) as bigint;
272
+
273
+ if (BigInt(currentSlot) !== 1n) {
274
+ throw new Error(`Error jumping time: current slot is ${currentSlot}`);
275
+ }
276
+ logger.info(`Jumped to slot 1`);
277
+ }
278
+ } catch (e) {
279
+ throw new Error(`Error jumping time: ${e}`);
280
+ }
281
+ }
236
282
 
237
283
  // Set initial blocks as proven if requested
238
284
  if (args.assumeProvenUntil && args.assumeProvenUntil > 0) {
239
- const rollup = getContract({
240
- address: getAddress(rollupAddress.toString()),
241
- abi: contractsToDeploy.rollup.contractAbi,
242
- client: walletClient,
243
- });
244
285
  await rollup.write.setAssumeProvenUntilBlockNumber([BigInt(args.assumeProvenUntil)], { account });
245
286
  logger.info(`Set Rollup assumedProvenUntil to ${args.assumeProvenUntil}`);
246
287
  }
247
288
 
248
289
  // Inbox and Outbox are immutable and are deployed from Rollup's constructor so we just fetch them from the contract.
249
- let inboxAddress!: EthAddress;
250
- {
251
- const rollup = getContract({
252
- address: getAddress(rollupAddress.toString()),
253
- abi: contractsToDeploy.rollup.contractAbi,
254
- client: publicClient,
255
- });
256
- inboxAddress = EthAddress.fromString((await rollup.read.INBOX([])) as any);
257
- }
290
+ const inboxAddress = EthAddress.fromString((await rollup.read.INBOX([])) as any);
258
291
  logger.info(`Inbox available at ${inboxAddress}`);
259
292
 
260
- let outboxAddress!: EthAddress;
261
- {
262
- const rollup = getContract({
263
- address: getAddress(rollupAddress.toString()),
264
- abi: contractsToDeploy.rollup.contractAbi,
265
- client: publicClient,
266
- });
267
- outboxAddress = EthAddress.fromString((await rollup.read.OUTBOX([])) as any);
268
- }
293
+ const outboxAddress = EthAddress.fromString((await rollup.read.OUTBOX([])) as any);
269
294
  logger.info(`Outbox available at ${outboxAddress}`);
270
295
 
271
296
  // We need to call a function on the registry to set the various contract addresses.
@@ -275,12 +300,19 @@ export const deployL1Contracts = async (
275
300
  client: walletClient,
276
301
  });
277
302
  if (!(await registryContract.read.isRollupRegistered([getAddress(rollupAddress.toString())]))) {
278
- await registryContract.write.upgrade([getAddress(rollupAddress.toString())], { account });
279
- logger.verbose(`Upgraded registry contract at ${registryAddress} to rollup ${rollupAddress}`);
303
+ const upgradeTxHash = await registryContract.write.upgrade([getAddress(rollupAddress.toString())], { account });
304
+ logger.verbose(
305
+ `Upgrading registry contract at ${registryAddress} to rollup ${rollupAddress} in tx ${upgradeTxHash}`,
306
+ );
307
+ txHashes.push(upgradeTxHash);
280
308
  } else {
281
309
  logger.verbose(`Registry ${registryAddress} has already registered rollup ${rollupAddress}`);
282
310
  }
283
311
 
312
+ // Wait for all actions to be mined
313
+ await Promise.all(txHashes.map(txHash => publicClient.waitForTransactionReceipt({ hash: txHash })));
314
+ logger.verbose(`All transactions for L1 deployment have been mined`);
315
+
284
316
  const l1Contracts: L1ContractAddresses = {
285
317
  availabilityOracleAddress,
286
318
  rollupAddress,
@@ -300,6 +332,7 @@ export const deployL1Contracts = async (
300
332
 
301
333
  class L1Deployer {
302
334
  private salt: Hex | undefined;
335
+ private txHashes: Hex[] = [];
303
336
  constructor(
304
337
  private walletClient: WalletClient<HttpTransport, Chain, Account>,
305
338
  private publicClient: PublicClient<HttpTransport, Chain>,
@@ -309,11 +342,11 @@ class L1Deployer {
309
342
  this.salt = maybeSalt ? padHex(numberToHex(maybeSalt), { size: 32 }) : undefined;
310
343
  }
311
344
 
312
- deploy(
345
+ async deploy(
313
346
  params: { contractAbi: Narrow<Abi | readonly unknown[]>; contractBytecode: Hex },
314
347
  args: readonly unknown[] = [],
315
348
  ): Promise<EthAddress> {
316
- return deployL1Contract(
349
+ const { txHash, address } = await deployL1Contract(
317
350
  this.walletClient,
318
351
  this.publicClient,
319
352
  params.contractAbi,
@@ -322,6 +355,14 @@ class L1Deployer {
322
355
  this.salt,
323
356
  this.logger,
324
357
  );
358
+ if (txHash) {
359
+ this.txHashes.push(txHash);
360
+ }
361
+ return address;
362
+ }
363
+
364
+ async waitForDeployments(): Promise<void> {
365
+ await Promise.all(this.txHashes.map(txHash => this.publicClient.waitForTransactionReceipt({ hash: txHash })));
325
366
  }
326
367
  }
327
368
 
@@ -333,6 +374,7 @@ class L1Deployer {
333
374
  * @param abi - The ETH contract's ABI (as abitype's Abi).
334
375
  * @param bytecode - The ETH contract's bytecode.
335
376
  * @param args - Constructor arguments for the contract.
377
+ * @param maybeSalt - Optional salt for CREATE2 deployment (does not wait for deployment tx to be mined if set, does not send tx if contract already exists).
336
378
  * @returns The ETH address the contract was deployed to.
337
379
  */
338
380
  export async function deployL1Contract(
@@ -343,38 +385,37 @@ export async function deployL1Contract(
343
385
  args: readonly unknown[] = [],
344
386
  maybeSalt?: Hex,
345
387
  logger?: DebugLogger,
346
- ): Promise<EthAddress> {
388
+ ): Promise<{ address: EthAddress; txHash: Hex | undefined }> {
389
+ let txHash: Hex | undefined = undefined;
390
+ let address: Hex | null | undefined = undefined;
391
+
347
392
  if (maybeSalt) {
348
393
  const salt = padHex(maybeSalt, { size: 32 });
349
394
  const deployer: Hex = '0x4e59b44847b379578588920cA78FbF26c0B4956C';
350
395
  const calldata = encodeDeployData({ abi, bytecode, args });
351
- const address = getContractAddress({ from: deployer, salt, bytecode: calldata, opcode: 'CREATE2' });
396
+ address = getContractAddress({ from: deployer, salt, bytecode: calldata, opcode: 'CREATE2' });
352
397
  const existing = await publicClient.getBytecode({ address });
353
398
 
354
399
  if (existing === undefined || existing === '0x') {
355
- const hash = await walletClient.sendTransaction({
356
- to: deployer,
357
- data: concatHex([salt, calldata]),
358
- });
359
- logger?.verbose(`Deploying contract with salt ${salt} to address ${address} in tx ${hash}`);
360
- await publicClient.waitForTransactionReceipt({ hash, pollingInterval: 100 });
400
+ txHash = await walletClient.sendTransaction({ to: deployer, data: concatHex([salt, calldata]) });
401
+ logger?.verbose(`Deploying contract with salt ${salt} to address ${address} in tx ${txHash}`);
361
402
  } else {
362
403
  logger?.verbose(`Skipping existing deployment of contract with salt ${salt} to address ${address}`);
363
404
  }
364
- return EthAddress.fromString(address);
365
405
  } else {
366
- const hash = await walletClient.deployContract({ abi, bytecode, args });
367
- logger?.verbose(`Deploying contract in tx ${hash}`);
368
- const receipt = await publicClient.waitForTransactionReceipt({ hash, pollingInterval: 100 });
369
- const contractAddress = receipt.contractAddress;
370
- if (!contractAddress) {
406
+ txHash = await walletClient.deployContract({ abi, bytecode, args });
407
+ logger?.verbose(`Deploying contract in tx ${txHash}`);
408
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash, pollingInterval: 100 });
409
+ address = receipt.contractAddress;
410
+ if (!address) {
371
411
  throw new Error(
372
412
  `No contract address found in receipt: ${JSON.stringify(receipt, (_, val) =>
373
413
  typeof val === 'bigint' ? String(val) : val,
374
414
  )}`,
375
415
  );
376
416
  }
377
- return EthAddress.fromString(contractAddress);
378
417
  }
418
+
419
+ return { address: EthAddress.fromString(address!), txHash };
379
420
  }
380
421
  // docs:end:deployL1Contract