@aztec/ethereum 2.1.0-rc.9 → 2.1.1-rc.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.
@@ -123,6 +123,19 @@ export const deploySharedContracts = async (l1Client, deployer, args, logger)=>{
123
123
  ]);
124
124
  feeAssetAddress = deployedFee.address;
125
125
  logger.verbose(`Deployed Fee Asset at ${feeAssetAddress}`);
126
+ // Mint a tiny bit of tokens to satisfy coin-issuer constraints
127
+ const { txHash } = await deployer.sendTransaction({
128
+ to: feeAssetAddress.toString(),
129
+ data: encodeFunctionData({
130
+ abi: FeeAssetArtifact.contractAbi,
131
+ functionName: 'mint',
132
+ args: [
133
+ l1Client.account.address,
134
+ 1n * 10n ** 18n
135
+ ]
136
+ })
137
+ });
138
+ logger.verbose(`Minted tiny bit of tokens to satisfy coin-issuer constraints in ${txHash}`);
126
139
  const deployedStaking = await deployer.deploy(StakingAssetArtifact, [
127
140
  'Staking',
128
141
  'STK',
@@ -130,6 +143,7 @@ export const deploySharedContracts = async (l1Client, deployer, args, logger)=>{
130
143
  ]);
131
144
  stakingAssetAddress = deployedStaking.address;
132
145
  logger.verbose(`Deployed Staking Asset at ${stakingAssetAddress}`);
146
+ await deployer.waitForDeployments();
133
147
  }
134
148
  const gseAddress = (await deployer.deploy(GSEArtifact, [
135
149
  l1Client.account.address,
@@ -194,9 +208,11 @@ export const deploySharedContracts = async (l1Client, deployer, args, logger)=>{
194
208
  }
195
209
  const coinIssuerAddress = (await deployer.deploy(CoinIssuerArtifact, [
196
210
  feeAssetAddress.toString(),
197
- 25_000_000_000n * 10n ** 18n / (60n * 60n * 24n * 365n),
211
+ 2n * 10n ** 17n,
198
212
  l1Client.account.address
199
- ])).address;
213
+ ], {
214
+ gasLimit: 1_000_000n
215
+ })).address;
200
216
  logger.verbose(`Deployed CoinIssuer at ${coinIssuerAddress}`);
201
217
  logger.verbose(`Waiting for deployments to complete`);
202
218
  await deployer.waitForDeployments();
@@ -332,6 +348,224 @@ const getZkPassportVerifierAddress = async (deployer, args)=>{
332
348
  scope
333
349
  ];
334
350
  };
351
+ /**
352
+ * Generates verification records for a deployed rollup and its associated contracts (Inbox, Outbox, Slasher, etc).
353
+ * @param rollup - The deployed rollup contract.
354
+ * @param deployer - The L1 deployer instance.
355
+ * @param args - The deployment arguments used for the rollup.
356
+ * @param addresses - The L1 contract addresses.
357
+ * @param extendedClient - The extended viem wallet client.
358
+ * @param logger - The logger.
359
+ */ async function generateRollupVerificationRecords(rollup, deployer, args, addresses, extendedClient, logger) {
360
+ try {
361
+ // Add Inbox / Outbox verification records (constructor args are created inside RollupCore)
362
+ const rollupAddr = rollup.address;
363
+ const rollupAddresses = await rollup.getRollupAddresses();
364
+ const inboxAddr = rollupAddresses.inboxAddress.toString();
365
+ const outboxAddr = rollupAddresses.outboxAddress.toString();
366
+ const feeAsset = rollupAddresses.feeJuiceAddress.toString();
367
+ const version = await rollup.getVersion();
368
+ const inboxCtor = encodeAbiParameters([
369
+ {
370
+ type: 'address'
371
+ },
372
+ {
373
+ type: 'address'
374
+ },
375
+ {
376
+ type: 'uint256'
377
+ },
378
+ {
379
+ type: 'uint256'
380
+ }
381
+ ], [
382
+ rollupAddr,
383
+ feeAsset,
384
+ version,
385
+ BigInt(L1_TO_L2_MSG_SUBTREE_HEIGHT)
386
+ ]);
387
+ const outboxCtor = encodeAbiParameters([
388
+ {
389
+ type: 'address'
390
+ },
391
+ {
392
+ type: 'uint256'
393
+ }
394
+ ], [
395
+ rollupAddr,
396
+ version
397
+ ]);
398
+ deployer.verificationRecords.push({
399
+ name: 'Inbox',
400
+ address: inboxAddr,
401
+ constructorArgsHex: inboxCtor,
402
+ libraries: []
403
+ }, {
404
+ name: 'Outbox',
405
+ address: outboxAddr,
406
+ constructorArgsHex: outboxCtor,
407
+ libraries: []
408
+ });
409
+ // Include Slasher and SlashingProposer (if deployed) in verification data
410
+ try {
411
+ const slasherAddrHex = await rollup.getSlasherAddress();
412
+ const slasherAddr = EthAddress.fromString(slasherAddrHex);
413
+ if (!slasherAddr.isZero()) {
414
+ // Slasher constructor: (address _vetoer, address _governance)
415
+ const slasherCtor = encodeAbiParameters([
416
+ {
417
+ type: 'address'
418
+ },
419
+ {
420
+ type: 'address'
421
+ }
422
+ ], [
423
+ args.slashingVetoer.toString(),
424
+ extendedClient.account.address
425
+ ]);
426
+ deployer.verificationRecords.push({
427
+ name: 'Slasher',
428
+ address: slasherAddr.toString(),
429
+ constructorArgsHex: slasherCtor,
430
+ libraries: []
431
+ });
432
+ // Proposer address is stored in Slasher.PROPOSER()
433
+ const proposerAddr = (await rollup.getSlashingProposerAddress()).toString();
434
+ // Compute constructor args matching deployment path in RollupCore
435
+ const computedRoundSize = BigInt(args.slashingRoundSizeInEpochs * args.aztecEpochDuration);
436
+ const computedQuorum = BigInt(args.slashingQuorum ?? args.slashingRoundSizeInEpochs * args.aztecEpochDuration / 2 + 1);
437
+ const lifetimeInRounds = BigInt(args.slashingLifetimeInRounds);
438
+ const executionDelayInRounds = BigInt(args.slashingExecutionDelayInRounds);
439
+ if (args.slasherFlavor === 'tally') {
440
+ const slashAmounts = [
441
+ args.slashAmountSmall,
442
+ args.slashAmountMedium,
443
+ args.slashAmountLarge
444
+ ];
445
+ const committeeSize = BigInt(args.aztecTargetCommitteeSize);
446
+ const epochDuration = BigInt(args.aztecEpochDuration);
447
+ const slashOffsetInRounds = BigInt(args.slashingOffsetInRounds);
448
+ const proposerCtor = encodeAbiParameters([
449
+ {
450
+ type: 'address'
451
+ },
452
+ {
453
+ type: 'address'
454
+ },
455
+ {
456
+ type: 'uint256'
457
+ },
458
+ {
459
+ type: 'uint256'
460
+ },
461
+ {
462
+ type: 'uint256'
463
+ },
464
+ {
465
+ type: 'uint256'
466
+ },
467
+ {
468
+ type: 'uint256[3]'
469
+ },
470
+ {
471
+ type: 'uint256'
472
+ },
473
+ {
474
+ type: 'uint256'
475
+ },
476
+ {
477
+ type: 'uint256'
478
+ }
479
+ ], [
480
+ rollup.address,
481
+ slasherAddr.toString(),
482
+ computedQuorum,
483
+ computedRoundSize,
484
+ lifetimeInRounds,
485
+ executionDelayInRounds,
486
+ slashAmounts,
487
+ committeeSize,
488
+ epochDuration,
489
+ slashOffsetInRounds
490
+ ]);
491
+ deployer.verificationRecords.push({
492
+ name: 'TallySlashingProposer',
493
+ address: proposerAddr,
494
+ constructorArgsHex: proposerCtor,
495
+ libraries: []
496
+ });
497
+ } else if (args.slasherFlavor === 'empire') {
498
+ const proposerCtor = encodeAbiParameters([
499
+ {
500
+ type: 'address'
501
+ },
502
+ {
503
+ type: 'address'
504
+ },
505
+ {
506
+ type: 'uint256'
507
+ },
508
+ {
509
+ type: 'uint256'
510
+ },
511
+ {
512
+ type: 'uint256'
513
+ },
514
+ {
515
+ type: 'uint256'
516
+ }
517
+ ], [
518
+ rollup.address,
519
+ slasherAddr.toString(),
520
+ computedQuorum,
521
+ computedRoundSize,
522
+ lifetimeInRounds,
523
+ executionDelayInRounds
524
+ ]);
525
+ deployer.verificationRecords.push({
526
+ name: 'EmpireSlashingProposer',
527
+ address: proposerAddr,
528
+ constructorArgsHex: proposerCtor,
529
+ libraries: []
530
+ });
531
+ }
532
+ }
533
+ } catch (e) {
534
+ logger.warn(`Failed to add Slasher/Proposer verification records: ${String(e)}`);
535
+ }
536
+ } catch (e) {
537
+ throw new Error(`Failed to generate rollup verification records: ${String(e)}`);
538
+ }
539
+ }
540
+ /**
541
+ * Writes verification records to a JSON file for later forge verify.
542
+ * @param deployer - The L1 deployer containing verification records.
543
+ * @param outputDirectory - The directory to write the verification file to.
544
+ * @param chainId - The chain ID.
545
+ * @param filenameSuffix - Optional suffix for the filename (e.g., 'upgrade').
546
+ * @param logger - The logger.
547
+ */ async function writeVerificationJson(deployer, outputDirectory, chainId, filenameSuffix = '', logger) {
548
+ try {
549
+ const date = new Date();
550
+ const formattedDate = date.toISOString().slice(2, 19).replace(/[-T:]/g, '');
551
+ // Ensure the verification output directory exists
552
+ await mkdir(outputDirectory, {
553
+ recursive: true
554
+ });
555
+ const suffix = filenameSuffix ? `-${filenameSuffix}` : '';
556
+ const verificationOutputPath = `${outputDirectory}/l1-verify${suffix}-${chainId}-${formattedDate.slice(0, 6)}-${formattedDate.slice(6)}.json`;
557
+ const networkName = getActiveNetworkName();
558
+ const verificationData = {
559
+ chainId: chainId,
560
+ network: networkName,
561
+ records: deployer.verificationRecords
562
+ };
563
+ await writeFile(verificationOutputPath, JSON.stringify(verificationData, null, 2));
564
+ logger.info(`Wrote L1 verification data to ${verificationOutputPath}`);
565
+ } catch (e) {
566
+ logger.warn(`Failed to write L1 verification data file: ${String(e)}`);
567
+ }
568
+ }
335
569
  /**
336
570
  * Deploys a new rollup, using the existing canonical version to derive certain values (addresses of assets etc).
337
571
  * @param clients - The L1 clients.
@@ -339,11 +573,17 @@ const getZkPassportVerifierAddress = async (deployer, args)=>{
339
573
  * @param registryAddress - The address of the registry.
340
574
  * @param logger - The logger.
341
575
  * @param txUtilsConfig - The L1 tx utils config.
342
- */ export const deployRollupForUpgrade = async (extendedClient, args, registryAddress, logger, txUtilsConfig)=>{
343
- const deployer = new L1Deployer(extendedClient, args.salt, undefined, args.acceleratedTestDeployments, logger, txUtilsConfig);
576
+ * @param createVerificationJson - Optional path to write verification data for forge verify.
577
+ */ export const deployRollupForUpgrade = async (extendedClient, args, registryAddress, logger, txUtilsConfig, createVerificationJson = false)=>{
578
+ const deployer = new L1Deployer(extendedClient, args.salt, undefined, args.acceleratedTestDeployments, logger, txUtilsConfig, !!createVerificationJson);
344
579
  const addresses = await RegistryContract.collectAddresses(extendedClient, registryAddress, 'canonical');
345
580
  const { rollup, slashFactoryAddress } = await deployRollup(extendedClient, deployer, args, addresses, logger);
346
581
  await deployer.waitForDeployments();
582
+ // Write verification data (constructor args + linked libraries) to file for later forge verify
583
+ if (createVerificationJson) {
584
+ await generateRollupVerificationRecords(rollup, deployer, args, addresses, extendedClient, logger);
585
+ await writeVerificationJson(deployer, createVerificationJson, extendedClient.chain.id, 'upgrade', logger);
586
+ }
347
587
  return {
348
588
  rollup,
349
589
  slashFactoryAddress
@@ -425,7 +665,8 @@ function slasherFlavorToSolidityEnum(flavor) {
425
665
  args.slashAmountLarge
426
666
  ],
427
667
  localEjectionThreshold: args.localEjectionThreshold,
428
- slashingDisableDuration: BigInt(args.slashingDisableDuration ?? 0n)
668
+ slashingDisableDuration: BigInt(args.slashingDisableDuration ?? 0n),
669
+ earliestRewardsClaimableTimestamp: 0n
429
670
  };
430
671
  const genesisStateArgs = {
431
672
  vkTreeRoot: args.vkTreeRoot.toString(),
@@ -763,7 +1004,7 @@ export const handoverToGovernance = async (extendedClient, deployer, registryAdd
763
1004
  functionName: 'addValidators',
764
1005
  args: [
765
1006
  c,
766
- BigInt(chunkSize)
1007
+ BigInt(0)
767
1008
  ]
768
1009
  })
769
1010
  }, {
@@ -780,13 +1021,16 @@ export const handoverToGovernance = async (extendedClient, deployer, registryAdd
780
1021
  while(true){
781
1022
  // If the queue is empty, we can break
782
1023
  if (await rollup.getEntryQueueLength() == 0n) {
1024
+ logger.debug('Entry queue is empty, stopping flush attempts');
783
1025
  break;
784
1026
  }
785
1027
  // If there are no available validator flushes, no need to even try
786
1028
  if (await rollup.getAvailableValidatorFlushes() == 0n) {
1029
+ logger.debug('No available validator flushes, stopping flush attempts');
787
1030
  break;
788
1031
  }
789
1032
  // Note that we are flushing at most `chunkSize` at each call
1033
+ logger.debug(`Flushing entry queue for ${chunkSize} validators`);
790
1034
  await deployer.l1TxUtils.sendAndMonitorTransaction({
791
1035
  to: rollup.address,
792
1036
  data: encodeFunctionData({
@@ -898,199 +1142,8 @@ export const cheat_initializeFeeAssetHandler = async (extendedClient, deployer,
898
1142
  logger.info(`Aztec L1 contracts initialized`, l1Contracts);
899
1143
  // Write verification data (constructor args + linked libraries) to file for later forge verify
900
1144
  if (createVerificationJson) {
901
- try {
902
- // Add Inbox / Outbox verification records (constructor args are created inside RollupCore)
903
- const rollupAddr = l1Contracts.rollupAddress.toString();
904
- const inboxAddr = l1Contracts.inboxAddress.toString();
905
- const outboxAddr = l1Contracts.outboxAddress.toString();
906
- const feeAsset = l1Contracts.feeJuiceAddress.toString();
907
- const version = await rollup.getVersion();
908
- const inboxCtor = encodeAbiParameters([
909
- {
910
- type: 'address'
911
- },
912
- {
913
- type: 'address'
914
- },
915
- {
916
- type: 'uint256'
917
- },
918
- {
919
- type: 'uint256'
920
- }
921
- ], [
922
- rollupAddr,
923
- feeAsset,
924
- version,
925
- BigInt(L1_TO_L2_MSG_SUBTREE_HEIGHT)
926
- ]);
927
- const outboxCtor = encodeAbiParameters([
928
- {
929
- type: 'address'
930
- },
931
- {
932
- type: 'uint256'
933
- }
934
- ], [
935
- rollupAddr,
936
- version
937
- ]);
938
- deployer.verificationRecords.push({
939
- name: 'Inbox',
940
- address: inboxAddr,
941
- constructorArgsHex: inboxCtor,
942
- libraries: []
943
- }, {
944
- name: 'Outbox',
945
- address: outboxAddr,
946
- constructorArgsHex: outboxCtor,
947
- libraries: []
948
- });
949
- // Include Slasher and SlashingProposer (if deployed) in verification data
950
- try {
951
- const slasherAddrHex = await rollup.getSlasherAddress();
952
- const slasherAddr = EthAddress.fromString(slasherAddrHex);
953
- if (!slasherAddr.isZero()) {
954
- // Slasher constructor: (address _vetoer, address _governance)
955
- const slasherCtor = encodeAbiParameters([
956
- {
957
- type: 'address'
958
- },
959
- {
960
- type: 'address'
961
- }
962
- ], [
963
- args.slashingVetoer.toString(),
964
- l1Client.account.address
965
- ]);
966
- deployer.verificationRecords.push({
967
- name: 'Slasher',
968
- address: slasherAddr.toString(),
969
- constructorArgsHex: slasherCtor,
970
- libraries: []
971
- });
972
- // Proposer address is stored in Slasher.PROPOSER()
973
- const proposerAddr = (await rollup.getSlashingProposerAddress()).toString();
974
- // Compute constructor args matching deployment path in RollupCore
975
- const computedRoundSize = BigInt(args.slashingRoundSizeInEpochs * args.aztecEpochDuration);
976
- const computedQuorum = BigInt(args.slashingQuorum ?? args.slashingRoundSizeInEpochs * args.aztecEpochDuration / 2 + 1);
977
- const lifetimeInRounds = BigInt(args.slashingLifetimeInRounds);
978
- const executionDelayInRounds = BigInt(args.slashingExecutionDelayInRounds);
979
- if (args.slasherFlavor === 'tally') {
980
- const slashAmounts = [
981
- args.slashAmountSmall,
982
- args.slashAmountMedium,
983
- args.slashAmountLarge
984
- ];
985
- const committeeSize = BigInt(args.aztecTargetCommitteeSize);
986
- const epochDuration = BigInt(args.aztecEpochDuration);
987
- const slashOffsetInRounds = BigInt(args.slashingOffsetInRounds);
988
- const proposerCtor = encodeAbiParameters([
989
- {
990
- type: 'address'
991
- },
992
- {
993
- type: 'address'
994
- },
995
- {
996
- type: 'uint256'
997
- },
998
- {
999
- type: 'uint256'
1000
- },
1001
- {
1002
- type: 'uint256'
1003
- },
1004
- {
1005
- type: 'uint256'
1006
- },
1007
- {
1008
- type: 'uint256[3]'
1009
- },
1010
- {
1011
- type: 'uint256'
1012
- },
1013
- {
1014
- type: 'uint256'
1015
- },
1016
- {
1017
- type: 'uint256'
1018
- }
1019
- ], [
1020
- rollup.address,
1021
- slasherAddr.toString(),
1022
- computedQuorum,
1023
- computedRoundSize,
1024
- lifetimeInRounds,
1025
- executionDelayInRounds,
1026
- slashAmounts,
1027
- committeeSize,
1028
- epochDuration,
1029
- slashOffsetInRounds
1030
- ]);
1031
- deployer.verificationRecords.push({
1032
- name: 'TallySlashingProposer',
1033
- address: proposerAddr,
1034
- constructorArgsHex: proposerCtor,
1035
- libraries: []
1036
- });
1037
- } else if (args.slasherFlavor === 'empire') {
1038
- const proposerCtor = encodeAbiParameters([
1039
- {
1040
- type: 'address'
1041
- },
1042
- {
1043
- type: 'address'
1044
- },
1045
- {
1046
- type: 'uint256'
1047
- },
1048
- {
1049
- type: 'uint256'
1050
- },
1051
- {
1052
- type: 'uint256'
1053
- },
1054
- {
1055
- type: 'uint256'
1056
- }
1057
- ], [
1058
- rollup.address,
1059
- slasherAddr.toString(),
1060
- computedQuorum,
1061
- computedRoundSize,
1062
- lifetimeInRounds,
1063
- executionDelayInRounds
1064
- ]);
1065
- deployer.verificationRecords.push({
1066
- name: 'EmpireSlashingProposer',
1067
- address: proposerAddr,
1068
- constructorArgsHex: proposerCtor,
1069
- libraries: []
1070
- });
1071
- }
1072
- }
1073
- } catch (e) {
1074
- logger.warn(`Failed to add Slasher/Proposer verification records: ${String(e)}`);
1075
- }
1076
- const date = new Date();
1077
- const formattedDate = date.toISOString().slice(2, 19).replace(/[-T:]/g, '');
1078
- // Ensure the verification output directory exists
1079
- await mkdir(createVerificationJson, {
1080
- recursive: true
1081
- });
1082
- const verificationOutputPath = `${createVerificationJson}/l1-verify-${chain.id}-${formattedDate.slice(0, 6)}-${formattedDate.slice(6)}.json`;
1083
- const networkName = getActiveNetworkName();
1084
- const verificationData = {
1085
- chainId: chain.id,
1086
- network: networkName,
1087
- records: deployer.verificationRecords
1088
- };
1089
- await writeFile(verificationOutputPath, JSON.stringify(verificationData, null, 2));
1090
- logger.info(`Wrote L1 verification data to ${verificationOutputPath}`);
1091
- } catch (e) {
1092
- logger.warn(`Failed to write L1 verification data file: ${String(e)}`);
1093
- }
1145
+ await generateRollupVerificationRecords(rollup, deployer, args, l1Contracts, l1Client, logger);
1146
+ await writeVerificationJson(deployer, createVerificationJson, chain.id, '', logger);
1094
1147
  }
1095
1148
  if (isAnvilTestChain(chain.id)) {
1096
1149
  // @note We make a time jump PAST the very first slot to not have to deal with the edge case of the first slot.