@aztec/ethereum 3.0.0-nightly.20251024 → 3.0.0-nightly.20251025

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.
@@ -516,6 +516,199 @@ const getZkPassportScopes = (args: DeployL1ContractsArgs): [string, string] => {
516
516
  return [domain, scope];
517
517
  };
518
518
 
519
+ /**
520
+ * Generates verification records for a deployed rollup and its associated contracts (Inbox, Outbox, Slasher, etc).
521
+ * @param rollup - The deployed rollup contract.
522
+ * @param deployer - The L1 deployer instance.
523
+ * @param args - The deployment arguments used for the rollup.
524
+ * @param addresses - The L1 contract addresses.
525
+ * @param extendedClient - The extended viem wallet client.
526
+ * @param logger - The logger.
527
+ */
528
+ async function generateRollupVerificationRecords(
529
+ rollup: RollupContract,
530
+ deployer: L1Deployer,
531
+ args: {
532
+ slashingVetoer: EthAddress;
533
+ slashingRoundSizeInEpochs: number;
534
+ aztecEpochDuration: number;
535
+ slashingQuorum?: number;
536
+ slashingLifetimeInRounds: number;
537
+ slashingExecutionDelayInRounds: number;
538
+ slasherFlavor: 'none' | 'tally' | 'empire';
539
+ slashAmountSmall: bigint;
540
+ slashAmountMedium: bigint;
541
+ slashAmountLarge: bigint;
542
+ aztecTargetCommitteeSize: number;
543
+ slashingOffsetInRounds: number;
544
+ },
545
+ addresses: Pick<L1ContractAddresses, 'feeJuiceAddress'>,
546
+ extendedClient: ExtendedViemWalletClient,
547
+ logger: Logger,
548
+ ): Promise<void> {
549
+ try {
550
+ // Add Inbox / Outbox verification records (constructor args are created inside RollupCore)
551
+ const rollupAddr = rollup.address;
552
+ const rollupAddresses = await rollup.getRollupAddresses();
553
+ const inboxAddr = rollupAddresses.inboxAddress.toString();
554
+ const outboxAddr = rollupAddresses.outboxAddress.toString();
555
+ const feeAsset = rollupAddresses.feeJuiceAddress.toString();
556
+ const version = await rollup.getVersion();
557
+
558
+ const inboxCtor = encodeAbiParameters(
559
+ [{ type: 'address' }, { type: 'address' }, { type: 'uint256' }, { type: 'uint256' }],
560
+ [rollupAddr, feeAsset, version, BigInt(L1_TO_L2_MSG_SUBTREE_HEIGHT)],
561
+ );
562
+
563
+ const outboxCtor = encodeAbiParameters([{ type: 'address' }, { type: 'uint256' }], [rollupAddr, version]);
564
+
565
+ deployer.verificationRecords.push(
566
+ { name: 'Inbox', address: inboxAddr, constructorArgsHex: inboxCtor, libraries: [] },
567
+ { name: 'Outbox', address: outboxAddr, constructorArgsHex: outboxCtor, libraries: [] },
568
+ );
569
+
570
+ // Include Slasher and SlashingProposer (if deployed) in verification data
571
+ try {
572
+ const slasherAddrHex = await rollup.getSlasherAddress();
573
+ const slasherAddr = EthAddress.fromString(slasherAddrHex);
574
+ if (!slasherAddr.isZero()) {
575
+ // Slasher constructor: (address _vetoer, address _governance)
576
+ const slasherCtor = encodeAbiParameters(
577
+ [{ type: 'address' }, { type: 'address' }],
578
+ [args.slashingVetoer.toString(), extendedClient.account.address],
579
+ );
580
+ deployer.verificationRecords.push({
581
+ name: 'Slasher',
582
+ address: slasherAddr.toString(),
583
+ constructorArgsHex: slasherCtor,
584
+ libraries: [],
585
+ });
586
+
587
+ // Proposer address is stored in Slasher.PROPOSER()
588
+ const proposerAddr = (await rollup.getSlashingProposerAddress()).toString();
589
+
590
+ // Compute constructor args matching deployment path in RollupCore
591
+ const computedRoundSize = BigInt(args.slashingRoundSizeInEpochs * args.aztecEpochDuration);
592
+ const computedQuorum = BigInt(
593
+ args.slashingQuorum ?? (args.slashingRoundSizeInEpochs * args.aztecEpochDuration) / 2 + 1,
594
+ );
595
+ const lifetimeInRounds = BigInt(args.slashingLifetimeInRounds);
596
+ const executionDelayInRounds = BigInt(args.slashingExecutionDelayInRounds);
597
+
598
+ if (args.slasherFlavor === 'tally') {
599
+ const slashAmounts: readonly [bigint, bigint, bigint] = [
600
+ args.slashAmountSmall,
601
+ args.slashAmountMedium,
602
+ args.slashAmountLarge,
603
+ ];
604
+ const committeeSize = BigInt(args.aztecTargetCommitteeSize);
605
+ const epochDuration = BigInt(args.aztecEpochDuration);
606
+ const slashOffsetInRounds = BigInt(args.slashingOffsetInRounds);
607
+
608
+ const proposerCtor = encodeAbiParameters(
609
+ [
610
+ { type: 'address' },
611
+ { type: 'address' },
612
+ { type: 'uint256' },
613
+ { type: 'uint256' },
614
+ { type: 'uint256' },
615
+ { type: 'uint256' },
616
+ { type: 'uint256[3]' },
617
+ { type: 'uint256' },
618
+ { type: 'uint256' },
619
+ { type: 'uint256' },
620
+ ],
621
+ [
622
+ rollup.address,
623
+ slasherAddr.toString(),
624
+ computedQuorum,
625
+ computedRoundSize,
626
+ lifetimeInRounds,
627
+ executionDelayInRounds,
628
+ slashAmounts,
629
+ committeeSize,
630
+ epochDuration,
631
+ slashOffsetInRounds,
632
+ ],
633
+ );
634
+
635
+ deployer.verificationRecords.push({
636
+ name: 'TallySlashingProposer',
637
+ address: proposerAddr,
638
+ constructorArgsHex: proposerCtor,
639
+ libraries: [],
640
+ });
641
+ } else if (args.slasherFlavor === 'empire') {
642
+ const proposerCtor = encodeAbiParameters(
643
+ [
644
+ { type: 'address' },
645
+ { type: 'address' },
646
+ { type: 'uint256' },
647
+ { type: 'uint256' },
648
+ { type: 'uint256' },
649
+ { type: 'uint256' },
650
+ ],
651
+ [
652
+ rollup.address,
653
+ slasherAddr.toString(),
654
+ computedQuorum,
655
+ computedRoundSize,
656
+ lifetimeInRounds,
657
+ executionDelayInRounds,
658
+ ],
659
+ );
660
+
661
+ deployer.verificationRecords.push({
662
+ name: 'EmpireSlashingProposer',
663
+ address: proposerAddr,
664
+ constructorArgsHex: proposerCtor,
665
+ libraries: [],
666
+ });
667
+ }
668
+ }
669
+ } catch (e) {
670
+ logger.warn(`Failed to add Slasher/Proposer verification records: ${String(e)}`);
671
+ }
672
+ } catch (e) {
673
+ throw new Error(`Failed to generate rollup verification records: ${String(e)}`);
674
+ }
675
+ }
676
+
677
+ /**
678
+ * Writes verification records to a JSON file for later forge verify.
679
+ * @param deployer - The L1 deployer containing verification records.
680
+ * @param outputDirectory - The directory to write the verification file to.
681
+ * @param chainId - The chain ID.
682
+ * @param filenameSuffix - Optional suffix for the filename (e.g., 'upgrade').
683
+ * @param logger - The logger.
684
+ */
685
+ async function writeVerificationJson(
686
+ deployer: L1Deployer,
687
+ outputDirectory: string,
688
+ chainId: number,
689
+ filenameSuffix: string = '',
690
+ logger: Logger,
691
+ ): Promise<void> {
692
+ try {
693
+ const date = new Date();
694
+ const formattedDate = date.toISOString().slice(2, 19).replace(/[-T:]/g, '');
695
+ // Ensure the verification output directory exists
696
+ await mkdir(outputDirectory, { recursive: true });
697
+ const suffix = filenameSuffix ? `-${filenameSuffix}` : '';
698
+ const verificationOutputPath = `${outputDirectory}/l1-verify${suffix}-${chainId}-${formattedDate.slice(0, 6)}-${formattedDate.slice(6)}.json`;
699
+ const networkName = getActiveNetworkName();
700
+ const verificationData = {
701
+ chainId: chainId,
702
+ network: networkName,
703
+ records: deployer.verificationRecords,
704
+ };
705
+ await writeFile(verificationOutputPath, JSON.stringify(verificationData, null, 2));
706
+ logger.info(`Wrote L1 verification data to ${verificationOutputPath}`);
707
+ } catch (e) {
708
+ logger.warn(`Failed to write L1 verification data file: ${String(e)}`);
709
+ }
710
+ }
711
+
519
712
  /**
520
713
  * Deploys a new rollup, using the existing canonical version to derive certain values (addresses of assets etc).
521
714
  * @param clients - The L1 clients.
@@ -523,6 +716,7 @@ const getZkPassportScopes = (args: DeployL1ContractsArgs): [string, string] => {
523
716
  * @param registryAddress - The address of the registry.
524
717
  * @param logger - The logger.
525
718
  * @param txUtilsConfig - The L1 tx utils config.
719
+ * @param createVerificationJson - Optional path to write verification data for forge verify.
526
720
  */
527
721
  export const deployRollupForUpgrade = async (
528
722
  extendedClient: ExtendedViemWalletClient,
@@ -533,6 +727,7 @@ export const deployRollupForUpgrade = async (
533
727
  registryAddress: EthAddress,
534
728
  logger: Logger,
535
729
  txUtilsConfig: L1TxUtilsConfig,
730
+ createVerificationJson: string | false = false,
536
731
  ) => {
537
732
  const deployer = new L1Deployer(
538
733
  extendedClient,
@@ -541,6 +736,7 @@ export const deployRollupForUpgrade = async (
541
736
  args.acceleratedTestDeployments,
542
737
  logger,
543
738
  txUtilsConfig,
739
+ !!createVerificationJson,
544
740
  );
545
741
 
546
742
  const addresses = await RegistryContract.collectAddresses(extendedClient, registryAddress, 'canonical');
@@ -549,6 +745,12 @@ export const deployRollupForUpgrade = async (
549
745
 
550
746
  await deployer.waitForDeployments();
551
747
 
748
+ // Write verification data (constructor args + linked libraries) to file for later forge verify
749
+ if (createVerificationJson) {
750
+ await generateRollupVerificationRecords(rollup, deployer, args, addresses, extendedClient, logger);
751
+ await writeVerificationJson(deployer, createVerificationJson, extendedClient.chain.id, 'upgrade', logger);
752
+ }
753
+
552
754
  return { rollup, slashFactoryAddress };
553
755
  };
554
756
 
@@ -655,6 +857,7 @@ export const deployRollup = async (
655
857
  slashAmounts: [args.slashAmountSmall, args.slashAmountMedium, args.slashAmountLarge],
656
858
  localEjectionThreshold: args.localEjectionThreshold,
657
859
  slashingDisableDuration: BigInt(args.slashingDisableDuration ?? 0n),
860
+ earliestRewardsClaimableTimestamp: 0n,
658
861
  };
659
862
 
660
863
  const genesisStateArgs = {
@@ -1279,144 +1482,8 @@ export const deployL1Contracts = async (
1279
1482
 
1280
1483
  // Write verification data (constructor args + linked libraries) to file for later forge verify
1281
1484
  if (createVerificationJson) {
1282
- try {
1283
- // Add Inbox / Outbox verification records (constructor args are created inside RollupCore)
1284
- const rollupAddr = l1Contracts.rollupAddress.toString();
1285
- const inboxAddr = l1Contracts.inboxAddress.toString();
1286
- const outboxAddr = l1Contracts.outboxAddress.toString();
1287
- const feeAsset = l1Contracts.feeJuiceAddress.toString();
1288
- const version = await rollup.getVersion();
1289
-
1290
- const inboxCtor = encodeAbiParameters(
1291
- [{ type: 'address' }, { type: 'address' }, { type: 'uint256' }, { type: 'uint256' }],
1292
- [rollupAddr, feeAsset, version, BigInt(L1_TO_L2_MSG_SUBTREE_HEIGHT)],
1293
- );
1294
-
1295
- const outboxCtor = encodeAbiParameters([{ type: 'address' }, { type: 'uint256' }], [rollupAddr, version]);
1296
-
1297
- deployer.verificationRecords.push(
1298
- { name: 'Inbox', address: inboxAddr, constructorArgsHex: inboxCtor, libraries: [] },
1299
- { name: 'Outbox', address: outboxAddr, constructorArgsHex: outboxCtor, libraries: [] },
1300
- );
1301
-
1302
- // Include Slasher and SlashingProposer (if deployed) in verification data
1303
- try {
1304
- const slasherAddrHex = await rollup.getSlasherAddress();
1305
- const slasherAddr = EthAddress.fromString(slasherAddrHex);
1306
- if (!slasherAddr.isZero()) {
1307
- // Slasher constructor: (address _vetoer, address _governance)
1308
- const slasherCtor = encodeAbiParameters(
1309
- [{ type: 'address' }, { type: 'address' }],
1310
- [args.slashingVetoer.toString(), l1Client.account.address],
1311
- );
1312
- deployer.verificationRecords.push({
1313
- name: 'Slasher',
1314
- address: slasherAddr.toString(),
1315
- constructorArgsHex: slasherCtor,
1316
- libraries: [],
1317
- });
1318
-
1319
- // Proposer address is stored in Slasher.PROPOSER()
1320
- const proposerAddr = (await rollup.getSlashingProposerAddress()).toString();
1321
-
1322
- // Compute constructor args matching deployment path in RollupCore
1323
- const computedRoundSize = BigInt(args.slashingRoundSizeInEpochs * args.aztecEpochDuration);
1324
- const computedQuorum = BigInt(
1325
- args.slashingQuorum ?? (args.slashingRoundSizeInEpochs * args.aztecEpochDuration) / 2 + 1,
1326
- );
1327
- const lifetimeInRounds = BigInt(args.slashingLifetimeInRounds);
1328
- const executionDelayInRounds = BigInt(args.slashingExecutionDelayInRounds);
1329
-
1330
- if (args.slasherFlavor === 'tally') {
1331
- const slashAmounts: readonly [bigint, bigint, bigint] = [
1332
- args.slashAmountSmall,
1333
- args.slashAmountMedium,
1334
- args.slashAmountLarge,
1335
- ];
1336
- const committeeSize = BigInt(args.aztecTargetCommitteeSize);
1337
- const epochDuration = BigInt(args.aztecEpochDuration);
1338
- const slashOffsetInRounds = BigInt(args.slashingOffsetInRounds);
1339
-
1340
- const proposerCtor = encodeAbiParameters(
1341
- [
1342
- { type: 'address' },
1343
- { type: 'address' },
1344
- { type: 'uint256' },
1345
- { type: 'uint256' },
1346
- { type: 'uint256' },
1347
- { type: 'uint256' },
1348
- { type: 'uint256[3]' },
1349
- { type: 'uint256' },
1350
- { type: 'uint256' },
1351
- { type: 'uint256' },
1352
- ],
1353
- [
1354
- rollup.address,
1355
- slasherAddr.toString(),
1356
- computedQuorum,
1357
- computedRoundSize,
1358
- lifetimeInRounds,
1359
- executionDelayInRounds,
1360
- slashAmounts,
1361
- committeeSize,
1362
- epochDuration,
1363
- slashOffsetInRounds,
1364
- ],
1365
- );
1366
-
1367
- deployer.verificationRecords.push({
1368
- name: 'TallySlashingProposer',
1369
- address: proposerAddr,
1370
- constructorArgsHex: proposerCtor,
1371
- libraries: [],
1372
- });
1373
- } else if (args.slasherFlavor === 'empire') {
1374
- const proposerCtor = encodeAbiParameters(
1375
- [
1376
- { type: 'address' },
1377
- { type: 'address' },
1378
- { type: 'uint256' },
1379
- { type: 'uint256' },
1380
- { type: 'uint256' },
1381
- { type: 'uint256' },
1382
- ],
1383
- [
1384
- rollup.address,
1385
- slasherAddr.toString(),
1386
- computedQuorum,
1387
- computedRoundSize,
1388
- lifetimeInRounds,
1389
- executionDelayInRounds,
1390
- ],
1391
- );
1392
-
1393
- deployer.verificationRecords.push({
1394
- name: 'EmpireSlashingProposer',
1395
- address: proposerAddr,
1396
- constructorArgsHex: proposerCtor,
1397
- libraries: [],
1398
- });
1399
- }
1400
- }
1401
- } catch (e) {
1402
- logger.warn(`Failed to add Slasher/Proposer verification records: ${String(e)}`);
1403
- }
1404
- const date = new Date();
1405
- const formattedDate = date.toISOString().slice(2, 19).replace(/[-T:]/g, '');
1406
- // Ensure the verification output directory exists
1407
- await mkdir(createVerificationJson, { recursive: true });
1408
- const verificationOutputPath = `${createVerificationJson}/l1-verify-${chain.id}-${formattedDate.slice(0, 6)}-${formattedDate.slice(6)}.json`;
1409
- const networkName = getActiveNetworkName();
1410
- const verificationData = {
1411
- chainId: chain.id,
1412
- network: networkName,
1413
- records: deployer.verificationRecords,
1414
- };
1415
- await writeFile(verificationOutputPath, JSON.stringify(verificationData, null, 2));
1416
- logger.info(`Wrote L1 verification data to ${verificationOutputPath}`);
1417
- } catch (e) {
1418
- logger.warn(`Failed to write L1 verification data file: ${String(e)}`);
1419
- }
1485
+ await generateRollupVerificationRecords(rollup, deployer, args, l1Contracts, l1Client, logger);
1486
+ await writeVerificationJson(deployer, createVerificationJson, chain.id, '', logger);
1420
1487
  }
1421
1488
 
1422
1489
  if (isAnvilTestChain(chain.id)) {
@@ -33,10 +33,10 @@ import {
33
33
  RegisterNewRollupVersionPayloadBytecode,
34
34
  RegistryAbi,
35
35
  RegistryBytecode,
36
- RewardDeploymentExtLibAbi,
37
- RewardDeploymentExtLibBytecode,
38
36
  RewardDistributorAbi,
39
37
  RewardDistributorBytecode,
38
+ RewardExtLibAbi,
39
+ RewardExtLibBytecode,
40
40
  RollupAbi,
41
41
  RollupBytecode,
42
42
  RollupLinkReferences,
@@ -102,10 +102,10 @@ export const RollupArtifact = {
102
102
  contractAbi: ValidatorOperationsExtLibAbi,
103
103
  contractBytecode: ValidatorOperationsExtLibBytecode as Hex,
104
104
  },
105
- RewardDeploymentExtLib: {
106
- name: 'RewardDeploymentExtLib',
107
- contractAbi: RewardDeploymentExtLibAbi,
108
- contractBytecode: RewardDeploymentExtLibBytecode as Hex,
105
+ RewardExtLib: {
106
+ name: 'RewardExtLib',
107
+ contractAbi: RewardExtLibAbi,
108
+ contractBytecode: RewardExtLibBytecode as Hex,
109
109
  },
110
110
  TallySlasherDeploymentExtLib: {
111
111
  name: 'TallySlasherDeploymentExtLib',