@aztec/ethereum 4.0.0-nightly.20250907 → 4.0.0-nightly.20260108
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/account.d.ts +1 -1
- package/dest/chain.d.ts +1 -1
- package/dest/client.d.ts +2 -2
- package/dest/client.d.ts.map +1 -1
- package/dest/client.js +6 -2
- package/dest/config.d.ts +18 -46
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +40 -285
- package/dest/constants.d.ts +1 -1
- package/dest/contracts/empire_base.d.ts +8 -6
- package/dest/contracts/empire_base.d.ts.map +1 -1
- package/dest/contracts/empire_base.js +1 -1
- package/dest/contracts/empire_slashing_proposer.d.ts +8 -6
- package/dest/contracts/empire_slashing_proposer.d.ts.map +1 -1
- package/dest/contracts/empire_slashing_proposer.js +18 -3
- package/dest/contracts/errors.d.ts +1 -1
- package/dest/contracts/errors.d.ts.map +1 -1
- package/dest/contracts/fee_asset_handler.d.ts +4 -4
- package/dest/contracts/fee_asset_handler.d.ts.map +1 -1
- package/dest/contracts/fee_juice.d.ts +1 -1
- package/dest/contracts/fee_juice.d.ts.map +1 -1
- package/dest/contracts/governance.d.ts +16 -16
- package/dest/contracts/governance.d.ts.map +1 -1
- package/dest/contracts/governance.js +7 -3
- package/dest/contracts/governance_proposer.d.ts +7 -6
- package/dest/contracts/governance_proposer.d.ts.map +1 -1
- package/dest/contracts/governance_proposer.js +400 -12
- package/dest/contracts/gse.d.ts +1 -1
- package/dest/contracts/gse.d.ts.map +1 -1
- package/dest/contracts/inbox.d.ts +7 -3
- package/dest/contracts/inbox.d.ts.map +1 -1
- package/dest/contracts/inbox.js +4 -0
- package/dest/contracts/index.d.ts +1 -1
- package/dest/contracts/multicall.d.ts +5 -7
- package/dest/contracts/multicall.d.ts.map +1 -1
- package/dest/contracts/multicall.js +6 -4
- package/dest/contracts/registry.d.ts +1 -1
- package/dest/contracts/registry.d.ts.map +1 -1
- package/dest/contracts/rollup.d.ts +169 -118
- package/dest/contracts/rollup.d.ts.map +1 -1
- package/dest/contracts/rollup.js +714 -243
- package/dest/contracts/slasher_contract.d.ts +11 -1
- package/dest/contracts/slasher_contract.d.ts.map +1 -1
- package/dest/contracts/slasher_contract.js +18 -0
- package/dest/contracts/tally_slashing_proposer.d.ts +15 -7
- package/dest/contracts/tally_slashing_proposer.d.ts.map +1 -1
- package/dest/contracts/tally_slashing_proposer.js +15 -5
- package/dest/contracts/utils.d.ts +1 -1
- package/dest/deploy_aztec_l1_contracts.d.ts +247 -0
- package/dest/deploy_aztec_l1_contracts.d.ts.map +1 -0
- package/dest/deploy_aztec_l1_contracts.js +336 -0
- package/dest/deploy_l1_contract.d.ts +68 -0
- package/dest/deploy_l1_contract.d.ts.map +1 -0
- package/dest/deploy_l1_contract.js +312 -0
- package/dest/eth-signer/eth-signer.d.ts +1 -1
- package/dest/eth-signer/index.d.ts +1 -1
- package/dest/forwarder_proxy.d.ts +32 -0
- package/dest/forwarder_proxy.d.ts.map +1 -0
- package/dest/forwarder_proxy.js +93 -0
- package/dest/l1_artifacts.d.ts +17733 -6280
- package/dest/l1_artifacts.d.ts.map +1 -1
- package/dest/l1_artifacts.js +10 -5
- package/dest/l1_contract_addresses.d.ts +8 -4
- package/dest/l1_contract_addresses.d.ts.map +1 -1
- package/dest/l1_contract_addresses.js +5 -4
- package/dest/l1_reader.d.ts +4 -2
- package/dest/l1_reader.d.ts.map +1 -1
- package/dest/l1_reader.js +7 -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 +96 -0
- package/dest/l1_tx_utils/constants.d.ts +12 -0
- package/dest/l1_tx_utils/constants.d.ts.map +1 -0
- package/dest/l1_tx_utils/constants.js +39 -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/fee-strategies/index.d.ts +10 -0
- package/dest/l1_tx_utils/fee-strategies/index.d.ts.map +1 -0
- package/dest/l1_tx_utils/fee-strategies/index.js +12 -0
- package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts +8 -0
- package/dest/l1_tx_utils/fee-strategies/p75_competitive.d.ts.map +1 -0
- package/dest/l1_tx_utils/fee-strategies/p75_competitive.js +129 -0
- package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.d.ts +23 -0
- package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.d.ts.map +1 -0
- package/dest/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.js +191 -0
- package/dest/l1_tx_utils/fee-strategies/types.d.ts +51 -0
- package/dest/l1_tx_utils/fee-strategies/types.d.ts.map +1 -0
- package/dest/l1_tx_utils/fee-strategies/types.js +3 -0
- package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts +41 -0
- package/dest/l1_tx_utils/forwarder_l1_tx_utils.d.ts.map +1 -0
- package/dest/l1_tx_utils/forwarder_l1_tx_utils.js +48 -0
- package/dest/l1_tx_utils/index-blobs.d.ts +3 -0
- package/dest/l1_tx_utils/index-blobs.d.ts.map +1 -0
- package/dest/l1_tx_utils/index-blobs.js +2 -0
- package/dest/l1_tx_utils/index.d.ts +12 -0
- package/dest/l1_tx_utils/index.d.ts.map +1 -0
- package/dest/l1_tx_utils/index.js +12 -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_fee_analyzer.d.ts +233 -0
- package/dest/l1_tx_utils/l1_fee_analyzer.d.ts.map +1 -0
- package/dest/l1_tx_utils/l1_fee_analyzer.js +506 -0
- package/dest/l1_tx_utils/l1_tx_utils.d.ts +94 -0
- package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -0
- package/dest/l1_tx_utils/l1_tx_utils.js +623 -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 +83 -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 +323 -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/l1_types.d.ts +1 -1
- package/dest/publisher_manager.d.ts +8 -3
- package/dest/publisher_manager.d.ts.map +1 -1
- package/dest/publisher_manager.js +36 -8
- package/dest/queries.d.ts +1 -1
- package/dest/queries.d.ts.map +1 -1
- package/dest/queries.js +20 -14
- package/dest/test/chain_monitor.d.ts +29 -22
- package/dest/test/chain_monitor.d.ts.map +1 -1
- package/dest/test/chain_monitor.js +81 -38
- package/dest/test/delayed_tx_utils.d.ts +3 -3
- 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 +36 -14
- package/dest/test/eth_cheat_codes.d.ts.map +1 -1
- package/dest/test/eth_cheat_codes.js +126 -31
- package/dest/test/eth_cheat_codes_with_state.d.ts +1 -1
- package/dest/test/eth_cheat_codes_with_state.d.ts.map +1 -1
- package/dest/test/index.d.ts +1 -1
- package/dest/test/rollup_cheat_codes.d.ts +23 -20
- package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
- package/dest/test/rollup_cheat_codes.js +82 -43
- package/dest/test/start_anvil.d.ts +4 -1
- package/dest/test/start_anvil.d.ts.map +1 -1
- package/dest/test/start_anvil.js +2 -1
- package/dest/test/tx_delayer.d.ts +1 -1
- package/dest/test/tx_delayer.d.ts.map +1 -1
- package/dest/test/tx_delayer.js +4 -3
- package/dest/test/upgrade_utils.d.ts +1 -1
- package/dest/test/upgrade_utils.d.ts.map +1 -1
- package/dest/test/upgrade_utils.js +3 -2
- package/dest/types.d.ts +57 -2
- package/dest/types.d.ts.map +1 -1
- package/dest/utils.d.ts +15 -3
- package/dest/utils.d.ts.map +1 -1
- package/dest/utils.js +28 -161
- package/dest/zkPassportVerifierAddress.d.ts +1 -1
- package/dest/zkPassportVerifierAddress.js +1 -1
- package/package.json +33 -14
- package/src/client.ts +3 -3
- package/src/config.ts +49 -358
- package/src/contracts/empire_base.ts +7 -6
- package/src/contracts/empire_slashing_proposer.ts +23 -8
- package/src/contracts/fee_asset_handler.ts +1 -1
- package/src/contracts/governance.ts +3 -3
- package/src/contracts/governance_proposer.ts +19 -9
- package/src/contracts/inbox.ts +7 -2
- package/src/contracts/multicall.ts +12 -10
- package/src/contracts/rollup.ts +374 -236
- package/src/contracts/slasher_contract.ts +22 -0
- package/src/contracts/tally_slashing_proposer.ts +21 -9
- package/src/deploy_aztec_l1_contracts.ts +557 -0
- package/src/deploy_l1_contract.ts +362 -0
- package/src/forwarder_proxy.ts +108 -0
- package/src/l1_artifacts.ts +14 -6
- package/src/l1_contract_addresses.ts +24 -20
- package/src/l1_reader.ts +10 -2
- package/src/l1_tx_utils/README.md +177 -0
- package/src/l1_tx_utils/config.ts +161 -0
- package/src/l1_tx_utils/constants.ts +29 -0
- package/src/l1_tx_utils/factory.ts +64 -0
- package/src/l1_tx_utils/fee-strategies/index.ts +22 -0
- package/src/l1_tx_utils/fee-strategies/p75_competitive.ts +163 -0
- package/src/l1_tx_utils/fee-strategies/p75_competitive_blob_txs_only.ts +245 -0
- package/src/l1_tx_utils/fee-strategies/types.ts +56 -0
- package/src/l1_tx_utils/forwarder_l1_tx_utils.ts +119 -0
- package/src/l1_tx_utils/index-blobs.ts +2 -0
- package/src/l1_tx_utils/index.ts +14 -0
- package/src/l1_tx_utils/interfaces.ts +86 -0
- package/src/l1_tx_utils/l1_fee_analyzer.ts +803 -0
- package/src/l1_tx_utils/l1_tx_utils.ts +738 -0
- package/src/l1_tx_utils/l1_tx_utils_with_blobs.ts +77 -0
- package/src/l1_tx_utils/readonly_l1_tx_utils.ts +419 -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 +24 -10
- package/src/test/chain_monitor.ts +102 -44
- package/src/test/delayed_tx_utils.ts +2 -2
- package/src/test/eth_cheat_codes.ts +150 -31
- package/src/test/rollup_cheat_codes.ts +95 -53
- package/src/test/start_anvil.ts +4 -0
- package/src/test/tx_delayer.ts +5 -3
- package/src/test/upgrade_utils.ts +3 -2
- package/src/types.ts +62 -0
- package/src/utils.ts +41 -184
- package/src/zkPassportVerifierAddress.ts +1 -1
- package/dest/deploy_l1_contracts.d.ts +0 -211
- package/dest/deploy_l1_contracts.d.ts.map +0 -1
- package/dest/deploy_l1_contracts.js +0 -1267
- package/dest/index.d.ts +0 -18
- package/dest/index.d.ts.map +0 -1
- package/dest/index.js +0 -17
- package/dest/l1_tx_utils.d.ts +0 -250
- package/dest/l1_tx_utils.d.ts.map +0 -1
- package/dest/l1_tx_utils.js +0 -826
- package/dest/l1_tx_utils_with_blobs.d.ts +0 -19
- package/dest/l1_tx_utils_with_blobs.d.ts.map +0 -1
- package/dest/l1_tx_utils_with_blobs.js +0 -85
- package/src/deploy_l1_contracts.ts +0 -1596
- package/src/index.ts +0 -17
- package/src/l1_tx_utils.ts +0 -1105
- package/src/l1_tx_utils_with_blobs.ts +0 -144
|
@@ -1,1267 +0,0 @@
|
|
|
1
|
-
import { L1_TO_L2_MSG_SUBTREE_HEIGHT } from '@aztec/constants';
|
|
2
|
-
import { getActiveNetworkName } from '@aztec/foundation/config';
|
|
3
|
-
import { keccak256String } from '@aztec/foundation/crypto';
|
|
4
|
-
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
5
|
-
import { jsonStringify } from '@aztec/foundation/json-rpc';
|
|
6
|
-
import { createLogger } from '@aztec/foundation/log';
|
|
7
|
-
import { DateProvider } from '@aztec/foundation/timer';
|
|
8
|
-
import { mkdir, writeFile } from 'fs/promises';
|
|
9
|
-
import { concatHex, encodeAbiParameters, encodeDeployData, encodeFunctionData, getAddress, getContract, getContractAddress, numberToHex, padHex } from 'viem';
|
|
10
|
-
import { foundry } from 'viem/chains';
|
|
11
|
-
import { isAnvilTestChain } from './chain.js';
|
|
12
|
-
import { createExtendedL1Client } from './client.js';
|
|
13
|
-
import { getEntryQueueConfig, getGSEConfiguration, getGovernanceConfiguration, getRewardBoostConfig, getRewardConfig, validateConfig } from './config.js';
|
|
14
|
-
import { GSEContract } from './contracts/gse.js';
|
|
15
|
-
import { deployMulticall3 } from './contracts/multicall.js';
|
|
16
|
-
import { RegistryContract } from './contracts/registry.js';
|
|
17
|
-
import { RollupContract, SlashingProposerType } from './contracts/rollup.js';
|
|
18
|
-
import { CoinIssuerArtifact, FeeAssetArtifact, FeeAssetHandlerArtifact, GSEArtifact, GovernanceArtifact, GovernanceProposerArtifact, MultiAdderArtifact, RegisterNewRollupVersionPayloadArtifact, RegistryArtifact, RollupArtifact, SlashFactoryArtifact, StakingAssetArtifact, StakingAssetHandlerArtifact, l1ArtifactsVerifiers, mockVerifiers } from './l1_artifacts.js';
|
|
19
|
-
import { createL1TxUtilsFromViemWallet, getL1TxUtilsConfigEnvVars } from './l1_tx_utils.js';
|
|
20
|
-
import { formatViemError } from './utils.js';
|
|
21
|
-
import { ZK_PASSPORT_DOMAIN, ZK_PASSPORT_SCOPE, ZK_PASSPORT_VERIFIER_ADDRESS } from './zkPassportVerifierAddress.js';
|
|
22
|
-
export const DEPLOYER_ADDRESS = '0x4e59b44847b379578588920cA78FbF26c0B4956C';
|
|
23
|
-
const networkName = getActiveNetworkName();
|
|
24
|
-
export const deploySharedContracts = async (l1Client, deployer, args, logger)=>{
|
|
25
|
-
logger.info(`Deploying shared contracts for network configration: ${networkName}`);
|
|
26
|
-
const txHashes = [];
|
|
27
|
-
const feeAssetAddress = await deployer.deploy(FeeAssetArtifact, [
|
|
28
|
-
'FeeJuice',
|
|
29
|
-
'FEE',
|
|
30
|
-
l1Client.account.address
|
|
31
|
-
]);
|
|
32
|
-
logger.verbose(`Deployed Fee Asset at ${feeAssetAddress}`);
|
|
33
|
-
const stakingAssetAddress = await deployer.deploy(StakingAssetArtifact, [
|
|
34
|
-
'Staking',
|
|
35
|
-
'STK',
|
|
36
|
-
l1Client.account.address
|
|
37
|
-
]);
|
|
38
|
-
logger.verbose(`Deployed Staking Asset at ${stakingAssetAddress}`);
|
|
39
|
-
const gseConfiguration = getGSEConfiguration(networkName);
|
|
40
|
-
const gseAddress = await deployer.deploy(GSEArtifact, [
|
|
41
|
-
l1Client.account.address,
|
|
42
|
-
stakingAssetAddress.toString(),
|
|
43
|
-
gseConfiguration.activationThreshold,
|
|
44
|
-
gseConfiguration.ejectionThreshold
|
|
45
|
-
]);
|
|
46
|
-
logger.verbose(`Deployed GSE at ${gseAddress}`);
|
|
47
|
-
const registryAddress = await deployer.deploy(RegistryArtifact, [
|
|
48
|
-
l1Client.account.address,
|
|
49
|
-
feeAssetAddress.toString()
|
|
50
|
-
]);
|
|
51
|
-
logger.verbose(`Deployed Registry at ${registryAddress}`);
|
|
52
|
-
const governanceProposerAddress = await deployer.deploy(GovernanceProposerArtifact, [
|
|
53
|
-
registryAddress.toString(),
|
|
54
|
-
gseAddress.toString(),
|
|
55
|
-
BigInt(args.governanceProposerQuorum ?? args.governanceProposerRoundSize / 2 + 1),
|
|
56
|
-
BigInt(args.governanceProposerRoundSize)
|
|
57
|
-
]);
|
|
58
|
-
logger.verbose(`Deployed GovernanceProposer at ${governanceProposerAddress}`);
|
|
59
|
-
// @note @LHerskind the assets are expected to be the same at some point, but for better
|
|
60
|
-
// configurability they are different for now.
|
|
61
|
-
const governanceAddress = await deployer.deploy(GovernanceArtifact, [
|
|
62
|
-
stakingAssetAddress.toString(),
|
|
63
|
-
governanceProposerAddress.toString(),
|
|
64
|
-
gseAddress.toString(),
|
|
65
|
-
getGovernanceConfiguration(networkName)
|
|
66
|
-
]);
|
|
67
|
-
logger.verbose(`Deployed Governance at ${governanceAddress}`);
|
|
68
|
-
let needToSetGovernance = false;
|
|
69
|
-
const existingCode = await l1Client.getCode({
|
|
70
|
-
address: gseAddress.toString()
|
|
71
|
-
});
|
|
72
|
-
if (!existingCode || existingCode === '0x') {
|
|
73
|
-
needToSetGovernance = true;
|
|
74
|
-
} else {
|
|
75
|
-
const gseContract = getContract({
|
|
76
|
-
address: getAddress(gseAddress.toString()),
|
|
77
|
-
abi: GSEArtifact.contractAbi,
|
|
78
|
-
client: l1Client
|
|
79
|
-
});
|
|
80
|
-
const existingGovernance = await gseContract.read.getGovernance();
|
|
81
|
-
if (EthAddress.fromString(existingGovernance).equals(EthAddress.ZERO)) {
|
|
82
|
-
needToSetGovernance = true;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
if (needToSetGovernance) {
|
|
86
|
-
const { txHash } = await deployer.sendTransaction({
|
|
87
|
-
to: gseAddress.toString(),
|
|
88
|
-
data: encodeFunctionData({
|
|
89
|
-
abi: GSEArtifact.contractAbi,
|
|
90
|
-
functionName: 'setGovernance',
|
|
91
|
-
args: [
|
|
92
|
-
governanceAddress.toString()
|
|
93
|
-
]
|
|
94
|
-
})
|
|
95
|
-
}, {
|
|
96
|
-
gasLimit: 100_000n
|
|
97
|
-
});
|
|
98
|
-
logger.verbose(`Set governance on GSE in ${txHash}`);
|
|
99
|
-
txHashes.push(txHash);
|
|
100
|
-
}
|
|
101
|
-
const coinIssuerAddress = await deployer.deploy(CoinIssuerArtifact, [
|
|
102
|
-
feeAssetAddress.toString(),
|
|
103
|
-
1_000_000n * 10n ** 18n,
|
|
104
|
-
l1Client.account.address
|
|
105
|
-
]);
|
|
106
|
-
logger.verbose(`Deployed CoinIssuer at ${coinIssuerAddress}`);
|
|
107
|
-
logger.verbose(`Waiting for deployments to complete`);
|
|
108
|
-
await deployer.waitForDeployments();
|
|
109
|
-
// Registry ownership will be transferred to governance later, after rollup is added
|
|
110
|
-
let feeAssetHandlerAddress = undefined;
|
|
111
|
-
let stakingAssetHandlerAddress = undefined;
|
|
112
|
-
let zkPassportVerifierAddress = undefined;
|
|
113
|
-
// Only if not on mainnet will we deploy the handlers
|
|
114
|
-
if (l1Client.chain.id !== 1) {
|
|
115
|
-
/* -------------------------------------------------------------------------- */ /* CHEAT CODES START HERE */ /* -------------------------------------------------------------------------- */ feeAssetHandlerAddress = await deployer.deploy(FeeAssetHandlerArtifact, [
|
|
116
|
-
l1Client.account.address,
|
|
117
|
-
feeAssetAddress.toString(),
|
|
118
|
-
BigInt(1000n * 10n ** 18n)
|
|
119
|
-
]);
|
|
120
|
-
logger.verbose(`Deployed FeeAssetHandler at ${feeAssetHandlerAddress}`);
|
|
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
|
-
}
|
|
136
|
-
// Only if on sepolia will we deploy the staking asset handler
|
|
137
|
-
// Should not be deployed to devnet since it would cause caos with sequencers there etc.
|
|
138
|
-
if ([
|
|
139
|
-
11155111,
|
|
140
|
-
foundry.id
|
|
141
|
-
].includes(l1Client.chain.id)) {
|
|
142
|
-
const AMIN = EthAddress.fromString('0x3b218d0F26d15B36C715cB06c949210a0d630637');
|
|
143
|
-
zkPassportVerifierAddress = await getZkPassportVerifierAddress(deployer, args);
|
|
144
|
-
const [domain, scope] = getZkPassportScopes(args);
|
|
145
|
-
const stakingAssetHandlerDeployArgs = {
|
|
146
|
-
owner: l1Client.account.address,
|
|
147
|
-
stakingAsset: stakingAssetAddress.toString(),
|
|
148
|
-
registry: registryAddress.toString(),
|
|
149
|
-
withdrawer: AMIN.toString(),
|
|
150
|
-
mintInterval: BigInt(60 * 60 * 24),
|
|
151
|
-
depositsPerMint: BigInt(10),
|
|
152
|
-
depositMerkleRoot: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
153
|
-
zkPassportVerifier: zkPassportVerifierAddress.toString(),
|
|
154
|
-
unhinged: [
|
|
155
|
-
AMIN.toString()
|
|
156
|
-
],
|
|
157
|
-
// Scopes
|
|
158
|
-
domain: domain,
|
|
159
|
-
scope: scope,
|
|
160
|
-
// Skip checks
|
|
161
|
-
skipBindCheck: args.zkPassportArgs?.mockZkPassportVerifier ?? false,
|
|
162
|
-
skipMerkleCheck: true
|
|
163
|
-
};
|
|
164
|
-
stakingAssetHandlerAddress = await deployer.deploy(StakingAssetHandlerArtifact, [
|
|
165
|
-
stakingAssetHandlerDeployArgs
|
|
166
|
-
]);
|
|
167
|
-
logger.verbose(`Deployed StakingAssetHandler at ${stakingAssetHandlerAddress}`);
|
|
168
|
-
const { txHash: stakingMinterTxHash } = await deployer.sendTransaction({
|
|
169
|
-
to: stakingAssetAddress.toString(),
|
|
170
|
-
data: encodeFunctionData({
|
|
171
|
-
abi: StakingAssetArtifact.contractAbi,
|
|
172
|
-
functionName: 'addMinter',
|
|
173
|
-
args: [
|
|
174
|
-
stakingAssetHandlerAddress.toString()
|
|
175
|
-
]
|
|
176
|
-
})
|
|
177
|
-
});
|
|
178
|
-
logger.verbose(`Added staking asset handler ${stakingAssetHandlerAddress} as minter on staking asset in ${stakingMinterTxHash}`);
|
|
179
|
-
txHashes.push(stakingMinterTxHash);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
/* -------------------------------------------------------------------------- */ /* CHEAT CODES END HERE */ /* -------------------------------------------------------------------------- */ logger.verbose(`Waiting for deployments to complete`);
|
|
183
|
-
await deployer.waitForDeployments();
|
|
184
|
-
await Promise.all(txHashes.map((txHash)=>l1Client.waitForTransactionReceipt({
|
|
185
|
-
hash: txHash
|
|
186
|
-
})));
|
|
187
|
-
logger.verbose(`Deployed shared contracts`);
|
|
188
|
-
const registry = new RegistryContract(l1Client, registryAddress);
|
|
189
|
-
/* -------------------------------------------------------------------------- */ /* FUND REWARD DISTRIBUTOR START */ /* -------------------------------------------------------------------------- */ const rewardDistributorAddress = await registry.getRewardDistributor();
|
|
190
|
-
const blockReward = getRewardConfig(networkName).blockReward;
|
|
191
|
-
const funding = blockReward * 200000n;
|
|
192
|
-
const { txHash: fundRewardDistributorTxHash } = await deployer.sendTransaction({
|
|
193
|
-
to: feeAssetAddress.toString(),
|
|
194
|
-
data: encodeFunctionData({
|
|
195
|
-
abi: FeeAssetArtifact.contractAbi,
|
|
196
|
-
functionName: 'mint',
|
|
197
|
-
args: [
|
|
198
|
-
rewardDistributorAddress.toString(),
|
|
199
|
-
funding
|
|
200
|
-
]
|
|
201
|
-
})
|
|
202
|
-
});
|
|
203
|
-
logger.verbose(`Funded reward distributor with ${funding} fee asset in ${fundRewardDistributorTxHash}`);
|
|
204
|
-
/* -------------------------------------------------------------------------- */ /* FUND REWARD DISTRIBUTOR STOP */ /* -------------------------------------------------------------------------- */ return {
|
|
205
|
-
feeAssetAddress,
|
|
206
|
-
feeAssetHandlerAddress,
|
|
207
|
-
stakingAssetAddress,
|
|
208
|
-
stakingAssetHandlerAddress,
|
|
209
|
-
zkPassportVerifierAddress,
|
|
210
|
-
registryAddress,
|
|
211
|
-
gseAddress,
|
|
212
|
-
governanceAddress,
|
|
213
|
-
governanceProposerAddress,
|
|
214
|
-
coinIssuerAddress,
|
|
215
|
-
rewardDistributorAddress: await registry.getRewardDistributor()
|
|
216
|
-
};
|
|
217
|
-
};
|
|
218
|
-
const getZkPassportVerifierAddress = async (deployer, args)=>{
|
|
219
|
-
if (args.zkPassportArgs?.mockZkPassportVerifier) {
|
|
220
|
-
return await deployer.deploy(mockVerifiers.mockZkPassportVerifier);
|
|
221
|
-
}
|
|
222
|
-
return ZK_PASSPORT_VERIFIER_ADDRESS;
|
|
223
|
-
};
|
|
224
|
-
/**
|
|
225
|
-
* Get the zk passport scopes - default to testnet values if not provided
|
|
226
|
-
* @param args - The deployment arguments
|
|
227
|
-
* @returns The zk passport scopes
|
|
228
|
-
*/ const getZkPassportScopes = (args)=>{
|
|
229
|
-
const domain = args.zkPassportArgs?.zkPassportDomain ?? ZK_PASSPORT_DOMAIN;
|
|
230
|
-
const scope = args.zkPassportArgs?.zkPassportScope ?? ZK_PASSPORT_SCOPE;
|
|
231
|
-
return [
|
|
232
|
-
domain,
|
|
233
|
-
scope
|
|
234
|
-
];
|
|
235
|
-
};
|
|
236
|
-
/**
|
|
237
|
-
* Deploys a new rollup, using the existing canonical version to derive certain values (addresses of assets etc).
|
|
238
|
-
* @param clients - The L1 clients.
|
|
239
|
-
* @param args - The deployment arguments.
|
|
240
|
-
* @param registryAddress - The address of the registry.
|
|
241
|
-
* @param logger - The logger.
|
|
242
|
-
* @param txUtilsConfig - The L1 tx utils config.
|
|
243
|
-
*/ export const deployRollupForUpgrade = async (extendedClient, args, registryAddress, logger, txUtilsConfig)=>{
|
|
244
|
-
const deployer = new L1Deployer(extendedClient, args.salt, undefined, args.acceleratedTestDeployments, logger, txUtilsConfig);
|
|
245
|
-
const addresses = await RegistryContract.collectAddresses(extendedClient, registryAddress, 'canonical');
|
|
246
|
-
const { rollup, slashFactoryAddress } = await deployRollup(extendedClient, deployer, args, addresses, logger);
|
|
247
|
-
await deployer.waitForDeployments();
|
|
248
|
-
return {
|
|
249
|
-
rollup,
|
|
250
|
-
slashFactoryAddress
|
|
251
|
-
};
|
|
252
|
-
};
|
|
253
|
-
export const deploySlashFactory = async (deployer, rollupAddress, logger)=>{
|
|
254
|
-
const slashFactoryAddress = await deployer.deploy(SlashFactoryArtifact, [
|
|
255
|
-
rollupAddress
|
|
256
|
-
]);
|
|
257
|
-
logger.verbose(`Deployed SlashFactory at ${slashFactoryAddress}`);
|
|
258
|
-
return slashFactoryAddress;
|
|
259
|
-
};
|
|
260
|
-
export const deployUpgradePayload = async (deployer, addresses)=>{
|
|
261
|
-
const payloadAddress = await deployer.deploy(RegisterNewRollupVersionPayloadArtifact, [
|
|
262
|
-
addresses.registryAddress.toString(),
|
|
263
|
-
addresses.rollupAddress.toString()
|
|
264
|
-
]);
|
|
265
|
-
return payloadAddress;
|
|
266
|
-
};
|
|
267
|
-
function slasherFlavorToSolidityEnum(flavor) {
|
|
268
|
-
switch(flavor){
|
|
269
|
-
case 'none':
|
|
270
|
-
return SlashingProposerType.None.valueOf();
|
|
271
|
-
case 'tally':
|
|
272
|
-
return SlashingProposerType.Tally.valueOf();
|
|
273
|
-
case 'empire':
|
|
274
|
-
return SlashingProposerType.Empire.valueOf();
|
|
275
|
-
default:
|
|
276
|
-
{
|
|
277
|
-
const _ = flavor;
|
|
278
|
-
throw new Error(`Unexpected slasher flavor ${flavor}`);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
/**
|
|
283
|
-
* Deploys a new rollup contract, funds and initializes the fee juice portal, and initializes the validator set.
|
|
284
|
-
*/ export const deployRollup = async (extendedClient, deployer, args, addresses, logger)=>{
|
|
285
|
-
if (!addresses.gseAddress) {
|
|
286
|
-
throw new Error('GSE address is required when deploying');
|
|
287
|
-
}
|
|
288
|
-
logger.info(`Deploying rollup using network configuration: ${networkName}`);
|
|
289
|
-
const txHashes = [];
|
|
290
|
-
let epochProofVerifier = EthAddress.ZERO;
|
|
291
|
-
if (args.realVerifier) {
|
|
292
|
-
epochProofVerifier = await deployer.deploy(l1ArtifactsVerifiers.honkVerifier);
|
|
293
|
-
logger.verbose(`Rollup will use the real verifier at ${epochProofVerifier}`);
|
|
294
|
-
} else {
|
|
295
|
-
epochProofVerifier = await deployer.deploy(mockVerifiers.mockVerifier);
|
|
296
|
-
logger.verbose(`Rollup will use the mock verifier at ${epochProofVerifier}`);
|
|
297
|
-
}
|
|
298
|
-
const rewardConfig = {
|
|
299
|
-
...getRewardConfig(networkName),
|
|
300
|
-
rewardDistributor: addresses.rewardDistributorAddress.toString()
|
|
301
|
-
};
|
|
302
|
-
const rollupConfigArgs = {
|
|
303
|
-
aztecSlotDuration: BigInt(args.aztecSlotDuration),
|
|
304
|
-
aztecEpochDuration: BigInt(args.aztecEpochDuration),
|
|
305
|
-
targetCommitteeSize: BigInt(args.aztecTargetCommitteeSize),
|
|
306
|
-
aztecProofSubmissionEpochs: BigInt(args.aztecProofSubmissionEpochs),
|
|
307
|
-
slashingQuorum: BigInt(args.slashingQuorum ?? args.slashingRoundSizeInEpochs * args.aztecEpochDuration / 2 + 1),
|
|
308
|
-
slashingRoundSize: BigInt(args.slashingRoundSizeInEpochs * args.aztecEpochDuration),
|
|
309
|
-
slashingLifetimeInRounds: BigInt(args.slashingLifetimeInRounds),
|
|
310
|
-
slashingExecutionDelayInRounds: BigInt(args.slashingExecutionDelayInRounds),
|
|
311
|
-
slashingVetoer: args.slashingVetoer.toString(),
|
|
312
|
-
manaTarget: args.manaTarget,
|
|
313
|
-
provingCostPerMana: args.provingCostPerMana,
|
|
314
|
-
rewardConfig: rewardConfig,
|
|
315
|
-
version: 0,
|
|
316
|
-
rewardBoostConfig: getRewardBoostConfig(networkName),
|
|
317
|
-
stakingQueueConfig: getEntryQueueConfig(networkName),
|
|
318
|
-
exitDelaySeconds: BigInt(args.exitDelaySeconds),
|
|
319
|
-
slasherFlavor: slasherFlavorToSolidityEnum(args.slasherFlavor),
|
|
320
|
-
slashingOffsetInRounds: BigInt(args.slashingOffsetInRounds),
|
|
321
|
-
slashAmounts: [
|
|
322
|
-
args.slashAmountSmall,
|
|
323
|
-
args.slashAmountMedium,
|
|
324
|
-
args.slashAmountLarge
|
|
325
|
-
]
|
|
326
|
-
};
|
|
327
|
-
const genesisStateArgs = {
|
|
328
|
-
vkTreeRoot: args.vkTreeRoot.toString(),
|
|
329
|
-
protocolContractTreeRoot: args.protocolContractTreeRoot.toString(),
|
|
330
|
-
genesisArchiveRoot: args.genesisArchiveRoot.toString()
|
|
331
|
-
};
|
|
332
|
-
// Until there is an actual chain-id for the version, we will just draw a random value.
|
|
333
|
-
// TODO(https://linear.app/aztec-labs/issue/TMNT-139/version-at-deployment)
|
|
334
|
-
rollupConfigArgs.version = Buffer.from(keccak256String(jsonStringify({
|
|
335
|
-
rollupConfigArgs,
|
|
336
|
-
genesisStateArgs
|
|
337
|
-
}))).readUint32BE(0);
|
|
338
|
-
logger.verbose(`Rollup config args`, rollupConfigArgs);
|
|
339
|
-
const rollupArgs = [
|
|
340
|
-
addresses.feeJuiceAddress.toString(),
|
|
341
|
-
addresses.stakingAssetAddress.toString(),
|
|
342
|
-
addresses.gseAddress.toString(),
|
|
343
|
-
epochProofVerifier.toString(),
|
|
344
|
-
extendedClient.account.address,
|
|
345
|
-
genesisStateArgs,
|
|
346
|
-
rollupConfigArgs
|
|
347
|
-
];
|
|
348
|
-
const rollupAddress = await deployer.deploy(RollupArtifact, rollupArgs, {
|
|
349
|
-
gasLimit: 15_000_000n
|
|
350
|
-
});
|
|
351
|
-
logger.verbose(`Deployed Rollup at ${rollupAddress}`, rollupConfigArgs);
|
|
352
|
-
const rollupContract = new RollupContract(extendedClient, rollupAddress);
|
|
353
|
-
await deployer.waitForDeployments();
|
|
354
|
-
logger.verbose(`All core contracts have been deployed`);
|
|
355
|
-
if (args.feeJuicePortalInitialBalance && args.feeJuicePortalInitialBalance > 0n) {
|
|
356
|
-
const feeJuicePortalAddress = await rollupContract.getFeeJuicePortal();
|
|
357
|
-
// In fast mode, use the L1TxUtils to send transactions with nonce management
|
|
358
|
-
const { txHash: mintTxHash } = await deployer.sendTransaction({
|
|
359
|
-
to: addresses.feeJuiceAddress.toString(),
|
|
360
|
-
data: encodeFunctionData({
|
|
361
|
-
abi: FeeAssetArtifact.contractAbi,
|
|
362
|
-
functionName: 'mint',
|
|
363
|
-
args: [
|
|
364
|
-
feeJuicePortalAddress.toString(),
|
|
365
|
-
args.feeJuicePortalInitialBalance
|
|
366
|
-
]
|
|
367
|
-
})
|
|
368
|
-
});
|
|
369
|
-
logger.verbose(`Funding fee juice portal with ${args.feeJuicePortalInitialBalance} fee juice in ${mintTxHash} (accelerated test deployments)`);
|
|
370
|
-
txHashes.push(mintTxHash);
|
|
371
|
-
}
|
|
372
|
-
const slashFactoryAddress = await deployer.deploy(SlashFactoryArtifact, [
|
|
373
|
-
rollupAddress.toString()
|
|
374
|
-
]);
|
|
375
|
-
logger.verbose(`Deployed SlashFactory at ${slashFactoryAddress}`);
|
|
376
|
-
// We need to call a function on the registry to set the various contract addresses.
|
|
377
|
-
const registryContract = getContract({
|
|
378
|
-
address: getAddress(addresses.registryAddress.toString()),
|
|
379
|
-
abi: RegistryArtifact.contractAbi,
|
|
380
|
-
client: extendedClient
|
|
381
|
-
});
|
|
382
|
-
// Only if we are the owner will we be sending these transactions
|
|
383
|
-
if (await registryContract.read.owner() === getAddress(extendedClient.account.address)) {
|
|
384
|
-
const version = await rollupContract.getVersion();
|
|
385
|
-
try {
|
|
386
|
-
const retrievedRollupAddress = await registryContract.read.getRollup([
|
|
387
|
-
version
|
|
388
|
-
]);
|
|
389
|
-
logger.verbose(`Rollup ${retrievedRollupAddress} already exists in registry`);
|
|
390
|
-
} catch {
|
|
391
|
-
const { txHash: addRollupTxHash } = await deployer.sendTransaction({
|
|
392
|
-
to: addresses.registryAddress.toString(),
|
|
393
|
-
data: encodeFunctionData({
|
|
394
|
-
abi: RegistryArtifact.contractAbi,
|
|
395
|
-
functionName: 'addRollup',
|
|
396
|
-
args: [
|
|
397
|
-
getAddress(rollupContract.address)
|
|
398
|
-
]
|
|
399
|
-
})
|
|
400
|
-
});
|
|
401
|
-
logger.verbose(`Adding rollup ${rollupContract.address} to registry ${addresses.registryAddress} in tx ${addRollupTxHash}`);
|
|
402
|
-
txHashes.push(addRollupTxHash);
|
|
403
|
-
}
|
|
404
|
-
} else {
|
|
405
|
-
logger.verbose(`Not the owner of the registry, skipping rollup addition`);
|
|
406
|
-
}
|
|
407
|
-
// We need to call a function on the registry to set the various contract addresses.
|
|
408
|
-
const gseContract = getContract({
|
|
409
|
-
address: getAddress(addresses.gseAddress.toString()),
|
|
410
|
-
abi: GSEArtifact.contractAbi,
|
|
411
|
-
client: extendedClient
|
|
412
|
-
});
|
|
413
|
-
if (await gseContract.read.owner() === getAddress(extendedClient.account.address)) {
|
|
414
|
-
if (!await gseContract.read.isRollupRegistered([
|
|
415
|
-
rollupContract.address
|
|
416
|
-
])) {
|
|
417
|
-
const { txHash: addRollupTxHash } = await deployer.sendTransaction({
|
|
418
|
-
to: addresses.gseAddress.toString(),
|
|
419
|
-
data: encodeFunctionData({
|
|
420
|
-
abi: GSEArtifact.contractAbi,
|
|
421
|
-
functionName: 'addRollup',
|
|
422
|
-
args: [
|
|
423
|
-
getAddress(rollupContract.address)
|
|
424
|
-
]
|
|
425
|
-
})
|
|
426
|
-
});
|
|
427
|
-
logger.verbose(`Adding rollup ${rollupContract.address} to GSE ${addresses.gseAddress} in tx ${addRollupTxHash}`);
|
|
428
|
-
// wait for this tx to land in case we have to register initialValidators
|
|
429
|
-
await extendedClient.waitForTransactionReceipt({
|
|
430
|
-
hash: addRollupTxHash
|
|
431
|
-
});
|
|
432
|
-
} else {
|
|
433
|
-
logger.verbose(`Rollup ${rollupContract.address} is already registered in GSE ${addresses.gseAddress}`);
|
|
434
|
-
}
|
|
435
|
-
} else {
|
|
436
|
-
logger.verbose(`Not the owner of the gse, skipping rollup addition`);
|
|
437
|
-
}
|
|
438
|
-
if (args.initialValidators && await gseContract.read.isRollupRegistered([
|
|
439
|
-
rollupContract.address
|
|
440
|
-
])) {
|
|
441
|
-
await addMultipleValidators(extendedClient, deployer, addresses.gseAddress.toString(), rollupAddress.toString(), addresses.stakingAssetAddress.toString(), args.initialValidators, args.acceleratedTestDeployments, logger);
|
|
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
|
-
}
|
|
460
|
-
await deployer.waitForDeployments();
|
|
461
|
-
await Promise.all(txHashes.map((txHash)=>extendedClient.waitForTransactionReceipt({
|
|
462
|
-
hash: txHash
|
|
463
|
-
})));
|
|
464
|
-
logger.verbose(`Rollup deployed`);
|
|
465
|
-
return {
|
|
466
|
-
rollup: rollupContract,
|
|
467
|
-
slashFactoryAddress
|
|
468
|
-
};
|
|
469
|
-
};
|
|
470
|
-
export const handoverToGovernance = async (extendedClient, deployer, registryAddress, gseAddress, coinIssuerAddress, feeAssetAddress, governanceAddress, logger, acceleratedTestDeployments)=>{
|
|
471
|
-
// We need to call a function on the registry to set the various contract addresses.
|
|
472
|
-
const registryContract = getContract({
|
|
473
|
-
address: getAddress(registryAddress.toString()),
|
|
474
|
-
abi: RegistryArtifact.contractAbi,
|
|
475
|
-
client: extendedClient
|
|
476
|
-
});
|
|
477
|
-
const gseContract = getContract({
|
|
478
|
-
address: getAddress(gseAddress.toString()),
|
|
479
|
-
abi: GSEArtifact.contractAbi,
|
|
480
|
-
client: extendedClient
|
|
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
|
-
});
|
|
492
|
-
const txHashes = [];
|
|
493
|
-
// If the owner is not the Governance contract, transfer ownership to the Governance contract
|
|
494
|
-
if (acceleratedTestDeployments || await registryContract.read.owner() !== getAddress(governanceAddress.toString())) {
|
|
495
|
-
// TODO(md): add send transaction to the deployer such that we do not need to manage tx hashes here
|
|
496
|
-
const { txHash: transferOwnershipTxHash } = await deployer.sendTransaction({
|
|
497
|
-
to: registryAddress.toString(),
|
|
498
|
-
data: encodeFunctionData({
|
|
499
|
-
abi: RegistryArtifact.contractAbi,
|
|
500
|
-
functionName: 'transferOwnership',
|
|
501
|
-
args: [
|
|
502
|
-
getAddress(governanceAddress.toString())
|
|
503
|
-
]
|
|
504
|
-
})
|
|
505
|
-
});
|
|
506
|
-
logger.verbose(`Transferring the ownership of the registry contract at ${registryAddress} to the Governance ${governanceAddress} in tx ${transferOwnershipTxHash}`);
|
|
507
|
-
txHashes.push(transferOwnershipTxHash);
|
|
508
|
-
}
|
|
509
|
-
// If the owner is not the Governance contract, transfer ownership to the Governance contract
|
|
510
|
-
if (acceleratedTestDeployments || await gseContract.read.owner() !== getAddress(governanceAddress.toString())) {
|
|
511
|
-
// TODO(md): add send transaction to the deployer such that we do not need to manage tx hashes here
|
|
512
|
-
const { txHash: transferOwnershipTxHash } = await deployer.sendTransaction({
|
|
513
|
-
to: gseContract.address,
|
|
514
|
-
data: encodeFunctionData({
|
|
515
|
-
abi: GSEArtifact.contractAbi,
|
|
516
|
-
functionName: 'transferOwnership',
|
|
517
|
-
args: [
|
|
518
|
-
getAddress(governanceAddress.toString())
|
|
519
|
-
]
|
|
520
|
-
})
|
|
521
|
-
});
|
|
522
|
-
logger.verbose(`Transferring the ownership of the gse contract at ${gseAddress} to the Governance ${governanceAddress} in tx ${transferOwnershipTxHash}`);
|
|
523
|
-
txHashes.push(transferOwnershipTxHash);
|
|
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
|
-
}
|
|
567
|
-
// Wait for all actions to be mined
|
|
568
|
-
await deployer.waitForDeployments();
|
|
569
|
-
await Promise.all(txHashes.map((txHash)=>extendedClient.waitForTransactionReceipt({
|
|
570
|
-
hash: txHash
|
|
571
|
-
})));
|
|
572
|
-
};
|
|
573
|
-
/*
|
|
574
|
-
* Adds multiple validators to the rollup
|
|
575
|
-
*
|
|
576
|
-
* @param extendedClient - The L1 clients.
|
|
577
|
-
* @param deployer - The L1 deployer.
|
|
578
|
-
* @param rollupAddress - The address of the rollup.
|
|
579
|
-
* @param stakingAssetAddress - The address of the staking asset.
|
|
580
|
-
* @param validators - The validators to initialize.
|
|
581
|
-
* @param acceleratedTestDeployments - Whether to use accelerated test deployments.
|
|
582
|
-
* @param logger - The logger.
|
|
583
|
-
*/ export const addMultipleValidators = async (extendedClient, deployer, gseAddress, rollupAddress, stakingAssetAddress, validators, acceleratedTestDeployments, logger)=>{
|
|
584
|
-
const rollup = new RollupContract(extendedClient, rollupAddress);
|
|
585
|
-
const activationThreshold = await rollup.getActivationThreshold();
|
|
586
|
-
if (validators && validators.length > 0) {
|
|
587
|
-
// Check if some of the initial validators are already registered, so we support idempotent deployments
|
|
588
|
-
if (!acceleratedTestDeployments) {
|
|
589
|
-
const enrichedValidators = await Promise.all(validators.map(async (operator)=>({
|
|
590
|
-
operator,
|
|
591
|
-
status: await rollup.getStatus(operator.attester)
|
|
592
|
-
})));
|
|
593
|
-
const existingValidators = enrichedValidators.filter((v)=>v.status !== 0);
|
|
594
|
-
if (existingValidators.length > 0) {
|
|
595
|
-
logger.warn(`Validators ${existingValidators.map((v)=>v.operator.attester).join(', ')} already exist. Skipping from initialization.`);
|
|
596
|
-
}
|
|
597
|
-
validators = enrichedValidators.filter((v)=>v.status === 0).map((v)=>v.operator);
|
|
598
|
-
}
|
|
599
|
-
if (validators.length > 0) {
|
|
600
|
-
const gseContract = new GSEContract(extendedClient, gseAddress);
|
|
601
|
-
const multiAdder = await deployer.deploy(MultiAdderArtifact, [
|
|
602
|
-
rollupAddress,
|
|
603
|
-
deployer.client.account.address
|
|
604
|
-
]);
|
|
605
|
-
const makeValidatorTuples = async (validator)=>{
|
|
606
|
-
const registrationTuple = await gseContract.makeRegistrationTuple(validator.bn254SecretKey.getValue());
|
|
607
|
-
return {
|
|
608
|
-
attester: getAddress(validator.attester.toString()),
|
|
609
|
-
withdrawer: getAddress(validator.withdrawer.toString()),
|
|
610
|
-
...registrationTuple
|
|
611
|
-
};
|
|
612
|
-
};
|
|
613
|
-
const validatorsTuples = await Promise.all(validators.map(makeValidatorTuples));
|
|
614
|
-
// Mint tokens, approve them, use cheat code to initialize validator set without setting up the epoch.
|
|
615
|
-
const stakeNeeded = activationThreshold * BigInt(validators.length);
|
|
616
|
-
await deployer.l1TxUtils.sendAndMonitorTransaction({
|
|
617
|
-
to: stakingAssetAddress,
|
|
618
|
-
data: encodeFunctionData({
|
|
619
|
-
abi: StakingAssetArtifact.contractAbi,
|
|
620
|
-
functionName: 'mint',
|
|
621
|
-
args: [
|
|
622
|
-
multiAdder.toString(),
|
|
623
|
-
stakeNeeded
|
|
624
|
-
]
|
|
625
|
-
})
|
|
626
|
-
});
|
|
627
|
-
const entryQueueLengthBefore = await rollup.getEntryQueueLength();
|
|
628
|
-
const validatorCountBefore = await rollup.getActiveAttesterCount();
|
|
629
|
-
logger.info(`Adding ${validators.length} validators to the rollup`);
|
|
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
|
-
}
|
|
671
|
-
const entryQueueLengthAfter = await rollup.getEntryQueueLength();
|
|
672
|
-
const validatorCountAfter = await rollup.getActiveAttesterCount();
|
|
673
|
-
if (entryQueueLengthAfter + validatorCountAfter < entryQueueLengthBefore + validatorCountBefore + BigInt(validators.length)) {
|
|
674
|
-
throw new Error(`Failed to add ${validators.length} validators. Active validators: ${validatorCountBefore} -> ${validatorCountAfter}. Queue: ${entryQueueLengthBefore} -> ${entryQueueLengthAfter}`);
|
|
675
|
-
}
|
|
676
|
-
logger.info(`Added ${validators.length} validators. Active validators: ${validatorCountBefore} -> ${validatorCountAfter}. Queue: ${entryQueueLengthBefore} -> ${entryQueueLengthAfter}`);
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
};
|
|
680
|
-
/**
|
|
681
|
-
* Initialize the fee asset handler and make it a minter on the fee asset.
|
|
682
|
-
* @note This function will only be used for testing purposes.
|
|
683
|
-
*
|
|
684
|
-
* @param extendedClient - The L1 clients.
|
|
685
|
-
* @param deployer - The L1 deployer.
|
|
686
|
-
* @param feeAssetAddress - The address of the fee asset.
|
|
687
|
-
* @param logger - The logger.
|
|
688
|
-
*/ // eslint-disable-next-line camelcase
|
|
689
|
-
export const cheat_initializeFeeAssetHandler = async (extendedClient, deployer, feeAssetAddress, logger)=>{
|
|
690
|
-
const feeAssetHandlerAddress = await deployer.deploy(FeeAssetHandlerArtifact, [
|
|
691
|
-
extendedClient.account.address,
|
|
692
|
-
feeAssetAddress.toString(),
|
|
693
|
-
BigInt(1e18)
|
|
694
|
-
]);
|
|
695
|
-
logger.verbose(`Deployed FeeAssetHandler at ${feeAssetHandlerAddress}`);
|
|
696
|
-
const { txHash } = await deployer.sendTransaction({
|
|
697
|
-
to: feeAssetAddress.toString(),
|
|
698
|
-
data: encodeFunctionData({
|
|
699
|
-
abi: FeeAssetArtifact.contractAbi,
|
|
700
|
-
functionName: 'addMinter',
|
|
701
|
-
args: [
|
|
702
|
-
feeAssetHandlerAddress.toString()
|
|
703
|
-
]
|
|
704
|
-
})
|
|
705
|
-
});
|
|
706
|
-
logger.verbose(`Added fee asset handler ${feeAssetHandlerAddress} as minter on fee asset in ${txHash}`);
|
|
707
|
-
return {
|
|
708
|
-
feeAssetHandlerAddress,
|
|
709
|
-
txHash
|
|
710
|
-
};
|
|
711
|
-
};
|
|
712
|
-
/**
|
|
713
|
-
* Deploys the aztec L1 contracts; Rollup & (optionally) Decoder Helper.
|
|
714
|
-
* @param rpcUrls - List of URLs of the ETH RPC to use for deployment.
|
|
715
|
-
* @param account - Private Key or HD Account that will deploy the contracts.
|
|
716
|
-
* @param chain - The chain instance to deploy to.
|
|
717
|
-
* @param logger - A logger object.
|
|
718
|
-
* @param args - Arguments for initialization of L1 contracts
|
|
719
|
-
* @returns A list of ETH addresses of the deployed contracts.
|
|
720
|
-
*/ export const deployL1Contracts = async (rpcUrls, account, chain, logger, args, txUtilsConfig = getL1TxUtilsConfigEnvVars(), createVerificationJson = false)=>{
|
|
721
|
-
logger.info(`Deploying L1 contracts with config: ${jsonStringify(args)}`);
|
|
722
|
-
validateConfig(args);
|
|
723
|
-
const l1Client = createExtendedL1Client(rpcUrls, account, chain);
|
|
724
|
-
// Deploy multicall3 if it does not exist in this network
|
|
725
|
-
await deployMulticall3(l1Client, logger);
|
|
726
|
-
// We are assuming that you are running this on a local anvil node which have 1s block times
|
|
727
|
-
// To align better with actual deployment, we update the block interval to 12s
|
|
728
|
-
const rpcCall = async (method, params)=>{
|
|
729
|
-
logger.info(`Calling ${method} with params: ${JSON.stringify(params)}`);
|
|
730
|
-
return await l1Client.transport.request({
|
|
731
|
-
method,
|
|
732
|
-
params
|
|
733
|
-
});
|
|
734
|
-
};
|
|
735
|
-
if (isAnvilTestChain(chain.id)) {
|
|
736
|
-
try {
|
|
737
|
-
await rpcCall('anvil_setBlockTimestampInterval', [
|
|
738
|
-
args.ethereumSlotDuration
|
|
739
|
-
]);
|
|
740
|
-
logger.warn(`Set block interval to ${args.ethereumSlotDuration}`);
|
|
741
|
-
} catch (e) {
|
|
742
|
-
logger.error(`Error setting block interval: ${e}`);
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
logger.verbose(`Deploying contracts from ${account.address.toString()}`);
|
|
746
|
-
const dateProvider = new DateProvider();
|
|
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);
|
|
749
|
-
const { rollup, slashFactoryAddress } = await deployRollup(l1Client, deployer, args, {
|
|
750
|
-
feeJuiceAddress: feeAssetAddress,
|
|
751
|
-
registryAddress,
|
|
752
|
-
gseAddress,
|
|
753
|
-
rewardDistributorAddress,
|
|
754
|
-
stakingAssetAddress,
|
|
755
|
-
governanceAddress
|
|
756
|
-
}, logger);
|
|
757
|
-
logger.verbose('Waiting for rollup and slash factory to be deployed');
|
|
758
|
-
await deployer.waitForDeployments();
|
|
759
|
-
// Now that the rollup has been deployed and added to the registry, transfer ownership to governance
|
|
760
|
-
await handoverToGovernance(l1Client, deployer, registryAddress, gseAddress, coinIssuerAddress, feeAssetAddress, governanceAddress, logger, args.acceleratedTestDeployments);
|
|
761
|
-
logger.info(`Handing over to governance complete`);
|
|
762
|
-
logger.verbose(`All transactions for L1 deployment have been mined`);
|
|
763
|
-
const l1Contracts = await RegistryContract.collectAddresses(l1Client, registryAddress, 'canonical');
|
|
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
|
-
}
|
|
960
|
-
if (isAnvilTestChain(chain.id)) {
|
|
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.
|
|
962
|
-
// The edge case being that the genesis block is already occupying slot 0, so we cannot have another block.
|
|
963
|
-
try {
|
|
964
|
-
// Need to get the time
|
|
965
|
-
const currentSlot = await rollup.getSlotNumber();
|
|
966
|
-
if (BigInt(currentSlot) === 0n) {
|
|
967
|
-
const ts = Number(await rollup.getTimestampForSlot(1n));
|
|
968
|
-
await rpcCall('evm_setNextBlockTimestamp', [
|
|
969
|
-
ts
|
|
970
|
-
]);
|
|
971
|
-
await rpcCall('hardhat_mine', [
|
|
972
|
-
1
|
|
973
|
-
]);
|
|
974
|
-
const currentSlot = await rollup.getSlotNumber();
|
|
975
|
-
if (BigInt(currentSlot) !== 1n) {
|
|
976
|
-
throw new Error(`Error jumping time: current slot is ${currentSlot}`);
|
|
977
|
-
}
|
|
978
|
-
logger.info(`Jumped to slot 1`);
|
|
979
|
-
}
|
|
980
|
-
} catch (e) {
|
|
981
|
-
throw new Error(`Error jumping time: ${e}`);
|
|
982
|
-
}
|
|
983
|
-
}
|
|
984
|
-
return {
|
|
985
|
-
rollupVersion: Number(await rollup.getVersion()),
|
|
986
|
-
l1Client: l1Client,
|
|
987
|
-
l1ContractAddresses: {
|
|
988
|
-
...l1Contracts,
|
|
989
|
-
slashFactoryAddress,
|
|
990
|
-
feeAssetHandlerAddress,
|
|
991
|
-
stakingAssetHandlerAddress,
|
|
992
|
-
zkPassportVerifierAddress,
|
|
993
|
-
coinIssuerAddress
|
|
994
|
-
}
|
|
995
|
-
};
|
|
996
|
-
};
|
|
997
|
-
export class L1Deployer {
|
|
998
|
-
client;
|
|
999
|
-
acceleratedTestDeployments;
|
|
1000
|
-
logger;
|
|
1001
|
-
txUtilsConfig;
|
|
1002
|
-
createVerificationJson;
|
|
1003
|
-
salt;
|
|
1004
|
-
txHashes;
|
|
1005
|
-
l1TxUtils;
|
|
1006
|
-
verificationRecords;
|
|
1007
|
-
constructor(client, maybeSalt, dateProvider = new DateProvider(), acceleratedTestDeployments = false, logger = createLogger('L1Deployer'), txUtilsConfig, createVerificationJson = false){
|
|
1008
|
-
this.client = client;
|
|
1009
|
-
this.acceleratedTestDeployments = acceleratedTestDeployments;
|
|
1010
|
-
this.logger = logger;
|
|
1011
|
-
this.txUtilsConfig = txUtilsConfig;
|
|
1012
|
-
this.createVerificationJson = createVerificationJson;
|
|
1013
|
-
this.txHashes = [];
|
|
1014
|
-
this.verificationRecords = [];
|
|
1015
|
-
this.salt = maybeSalt ? padHex(numberToHex(maybeSalt), {
|
|
1016
|
-
size: 32
|
|
1017
|
-
}) : undefined;
|
|
1018
|
-
this.l1TxUtils = createL1TxUtilsFromViemWallet(this.client, this.logger, dateProvider, this.txUtilsConfig, this.acceleratedTestDeployments);
|
|
1019
|
-
}
|
|
1020
|
-
async deploy(params, args, opts = {}) {
|
|
1021
|
-
this.logger.debug(`Deploying ${params.name} contract`, {
|
|
1022
|
-
args
|
|
1023
|
-
});
|
|
1024
|
-
try {
|
|
1025
|
-
const { txHash, address, deployedLibraries } = await deployL1Contract(this.client, params.contractAbi, params.contractBytecode, args ?? [], {
|
|
1026
|
-
salt: this.salt,
|
|
1027
|
-
libraries: params.libraries,
|
|
1028
|
-
logger: this.logger,
|
|
1029
|
-
l1TxUtils: this.l1TxUtils,
|
|
1030
|
-
acceleratedTestDeployments: this.acceleratedTestDeployments,
|
|
1031
|
-
gasLimit: opts.gasLimit
|
|
1032
|
-
});
|
|
1033
|
-
if (txHash) {
|
|
1034
|
-
this.txHashes.push(txHash);
|
|
1035
|
-
}
|
|
1036
|
-
this.logger.debug(`Deployed ${params.name} at ${address}`, {
|
|
1037
|
-
args
|
|
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
|
-
}
|
|
1056
|
-
return address;
|
|
1057
|
-
} catch (error) {
|
|
1058
|
-
throw new Error(`Failed to deploy ${params.name}`, {
|
|
1059
|
-
cause: formatViemError(error)
|
|
1060
|
-
});
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1063
|
-
async waitForDeployments() {
|
|
1064
|
-
if (this.acceleratedTestDeployments) {
|
|
1065
|
-
this.logger.info('Accelerated test deployments - skipping waiting for deployments');
|
|
1066
|
-
return;
|
|
1067
|
-
}
|
|
1068
|
-
if (this.txHashes.length === 0) {
|
|
1069
|
-
return;
|
|
1070
|
-
}
|
|
1071
|
-
this.logger.verbose(`Waiting for ${this.txHashes.length} transactions to be mined`, {
|
|
1072
|
-
txHashes: this.txHashes
|
|
1073
|
-
});
|
|
1074
|
-
const receipts = await Promise.all(this.txHashes.map((txHash)=>this.client.waitForTransactionReceipt({
|
|
1075
|
-
hash: txHash
|
|
1076
|
-
})));
|
|
1077
|
-
const failed = receipts.filter((r)=>r.status !== 'success');
|
|
1078
|
-
if (failed.length > 0) {
|
|
1079
|
-
throw new Error(`Some deployment txs have failed: ${failed.map((f)=>f.transactionHash).join(', ')}`);
|
|
1080
|
-
}
|
|
1081
|
-
this.logger.info('All transactions mined successfully', {
|
|
1082
|
-
txHashes: this.txHashes
|
|
1083
|
-
});
|
|
1084
|
-
}
|
|
1085
|
-
sendTransaction(tx, options) {
|
|
1086
|
-
return this.l1TxUtils.sendTransaction(tx, options);
|
|
1087
|
-
}
|
|
1088
|
-
}
|
|
1089
|
-
// docs:start:deployL1Contract
|
|
1090
|
-
/**
|
|
1091
|
-
* Helper function to deploy ETH contracts.
|
|
1092
|
-
* @param walletClient - A viem WalletClient.
|
|
1093
|
-
* @param publicClient - A viem PublicClient.
|
|
1094
|
-
* @param abi - The ETH contract's ABI (as abitype's Abi).
|
|
1095
|
-
* @param bytecode - The ETH contract's bytecode.
|
|
1096
|
-
* @param args - Constructor arguments for the contract.
|
|
1097
|
-
* @param salt - Optional salt for CREATE2 deployment (does not wait for deployment tx to be mined if set, does not send tx if contract already exists).
|
|
1098
|
-
* @returns The ETH address the contract was deployed to.
|
|
1099
|
-
*/ export async function deployL1Contract(extendedClient, abi, bytecode, args = [], opts = {}) {
|
|
1100
|
-
let txHash = undefined;
|
|
1101
|
-
let resultingAddress = undefined;
|
|
1102
|
-
const deployedLibraries = [];
|
|
1103
|
-
const { salt: saltFromOpts, libraries, logger, gasLimit, acceleratedTestDeployments } = opts;
|
|
1104
|
-
let { l1TxUtils } = opts;
|
|
1105
|
-
if (!l1TxUtils) {
|
|
1106
|
-
const config = getL1TxUtilsConfigEnvVars();
|
|
1107
|
-
l1TxUtils = createL1TxUtilsFromViemWallet(extendedClient, logger, undefined, config, acceleratedTestDeployments);
|
|
1108
|
-
}
|
|
1109
|
-
if (libraries) {
|
|
1110
|
-
// Note that this does NOT work well for linked libraries having linked libraries.
|
|
1111
|
-
// Verify that all link references have corresponding code
|
|
1112
|
-
for(const linkRef in libraries.linkReferences){
|
|
1113
|
-
for(const contractName in libraries.linkReferences[linkRef]){
|
|
1114
|
-
if (!libraries.libraryCode[contractName]) {
|
|
1115
|
-
throw new Error(`Missing library code for ${contractName}`);
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
}
|
|
1119
|
-
const replacements = {};
|
|
1120
|
-
const libraryTxs = [];
|
|
1121
|
-
for(const libraryName in libraries?.libraryCode){
|
|
1122
|
-
const lib = libraries.libraryCode[libraryName];
|
|
1123
|
-
const { libraries: _libraries, ...optsWithoutLibraries } = opts;
|
|
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
|
-
});
|
|
1131
|
-
if (txHash) {
|
|
1132
|
-
libraryTxs.push(txHash);
|
|
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
|
-
}
|
|
1149
|
-
for(const linkRef in libraries.linkReferences){
|
|
1150
|
-
for(const contractName in libraries.linkReferences[linkRef]){
|
|
1151
|
-
// If the library name matches the one we just deployed, we replace it.
|
|
1152
|
-
if (contractName !== libraryName) {
|
|
1153
|
-
continue;
|
|
1154
|
-
}
|
|
1155
|
-
// We read the first instance to figure out what we are to replace.
|
|
1156
|
-
const start = 2 + 2 * libraries.linkReferences[linkRef][contractName][0].start;
|
|
1157
|
-
const length = 2 * libraries.linkReferences[linkRef][contractName][0].length;
|
|
1158
|
-
const toReplace = bytecode.slice(start, start + length);
|
|
1159
|
-
replacements[toReplace] = address;
|
|
1160
|
-
}
|
|
1161
|
-
}
|
|
1162
|
-
}
|
|
1163
|
-
const escapeRegExp = (s)=>{
|
|
1164
|
-
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // Escape special characters
|
|
1165
|
-
};
|
|
1166
|
-
for(const toReplace in replacements){
|
|
1167
|
-
const replacement = replacements[toReplace].toString().slice(2);
|
|
1168
|
-
bytecode = bytecode.replace(new RegExp(escapeRegExp(toReplace), 'g'), replacement);
|
|
1169
|
-
}
|
|
1170
|
-
// Reth fails gas estimation if the deployed contract attempts to call a library that is not yet deployed,
|
|
1171
|
-
// so we wait for all library deployments to be mined before deploying the contract.
|
|
1172
|
-
// However, if we are in fast mode or using debugMaxGasLimit, we will skip simulation, so we can skip waiting.
|
|
1173
|
-
if (libraryTxs.length > 0 && !acceleratedTestDeployments) {
|
|
1174
|
-
logger?.verbose(`Awaiting for linked libraries to be deployed`);
|
|
1175
|
-
await Promise.all(libraryTxs.map((txHash)=>extendedClient.waitForTransactionReceipt({
|
|
1176
|
-
hash: txHash
|
|
1177
|
-
})));
|
|
1178
|
-
} else {
|
|
1179
|
-
logger?.verbose(`Skipping waiting for linked libraries to be deployed ${acceleratedTestDeployments ? '(accelerated test deployments)' : ''}`);
|
|
1180
|
-
}
|
|
1181
|
-
}
|
|
1182
|
-
if (saltFromOpts) {
|
|
1183
|
-
logger?.info(`Deploying contract with salt ${saltFromOpts}`);
|
|
1184
|
-
const { address, paddedSalt: salt, calldata } = getExpectedAddress(abi, bytecode, args, saltFromOpts);
|
|
1185
|
-
resultingAddress = address;
|
|
1186
|
-
const existing = await extendedClient.getCode({
|
|
1187
|
-
address: resultingAddress
|
|
1188
|
-
});
|
|
1189
|
-
if (existing === undefined || existing === '0x') {
|
|
1190
|
-
try {
|
|
1191
|
-
await l1TxUtils.simulate({
|
|
1192
|
-
to: DEPLOYER_ADDRESS,
|
|
1193
|
-
data: concatHex([
|
|
1194
|
-
salt,
|
|
1195
|
-
calldata
|
|
1196
|
-
])
|
|
1197
|
-
}, {
|
|
1198
|
-
gasLimit
|
|
1199
|
-
});
|
|
1200
|
-
} catch (err) {
|
|
1201
|
-
logger?.error(`Failed to simulate deployment tx using universal deployer`, err);
|
|
1202
|
-
await l1TxUtils.simulate({
|
|
1203
|
-
to: null,
|
|
1204
|
-
data: encodeDeployData({
|
|
1205
|
-
abi,
|
|
1206
|
-
bytecode,
|
|
1207
|
-
args
|
|
1208
|
-
})
|
|
1209
|
-
});
|
|
1210
|
-
}
|
|
1211
|
-
const res = await l1TxUtils.sendTransaction({
|
|
1212
|
-
to: DEPLOYER_ADDRESS,
|
|
1213
|
-
data: concatHex([
|
|
1214
|
-
salt,
|
|
1215
|
-
calldata
|
|
1216
|
-
])
|
|
1217
|
-
}, {
|
|
1218
|
-
gasLimit
|
|
1219
|
-
});
|
|
1220
|
-
txHash = res.txHash;
|
|
1221
|
-
logger?.verbose(`Deployed contract with salt ${salt} to address ${resultingAddress} in tx ${txHash}.`);
|
|
1222
|
-
} else {
|
|
1223
|
-
logger?.verbose(`Skipping existing deployment of contract with salt ${salt} to address ${resultingAddress}`);
|
|
1224
|
-
}
|
|
1225
|
-
} else {
|
|
1226
|
-
const deployData = encodeDeployData({
|
|
1227
|
-
abi,
|
|
1228
|
-
bytecode,
|
|
1229
|
-
args
|
|
1230
|
-
});
|
|
1231
|
-
const { receipt } = await l1TxUtils.sendAndMonitorTransaction({
|
|
1232
|
-
to: null,
|
|
1233
|
-
data: deployData
|
|
1234
|
-
});
|
|
1235
|
-
txHash = receipt.transactionHash;
|
|
1236
|
-
resultingAddress = receipt.contractAddress;
|
|
1237
|
-
if (!resultingAddress) {
|
|
1238
|
-
throw new Error(`No contract address found in receipt: ${JSON.stringify(receipt, (_, val)=>typeof val === 'bigint' ? String(val) : val)}`);
|
|
1239
|
-
}
|
|
1240
|
-
}
|
|
1241
|
-
return {
|
|
1242
|
-
address: EthAddress.fromString(resultingAddress),
|
|
1243
|
-
txHash,
|
|
1244
|
-
deployedLibraries
|
|
1245
|
-
};
|
|
1246
|
-
}
|
|
1247
|
-
export function getExpectedAddress(abi, bytecode, args, salt) {
|
|
1248
|
-
const paddedSalt = padHex(salt, {
|
|
1249
|
-
size: 32
|
|
1250
|
-
});
|
|
1251
|
-
const calldata = encodeDeployData({
|
|
1252
|
-
abi,
|
|
1253
|
-
bytecode,
|
|
1254
|
-
args
|
|
1255
|
-
});
|
|
1256
|
-
const address = getContractAddress({
|
|
1257
|
-
from: DEPLOYER_ADDRESS,
|
|
1258
|
-
salt: paddedSalt,
|
|
1259
|
-
bytecode: calldata,
|
|
1260
|
-
opcode: 'CREATE2'
|
|
1261
|
-
});
|
|
1262
|
-
return {
|
|
1263
|
-
address,
|
|
1264
|
-
paddedSalt,
|
|
1265
|
-
calldata
|
|
1266
|
-
};
|
|
1267
|
-
} // docs:end:deployL1Contract
|