@aztec/ethereum 2.0.0-nightly.20250902 → 3.0.0-canary.a9708bd
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.map +1 -1
- package/dest/config.js +61 -54
- package/dest/contracts/fee_asset_handler.d.ts +3 -2
- package/dest/contracts/fee_asset_handler.d.ts.map +1 -1
- package/dest/contracts/fee_asset_handler.js +14 -0
- package/dest/contracts/fee_juice.d.ts +2 -1
- package/dest/contracts/fee_juice.d.ts.map +1 -1
- package/dest/contracts/fee_juice.js +6 -0
- package/dest/contracts/governance.d.ts +1 -1
- package/dest/contracts/governance.d.ts.map +1 -1
- package/dest/contracts/governance.js +3 -0
- package/dest/contracts/governance_proposer.d.ts +1 -1
- package/dest/contracts/governance_proposer.d.ts.map +1 -1
- package/dest/contracts/governance_proposer.js +3 -0
- package/dest/contracts/gse.d.ts +2 -0
- package/dest/contracts/gse.d.ts.map +1 -1
- package/dest/contracts/gse.js +6 -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 +383 -61
- package/dest/l1_artifacts.d.ts +39210 -39196
- package/dest/l1_artifacts.d.ts.map +1 -1
- package/dest/test/eth_cheat_codes.d.ts +3 -2
- package/dest/test/eth_cheat_codes.d.ts.map +1 -1
- package/dest/test/eth_cheat_codes.js +11 -0
- package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
- package/dest/test/rollup_cheat_codes.js +2 -1
- package/dest/test/tx_delayer.d.ts +2 -2
- package/dest/test/tx_delayer.d.ts.map +1 -1
- package/dest/test/tx_delayer.js +4 -4
- package/package.json +5 -4
- package/src/config.ts +81 -72
- package/src/contracts/fee_asset_handler.ts +17 -2
- package/src/contracts/fee_juice.ts +8 -1
- package/src/contracts/governance.ts +4 -1
- package/src/contracts/governance_proposer.ts +4 -1
- package/src/contracts/gse.ts +8 -0
- package/src/deploy_l1_contracts.ts +357 -52
- package/src/test/eth_cheat_codes.ts +12 -2
- package/src/test/rollup_cheat_codes.ts +5 -1
- package/src/test/tx_delayer.ts +14 -4
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { L1_TO_L2_MSG_SUBTREE_HEIGHT } from '@aztec/constants';
|
|
1
2
|
import { getActiveNetworkName } from '@aztec/foundation/config';
|
|
2
3
|
import { keccak256String } from '@aztec/foundation/crypto';
|
|
3
4
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
4
5
|
import { jsonStringify } from '@aztec/foundation/json-rpc';
|
|
5
6
|
import { createLogger } from '@aztec/foundation/log';
|
|
6
7
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
7
|
-
import {
|
|
8
|
+
import { mkdir, writeFile } from 'fs/promises';
|
|
9
|
+
import { concatHex, encodeAbiParameters, encodeDeployData, encodeFunctionData, getAddress, getContract, getContractAddress, numberToHex, padHex } from 'viem';
|
|
8
10
|
import { foundry } from 'viem/chains';
|
|
9
11
|
import { isAnvilTestChain } from './chain.js';
|
|
10
12
|
import { createExtendedL1Client } from './client.js';
|
|
@@ -98,35 +100,12 @@ export const deploySharedContracts = async (l1Client, deployer, args, logger)=>{
|
|
|
98
100
|
}
|
|
99
101
|
const coinIssuerAddress = await deployer.deploy(CoinIssuerArtifact, [
|
|
100
102
|
feeAssetAddress.toString(),
|
|
101
|
-
|
|
102
|
-
|
|
103
|
+
1_000_000n * 10n ** 18n,
|
|
104
|
+
l1Client.account.address
|
|
103
105
|
]);
|
|
104
106
|
logger.verbose(`Deployed CoinIssuer at ${coinIssuerAddress}`);
|
|
105
|
-
const feeAsset = getContract({
|
|
106
|
-
address: feeAssetAddress.toString(),
|
|
107
|
-
abi: FeeAssetArtifact.contractAbi,
|
|
108
|
-
client: l1Client
|
|
109
|
-
});
|
|
110
107
|
logger.verbose(`Waiting for deployments to complete`);
|
|
111
108
|
await deployer.waitForDeployments();
|
|
112
|
-
if (args.acceleratedTestDeployments || !await feeAsset.read.minters([
|
|
113
|
-
coinIssuerAddress.toString()
|
|
114
|
-
])) {
|
|
115
|
-
const { txHash } = await deployer.sendTransaction({
|
|
116
|
-
to: feeAssetAddress.toString(),
|
|
117
|
-
data: encodeFunctionData({
|
|
118
|
-
abi: FeeAssetArtifact.contractAbi,
|
|
119
|
-
functionName: 'addMinter',
|
|
120
|
-
args: [
|
|
121
|
-
coinIssuerAddress.toString()
|
|
122
|
-
]
|
|
123
|
-
})
|
|
124
|
-
}, {
|
|
125
|
-
gasLimit: 100_000n
|
|
126
|
-
});
|
|
127
|
-
logger.verbose(`Added coin issuer ${coinIssuerAddress} as minter on fee asset in ${txHash}`);
|
|
128
|
-
txHashes.push(txHash);
|
|
129
|
-
}
|
|
130
109
|
// Registry ownership will be transferred to governance later, after rollup is added
|
|
131
110
|
let feeAssetHandlerAddress = undefined;
|
|
132
111
|
let stakingAssetHandlerAddress = undefined;
|
|
@@ -136,21 +115,24 @@ export const deploySharedContracts = async (l1Client, deployer, args, logger)=>{
|
|
|
136
115
|
/* -------------------------------------------------------------------------- */ /* CHEAT CODES START HERE */ /* -------------------------------------------------------------------------- */ feeAssetHandlerAddress = await deployer.deploy(FeeAssetHandlerArtifact, [
|
|
137
116
|
l1Client.account.address,
|
|
138
117
|
feeAssetAddress.toString(),
|
|
139
|
-
BigInt(
|
|
118
|
+
BigInt(1000n * 10n ** 18n)
|
|
140
119
|
]);
|
|
141
120
|
logger.verbose(`Deployed FeeAssetHandler at ${feeAssetHandlerAddress}`);
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
121
|
+
// Only if we are "fresh" will we be adding as a minter, otherwise above will simply get same address
|
|
122
|
+
if (needToSetGovernance) {
|
|
123
|
+
const { txHash } = await deployer.sendTransaction({
|
|
124
|
+
to: feeAssetAddress.toString(),
|
|
125
|
+
data: encodeFunctionData({
|
|
126
|
+
abi: FeeAssetArtifact.contractAbi,
|
|
127
|
+
functionName: 'addMinter',
|
|
128
|
+
args: [
|
|
129
|
+
feeAssetHandlerAddress.toString()
|
|
130
|
+
]
|
|
131
|
+
})
|
|
132
|
+
});
|
|
133
|
+
logger.verbose(`Added fee asset handler ${feeAssetHandlerAddress} as minter on fee asset in ${txHash}`);
|
|
134
|
+
txHashes.push(txHash);
|
|
135
|
+
}
|
|
154
136
|
// Only if on sepolia will we deploy the staking asset handler
|
|
155
137
|
// Should not be deployed to devnet since it would cause caos with sequencers there etc.
|
|
156
138
|
if ([
|
|
@@ -458,6 +440,23 @@ function slasherFlavorToSolidityEnum(flavor) {
|
|
|
458
440
|
])) {
|
|
459
441
|
await addMultipleValidators(extendedClient, deployer, addresses.gseAddress.toString(), rollupAddress.toString(), addresses.stakingAssetAddress.toString(), args.initialValidators, args.acceleratedTestDeployments, logger);
|
|
460
442
|
}
|
|
443
|
+
// If the owner is not the Governance contract, transfer ownership to the Governance contract
|
|
444
|
+
logger.verbose(addresses.governanceAddress.toString());
|
|
445
|
+
if (getAddress(await rollupContract.getOwner()) !== getAddress(addresses.governanceAddress.toString())) {
|
|
446
|
+
// TODO(md): add send transaction to the deployer such that we do not need to manage tx hashes here
|
|
447
|
+
const { txHash: transferOwnershipTxHash } = await deployer.sendTransaction({
|
|
448
|
+
to: rollupContract.address,
|
|
449
|
+
data: encodeFunctionData({
|
|
450
|
+
abi: RegistryArtifact.contractAbi,
|
|
451
|
+
functionName: 'transferOwnership',
|
|
452
|
+
args: [
|
|
453
|
+
getAddress(addresses.governanceAddress.toString())
|
|
454
|
+
]
|
|
455
|
+
})
|
|
456
|
+
});
|
|
457
|
+
logger.verbose(`Transferring the ownership of the rollup contract at ${rollupContract.address} to the Governance ${addresses.governanceAddress} in tx ${transferOwnershipTxHash}`);
|
|
458
|
+
txHashes.push(transferOwnershipTxHash);
|
|
459
|
+
}
|
|
461
460
|
await deployer.waitForDeployments();
|
|
462
461
|
await Promise.all(txHashes.map((txHash)=>extendedClient.waitForTransactionReceipt({
|
|
463
462
|
hash: txHash
|
|
@@ -468,7 +467,7 @@ function slasherFlavorToSolidityEnum(flavor) {
|
|
|
468
467
|
slashFactoryAddress
|
|
469
468
|
};
|
|
470
469
|
};
|
|
471
|
-
export const handoverToGovernance = async (extendedClient, deployer, registryAddress, gseAddress, governanceAddress, logger, acceleratedTestDeployments)=>{
|
|
470
|
+
export const handoverToGovernance = async (extendedClient, deployer, registryAddress, gseAddress, coinIssuerAddress, feeAssetAddress, governanceAddress, logger, acceleratedTestDeployments)=>{
|
|
472
471
|
// We need to call a function on the registry to set the various contract addresses.
|
|
473
472
|
const registryContract = getContract({
|
|
474
473
|
address: getAddress(registryAddress.toString()),
|
|
@@ -480,6 +479,16 @@ export const handoverToGovernance = async (extendedClient, deployer, registryAdd
|
|
|
480
479
|
abi: GSEArtifact.contractAbi,
|
|
481
480
|
client: extendedClient
|
|
482
481
|
});
|
|
482
|
+
const coinIssuerContract = getContract({
|
|
483
|
+
address: getAddress(coinIssuerAddress.toString()),
|
|
484
|
+
abi: CoinIssuerArtifact.contractAbi,
|
|
485
|
+
client: extendedClient
|
|
486
|
+
});
|
|
487
|
+
const feeAsset = getContract({
|
|
488
|
+
address: getAddress(feeAssetAddress.toString()),
|
|
489
|
+
abi: FeeAssetArtifact.contractAbi,
|
|
490
|
+
client: extendedClient
|
|
491
|
+
});
|
|
483
492
|
const txHashes = [];
|
|
484
493
|
// If the owner is not the Governance contract, transfer ownership to the Governance contract
|
|
485
494
|
if (acceleratedTestDeployments || await registryContract.read.owner() !== getAddress(governanceAddress.toString())) {
|
|
@@ -513,6 +522,48 @@ export const handoverToGovernance = async (extendedClient, deployer, registryAdd
|
|
|
513
522
|
logger.verbose(`Transferring the ownership of the gse contract at ${gseAddress} to the Governance ${governanceAddress} in tx ${transferOwnershipTxHash}`);
|
|
514
523
|
txHashes.push(transferOwnershipTxHash);
|
|
515
524
|
}
|
|
525
|
+
if (acceleratedTestDeployments || await feeAsset.read.owner() !== coinIssuerAddress.toString()) {
|
|
526
|
+
const { txHash } = await deployer.sendTransaction({
|
|
527
|
+
to: feeAssetAddress.toString(),
|
|
528
|
+
data: encodeFunctionData({
|
|
529
|
+
abi: FeeAssetArtifact.contractAbi,
|
|
530
|
+
functionName: 'transferOwnership',
|
|
531
|
+
args: [
|
|
532
|
+
coinIssuerAddress.toString()
|
|
533
|
+
]
|
|
534
|
+
})
|
|
535
|
+
}, {
|
|
536
|
+
gasLimit: 500_000n
|
|
537
|
+
});
|
|
538
|
+
logger.verbose(`Transfer ownership of fee asset to coin issuer ${coinIssuerAddress} in ${txHash}`);
|
|
539
|
+
txHashes.push(txHash);
|
|
540
|
+
const { txHash: acceptTokenOwnershipTxHash } = await deployer.sendTransaction({
|
|
541
|
+
to: coinIssuerAddress.toString(),
|
|
542
|
+
data: encodeFunctionData({
|
|
543
|
+
abi: CoinIssuerArtifact.contractAbi,
|
|
544
|
+
functionName: 'acceptTokenOwnership'
|
|
545
|
+
})
|
|
546
|
+
}, {
|
|
547
|
+
gasLimit: 500_000n
|
|
548
|
+
});
|
|
549
|
+
logger.verbose(`Accept ownership of fee asset in ${acceptTokenOwnershipTxHash}`);
|
|
550
|
+
txHashes.push(acceptTokenOwnershipTxHash);
|
|
551
|
+
}
|
|
552
|
+
// If the owner is not the Governance contract, transfer ownership to the Governance contract
|
|
553
|
+
if (acceleratedTestDeployments || await coinIssuerContract.read.owner() !== getAddress(governanceAddress.toString())) {
|
|
554
|
+
const { txHash: transferOwnershipTxHash } = await deployer.sendTransaction({
|
|
555
|
+
to: coinIssuerContract.address,
|
|
556
|
+
data: encodeFunctionData({
|
|
557
|
+
abi: CoinIssuerArtifact.contractAbi,
|
|
558
|
+
functionName: 'transferOwnership',
|
|
559
|
+
args: [
|
|
560
|
+
getAddress(governanceAddress.toString())
|
|
561
|
+
]
|
|
562
|
+
})
|
|
563
|
+
});
|
|
564
|
+
logger.verbose(`Transferring the ownership of the coin issuer contract at ${coinIssuerAddress} to the Governance ${governanceAddress} in tx ${transferOwnershipTxHash}`);
|
|
565
|
+
txHashes.push(transferOwnershipTxHash);
|
|
566
|
+
}
|
|
516
567
|
// Wait for all actions to be mined
|
|
517
568
|
await deployer.waitForDeployments();
|
|
518
569
|
await Promise.all(txHashes.map((txHash)=>extendedClient.waitForTransactionReceipt({
|
|
@@ -576,18 +627,47 @@ export const handoverToGovernance = async (extendedClient, deployer, registryAdd
|
|
|
576
627
|
const entryQueueLengthBefore = await rollup.getEntryQueueLength();
|
|
577
628
|
const validatorCountBefore = await rollup.getActiveAttesterCount();
|
|
578
629
|
logger.info(`Adding ${validators.length} validators to the rollup`);
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
630
|
+
// Adding to the queue and flushing need to be done in two transactions
|
|
631
|
+
// if we are adding many validators.
|
|
632
|
+
if (validatorsTuples.length > 10) {
|
|
633
|
+
await deployer.l1TxUtils.sendAndMonitorTransaction({
|
|
634
|
+
to: multiAdder.toString(),
|
|
635
|
+
data: encodeFunctionData({
|
|
636
|
+
abi: MultiAdderArtifact.contractAbi,
|
|
637
|
+
functionName: 'addValidators',
|
|
638
|
+
args: [
|
|
639
|
+
validatorsTuples,
|
|
640
|
+
true
|
|
641
|
+
]
|
|
642
|
+
})
|
|
643
|
+
}, {
|
|
644
|
+
gasLimit: 40_000_000n
|
|
645
|
+
});
|
|
646
|
+
await deployer.l1TxUtils.sendAndMonitorTransaction({
|
|
647
|
+
to: rollupAddress,
|
|
648
|
+
data: encodeFunctionData({
|
|
649
|
+
abi: RollupArtifact.contractAbi,
|
|
650
|
+
functionName: 'flushEntryQueue',
|
|
651
|
+
args: []
|
|
652
|
+
})
|
|
653
|
+
}, {
|
|
654
|
+
gasLimit: 40_000_000n
|
|
655
|
+
});
|
|
656
|
+
} else {
|
|
657
|
+
await deployer.l1TxUtils.sendAndMonitorTransaction({
|
|
658
|
+
to: multiAdder.toString(),
|
|
659
|
+
data: encodeFunctionData({
|
|
660
|
+
abi: MultiAdderArtifact.contractAbi,
|
|
661
|
+
functionName: 'addValidators',
|
|
662
|
+
args: [
|
|
663
|
+
validatorsTuples,
|
|
664
|
+
false
|
|
665
|
+
]
|
|
666
|
+
})
|
|
667
|
+
}, {
|
|
668
|
+
gasLimit: 45_000_000n
|
|
669
|
+
});
|
|
670
|
+
}
|
|
591
671
|
const entryQueueLengthAfter = await rollup.getEntryQueueLength();
|
|
592
672
|
const validatorCountAfter = await rollup.getActiveAttesterCount();
|
|
593
673
|
if (entryQueueLengthAfter + validatorCountAfter < entryQueueLengthBefore + validatorCountBefore + BigInt(validators.length)) {
|
|
@@ -637,7 +717,8 @@ export const cheat_initializeFeeAssetHandler = async (extendedClient, deployer,
|
|
|
637
717
|
* @param logger - A logger object.
|
|
638
718
|
* @param args - Arguments for initialization of L1 contracts
|
|
639
719
|
* @returns A list of ETH addresses of the deployed contracts.
|
|
640
|
-
*/ export const deployL1Contracts = async (rpcUrls, account, chain, logger, args, txUtilsConfig = getL1TxUtilsConfigEnvVars())=>{
|
|
720
|
+
*/ export const deployL1Contracts = async (rpcUrls, account, chain, logger, args, txUtilsConfig = getL1TxUtilsConfigEnvVars(), createVerificationJson = false)=>{
|
|
721
|
+
logger.info(`Deploying L1 contracts with config: ${jsonStringify(args)}`);
|
|
641
722
|
validateConfig(args);
|
|
642
723
|
const l1Client = createExtendedL1Client(rpcUrls, account, chain);
|
|
643
724
|
// Deploy multicall3 if it does not exist in this network
|
|
@@ -663,23 +744,219 @@ export const cheat_initializeFeeAssetHandler = async (extendedClient, deployer,
|
|
|
663
744
|
}
|
|
664
745
|
logger.verbose(`Deploying contracts from ${account.address.toString()}`);
|
|
665
746
|
const dateProvider = new DateProvider();
|
|
666
|
-
const deployer = new L1Deployer(l1Client, args.salt, dateProvider, args.acceleratedTestDeployments, logger, txUtilsConfig);
|
|
667
|
-
const { feeAssetAddress, feeAssetHandlerAddress, stakingAssetAddress, stakingAssetHandlerAddress, registryAddress, gseAddress, governanceAddress, rewardDistributorAddress, zkPassportVerifierAddress } = await deploySharedContracts(l1Client, deployer, args, logger);
|
|
747
|
+
const deployer = new L1Deployer(l1Client, args.salt, dateProvider, args.acceleratedTestDeployments, logger, txUtilsConfig, !!createVerificationJson);
|
|
748
|
+
const { feeAssetAddress, feeAssetHandlerAddress, stakingAssetAddress, stakingAssetHandlerAddress, registryAddress, gseAddress, governanceAddress, rewardDistributorAddress, zkPassportVerifierAddress, coinIssuerAddress } = await deploySharedContracts(l1Client, deployer, args, logger);
|
|
668
749
|
const { rollup, slashFactoryAddress } = await deployRollup(l1Client, deployer, args, {
|
|
669
750
|
feeJuiceAddress: feeAssetAddress,
|
|
670
751
|
registryAddress,
|
|
671
752
|
gseAddress,
|
|
672
753
|
rewardDistributorAddress,
|
|
673
|
-
stakingAssetAddress
|
|
754
|
+
stakingAssetAddress,
|
|
755
|
+
governanceAddress
|
|
674
756
|
}, logger);
|
|
675
757
|
logger.verbose('Waiting for rollup and slash factory to be deployed');
|
|
676
758
|
await deployer.waitForDeployments();
|
|
677
759
|
// Now that the rollup has been deployed and added to the registry, transfer ownership to governance
|
|
678
|
-
await handoverToGovernance(l1Client, deployer, registryAddress, gseAddress, governanceAddress, logger, args.acceleratedTestDeployments);
|
|
760
|
+
await handoverToGovernance(l1Client, deployer, registryAddress, gseAddress, coinIssuerAddress, feeAssetAddress, governanceAddress, logger, args.acceleratedTestDeployments);
|
|
679
761
|
logger.info(`Handing over to governance complete`);
|
|
680
762
|
logger.verbose(`All transactions for L1 deployment have been mined`);
|
|
681
763
|
const l1Contracts = await RegistryContract.collectAddresses(l1Client, registryAddress, 'canonical');
|
|
682
764
|
logger.info(`Aztec L1 contracts initialized`, l1Contracts);
|
|
765
|
+
// Write verification data (constructor args + linked libraries) to file for later forge verify
|
|
766
|
+
if (createVerificationJson) {
|
|
767
|
+
try {
|
|
768
|
+
// Add Inbox / Outbox verification records (constructor args are created inside RollupCore)
|
|
769
|
+
const rollupAddr = l1Contracts.rollupAddress.toString();
|
|
770
|
+
const inboxAddr = l1Contracts.inboxAddress.toString();
|
|
771
|
+
const outboxAddr = l1Contracts.outboxAddress.toString();
|
|
772
|
+
const feeAsset = l1Contracts.feeJuiceAddress.toString();
|
|
773
|
+
const version = await rollup.getVersion();
|
|
774
|
+
const inboxCtor = encodeAbiParameters([
|
|
775
|
+
{
|
|
776
|
+
type: 'address'
|
|
777
|
+
},
|
|
778
|
+
{
|
|
779
|
+
type: 'address'
|
|
780
|
+
},
|
|
781
|
+
{
|
|
782
|
+
type: 'uint256'
|
|
783
|
+
},
|
|
784
|
+
{
|
|
785
|
+
type: 'uint256'
|
|
786
|
+
}
|
|
787
|
+
], [
|
|
788
|
+
rollupAddr,
|
|
789
|
+
feeAsset,
|
|
790
|
+
version,
|
|
791
|
+
BigInt(L1_TO_L2_MSG_SUBTREE_HEIGHT)
|
|
792
|
+
]);
|
|
793
|
+
const outboxCtor = encodeAbiParameters([
|
|
794
|
+
{
|
|
795
|
+
type: 'address'
|
|
796
|
+
},
|
|
797
|
+
{
|
|
798
|
+
type: 'uint256'
|
|
799
|
+
}
|
|
800
|
+
], [
|
|
801
|
+
rollupAddr,
|
|
802
|
+
version
|
|
803
|
+
]);
|
|
804
|
+
deployer.verificationRecords.push({
|
|
805
|
+
name: 'Inbox',
|
|
806
|
+
address: inboxAddr,
|
|
807
|
+
constructorArgsHex: inboxCtor,
|
|
808
|
+
libraries: []
|
|
809
|
+
}, {
|
|
810
|
+
name: 'Outbox',
|
|
811
|
+
address: outboxAddr,
|
|
812
|
+
constructorArgsHex: outboxCtor,
|
|
813
|
+
libraries: []
|
|
814
|
+
});
|
|
815
|
+
// Include Slasher and SlashingProposer (if deployed) in verification data
|
|
816
|
+
try {
|
|
817
|
+
const slasherAddrHex = await rollup.getSlasher();
|
|
818
|
+
const slasherAddr = EthAddress.fromString(slasherAddrHex);
|
|
819
|
+
if (!slasherAddr.isZero()) {
|
|
820
|
+
// Slasher constructor: (address _vetoer, address _governance)
|
|
821
|
+
const slasherCtor = encodeAbiParameters([
|
|
822
|
+
{
|
|
823
|
+
type: 'address'
|
|
824
|
+
},
|
|
825
|
+
{
|
|
826
|
+
type: 'address'
|
|
827
|
+
}
|
|
828
|
+
], [
|
|
829
|
+
args.slashingVetoer.toString(),
|
|
830
|
+
l1Client.account.address
|
|
831
|
+
]);
|
|
832
|
+
deployer.verificationRecords.push({
|
|
833
|
+
name: 'Slasher',
|
|
834
|
+
address: slasherAddr.toString(),
|
|
835
|
+
constructorArgsHex: slasherCtor,
|
|
836
|
+
libraries: []
|
|
837
|
+
});
|
|
838
|
+
// Proposer address is stored in Slasher.PROPOSER()
|
|
839
|
+
const proposerAddr = (await rollup.getSlashingProposerAddress()).toString();
|
|
840
|
+
// Compute constructor args matching deployment path in RollupCore
|
|
841
|
+
const computedRoundSize = BigInt(args.slashingRoundSizeInEpochs * args.aztecEpochDuration);
|
|
842
|
+
const computedQuorum = BigInt(args.slashingQuorum ?? args.slashingRoundSizeInEpochs * args.aztecEpochDuration / 2 + 1);
|
|
843
|
+
const lifetimeInRounds = BigInt(args.slashingLifetimeInRounds);
|
|
844
|
+
const executionDelayInRounds = BigInt(args.slashingExecutionDelayInRounds);
|
|
845
|
+
if (args.slasherFlavor === 'tally') {
|
|
846
|
+
const slashAmounts = [
|
|
847
|
+
args.slashAmountSmall,
|
|
848
|
+
args.slashAmountMedium,
|
|
849
|
+
args.slashAmountLarge
|
|
850
|
+
];
|
|
851
|
+
const committeeSize = BigInt(args.aztecTargetCommitteeSize);
|
|
852
|
+
const epochDuration = BigInt(args.aztecEpochDuration);
|
|
853
|
+
const slashOffsetInRounds = BigInt(args.slashingOffsetInRounds);
|
|
854
|
+
const proposerCtor = encodeAbiParameters([
|
|
855
|
+
{
|
|
856
|
+
type: 'address'
|
|
857
|
+
},
|
|
858
|
+
{
|
|
859
|
+
type: 'address'
|
|
860
|
+
},
|
|
861
|
+
{
|
|
862
|
+
type: 'uint256'
|
|
863
|
+
},
|
|
864
|
+
{
|
|
865
|
+
type: 'uint256'
|
|
866
|
+
},
|
|
867
|
+
{
|
|
868
|
+
type: 'uint256'
|
|
869
|
+
},
|
|
870
|
+
{
|
|
871
|
+
type: 'uint256'
|
|
872
|
+
},
|
|
873
|
+
{
|
|
874
|
+
type: 'uint256[3]'
|
|
875
|
+
},
|
|
876
|
+
{
|
|
877
|
+
type: 'uint256'
|
|
878
|
+
},
|
|
879
|
+
{
|
|
880
|
+
type: 'uint256'
|
|
881
|
+
},
|
|
882
|
+
{
|
|
883
|
+
type: 'uint256'
|
|
884
|
+
}
|
|
885
|
+
], [
|
|
886
|
+
rollup.address,
|
|
887
|
+
slasherAddr.toString(),
|
|
888
|
+
computedQuorum,
|
|
889
|
+
computedRoundSize,
|
|
890
|
+
lifetimeInRounds,
|
|
891
|
+
executionDelayInRounds,
|
|
892
|
+
slashAmounts,
|
|
893
|
+
committeeSize,
|
|
894
|
+
epochDuration,
|
|
895
|
+
slashOffsetInRounds
|
|
896
|
+
]);
|
|
897
|
+
deployer.verificationRecords.push({
|
|
898
|
+
name: 'TallySlashingProposer',
|
|
899
|
+
address: proposerAddr,
|
|
900
|
+
constructorArgsHex: proposerCtor,
|
|
901
|
+
libraries: []
|
|
902
|
+
});
|
|
903
|
+
} else if (args.slasherFlavor === 'empire') {
|
|
904
|
+
const proposerCtor = encodeAbiParameters([
|
|
905
|
+
{
|
|
906
|
+
type: 'address'
|
|
907
|
+
},
|
|
908
|
+
{
|
|
909
|
+
type: 'address'
|
|
910
|
+
},
|
|
911
|
+
{
|
|
912
|
+
type: 'uint256'
|
|
913
|
+
},
|
|
914
|
+
{
|
|
915
|
+
type: 'uint256'
|
|
916
|
+
},
|
|
917
|
+
{
|
|
918
|
+
type: 'uint256'
|
|
919
|
+
},
|
|
920
|
+
{
|
|
921
|
+
type: 'uint256'
|
|
922
|
+
}
|
|
923
|
+
], [
|
|
924
|
+
rollup.address,
|
|
925
|
+
slasherAddr.toString(),
|
|
926
|
+
computedQuorum,
|
|
927
|
+
computedRoundSize,
|
|
928
|
+
lifetimeInRounds,
|
|
929
|
+
executionDelayInRounds
|
|
930
|
+
]);
|
|
931
|
+
deployer.verificationRecords.push({
|
|
932
|
+
name: 'EmpireSlashingProposer',
|
|
933
|
+
address: proposerAddr,
|
|
934
|
+
constructorArgsHex: proposerCtor,
|
|
935
|
+
libraries: []
|
|
936
|
+
});
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
} catch (e) {
|
|
940
|
+
logger.warn(`Failed to add Slasher/Proposer verification records: ${String(e)}`);
|
|
941
|
+
}
|
|
942
|
+
const date = new Date();
|
|
943
|
+
const formattedDate = date.toISOString().slice(2, 19).replace(/[-T:]/g, '');
|
|
944
|
+
// Ensure the verification output directory exists
|
|
945
|
+
await mkdir(createVerificationJson, {
|
|
946
|
+
recursive: true
|
|
947
|
+
});
|
|
948
|
+
const verificationOutputPath = `${createVerificationJson}/l1-verify-${chain.id}-${formattedDate.slice(0, 6)}-${formattedDate.slice(6)}.json`;
|
|
949
|
+
const verificationData = {
|
|
950
|
+
chainId: chain.id,
|
|
951
|
+
network: networkName,
|
|
952
|
+
records: deployer.verificationRecords
|
|
953
|
+
};
|
|
954
|
+
await writeFile(verificationOutputPath, JSON.stringify(verificationData, null, 2));
|
|
955
|
+
logger.info(`Wrote L1 verification data to ${verificationOutputPath}`);
|
|
956
|
+
} catch (e) {
|
|
957
|
+
logger.warn(`Failed to write L1 verification data file: ${String(e)}`);
|
|
958
|
+
}
|
|
959
|
+
}
|
|
683
960
|
if (isAnvilTestChain(chain.id)) {
|
|
684
961
|
// @note We make a time jump PAST the very first slot to not have to deal with the edge case of the first slot.
|
|
685
962
|
// The edge case being that the genesis block is already occupying slot 0, so we cannot have another block.
|
|
@@ -712,7 +989,8 @@ export const cheat_initializeFeeAssetHandler = async (extendedClient, deployer,
|
|
|
712
989
|
slashFactoryAddress,
|
|
713
990
|
feeAssetHandlerAddress,
|
|
714
991
|
stakingAssetHandlerAddress,
|
|
715
|
-
zkPassportVerifierAddress
|
|
992
|
+
zkPassportVerifierAddress,
|
|
993
|
+
coinIssuerAddress
|
|
716
994
|
}
|
|
717
995
|
};
|
|
718
996
|
};
|
|
@@ -721,15 +999,19 @@ export class L1Deployer {
|
|
|
721
999
|
acceleratedTestDeployments;
|
|
722
1000
|
logger;
|
|
723
1001
|
txUtilsConfig;
|
|
1002
|
+
createVerificationJson;
|
|
724
1003
|
salt;
|
|
725
1004
|
txHashes;
|
|
726
1005
|
l1TxUtils;
|
|
727
|
-
|
|
1006
|
+
verificationRecords;
|
|
1007
|
+
constructor(client, maybeSalt, dateProvider = new DateProvider(), acceleratedTestDeployments = false, logger = createLogger('L1Deployer'), txUtilsConfig, createVerificationJson = false){
|
|
728
1008
|
this.client = client;
|
|
729
1009
|
this.acceleratedTestDeployments = acceleratedTestDeployments;
|
|
730
1010
|
this.logger = logger;
|
|
731
1011
|
this.txUtilsConfig = txUtilsConfig;
|
|
1012
|
+
this.createVerificationJson = createVerificationJson;
|
|
732
1013
|
this.txHashes = [];
|
|
1014
|
+
this.verificationRecords = [];
|
|
733
1015
|
this.salt = maybeSalt ? padHex(numberToHex(maybeSalt), {
|
|
734
1016
|
size: 32
|
|
735
1017
|
}) : undefined;
|
|
@@ -740,7 +1022,7 @@ export class L1Deployer {
|
|
|
740
1022
|
args
|
|
741
1023
|
});
|
|
742
1024
|
try {
|
|
743
|
-
const { txHash, address } = await deployL1Contract(this.client, params.contractAbi, params.contractBytecode, args ?? [], {
|
|
1025
|
+
const { txHash, address, deployedLibraries } = await deployL1Contract(this.client, params.contractAbi, params.contractBytecode, args ?? [], {
|
|
744
1026
|
salt: this.salt,
|
|
745
1027
|
libraries: params.libraries,
|
|
746
1028
|
logger: this.logger,
|
|
@@ -754,6 +1036,23 @@ export class L1Deployer {
|
|
|
754
1036
|
this.logger.debug(`Deployed ${params.name} at ${address}`, {
|
|
755
1037
|
args
|
|
756
1038
|
});
|
|
1039
|
+
if (this.createVerificationJson) {
|
|
1040
|
+
// Encode constructor args for verification
|
|
1041
|
+
let constructorArgsHex = '0x';
|
|
1042
|
+
try {
|
|
1043
|
+
const abiItem = params.contractAbi.find((x)=>x && x.type === 'constructor');
|
|
1044
|
+
const inputDefs = abiItem && Array.isArray(abiItem.inputs) ? abiItem.inputs : [];
|
|
1045
|
+
constructorArgsHex = inputDefs.length > 0 ? encodeAbiParameters(inputDefs, args ?? []) : '0x';
|
|
1046
|
+
} catch {
|
|
1047
|
+
constructorArgsHex = '0x';
|
|
1048
|
+
}
|
|
1049
|
+
this.verificationRecords.push({
|
|
1050
|
+
name: params.name,
|
|
1051
|
+
address: address.toString(),
|
|
1052
|
+
constructorArgsHex,
|
|
1053
|
+
libraries: deployedLibraries ?? []
|
|
1054
|
+
});
|
|
1055
|
+
}
|
|
757
1056
|
return address;
|
|
758
1057
|
} catch (error) {
|
|
759
1058
|
throw new Error(`Failed to deploy ${params.name}`, {
|
|
@@ -800,6 +1099,7 @@ export class L1Deployer {
|
|
|
800
1099
|
*/ export async function deployL1Contract(extendedClient, abi, bytecode, args = [], opts = {}) {
|
|
801
1100
|
let txHash = undefined;
|
|
802
1101
|
let resultingAddress = undefined;
|
|
1102
|
+
const deployedLibraries = [];
|
|
803
1103
|
const { salt: saltFromOpts, libraries, logger, gasLimit, acceleratedTestDeployments } = opts;
|
|
804
1104
|
let { l1TxUtils } = opts;
|
|
805
1105
|
if (!l1TxUtils) {
|
|
@@ -822,9 +1122,30 @@ export class L1Deployer {
|
|
|
822
1122
|
const lib = libraries.libraryCode[libraryName];
|
|
823
1123
|
const { libraries: _libraries, ...optsWithoutLibraries } = opts;
|
|
824
1124
|
const { address, txHash } = await deployL1Contract(extendedClient, lib.contractAbi, lib.contractBytecode, [], optsWithoutLibraries);
|
|
1125
|
+
// Log deployed library name and address for easier verification/triage
|
|
1126
|
+
logger?.verbose(`Linked library deployed`, {
|
|
1127
|
+
library: libraryName,
|
|
1128
|
+
address: address.toString(),
|
|
1129
|
+
txHash
|
|
1130
|
+
});
|
|
825
1131
|
if (txHash) {
|
|
826
1132
|
libraryTxs.push(txHash);
|
|
827
1133
|
}
|
|
1134
|
+
// Try to find the source file for this library from linkReferences
|
|
1135
|
+
let fileNameForLibrary = undefined;
|
|
1136
|
+
for(const fileName in libraries.linkReferences){
|
|
1137
|
+
if (libraries.linkReferences[fileName] && libraries.linkReferences[fileName][libraryName]) {
|
|
1138
|
+
fileNameForLibrary = fileName;
|
|
1139
|
+
break;
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
if (fileNameForLibrary) {
|
|
1143
|
+
deployedLibraries.push({
|
|
1144
|
+
file: fileNameForLibrary,
|
|
1145
|
+
contract: libraryName,
|
|
1146
|
+
address: address.toString()
|
|
1147
|
+
});
|
|
1148
|
+
}
|
|
828
1149
|
for(const linkRef in libraries.linkReferences){
|
|
829
1150
|
for(const contractName in libraries.linkReferences[linkRef]){
|
|
830
1151
|
// If the library name matches the one we just deployed, we replace it.
|
|
@@ -919,7 +1240,8 @@ export class L1Deployer {
|
|
|
919
1240
|
}
|
|
920
1241
|
return {
|
|
921
1242
|
address: EthAddress.fromString(resultingAddress),
|
|
922
|
-
txHash
|
|
1243
|
+
txHash,
|
|
1244
|
+
deployedLibraries
|
|
923
1245
|
};
|
|
924
1246
|
}
|
|
925
1247
|
export function getExpectedAddress(abi, bytecode, args, salt) {
|