@aztec/ethereum 2.0.3 → 2.1.0-rc.2
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.
- package/dest/config.d.ts +10 -5
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +27 -39
- package/dest/contracts/empire_base.d.ts +1 -1
- package/dest/contracts/empire_base.d.ts.map +1 -1
- package/dest/contracts/empire_slashing_proposer.d.ts +1 -1
- package/dest/contracts/empire_slashing_proposer.d.ts.map +1 -1
- package/dest/contracts/fee_asset_handler.d.ts +3 -3
- package/dest/contracts/fee_asset_handler.d.ts.map +1 -1
- package/dest/contracts/governance.js +7 -3
- package/dest/contracts/governance_proposer.d.ts +1 -2
- package/dest/contracts/governance_proposer.d.ts.map +1 -1
- package/dest/contracts/governance_proposer.js +1 -2
- package/dest/contracts/multicall.d.ts +3 -5
- package/dest/contracts/multicall.d.ts.map +1 -1
- package/dest/contracts/multicall.js +6 -4
- package/dest/contracts/rollup.d.ts +13 -14
- package/dest/contracts/rollup.d.ts.map +1 -1
- package/dest/contracts/rollup.js +25 -67
- package/dest/contracts/slasher_contract.d.ts +10 -0
- package/dest/contracts/slasher_contract.d.ts.map +1 -1
- package/dest/contracts/slasher_contract.js +18 -0
- package/dest/deploy_l1_contracts.d.ts +18 -4
- package/dest/deploy_l1_contracts.d.ts.map +1 -1
- package/dest/deploy_l1_contracts.js +316 -159
- package/dest/index.d.ts +1 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -1
- package/dest/l1_artifacts.d.ts +8019 -5948
- package/dest/l1_artifacts.d.ts.map +1 -1
- package/dest/l1_artifacts.js +6 -1
- package/dest/l1_contract_addresses.d.ts +5 -1
- package/dest/l1_contract_addresses.d.ts.map +1 -1
- package/dest/l1_contract_addresses.js +2 -1
- package/dest/l1_tx_utils/config.d.ts +59 -0
- package/dest/l1_tx_utils/config.d.ts.map +1 -0
- package/dest/l1_tx_utils/config.js +73 -0
- package/dest/l1_tx_utils/constants.d.ts +6 -0
- package/dest/l1_tx_utils/constants.d.ts.map +1 -0
- package/dest/l1_tx_utils/constants.js +14 -0
- package/dest/l1_tx_utils/factory.d.ts +24 -0
- package/dest/l1_tx_utils/factory.d.ts.map +1 -0
- package/dest/l1_tx_utils/factory.js +12 -0
- package/dest/l1_tx_utils/index.d.ts +10 -0
- package/dest/l1_tx_utils/index.d.ts.map +1 -0
- package/dest/l1_tx_utils/index.js +10 -0
- package/dest/l1_tx_utils/interfaces.d.ts +76 -0
- package/dest/l1_tx_utils/interfaces.d.ts.map +1 -0
- package/dest/l1_tx_utils/interfaces.js +4 -0
- package/dest/l1_tx_utils/l1_tx_utils.d.ts +95 -0
- package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -0
- package/dest/l1_tx_utils/l1_tx_utils.js +610 -0
- package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts +26 -0
- package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts.map +1 -0
- package/dest/l1_tx_utils/l1_tx_utils_with_blobs.js +26 -0
- package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +81 -0
- package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -0
- package/dest/l1_tx_utils/readonly_l1_tx_utils.js +294 -0
- package/dest/l1_tx_utils/signer.d.ts +4 -0
- package/dest/l1_tx_utils/signer.d.ts.map +1 -0
- package/dest/l1_tx_utils/signer.js +16 -0
- package/dest/l1_tx_utils/types.d.ts +67 -0
- package/dest/l1_tx_utils/types.d.ts.map +1 -0
- package/dest/l1_tx_utils/types.js +26 -0
- package/dest/l1_tx_utils/utils.d.ts +4 -0
- package/dest/l1_tx_utils/utils.d.ts.map +1 -0
- package/dest/l1_tx_utils/utils.js +14 -0
- package/dest/publisher_manager.d.ts +7 -2
- package/dest/publisher_manager.d.ts.map +1 -1
- package/dest/publisher_manager.js +36 -8
- package/dest/queries.d.ts.map +1 -1
- package/dest/queries.js +8 -2
- package/dest/test/chain_monitor.js +2 -2
- package/dest/test/delayed_tx_utils.d.ts +2 -2
- package/dest/test/delayed_tx_utils.d.ts.map +1 -1
- package/dest/test/delayed_tx_utils.js +2 -2
- package/dest/test/eth_cheat_codes.d.ts +18 -1
- package/dest/test/eth_cheat_codes.d.ts.map +1 -1
- package/dest/test/eth_cheat_codes.js +101 -22
- package/dest/test/rollup_cheat_codes.d.ts +3 -1
- package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
- package/dest/test/rollup_cheat_codes.js +2 -2
- package/dest/test/upgrade_utils.js +1 -1
- package/package.json +6 -6
- package/src/config.ts +34 -44
- package/src/contracts/empire_base.ts +1 -1
- package/src/contracts/empire_slashing_proposer.ts +1 -1
- package/src/contracts/fee_asset_handler.ts +1 -1
- package/src/contracts/governance.ts +3 -3
- package/src/contracts/governance_proposer.ts +3 -4
- package/src/contracts/multicall.ts +12 -10
- package/src/contracts/rollup.ts +31 -86
- package/src/contracts/slasher_contract.ts +22 -0
- package/src/deploy_l1_contracts.ts +351 -178
- package/src/index.ts +1 -1
- package/src/l1_artifacts.ts +8 -0
- package/src/l1_contract_addresses.ts +3 -1
- package/src/l1_tx_utils/README.md +177 -0
- package/src/l1_tx_utils/config.ts +140 -0
- package/src/l1_tx_utils/constants.ts +18 -0
- package/src/l1_tx_utils/factory.ts +64 -0
- package/src/l1_tx_utils/index.ts +12 -0
- package/src/l1_tx_utils/interfaces.ts +86 -0
- package/src/l1_tx_utils/l1_tx_utils.ts +718 -0
- package/src/l1_tx_utils/l1_tx_utils_with_blobs.ts +77 -0
- package/src/l1_tx_utils/readonly_l1_tx_utils.ts +372 -0
- package/src/l1_tx_utils/signer.ts +28 -0
- package/src/l1_tx_utils/types.ts +85 -0
- package/src/l1_tx_utils/utils.ts +16 -0
- package/src/publisher_manager.ts +51 -9
- package/src/queries.ts +10 -1
- package/src/test/chain_monitor.ts +2 -2
- package/src/test/delayed_tx_utils.ts +2 -2
- package/src/test/eth_cheat_codes.ts +120 -20
- package/src/test/rollup_cheat_codes.ts +5 -2
- package/src/test/upgrade_utils.ts +1 -1
- package/dest/l1_tx_utils.d.ts +0 -252
- package/dest/l1_tx_utils.d.ts.map +0 -1
- package/dest/l1_tx_utils.js +0 -834
- package/dest/l1_tx_utils_with_blobs.d.ts +0 -20
- package/dest/l1_tx_utils_with_blobs.d.ts.map +0 -1
- package/dest/l1_tx_utils_with_blobs.js +0 -87
- package/src/l1_tx_utils.ts +0 -1124
- package/src/l1_tx_utils_with_blobs.ts +0 -150
|
@@ -6,10 +6,11 @@ import type { Fr } from '@aztec/foundation/fields';
|
|
|
6
6
|
import { jsonStringify } from '@aztec/foundation/json-rpc';
|
|
7
7
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
8
8
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
9
|
-
import
|
|
9
|
+
import { RollupAbi } from '@aztec/l1-artifacts/RollupAbi';
|
|
10
10
|
|
|
11
11
|
import type { Abi, Narrow } from 'abitype';
|
|
12
12
|
import { mkdir, writeFile } from 'fs/promises';
|
|
13
|
+
import chunk from 'lodash.chunk';
|
|
13
14
|
import {
|
|
14
15
|
type Chain,
|
|
15
16
|
type ContractConstructorArgs,
|
|
@@ -33,7 +34,6 @@ import { createExtendedL1Client } from './client.js';
|
|
|
33
34
|
import {
|
|
34
35
|
type L1ContractsConfig,
|
|
35
36
|
getEntryQueueConfig,
|
|
36
|
-
getGSEConfiguration,
|
|
37
37
|
getGovernanceConfiguration,
|
|
38
38
|
getRewardBoostConfig,
|
|
39
39
|
getRewardConfig,
|
|
@@ -45,6 +45,7 @@ import { RegistryContract } from './contracts/registry.js';
|
|
|
45
45
|
import { RollupContract, SlashingProposerType } from './contracts/rollup.js';
|
|
46
46
|
import {
|
|
47
47
|
CoinIssuerArtifact,
|
|
48
|
+
DateGatedRelayerArtifact,
|
|
48
49
|
FeeAssetArtifact,
|
|
49
50
|
FeeAssetHandlerArtifact,
|
|
50
51
|
GSEArtifact,
|
|
@@ -63,21 +64,19 @@ import {
|
|
|
63
64
|
import type { L1ContractAddresses } from './l1_contract_addresses.js';
|
|
64
65
|
import {
|
|
65
66
|
type GasPrice,
|
|
66
|
-
type
|
|
67
|
+
type L1TxConfig,
|
|
67
68
|
type L1TxRequest,
|
|
68
69
|
L1TxUtils,
|
|
69
70
|
type L1TxUtilsConfig,
|
|
70
71
|
createL1TxUtilsFromViemWallet,
|
|
71
72
|
getL1TxUtilsConfigEnvVars,
|
|
72
|
-
} from './l1_tx_utils.js';
|
|
73
|
+
} from './l1_tx_utils/index.js';
|
|
73
74
|
import type { ExtendedViemWalletClient } from './types.js';
|
|
74
75
|
import { formatViemError } from './utils.js';
|
|
75
76
|
import { ZK_PASSPORT_DOMAIN, ZK_PASSPORT_SCOPE, ZK_PASSPORT_VERIFIER_ADDRESS } from './zkPassportVerifierAddress.js';
|
|
76
77
|
|
|
77
78
|
export const DEPLOYER_ADDRESS: Hex = '0x4e59b44847b379578588920cA78FbF26c0B4956C';
|
|
78
79
|
|
|
79
|
-
const networkName = getActiveNetworkName();
|
|
80
|
-
|
|
81
80
|
export type Operator = {
|
|
82
81
|
attester: EthAddress;
|
|
83
82
|
withdrawer: EthAddress;
|
|
@@ -166,6 +165,8 @@ export interface DeployL1ContractsArgs extends Omit<L1ContractsConfig, keyof L1T
|
|
|
166
165
|
realVerifier: boolean;
|
|
167
166
|
/** The zk passport args */
|
|
168
167
|
zkPassportArgs?: ZKPassportArgs;
|
|
168
|
+
/** If provided, use this token for BOTH fee and staking assets (skip deployments) */
|
|
169
|
+
existingTokenAddress?: EthAddress;
|
|
169
170
|
}
|
|
170
171
|
|
|
171
172
|
export interface ZKPassportArgs {
|
|
@@ -177,39 +178,126 @@ export interface ZKPassportArgs {
|
|
|
177
178
|
zkPassportScope?: string;
|
|
178
179
|
}
|
|
179
180
|
|
|
181
|
+
// Minimal ERC20 ABI for validation purposes. We only read view methods.
|
|
182
|
+
const ERC20_VALIDATION_ABI = [
|
|
183
|
+
{
|
|
184
|
+
type: 'function',
|
|
185
|
+
name: 'totalSupply',
|
|
186
|
+
stateMutability: 'view',
|
|
187
|
+
inputs: [],
|
|
188
|
+
outputs: [{ name: '', type: 'uint256' }],
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
type: 'function',
|
|
192
|
+
name: 'name',
|
|
193
|
+
stateMutability: 'view',
|
|
194
|
+
inputs: [],
|
|
195
|
+
outputs: [{ name: '', type: 'string' }],
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
type: 'function',
|
|
199
|
+
name: 'symbol',
|
|
200
|
+
stateMutability: 'view',
|
|
201
|
+
inputs: [],
|
|
202
|
+
outputs: [{ name: '', type: 'string' }],
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
type: 'function',
|
|
206
|
+
name: 'decimals',
|
|
207
|
+
stateMutability: 'view',
|
|
208
|
+
inputs: [],
|
|
209
|
+
outputs: [{ name: '', type: 'uint8' }],
|
|
210
|
+
},
|
|
211
|
+
] as const;
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Validates that the provided address points to a contract that resembles an ERC20 token.
|
|
215
|
+
* Checks for contract code and attempts common ERC20 view calls.
|
|
216
|
+
* Throws an error if validation fails.
|
|
217
|
+
*/
|
|
218
|
+
export async function validateExistingErc20TokenAddress(
|
|
219
|
+
l1Client: ExtendedViemWalletClient,
|
|
220
|
+
tokenAddress: EthAddress,
|
|
221
|
+
logger: Logger,
|
|
222
|
+
): Promise<void> {
|
|
223
|
+
const addressString = tokenAddress.toString();
|
|
224
|
+
|
|
225
|
+
// Ensure there is contract code at the address
|
|
226
|
+
const code = await l1Client.getCode({ address: addressString });
|
|
227
|
+
if (!code || code === '0x') {
|
|
228
|
+
throw new Error(`No contract code found at provided token address ${addressString}`);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const contract = getContract({
|
|
232
|
+
address: getAddress(addressString),
|
|
233
|
+
abi: ERC20_VALIDATION_ABI,
|
|
234
|
+
client: l1Client,
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// Validate all required ERC20 methods in parallel
|
|
238
|
+
const checks = [
|
|
239
|
+
contract.read.totalSupply().then(total => typeof total === 'bigint'),
|
|
240
|
+
contract.read.name().then(() => true),
|
|
241
|
+
contract.read.symbol().then(() => true),
|
|
242
|
+
contract.read.decimals().then(dec => typeof dec === 'number' || typeof dec === 'bigint'),
|
|
243
|
+
];
|
|
244
|
+
|
|
245
|
+
const results = await Promise.allSettled(checks);
|
|
246
|
+
const failedChecks = results.filter(result => result.status === 'rejected' || result.value !== true);
|
|
247
|
+
|
|
248
|
+
if (failedChecks.length > 0) {
|
|
249
|
+
throw new Error(`Address ${addressString} does not appear to implement ERC20 view methods`);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
logger.verbose(`Validated existing token at ${addressString} appears to be ERC20-compatible`);
|
|
253
|
+
}
|
|
254
|
+
|
|
180
255
|
export const deploySharedContracts = async (
|
|
181
256
|
l1Client: ExtendedViemWalletClient,
|
|
182
257
|
deployer: L1Deployer,
|
|
183
258
|
args: DeployL1ContractsArgs,
|
|
184
259
|
logger: Logger,
|
|
185
260
|
) => {
|
|
261
|
+
const networkName = getActiveNetworkName();
|
|
262
|
+
|
|
186
263
|
logger.info(`Deploying shared contracts for network configuration: ${networkName}`);
|
|
187
264
|
|
|
188
265
|
const txHashes: Hex[] = [];
|
|
189
266
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
267
|
+
let feeAssetAddress: EthAddress;
|
|
268
|
+
let stakingAssetAddress: EthAddress;
|
|
269
|
+
if (args.existingTokenAddress) {
|
|
270
|
+
await validateExistingErc20TokenAddress(l1Client, args.existingTokenAddress, logger);
|
|
271
|
+
feeAssetAddress = args.existingTokenAddress;
|
|
272
|
+
stakingAssetAddress = args.existingTokenAddress;
|
|
273
|
+
logger.verbose(`Using existing token for fee and staking assets at ${args.existingTokenAddress}`);
|
|
274
|
+
} else {
|
|
275
|
+
const deployedFee = await deployer.deploy(FeeAssetArtifact, ['FeeJuice', 'FEE', l1Client.account.address]);
|
|
276
|
+
feeAssetAddress = deployedFee.address;
|
|
277
|
+
logger.verbose(`Deployed Fee Asset at ${feeAssetAddress}`);
|
|
195
278
|
|
|
196
|
-
|
|
279
|
+
const deployedStaking = await deployer.deploy(StakingAssetArtifact, ['Staking', 'STK', l1Client.account.address]);
|
|
280
|
+
stakingAssetAddress = deployedStaking.address;
|
|
281
|
+
logger.verbose(`Deployed Staking Asset at ${stakingAssetAddress}`);
|
|
282
|
+
}
|
|
197
283
|
|
|
198
|
-
const gseAddress =
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
284
|
+
const gseAddress = (
|
|
285
|
+
await deployer.deploy(GSEArtifact, [
|
|
286
|
+
l1Client.account.address,
|
|
287
|
+
stakingAssetAddress.toString(),
|
|
288
|
+
args.activationThreshold,
|
|
289
|
+
args.ejectionThreshold,
|
|
290
|
+
])
|
|
291
|
+
).address;
|
|
204
292
|
logger.verbose(`Deployed GSE at ${gseAddress}`);
|
|
205
293
|
|
|
206
|
-
const registryAddress = await deployer.deploy(RegistryArtifact, [
|
|
294
|
+
const { address: registryAddress } = await deployer.deploy(RegistryArtifact, [
|
|
207
295
|
l1Client.account.address,
|
|
208
296
|
feeAssetAddress.toString(),
|
|
209
297
|
]);
|
|
210
298
|
logger.verbose(`Deployed Registry at ${registryAddress}`);
|
|
211
299
|
|
|
212
|
-
const governanceProposerAddress = await deployer.deploy(GovernanceProposerArtifact, [
|
|
300
|
+
const { address: governanceProposerAddress } = await deployer.deploy(GovernanceProposerArtifact, [
|
|
213
301
|
registryAddress.toString(),
|
|
214
302
|
gseAddress.toString(),
|
|
215
303
|
BigInt(args.governanceProposerQuorum ?? args.governanceProposerRoundSize / 2 + 1),
|
|
@@ -219,7 +307,7 @@ export const deploySharedContracts = async (
|
|
|
219
307
|
|
|
220
308
|
// @note @LHerskind the assets are expected to be the same at some point, but for better
|
|
221
309
|
// configurability they are different for now.
|
|
222
|
-
const governanceAddress = await deployer.deploy(GovernanceArtifact, [
|
|
310
|
+
const { address: governanceAddress } = await deployer.deploy(GovernanceArtifact, [
|
|
223
311
|
stakingAssetAddress.toString(),
|
|
224
312
|
governanceProposerAddress.toString(),
|
|
225
313
|
gseAddress.toString(),
|
|
@@ -261,11 +349,13 @@ export const deploySharedContracts = async (
|
|
|
261
349
|
txHashes.push(txHash);
|
|
262
350
|
}
|
|
263
351
|
|
|
264
|
-
const coinIssuerAddress =
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
352
|
+
const coinIssuerAddress = (
|
|
353
|
+
await deployer.deploy(CoinIssuerArtifact, [
|
|
354
|
+
feeAssetAddress.toString(),
|
|
355
|
+
(25_000_000_000n * 10n ** 18n) / (60n * 60n * 24n * 365n),
|
|
356
|
+
l1Client.account.address,
|
|
357
|
+
])
|
|
358
|
+
).address;
|
|
269
359
|
logger.verbose(`Deployed CoinIssuer at ${coinIssuerAddress}`);
|
|
270
360
|
|
|
271
361
|
logger.verbose(`Waiting for deployments to complete`);
|
|
@@ -277,17 +367,19 @@ export const deploySharedContracts = async (
|
|
|
277
367
|
let stakingAssetHandlerAddress: EthAddress | undefined = undefined;
|
|
278
368
|
let zkPassportVerifierAddress: EthAddress | undefined = undefined;
|
|
279
369
|
|
|
280
|
-
// Only if not on mainnet will we deploy the handlers
|
|
281
|
-
if (l1Client.chain.id !== 1) {
|
|
370
|
+
// Only if not on mainnet will we deploy the handlers, and only when we control the token
|
|
371
|
+
if (l1Client.chain.id !== 1 && !args.existingTokenAddress) {
|
|
282
372
|
/* -------------------------------------------------------------------------- */
|
|
283
373
|
/* CHEAT CODES START HERE */
|
|
284
374
|
/* -------------------------------------------------------------------------- */
|
|
285
375
|
|
|
286
|
-
feeAssetHandlerAddress =
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
376
|
+
feeAssetHandlerAddress = (
|
|
377
|
+
await deployer.deploy(FeeAssetHandlerArtifact, [
|
|
378
|
+
l1Client.account.address,
|
|
379
|
+
feeAssetAddress.toString(),
|
|
380
|
+
BigInt(1000n * 10n ** 18n),
|
|
381
|
+
])
|
|
382
|
+
).address;
|
|
291
383
|
logger.verbose(`Deployed FeeAssetHandler at ${feeAssetHandlerAddress}`);
|
|
292
384
|
|
|
293
385
|
// Only if we are "fresh" will we be adding as a minter, otherwise above will simply get same address
|
|
@@ -316,6 +408,7 @@ export const deploySharedContracts = async (
|
|
|
316
408
|
stakingAsset: stakingAssetAddress.toString(),
|
|
317
409
|
registry: registryAddress.toString(),
|
|
318
410
|
withdrawer: AMIN.toString(),
|
|
411
|
+
validatorsToFlush: 16n,
|
|
319
412
|
mintInterval: BigInt(60 * 60 * 24),
|
|
320
413
|
depositsPerMint: BigInt(10),
|
|
321
414
|
depositMerkleRoot: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
@@ -329,7 +422,8 @@ export const deploySharedContracts = async (
|
|
|
329
422
|
skipMerkleCheck: true, // skip merkle check - needed for testing without generating proofs
|
|
330
423
|
} as const;
|
|
331
424
|
|
|
332
|
-
stakingAssetHandlerAddress = await deployer.deploy(StakingAssetHandlerArtifact, [stakingAssetHandlerDeployArgs])
|
|
425
|
+
stakingAssetHandlerAddress = (await deployer.deploy(StakingAssetHandlerArtifact, [stakingAssetHandlerDeployArgs]))
|
|
426
|
+
.address;
|
|
333
427
|
logger.verbose(`Deployed StakingAssetHandler at ${stakingAssetHandlerAddress}`);
|
|
334
428
|
|
|
335
429
|
const { txHash: stakingMinterTxHash } = await deployer.sendTransaction({
|
|
@@ -365,19 +459,23 @@ export const deploySharedContracts = async (
|
|
|
365
459
|
|
|
366
460
|
const rewardDistributorAddress = await registry.getRewardDistributor();
|
|
367
461
|
|
|
368
|
-
|
|
462
|
+
if (!args.existingTokenAddress) {
|
|
463
|
+
const blockReward = getRewardConfig(networkName).blockReward;
|
|
369
464
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
465
|
+
const funding = blockReward * 200000n;
|
|
466
|
+
const { txHash: fundRewardDistributorTxHash } = await deployer.sendTransaction({
|
|
467
|
+
to: feeAssetAddress.toString(),
|
|
468
|
+
data: encodeFunctionData({
|
|
469
|
+
abi: FeeAssetArtifact.contractAbi,
|
|
470
|
+
functionName: 'mint',
|
|
471
|
+
args: [rewardDistributorAddress.toString(), funding],
|
|
472
|
+
}),
|
|
473
|
+
});
|
|
379
474
|
|
|
380
|
-
|
|
475
|
+
logger.verbose(`Funded reward distributor with ${funding} fee asset in ${fundRewardDistributorTxHash}`);
|
|
476
|
+
} else {
|
|
477
|
+
logger.verbose(`Skipping reward distributor funding as existing token is provided`);
|
|
478
|
+
}
|
|
381
479
|
|
|
382
480
|
/* -------------------------------------------------------------------------- */
|
|
383
481
|
/* FUND REWARD DISTRIBUTOR STOP */
|
|
@@ -400,7 +498,7 @@ export const deploySharedContracts = async (
|
|
|
400
498
|
|
|
401
499
|
const getZkPassportVerifierAddress = async (deployer: L1Deployer, args: DeployL1ContractsArgs): Promise<EthAddress> => {
|
|
402
500
|
if (args.zkPassportArgs?.mockZkPassportVerifier) {
|
|
403
|
-
return await deployer.deploy(mockVerifiers.mockZkPassportVerifier);
|
|
501
|
+
return (await deployer.deploy(mockVerifiers.mockZkPassportVerifier)).address;
|
|
404
502
|
}
|
|
405
503
|
return ZK_PASSPORT_VERIFIER_ADDRESS;
|
|
406
504
|
};
|
|
@@ -453,7 +551,7 @@ export const deployRollupForUpgrade = async (
|
|
|
453
551
|
};
|
|
454
552
|
|
|
455
553
|
export const deploySlashFactory = async (deployer: L1Deployer, rollupAddress: Hex, logger: Logger) => {
|
|
456
|
-
const slashFactoryAddress = await deployer.deploy(SlashFactoryArtifact, [rollupAddress]);
|
|
554
|
+
const slashFactoryAddress = (await deployer.deploy(SlashFactoryArtifact, [rollupAddress])).address;
|
|
457
555
|
logger.verbose(`Deployed SlashFactory at ${slashFactoryAddress}`);
|
|
458
556
|
return slashFactoryAddress;
|
|
459
557
|
};
|
|
@@ -462,10 +560,12 @@ export const deployUpgradePayload = async (
|
|
|
462
560
|
deployer: L1Deployer,
|
|
463
561
|
addresses: Pick<L1ContractAddresses, 'registryAddress' | 'rollupAddress'>,
|
|
464
562
|
) => {
|
|
465
|
-
const payloadAddress =
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
563
|
+
const payloadAddress = (
|
|
564
|
+
await deployer.deploy(RegisterNewRollupVersionPayloadArtifact, [
|
|
565
|
+
addresses.registryAddress.toString(),
|
|
566
|
+
addresses.rollupAddress.toString(),
|
|
567
|
+
])
|
|
568
|
+
).address;
|
|
469
569
|
|
|
470
570
|
return payloadAddress;
|
|
471
571
|
};
|
|
@@ -509,6 +609,7 @@ export const deployRollup = async (
|
|
|
509
609
|
if (!addresses.gseAddress) {
|
|
510
610
|
throw new Error('GSE address is required when deploying');
|
|
511
611
|
}
|
|
612
|
+
const networkName = getActiveNetworkName();
|
|
512
613
|
|
|
513
614
|
logger.info(`Deploying rollup using network configuration: ${networkName}`);
|
|
514
615
|
|
|
@@ -517,10 +618,10 @@ export const deployRollup = async (
|
|
|
517
618
|
let epochProofVerifier = EthAddress.ZERO;
|
|
518
619
|
|
|
519
620
|
if (args.realVerifier) {
|
|
520
|
-
epochProofVerifier = await deployer.deploy(l1ArtifactsVerifiers.honkVerifier);
|
|
621
|
+
epochProofVerifier = (await deployer.deploy(l1ArtifactsVerifiers.honkVerifier)).address;
|
|
521
622
|
logger.verbose(`Rollup will use the real verifier at ${epochProofVerifier}`);
|
|
522
623
|
} else {
|
|
523
|
-
epochProofVerifier = await deployer.deploy(mockVerifiers.mockVerifier);
|
|
624
|
+
epochProofVerifier = (await deployer.deploy(mockVerifiers.mockVerifier)).address;
|
|
524
625
|
logger.verbose(`Rollup will use the mock verifier at ${epochProofVerifier}`);
|
|
525
626
|
}
|
|
526
627
|
|
|
@@ -533,6 +634,7 @@ export const deployRollup = async (
|
|
|
533
634
|
aztecSlotDuration: BigInt(args.aztecSlotDuration),
|
|
534
635
|
aztecEpochDuration: BigInt(args.aztecEpochDuration),
|
|
535
636
|
targetCommitteeSize: BigInt(args.aztecTargetCommitteeSize),
|
|
637
|
+
lagInEpochs: BigInt(args.lagInEpochs),
|
|
536
638
|
aztecProofSubmissionEpochs: BigInt(args.aztecProofSubmissionEpochs),
|
|
537
639
|
slashingQuorum: BigInt(args.slashingQuorum ?? (args.slashingRoundSizeInEpochs * args.aztecEpochDuration) / 2 + 1),
|
|
538
640
|
slashingRoundSize: BigInt(args.slashingRoundSizeInEpochs * args.aztecEpochDuration),
|
|
@@ -549,6 +651,8 @@ export const deployRollup = async (
|
|
|
549
651
|
slasherFlavor: slasherFlavorToSolidityEnum(args.slasherFlavor),
|
|
550
652
|
slashingOffsetInRounds: BigInt(args.slashingOffsetInRounds),
|
|
551
653
|
slashAmounts: [args.slashAmountSmall, args.slashAmountMedium, args.slashAmountLarge],
|
|
654
|
+
localEjectionThreshold: args.localEjectionThreshold,
|
|
655
|
+
slashingDisableDuration: BigInt(args.slashingDisableDuration ?? 0n),
|
|
552
656
|
};
|
|
553
657
|
|
|
554
658
|
const genesisStateArgs = {
|
|
@@ -579,8 +683,10 @@ export const deployRollup = async (
|
|
|
579
683
|
rollupConfigArgs,
|
|
580
684
|
] as const;
|
|
581
685
|
|
|
582
|
-
const rollupAddress = await deployer.deploy(RollupArtifact, rollupArgs, {
|
|
583
|
-
|
|
686
|
+
const { address: rollupAddress, existed: rollupExisted } = await deployer.deploy(RollupArtifact, rollupArgs, {
|
|
687
|
+
gasLimit: 15_000_000n,
|
|
688
|
+
});
|
|
689
|
+
logger.verbose(`Deployed Rollup at ${rollupAddress}, already existed: ${rollupExisted}`, rollupConfigArgs);
|
|
584
690
|
|
|
585
691
|
const rollupContract = new RollupContract(extendedClient, rollupAddress);
|
|
586
692
|
|
|
@@ -588,24 +694,29 @@ export const deployRollup = async (
|
|
|
588
694
|
logger.verbose(`All core contracts have been deployed`);
|
|
589
695
|
|
|
590
696
|
if (args.feeJuicePortalInitialBalance && args.feeJuicePortalInitialBalance > 0n) {
|
|
591
|
-
|
|
697
|
+
// Skip funding when using an external token, as we likely don't have mint permissions
|
|
698
|
+
if (!('existingTokenAddress' in args) || !args.existingTokenAddress) {
|
|
699
|
+
const feeJuicePortalAddress = await rollupContract.getFeeJuicePortal();
|
|
592
700
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
701
|
+
// In fast mode, use the L1TxUtils to send transactions with nonce management
|
|
702
|
+
const { txHash: mintTxHash } = await deployer.sendTransaction({
|
|
703
|
+
to: addresses.feeJuiceAddress.toString(),
|
|
704
|
+
data: encodeFunctionData({
|
|
705
|
+
abi: FeeAssetArtifact.contractAbi,
|
|
706
|
+
functionName: 'mint',
|
|
707
|
+
args: [feeJuicePortalAddress.toString(), args.feeJuicePortalInitialBalance],
|
|
708
|
+
}),
|
|
709
|
+
});
|
|
710
|
+
logger.verbose(
|
|
711
|
+
`Funding fee juice portal with ${args.feeJuicePortalInitialBalance} fee juice in ${mintTxHash} (accelerated test deployments)`,
|
|
712
|
+
);
|
|
713
|
+
txHashes.push(mintTxHash);
|
|
714
|
+
} else {
|
|
715
|
+
logger.verbose('Skipping fee juice portal funding due to external token usage');
|
|
716
|
+
}
|
|
606
717
|
}
|
|
607
718
|
|
|
608
|
-
const slashFactoryAddress = await deployer.deploy(SlashFactoryArtifact, [rollupAddress.toString()]);
|
|
719
|
+
const slashFactoryAddress = (await deployer.deploy(SlashFactoryArtifact, [rollupAddress.toString()])).address;
|
|
609
720
|
logger.verbose(`Deployed SlashFactory at ${slashFactoryAddress}`);
|
|
610
721
|
|
|
611
722
|
// We need to call a function on the registry to set the various contract addresses.
|
|
@@ -667,7 +778,17 @@ export const deployRollup = async (
|
|
|
667
778
|
logger.verbose(`Not the owner of the gse, skipping rollup addition`);
|
|
668
779
|
}
|
|
669
780
|
|
|
670
|
-
|
|
781
|
+
const activeAttestorCount = await rollupContract.getActiveAttesterCount();
|
|
782
|
+
const queuedAttestorCount = await rollupContract.getEntryQueueLength();
|
|
783
|
+
logger.info(`Rollup has ${activeAttestorCount} active attestors and ${queuedAttestorCount} queued attestors`);
|
|
784
|
+
|
|
785
|
+
const shouldAddValidators = activeAttestorCount === 0n && queuedAttestorCount === 0n;
|
|
786
|
+
|
|
787
|
+
if (
|
|
788
|
+
args.initialValidators &&
|
|
789
|
+
shouldAddValidators &&
|
|
790
|
+
(await gseContract.read.isRollupRegistered([rollupContract.address]))
|
|
791
|
+
) {
|
|
671
792
|
await addMultipleValidators(
|
|
672
793
|
extendedClient,
|
|
673
794
|
deployer,
|
|
@@ -715,6 +836,7 @@ export const handoverToGovernance = async (
|
|
|
715
836
|
governanceAddress: EthAddress,
|
|
716
837
|
logger: Logger,
|
|
717
838
|
acceleratedTestDeployments: boolean | undefined,
|
|
839
|
+
useExternalToken: boolean = false,
|
|
718
840
|
) => {
|
|
719
841
|
// We need to call a function on the registry to set the various contract addresses.
|
|
720
842
|
const registryContract = getContract({
|
|
@@ -780,7 +902,10 @@ export const handoverToGovernance = async (
|
|
|
780
902
|
txHashes.push(transferOwnershipTxHash);
|
|
781
903
|
}
|
|
782
904
|
|
|
783
|
-
if (
|
|
905
|
+
if (
|
|
906
|
+
!useExternalToken &&
|
|
907
|
+
(acceleratedTestDeployments || (await feeAsset.read.owner()) !== coinIssuerAddress.toString())
|
|
908
|
+
) {
|
|
784
909
|
const { txHash } = await deployer.sendTransaction(
|
|
785
910
|
{
|
|
786
911
|
to: feeAssetAddress.toString(),
|
|
@@ -807,23 +932,28 @@ export const handoverToGovernance = async (
|
|
|
807
932
|
);
|
|
808
933
|
logger.verbose(`Accept ownership of fee asset in ${acceptTokenOwnershipTxHash}`);
|
|
809
934
|
txHashes.push(acceptTokenOwnershipTxHash);
|
|
935
|
+
} else if (useExternalToken) {
|
|
936
|
+
logger.verbose('Skipping fee asset ownership transfer due to external token usage');
|
|
810
937
|
}
|
|
811
938
|
|
|
939
|
+
// Either deploy or at least predict the address of the date gated relayer
|
|
940
|
+
const dateGatedRelayer = await deployer.deploy(DateGatedRelayerArtifact, [
|
|
941
|
+
governanceAddress.toString(),
|
|
942
|
+
1798761600n, // 2027-01-01 00:00:00 UTC
|
|
943
|
+
]);
|
|
944
|
+
|
|
812
945
|
// If the owner is not the Governance contract, transfer ownership to the Governance contract
|
|
813
|
-
if (
|
|
814
|
-
acceleratedTestDeployments ||
|
|
815
|
-
(await coinIssuerContract.read.owner()) !== getAddress(governanceAddress.toString())
|
|
816
|
-
) {
|
|
946
|
+
if (acceleratedTestDeployments || (await coinIssuerContract.read.owner()) === deployer.client.account.address) {
|
|
817
947
|
const { txHash: transferOwnershipTxHash } = await deployer.sendTransaction({
|
|
818
948
|
to: coinIssuerContract.address,
|
|
819
949
|
data: encodeFunctionData({
|
|
820
950
|
abi: CoinIssuerArtifact.contractAbi,
|
|
821
951
|
functionName: 'transferOwnership',
|
|
822
|
-
args: [getAddress(
|
|
952
|
+
args: [getAddress(dateGatedRelayer.address.toString())],
|
|
823
953
|
}),
|
|
824
954
|
});
|
|
825
955
|
logger.verbose(
|
|
826
|
-
`Transferring the ownership of the coin issuer contract at ${coinIssuerAddress} to the
|
|
956
|
+
`Transferring the ownership of the coin issuer contract at ${coinIssuerAddress} to the DateGatedRelayer ${dateGatedRelayer.address} in tx ${transferOwnershipTxHash}`,
|
|
827
957
|
);
|
|
828
958
|
txHashes.push(transferOwnershipTxHash);
|
|
829
959
|
}
|
|
@@ -831,6 +961,8 @@ export const handoverToGovernance = async (
|
|
|
831
961
|
// Wait for all actions to be mined
|
|
832
962
|
await deployer.waitForDeployments();
|
|
833
963
|
await Promise.all(txHashes.map(txHash => extendedClient.waitForTransactionReceipt({ hash: txHash })));
|
|
964
|
+
|
|
965
|
+
return { dateGatedRelayerAddress: dateGatedRelayer.address };
|
|
834
966
|
};
|
|
835
967
|
|
|
836
968
|
/*
|
|
@@ -877,100 +1009,112 @@ export const addMultipleValidators = async (
|
|
|
877
1009
|
validators = enrichedValidators.filter(v => v.status === 0).map(v => v.operator);
|
|
878
1010
|
}
|
|
879
1011
|
|
|
880
|
-
if (validators.length
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
1012
|
+
if (validators.length === 0) {
|
|
1013
|
+
logger.warn('No validators to add. Skipping.');
|
|
1014
|
+
return;
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
const gseContract = new GSEContract(extendedClient, gseAddress);
|
|
1018
|
+
const multiAdder = (await deployer.deploy(MultiAdderArtifact, [rollupAddress, deployer.client.account.address]))
|
|
1019
|
+
.address;
|
|
1020
|
+
|
|
1021
|
+
const makeValidatorTuples = async (validator: Operator) => {
|
|
1022
|
+
const registrationTuple = await gseContract.makeRegistrationTuple(validator.bn254SecretKey.getValue());
|
|
1023
|
+
return {
|
|
1024
|
+
attester: getAddress(validator.attester.toString()),
|
|
1025
|
+
withdrawer: getAddress(validator.withdrawer.toString()),
|
|
1026
|
+
...registrationTuple,
|
|
891
1027
|
};
|
|
1028
|
+
};
|
|
892
1029
|
|
|
893
|
-
|
|
1030
|
+
const validatorsTuples = await Promise.all(validators.map(makeValidatorTuples));
|
|
894
1031
|
|
|
895
|
-
|
|
896
|
-
|
|
1032
|
+
// Mint tokens, approve them, use cheat code to initialize validator set without setting up the epoch.
|
|
1033
|
+
const stakeNeeded = activationThreshold * BigInt(validators.length);
|
|
897
1034
|
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
1035
|
+
await deployer.l1TxUtils.sendAndMonitorTransaction({
|
|
1036
|
+
to: stakingAssetAddress,
|
|
1037
|
+
data: encodeFunctionData({
|
|
1038
|
+
abi: StakingAssetArtifact.contractAbi,
|
|
1039
|
+
functionName: 'mint',
|
|
1040
|
+
args: [multiAdder.toString(), stakeNeeded],
|
|
1041
|
+
}),
|
|
1042
|
+
});
|
|
906
1043
|
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
logger.info(`Adding ${validators.length} validators to the rollup`);
|
|
911
|
-
|
|
912
|
-
// Adding to the queue and flushing need to be done in two transactions
|
|
913
|
-
// if we are adding many validators.
|
|
914
|
-
if (validatorsTuples.length > 10) {
|
|
915
|
-
await deployer.l1TxUtils.sendAndMonitorTransaction(
|
|
916
|
-
{
|
|
917
|
-
to: multiAdder.toString(),
|
|
918
|
-
data: encodeFunctionData({
|
|
919
|
-
abi: MultiAdderArtifact.contractAbi,
|
|
920
|
-
functionName: 'addValidators',
|
|
921
|
-
args: [validatorsTuples, true],
|
|
922
|
-
}),
|
|
923
|
-
},
|
|
924
|
-
{
|
|
925
|
-
gasLimit: 40_000_000n,
|
|
926
|
-
},
|
|
927
|
-
);
|
|
1044
|
+
const entryQueueLengthBefore = await rollup.getEntryQueueLength();
|
|
1045
|
+
const validatorCountBefore = await rollup.getActiveAttesterCount();
|
|
928
1046
|
|
|
929
|
-
|
|
930
|
-
{
|
|
931
|
-
to: rollupAddress,
|
|
932
|
-
data: encodeFunctionData({
|
|
933
|
-
abi: RollupArtifact.contractAbi,
|
|
934
|
-
functionName: 'flushEntryQueue',
|
|
935
|
-
args: [],
|
|
936
|
-
}),
|
|
937
|
-
},
|
|
938
|
-
{
|
|
939
|
-
gasLimit: 40_000_000n,
|
|
940
|
-
},
|
|
941
|
-
);
|
|
942
|
-
} else {
|
|
943
|
-
await deployer.l1TxUtils.sendAndMonitorTransaction(
|
|
944
|
-
{
|
|
945
|
-
to: multiAdder.toString(),
|
|
946
|
-
data: encodeFunctionData({
|
|
947
|
-
abi: MultiAdderArtifact.contractAbi,
|
|
948
|
-
functionName: 'addValidators',
|
|
949
|
-
args: [validatorsTuples, false],
|
|
950
|
-
}),
|
|
951
|
-
},
|
|
952
|
-
{
|
|
953
|
-
gasLimit: 45_000_000n,
|
|
954
|
-
},
|
|
955
|
-
);
|
|
956
|
-
}
|
|
1047
|
+
logger.info(`Adding ${validators.length} validators to the rollup`);
|
|
957
1048
|
|
|
958
|
-
|
|
959
|
-
const validatorCountAfter = await rollup.getActiveAttesterCount();
|
|
1049
|
+
const chunkSize = 16;
|
|
960
1050
|
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
1051
|
+
// We will add `chunkSize` validators to the queue until we have covered all of our validators.
|
|
1052
|
+
// The `chunkSize` needs to be small enough to fit inside a single tx, therefore 16.
|
|
1053
|
+
for (const c of chunk(validatorsTuples, chunkSize)) {
|
|
1054
|
+
await deployer.l1TxUtils.sendAndMonitorTransaction(
|
|
1055
|
+
{
|
|
1056
|
+
to: multiAdder.toString(),
|
|
1057
|
+
data: encodeFunctionData({
|
|
1058
|
+
abi: MultiAdderArtifact.contractAbi,
|
|
1059
|
+
functionName: 'addValidators',
|
|
1060
|
+
args: [c, BigInt(chunkSize)],
|
|
1061
|
+
}),
|
|
1062
|
+
},
|
|
1063
|
+
{
|
|
1064
|
+
gasLimit: 16_000_000n,
|
|
1065
|
+
},
|
|
1066
|
+
);
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
// After adding to the queue, we will now try to flush from it.
|
|
1070
|
+
// We are explicitly doing this as a second step instead of as part of adding to benefit
|
|
1071
|
+
// from the accounting used to speed the process up.
|
|
1072
|
+
// As the queue computes the amount of possible flushes in an epoch when told to flush,
|
|
1073
|
+
// waiting until we have added all we want allows us to benefit in the case were we added
|
|
1074
|
+
// enough to pass the bootstrap set size without needing to wait another epoch.
|
|
1075
|
+
// This is useful when we are testing as it speeds up the tests slightly.
|
|
1076
|
+
while (true) {
|
|
1077
|
+
// If the queue is empty, we can break
|
|
1078
|
+
if ((await rollup.getEntryQueueLength()) == 0n) {
|
|
1079
|
+
break;
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
// If there are no available validator flushes, no need to even try
|
|
1083
|
+
if ((await rollup.getAvailableValidatorFlushes()) == 0n) {
|
|
1084
|
+
break;
|
|
968
1085
|
}
|
|
969
1086
|
|
|
970
|
-
|
|
971
|
-
|
|
1087
|
+
// Note that we are flushing at most `chunkSize` at each call
|
|
1088
|
+
await deployer.l1TxUtils.sendAndMonitorTransaction(
|
|
1089
|
+
{
|
|
1090
|
+
to: rollup.address,
|
|
1091
|
+
data: encodeFunctionData({
|
|
1092
|
+
abi: RollupArtifact.contractAbi,
|
|
1093
|
+
functionName: 'flushEntryQueue',
|
|
1094
|
+
args: [BigInt(chunkSize)],
|
|
1095
|
+
}),
|
|
1096
|
+
},
|
|
1097
|
+
{
|
|
1098
|
+
gasLimit: 16_000_000n,
|
|
1099
|
+
},
|
|
972
1100
|
);
|
|
973
1101
|
}
|
|
1102
|
+
|
|
1103
|
+
const entryQueueLengthAfter = await rollup.getEntryQueueLength();
|
|
1104
|
+
const validatorCountAfter = await rollup.getActiveAttesterCount();
|
|
1105
|
+
|
|
1106
|
+
if (
|
|
1107
|
+
entryQueueLengthAfter + validatorCountAfter <
|
|
1108
|
+
entryQueueLengthBefore + validatorCountBefore + BigInt(validators.length)
|
|
1109
|
+
) {
|
|
1110
|
+
throw new Error(
|
|
1111
|
+
`Failed to add ${validators.length} validators. Active validators: ${validatorCountBefore} -> ${validatorCountAfter}. Queue: ${entryQueueLengthBefore} -> ${entryQueueLengthAfter}. A likely issue is the bootstrap size.`,
|
|
1112
|
+
);
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
logger.info(
|
|
1116
|
+
`Added ${validators.length} validators. Active validators: ${validatorCountBefore} -> ${validatorCountAfter}. Queue: ${entryQueueLengthBefore} -> ${entryQueueLengthAfter}`,
|
|
1117
|
+
);
|
|
974
1118
|
}
|
|
975
1119
|
};
|
|
976
1120
|
|
|
@@ -993,11 +1137,13 @@ export const cheat_initializeFeeAssetHandler = async (
|
|
|
993
1137
|
feeAssetHandlerAddress: EthAddress;
|
|
994
1138
|
txHash: Hex;
|
|
995
1139
|
}> => {
|
|
996
|
-
const feeAssetHandlerAddress =
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1140
|
+
const feeAssetHandlerAddress = (
|
|
1141
|
+
await deployer.deploy(FeeAssetHandlerArtifact, [
|
|
1142
|
+
extendedClient.account.address,
|
|
1143
|
+
feeAssetAddress.toString(),
|
|
1144
|
+
BigInt(1e18),
|
|
1145
|
+
])
|
|
1146
|
+
).address;
|
|
1001
1147
|
logger.verbose(`Deployed FeeAssetHandler at ${feeAssetHandlerAddress}`);
|
|
1002
1148
|
|
|
1003
1149
|
const { txHash } = await deployer.sendTransaction({
|
|
@@ -1033,6 +1179,13 @@ export const deployL1Contracts = async (
|
|
|
1033
1179
|
logger.info(`Deploying L1 contracts with config: ${jsonStringify(args)}`);
|
|
1034
1180
|
validateConfig(args);
|
|
1035
1181
|
|
|
1182
|
+
if (args.initialValidators && args.initialValidators.length > 0 && args.existingTokenAddress) {
|
|
1183
|
+
throw new Error(
|
|
1184
|
+
'Cannot deploy with both initialValidators and existingTokenAddress. ' +
|
|
1185
|
+
'Initial validator funding requires minting tokens, which is not possible with an external token.',
|
|
1186
|
+
);
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1036
1189
|
const l1Client = createExtendedL1Client(rpcUrls, account, chain);
|
|
1037
1190
|
|
|
1038
1191
|
// Deploy multicall3 if it does not exist in this network
|
|
@@ -1102,7 +1255,7 @@ export const deployL1Contracts = async (
|
|
|
1102
1255
|
await deployer.waitForDeployments();
|
|
1103
1256
|
|
|
1104
1257
|
// Now that the rollup has been deployed and added to the registry, transfer ownership to governance
|
|
1105
|
-
await handoverToGovernance(
|
|
1258
|
+
const { dateGatedRelayerAddress } = await handoverToGovernance(
|
|
1106
1259
|
l1Client,
|
|
1107
1260
|
deployer,
|
|
1108
1261
|
registryAddress,
|
|
@@ -1112,6 +1265,7 @@ export const deployL1Contracts = async (
|
|
|
1112
1265
|
governanceAddress,
|
|
1113
1266
|
logger,
|
|
1114
1267
|
args.acceleratedTestDeployments,
|
|
1268
|
+
!!args.existingTokenAddress,
|
|
1115
1269
|
);
|
|
1116
1270
|
|
|
1117
1271
|
logger.info(`Handing over to governance complete`);
|
|
@@ -1250,6 +1404,7 @@ export const deployL1Contracts = async (
|
|
|
1250
1404
|
// Ensure the verification output directory exists
|
|
1251
1405
|
await mkdir(createVerificationJson, { recursive: true });
|
|
1252
1406
|
const verificationOutputPath = `${createVerificationJson}/l1-verify-${chain.id}-${formattedDate.slice(0, 6)}-${formattedDate.slice(6)}.json`;
|
|
1407
|
+
const networkName = getActiveNetworkName();
|
|
1253
1408
|
const verificationData = {
|
|
1254
1409
|
chainId: chain.id,
|
|
1255
1410
|
network: networkName,
|
|
@@ -1295,6 +1450,7 @@ export const deployL1Contracts = async (
|
|
|
1295
1450
|
stakingAssetHandlerAddress,
|
|
1296
1451
|
zkPassportVerifierAddress,
|
|
1297
1452
|
coinIssuerAddress,
|
|
1453
|
+
dateGatedRelayerAddress,
|
|
1298
1454
|
},
|
|
1299
1455
|
};
|
|
1300
1456
|
};
|
|
@@ -1317,10 +1473,8 @@ export class L1Deployer {
|
|
|
1317
1473
|
this.salt = maybeSalt ? padHex(numberToHex(maybeSalt), { size: 32 }) : undefined;
|
|
1318
1474
|
this.l1TxUtils = createL1TxUtilsFromViemWallet(
|
|
1319
1475
|
this.client,
|
|
1320
|
-
this.logger,
|
|
1321
|
-
|
|
1322
|
-
this.txUtilsConfig,
|
|
1323
|
-
this.acceleratedTestDeployments,
|
|
1476
|
+
{ logger: this.logger, dateProvider },
|
|
1477
|
+
{ ...this.txUtilsConfig, debugMaxGasLimit: acceleratedTestDeployments },
|
|
1324
1478
|
);
|
|
1325
1479
|
}
|
|
1326
1480
|
|
|
@@ -1328,10 +1482,10 @@ export class L1Deployer {
|
|
|
1328
1482
|
params: ContractArtifacts<TAbi>,
|
|
1329
1483
|
args?: ContractConstructorArgs<TAbi>,
|
|
1330
1484
|
opts: { gasLimit?: bigint } = {},
|
|
1331
|
-
): Promise<EthAddress> {
|
|
1485
|
+
): Promise<{ address: EthAddress; existed: boolean }> {
|
|
1332
1486
|
this.logger.debug(`Deploying ${params.name} contract`, { args });
|
|
1333
1487
|
try {
|
|
1334
|
-
const { txHash, address, deployedLibraries } = await deployL1Contract(
|
|
1488
|
+
const { txHash, address, deployedLibraries, existed } = await deployL1Contract(
|
|
1335
1489
|
this.client,
|
|
1336
1490
|
params.contractAbi,
|
|
1337
1491
|
params.contractBytecode,
|
|
@@ -1369,7 +1523,10 @@ export class L1Deployer {
|
|
|
1369
1523
|
libraries: deployedLibraries ?? [],
|
|
1370
1524
|
});
|
|
1371
1525
|
}
|
|
1372
|
-
return
|
|
1526
|
+
return {
|
|
1527
|
+
address,
|
|
1528
|
+
existed,
|
|
1529
|
+
};
|
|
1373
1530
|
} catch (error) {
|
|
1374
1531
|
throw new Error(`Failed to deploy ${params.name}`, { cause: formatViemError(error) });
|
|
1375
1532
|
}
|
|
@@ -1397,9 +1554,13 @@ export class L1Deployer {
|
|
|
1397
1554
|
|
|
1398
1555
|
sendTransaction(
|
|
1399
1556
|
tx: L1TxRequest,
|
|
1400
|
-
options?:
|
|
1557
|
+
options?: L1TxConfig,
|
|
1401
1558
|
): Promise<{ txHash: Hex; gasLimit: bigint; gasPrice: GasPrice }> {
|
|
1402
|
-
return this.l1TxUtils.sendTransaction(tx, options)
|
|
1559
|
+
return this.l1TxUtils.sendTransaction(tx, options).then(({ txHash, state }) => ({
|
|
1560
|
+
txHash,
|
|
1561
|
+
gasLimit: state.gasLimit,
|
|
1562
|
+
gasPrice: state.gasPrice,
|
|
1563
|
+
}));
|
|
1403
1564
|
}
|
|
1404
1565
|
}
|
|
1405
1566
|
|
|
@@ -1427,7 +1588,12 @@ export async function deployL1Contract(
|
|
|
1427
1588
|
gasLimit?: bigint;
|
|
1428
1589
|
acceleratedTestDeployments?: boolean;
|
|
1429
1590
|
} = {},
|
|
1430
|
-
): Promise<{
|
|
1591
|
+
): Promise<{
|
|
1592
|
+
address: EthAddress;
|
|
1593
|
+
txHash: Hex | undefined;
|
|
1594
|
+
deployedLibraries?: VerificationLibraryEntry[];
|
|
1595
|
+
existed: boolean;
|
|
1596
|
+
}> {
|
|
1431
1597
|
let txHash: Hex | undefined = undefined;
|
|
1432
1598
|
let resultingAddress: Hex | null | undefined = undefined;
|
|
1433
1599
|
const deployedLibraries: VerificationLibraryEntry[] = [];
|
|
@@ -1437,7 +1603,11 @@ export async function deployL1Contract(
|
|
|
1437
1603
|
|
|
1438
1604
|
if (!l1TxUtils) {
|
|
1439
1605
|
const config = getL1TxUtilsConfigEnvVars();
|
|
1440
|
-
l1TxUtils = createL1TxUtilsFromViemWallet(
|
|
1606
|
+
l1TxUtils = createL1TxUtilsFromViemWallet(
|
|
1607
|
+
extendedClient,
|
|
1608
|
+
{ logger },
|
|
1609
|
+
{ ...config, debugMaxGasLimit: acceleratedTestDeployments },
|
|
1610
|
+
);
|
|
1441
1611
|
}
|
|
1442
1612
|
|
|
1443
1613
|
if (libraries) {
|
|
@@ -1529,6 +1699,8 @@ export async function deployL1Contract(
|
|
|
1529
1699
|
}
|
|
1530
1700
|
}
|
|
1531
1701
|
|
|
1702
|
+
let existed = false;
|
|
1703
|
+
|
|
1532
1704
|
if (saltFromOpts) {
|
|
1533
1705
|
logger?.info(`Deploying contract with salt ${saltFromOpts}`);
|
|
1534
1706
|
const { address, paddedSalt: salt, calldata } = getExpectedAddress(abi, bytecode, args, saltFromOpts);
|
|
@@ -1550,6 +1722,7 @@ export async function deployL1Contract(
|
|
|
1550
1722
|
logger?.verbose(`Deployed contract with salt ${salt} to address ${resultingAddress} in tx ${txHash}.`);
|
|
1551
1723
|
} else {
|
|
1552
1724
|
logger?.verbose(`Skipping existing deployment of contract with salt ${salt} to address ${resultingAddress}`);
|
|
1725
|
+
existed = true;
|
|
1553
1726
|
}
|
|
1554
1727
|
} else {
|
|
1555
1728
|
const deployData = encodeDeployData({ abi, bytecode, args });
|
|
@@ -1569,7 +1742,7 @@ export async function deployL1Contract(
|
|
|
1569
1742
|
}
|
|
1570
1743
|
}
|
|
1571
1744
|
|
|
1572
|
-
return { address: EthAddress.fromString(resultingAddress!), txHash, deployedLibraries };
|
|
1745
|
+
return { address: EthAddress.fromString(resultingAddress!), txHash, deployedLibraries, existed };
|
|
1573
1746
|
}
|
|
1574
1747
|
|
|
1575
1748
|
export function getExpectedAddress(
|