@aztec/ethereum 3.0.0-canary.a9708bd → 3.0.0-devnet.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/client.d.ts +1 -1
- package/dest/client.d.ts.map +1 -1
- package/dest/config.d.ts +11 -6
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +124 -64
- package/dest/contracts/empire_base.d.ts +1 -1
- package/dest/contracts/empire_base.d.ts.map +1 -1
- package/dest/contracts/empire_slashing_proposer.d.ts +2 -2
- package/dest/contracts/empire_slashing_proposer.d.ts.map +1 -1
- package/dest/contracts/empire_slashing_proposer.js +1 -1
- package/dest/contracts/fee_asset_handler.d.ts +3 -3
- package/dest/contracts/fee_asset_handler.d.ts.map +1 -1
- package/dest/contracts/governance.js +7 -3
- package/dest/contracts/governance_proposer.d.ts +1 -2
- package/dest/contracts/governance_proposer.d.ts.map +1 -1
- package/dest/contracts/governance_proposer.js +1 -2
- package/dest/contracts/multicall.d.ts +3 -5
- package/dest/contracts/multicall.d.ts.map +1 -1
- package/dest/contracts/multicall.js +6 -4
- package/dest/contracts/rollup.d.ts +39 -19
- package/dest/contracts/rollup.d.ts.map +1 -1
- package/dest/contracts/rollup.js +84 -88
- package/dest/contracts/slasher_contract.d.ts +10 -0
- package/dest/contracts/slasher_contract.d.ts.map +1 -1
- package/dest/contracts/slasher_contract.js +18 -0
- package/dest/contracts/tally_slashing_proposer.d.ts +22 -3
- package/dest/contracts/tally_slashing_proposer.d.ts.map +1 -1
- package/dest/contracts/tally_slashing_proposer.js +55 -5
- package/dest/deploy_l1_contracts.d.ts +22 -7
- package/dest/deploy_l1_contracts.d.ts.map +1 -1
- package/dest/deploy_l1_contracts.js +555 -362
- package/dest/index.d.ts +1 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -1
- package/dest/l1_artifacts.d.ts +8729 -6014
- package/dest/l1_artifacts.d.ts.map +1 -1
- package/dest/l1_artifacts.js +10 -5
- package/dest/l1_contract_addresses.d.ts +5 -1
- package/dest/l1_contract_addresses.d.ts.map +1 -1
- package/dest/l1_contract_addresses.js +16 -26
- package/dest/l1_reader.d.ts +1 -1
- package/dest/l1_reader.d.ts.map +1 -1
- package/dest/l1_reader.js +8 -8
- package/dest/l1_tx_utils/config.d.ts +59 -0
- package/dest/l1_tx_utils/config.d.ts.map +1 -0
- package/dest/l1_tx_utils/config.js +73 -0
- package/dest/l1_tx_utils/constants.d.ts +6 -0
- package/dest/l1_tx_utils/constants.d.ts.map +1 -0
- package/dest/l1_tx_utils/constants.js +14 -0
- package/dest/l1_tx_utils/factory.d.ts +24 -0
- package/dest/l1_tx_utils/factory.d.ts.map +1 -0
- package/dest/l1_tx_utils/factory.js +12 -0
- package/dest/l1_tx_utils/index.d.ts +10 -0
- package/dest/l1_tx_utils/index.d.ts.map +1 -0
- package/dest/l1_tx_utils/index.js +10 -0
- package/dest/l1_tx_utils/interfaces.d.ts +76 -0
- package/dest/l1_tx_utils/interfaces.d.ts.map +1 -0
- package/dest/l1_tx_utils/interfaces.js +4 -0
- package/dest/l1_tx_utils/l1_tx_utils.d.ts +95 -0
- package/dest/l1_tx_utils/l1_tx_utils.d.ts.map +1 -0
- package/dest/l1_tx_utils/l1_tx_utils.js +610 -0
- package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts +26 -0
- package/dest/l1_tx_utils/l1_tx_utils_with_blobs.d.ts.map +1 -0
- package/dest/l1_tx_utils/l1_tx_utils_with_blobs.js +26 -0
- package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts +81 -0
- package/dest/l1_tx_utils/readonly_l1_tx_utils.d.ts.map +1 -0
- package/dest/l1_tx_utils/readonly_l1_tx_utils.js +294 -0
- package/dest/l1_tx_utils/signer.d.ts +4 -0
- package/dest/l1_tx_utils/signer.d.ts.map +1 -0
- package/dest/l1_tx_utils/signer.js +16 -0
- package/dest/l1_tx_utils/types.d.ts +67 -0
- package/dest/l1_tx_utils/types.d.ts.map +1 -0
- package/dest/l1_tx_utils/types.js +26 -0
- package/dest/l1_tx_utils/utils.d.ts +4 -0
- package/dest/l1_tx_utils/utils.d.ts.map +1 -0
- package/dest/l1_tx_utils/utils.js +14 -0
- package/dest/publisher_manager.d.ts +7 -2
- package/dest/publisher_manager.d.ts.map +1 -1
- package/dest/publisher_manager.js +36 -8
- package/dest/queries.d.ts.map +1 -1
- package/dest/queries.js +11 -12
- package/dest/test/chain_monitor.d.ts +11 -0
- package/dest/test/chain_monitor.d.ts.map +1 -1
- package/dest/test/chain_monitor.js +81 -12
- package/dest/test/delayed_tx_utils.d.ts +2 -2
- package/dest/test/delayed_tx_utils.d.ts.map +1 -1
- package/dest/test/delayed_tx_utils.js +2 -2
- package/dest/test/eth_cheat_codes.d.ts +32 -6
- package/dest/test/eth_cheat_codes.d.ts.map +1 -1
- package/dest/test/eth_cheat_codes.js +115 -28
- package/dest/test/rollup_cheat_codes.d.ts +11 -9
- package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
- package/dest/test/rollup_cheat_codes.js +38 -6
- package/dest/test/upgrade_utils.d.ts.map +1 -1
- package/dest/test/upgrade_utils.js +3 -2
- package/dest/utils.d.ts.map +1 -1
- package/dest/utils.js +10 -161
- package/dest/zkPassportVerifierAddress.js +1 -1
- package/package.json +7 -7
- package/src/client.ts +1 -1
- package/src/config.ts +136 -68
- package/src/contracts/empire_base.ts +1 -1
- package/src/contracts/empire_slashing_proposer.ts +7 -3
- package/src/contracts/fee_asset_handler.ts +1 -1
- package/src/contracts/governance.ts +3 -3
- package/src/contracts/governance_proposer.ts +3 -4
- package/src/contracts/multicall.ts +12 -10
- package/src/contracts/rollup.ts +104 -106
- package/src/contracts/slasher_contract.ts +22 -0
- package/src/contracts/tally_slashing_proposer.ts +54 -6
- package/src/deploy_l1_contracts.ts +570 -328
- package/src/index.ts +1 -1
- package/src/l1_artifacts.ts +14 -6
- package/src/l1_contract_addresses.ts +17 -26
- package/src/l1_reader.ts +9 -9
- package/src/l1_tx_utils/README.md +177 -0
- package/src/l1_tx_utils/config.ts +140 -0
- package/src/l1_tx_utils/constants.ts +18 -0
- package/src/l1_tx_utils/factory.ts +64 -0
- package/src/l1_tx_utils/index.ts +12 -0
- package/src/l1_tx_utils/interfaces.ts +86 -0
- package/src/l1_tx_utils/l1_tx_utils.ts +718 -0
- package/src/l1_tx_utils/l1_tx_utils_with_blobs.ts +77 -0
- package/src/l1_tx_utils/readonly_l1_tx_utils.ts +372 -0
- package/src/l1_tx_utils/signer.ts +28 -0
- package/src/l1_tx_utils/types.ts +85 -0
- package/src/l1_tx_utils/utils.ts +16 -0
- package/src/publisher_manager.ts +51 -9
- package/src/queries.ts +13 -8
- package/src/test/chain_monitor.ts +89 -9
- package/src/test/delayed_tx_utils.ts +2 -2
- package/src/test/eth_cheat_codes.ts +142 -29
- package/src/test/rollup_cheat_codes.ts +54 -14
- package/src/test/upgrade_utils.ts +3 -2
- package/src/utils.ts +13 -185
- package/src/zkPassportVerifierAddress.ts +1 -1
- 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/l1_tx_utils.ts +0 -1105
- package/src/l1_tx_utils_with_blobs.ts +0 -144
|
@@ -6,50 +6,145 @@ import { jsonStringify } from '@aztec/foundation/json-rpc';
|
|
|
6
6
|
import { createLogger } from '@aztec/foundation/log';
|
|
7
7
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
8
8
|
import { mkdir, writeFile } from 'fs/promises';
|
|
9
|
+
import chunk from 'lodash.chunk';
|
|
9
10
|
import { concatHex, encodeAbiParameters, encodeDeployData, encodeFunctionData, getAddress, getContract, getContractAddress, numberToHex, padHex } from 'viem';
|
|
10
11
|
import { foundry } from 'viem/chains';
|
|
11
12
|
import { isAnvilTestChain } from './chain.js';
|
|
12
13
|
import { createExtendedL1Client } from './client.js';
|
|
13
|
-
import { getEntryQueueConfig,
|
|
14
|
+
import { getEntryQueueConfig, getGovernanceConfiguration, getRewardBoostConfig, getRewardConfig, validateConfig } from './config.js';
|
|
14
15
|
import { GSEContract } from './contracts/gse.js';
|
|
15
16
|
import { deployMulticall3 } from './contracts/multicall.js';
|
|
16
17
|
import { RegistryContract } from './contracts/registry.js';
|
|
17
18
|
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';
|
|
19
|
+
import { CoinIssuerArtifact, DateGatedRelayerArtifact, FeeAssetArtifact, FeeAssetHandlerArtifact, GSEArtifact, GovernanceArtifact, GovernanceProposerArtifact, MultiAdderArtifact, RegisterNewRollupVersionPayloadArtifact, RegistryArtifact, RollupArtifact, SlashFactoryArtifact, StakingAssetArtifact, StakingAssetHandlerArtifact, l1ArtifactsVerifiers, mockVerifiers } from './l1_artifacts.js';
|
|
20
|
+
import { createL1TxUtilsFromViemWallet, getL1TxUtilsConfigEnvVars } from './l1_tx_utils/index.js';
|
|
20
21
|
import { formatViemError } from './utils.js';
|
|
21
22
|
import { ZK_PASSPORT_DOMAIN, ZK_PASSPORT_SCOPE, ZK_PASSPORT_VERIFIER_ADDRESS } from './zkPassportVerifierAddress.js';
|
|
22
23
|
export const DEPLOYER_ADDRESS = '0x4e59b44847b379578588920cA78FbF26c0B4956C';
|
|
23
|
-
|
|
24
|
+
// Minimal ERC20 ABI for validation purposes. We only read view methods.
|
|
25
|
+
const ERC20_VALIDATION_ABI = [
|
|
26
|
+
{
|
|
27
|
+
type: 'function',
|
|
28
|
+
name: 'totalSupply',
|
|
29
|
+
stateMutability: 'view',
|
|
30
|
+
inputs: [],
|
|
31
|
+
outputs: [
|
|
32
|
+
{
|
|
33
|
+
name: '',
|
|
34
|
+
type: 'uint256'
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
type: 'function',
|
|
40
|
+
name: 'name',
|
|
41
|
+
stateMutability: 'view',
|
|
42
|
+
inputs: [],
|
|
43
|
+
outputs: [
|
|
44
|
+
{
|
|
45
|
+
name: '',
|
|
46
|
+
type: 'string'
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
type: 'function',
|
|
52
|
+
name: 'symbol',
|
|
53
|
+
stateMutability: 'view',
|
|
54
|
+
inputs: [],
|
|
55
|
+
outputs: [
|
|
56
|
+
{
|
|
57
|
+
name: '',
|
|
58
|
+
type: 'string'
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
type: 'function',
|
|
64
|
+
name: 'decimals',
|
|
65
|
+
stateMutability: 'view',
|
|
66
|
+
inputs: [],
|
|
67
|
+
outputs: [
|
|
68
|
+
{
|
|
69
|
+
name: '',
|
|
70
|
+
type: 'uint8'
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
];
|
|
75
|
+
/**
|
|
76
|
+
* Validates that the provided address points to a contract that resembles an ERC20 token.
|
|
77
|
+
* Checks for contract code and attempts common ERC20 view calls.
|
|
78
|
+
* Throws an error if validation fails.
|
|
79
|
+
*/ export async function validateExistingErc20TokenAddress(l1Client, tokenAddress, logger) {
|
|
80
|
+
const addressString = tokenAddress.toString();
|
|
81
|
+
// Ensure there is contract code at the address
|
|
82
|
+
const code = await l1Client.getCode({
|
|
83
|
+
address: addressString
|
|
84
|
+
});
|
|
85
|
+
if (!code || code === '0x') {
|
|
86
|
+
throw new Error(`No contract code found at provided token address ${addressString}`);
|
|
87
|
+
}
|
|
88
|
+
const contract = getContract({
|
|
89
|
+
address: getAddress(addressString),
|
|
90
|
+
abi: ERC20_VALIDATION_ABI,
|
|
91
|
+
client: l1Client
|
|
92
|
+
});
|
|
93
|
+
// Validate all required ERC20 methods in parallel
|
|
94
|
+
const checks = [
|
|
95
|
+
contract.read.totalSupply().then((total)=>typeof total === 'bigint'),
|
|
96
|
+
contract.read.name().then(()=>true),
|
|
97
|
+
contract.read.symbol().then(()=>true),
|
|
98
|
+
contract.read.decimals().then((dec)=>typeof dec === 'number' || typeof dec === 'bigint')
|
|
99
|
+
];
|
|
100
|
+
const results = await Promise.allSettled(checks);
|
|
101
|
+
const failedChecks = results.filter((result)=>result.status === 'rejected' || result.value !== true);
|
|
102
|
+
if (failedChecks.length > 0) {
|
|
103
|
+
throw new Error(`Address ${addressString} does not appear to implement ERC20 view methods`);
|
|
104
|
+
}
|
|
105
|
+
logger.verbose(`Validated existing token at ${addressString} appears to be ERC20-compatible`);
|
|
106
|
+
}
|
|
24
107
|
export const deploySharedContracts = async (l1Client, deployer, args, logger)=>{
|
|
25
|
-
|
|
108
|
+
const networkName = getActiveNetworkName();
|
|
109
|
+
logger.info(`Deploying shared contracts for network configuration: ${networkName}`);
|
|
26
110
|
const txHashes = [];
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
l1Client.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
111
|
+
let feeAssetAddress;
|
|
112
|
+
let stakingAssetAddress;
|
|
113
|
+
if (args.existingTokenAddress) {
|
|
114
|
+
await validateExistingErc20TokenAddress(l1Client, args.existingTokenAddress, logger);
|
|
115
|
+
feeAssetAddress = args.existingTokenAddress;
|
|
116
|
+
stakingAssetAddress = args.existingTokenAddress;
|
|
117
|
+
logger.verbose(`Using existing token for fee and staking assets at ${args.existingTokenAddress}`);
|
|
118
|
+
} else {
|
|
119
|
+
const deployedFee = await deployer.deploy(FeeAssetArtifact, [
|
|
120
|
+
'FeeJuice',
|
|
121
|
+
'FEE',
|
|
122
|
+
l1Client.account.address
|
|
123
|
+
]);
|
|
124
|
+
feeAssetAddress = deployedFee.address;
|
|
125
|
+
logger.verbose(`Deployed Fee Asset at ${feeAssetAddress}`);
|
|
126
|
+
const deployedStaking = await deployer.deploy(StakingAssetArtifact, [
|
|
127
|
+
'Staking',
|
|
128
|
+
'STK',
|
|
129
|
+
l1Client.account.address
|
|
130
|
+
]);
|
|
131
|
+
stakingAssetAddress = deployedStaking.address;
|
|
132
|
+
logger.verbose(`Deployed Staking Asset at ${stakingAssetAddress}`);
|
|
133
|
+
await deployer.waitForDeployments();
|
|
134
|
+
}
|
|
135
|
+
const gseAddress = (await deployer.deploy(GSEArtifact, [
|
|
41
136
|
l1Client.account.address,
|
|
42
137
|
stakingAssetAddress.toString(),
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
]);
|
|
138
|
+
args.activationThreshold,
|
|
139
|
+
args.ejectionThreshold
|
|
140
|
+
])).address;
|
|
46
141
|
logger.verbose(`Deployed GSE at ${gseAddress}`);
|
|
47
|
-
const registryAddress = await deployer.deploy(RegistryArtifact, [
|
|
142
|
+
const { address: registryAddress } = await deployer.deploy(RegistryArtifact, [
|
|
48
143
|
l1Client.account.address,
|
|
49
144
|
feeAssetAddress.toString()
|
|
50
145
|
]);
|
|
51
146
|
logger.verbose(`Deployed Registry at ${registryAddress}`);
|
|
52
|
-
const governanceProposerAddress = await deployer.deploy(GovernanceProposerArtifact, [
|
|
147
|
+
const { address: governanceProposerAddress } = await deployer.deploy(GovernanceProposerArtifact, [
|
|
53
148
|
registryAddress.toString(),
|
|
54
149
|
gseAddress.toString(),
|
|
55
150
|
BigInt(args.governanceProposerQuorum ?? args.governanceProposerRoundSize / 2 + 1),
|
|
@@ -58,7 +153,7 @@ export const deploySharedContracts = async (l1Client, deployer, args, logger)=>{
|
|
|
58
153
|
logger.verbose(`Deployed GovernanceProposer at ${governanceProposerAddress}`);
|
|
59
154
|
// @note @LHerskind the assets are expected to be the same at some point, but for better
|
|
60
155
|
// configurability they are different for now.
|
|
61
|
-
const governanceAddress = await deployer.deploy(GovernanceArtifact, [
|
|
156
|
+
const { address: governanceAddress } = await deployer.deploy(GovernanceArtifact, [
|
|
62
157
|
stakingAssetAddress.toString(),
|
|
63
158
|
governanceProposerAddress.toString(),
|
|
64
159
|
gseAddress.toString(),
|
|
@@ -98,11 +193,11 @@ export const deploySharedContracts = async (l1Client, deployer, args, logger)=>{
|
|
|
98
193
|
logger.verbose(`Set governance on GSE in ${txHash}`);
|
|
99
194
|
txHashes.push(txHash);
|
|
100
195
|
}
|
|
101
|
-
const coinIssuerAddress = await deployer.deploy(CoinIssuerArtifact, [
|
|
196
|
+
const coinIssuerAddress = (await deployer.deploy(CoinIssuerArtifact, [
|
|
102
197
|
feeAssetAddress.toString(),
|
|
103
|
-
|
|
198
|
+
2n * 10n ** 17n,
|
|
104
199
|
l1Client.account.address
|
|
105
|
-
]);
|
|
200
|
+
])).address;
|
|
106
201
|
logger.verbose(`Deployed CoinIssuer at ${coinIssuerAddress}`);
|
|
107
202
|
logger.verbose(`Waiting for deployments to complete`);
|
|
108
203
|
await deployer.waitForDeployments();
|
|
@@ -110,13 +205,13 @@ export const deploySharedContracts = async (l1Client, deployer, args, logger)=>{
|
|
|
110
205
|
let feeAssetHandlerAddress = undefined;
|
|
111
206
|
let stakingAssetHandlerAddress = undefined;
|
|
112
207
|
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, [
|
|
208
|
+
// Only if not on mainnet will we deploy the handlers, and only when we control the token
|
|
209
|
+
if (l1Client.chain.id !== 1 && !args.existingTokenAddress) {
|
|
210
|
+
/* -------------------------------------------------------------------------- */ /* CHEAT CODES START HERE */ /* -------------------------------------------------------------------------- */ feeAssetHandlerAddress = (await deployer.deploy(FeeAssetHandlerArtifact, [
|
|
116
211
|
l1Client.account.address,
|
|
117
212
|
feeAssetAddress.toString(),
|
|
118
213
|
BigInt(1000n * 10n ** 18n)
|
|
119
|
-
]);
|
|
214
|
+
])).address;
|
|
120
215
|
logger.verbose(`Deployed FeeAssetHandler at ${feeAssetHandlerAddress}`);
|
|
121
216
|
// Only if we are "fresh" will we be adding as a minter, otherwise above will simply get same address
|
|
122
217
|
if (needToSetGovernance) {
|
|
@@ -147,6 +242,7 @@ export const deploySharedContracts = async (l1Client, deployer, args, logger)=>{
|
|
|
147
242
|
stakingAsset: stakingAssetAddress.toString(),
|
|
148
243
|
registry: registryAddress.toString(),
|
|
149
244
|
withdrawer: AMIN.toString(),
|
|
245
|
+
validatorsToFlush: 16n,
|
|
150
246
|
mintInterval: BigInt(60 * 60 * 24),
|
|
151
247
|
depositsPerMint: BigInt(10),
|
|
152
248
|
depositMerkleRoot: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
@@ -161,9 +257,9 @@ export const deploySharedContracts = async (l1Client, deployer, args, logger)=>{
|
|
|
161
257
|
skipBindCheck: args.zkPassportArgs?.mockZkPassportVerifier ?? false,
|
|
162
258
|
skipMerkleCheck: true
|
|
163
259
|
};
|
|
164
|
-
stakingAssetHandlerAddress = await deployer.deploy(StakingAssetHandlerArtifact, [
|
|
260
|
+
stakingAssetHandlerAddress = (await deployer.deploy(StakingAssetHandlerArtifact, [
|
|
165
261
|
stakingAssetHandlerDeployArgs
|
|
166
|
-
]);
|
|
262
|
+
])).address;
|
|
167
263
|
logger.verbose(`Deployed StakingAssetHandler at ${stakingAssetHandlerAddress}`);
|
|
168
264
|
const { txHash: stakingMinterTxHash } = await deployer.sendTransaction({
|
|
169
265
|
to: stakingAssetAddress.toString(),
|
|
@@ -187,20 +283,24 @@ export const deploySharedContracts = async (l1Client, deployer, args, logger)=>{
|
|
|
187
283
|
logger.verbose(`Deployed shared contracts`);
|
|
188
284
|
const registry = new RegistryContract(l1Client, registryAddress);
|
|
189
285
|
/* -------------------------------------------------------------------------- */ /* FUND REWARD DISTRIBUTOR START */ /* -------------------------------------------------------------------------- */ const rewardDistributorAddress = await registry.getRewardDistributor();
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
286
|
+
if (!args.existingTokenAddress) {
|
|
287
|
+
const blockReward = getRewardConfig(networkName).blockReward;
|
|
288
|
+
const funding = blockReward * 200000n;
|
|
289
|
+
const { txHash: fundRewardDistributorTxHash } = await deployer.sendTransaction({
|
|
290
|
+
to: feeAssetAddress.toString(),
|
|
291
|
+
data: encodeFunctionData({
|
|
292
|
+
abi: FeeAssetArtifact.contractAbi,
|
|
293
|
+
functionName: 'mint',
|
|
294
|
+
args: [
|
|
295
|
+
rewardDistributorAddress.toString(),
|
|
296
|
+
funding
|
|
297
|
+
]
|
|
298
|
+
})
|
|
299
|
+
});
|
|
300
|
+
logger.verbose(`Funded reward distributor with ${funding} fee asset in ${fundRewardDistributorTxHash}`);
|
|
301
|
+
} else {
|
|
302
|
+
logger.verbose(`Skipping reward distributor funding as existing token is provided`);
|
|
303
|
+
}
|
|
204
304
|
/* -------------------------------------------------------------------------- */ /* FUND REWARD DISTRIBUTOR STOP */ /* -------------------------------------------------------------------------- */ return {
|
|
205
305
|
feeAssetAddress,
|
|
206
306
|
feeAssetHandlerAddress,
|
|
@@ -217,7 +317,7 @@ export const deploySharedContracts = async (l1Client, deployer, args, logger)=>{
|
|
|
217
317
|
};
|
|
218
318
|
const getZkPassportVerifierAddress = async (deployer, args)=>{
|
|
219
319
|
if (args.zkPassportArgs?.mockZkPassportVerifier) {
|
|
220
|
-
return await deployer.deploy(mockVerifiers.mockZkPassportVerifier);
|
|
320
|
+
return (await deployer.deploy(mockVerifiers.mockZkPassportVerifier)).address;
|
|
221
321
|
}
|
|
222
322
|
return ZK_PASSPORT_VERIFIER_ADDRESS;
|
|
223
323
|
};
|
|
@@ -233,6 +333,224 @@ const getZkPassportVerifierAddress = async (deployer, args)=>{
|
|
|
233
333
|
scope
|
|
234
334
|
];
|
|
235
335
|
};
|
|
336
|
+
/**
|
|
337
|
+
* Generates verification records for a deployed rollup and its associated contracts (Inbox, Outbox, Slasher, etc).
|
|
338
|
+
* @param rollup - The deployed rollup contract.
|
|
339
|
+
* @param deployer - The L1 deployer instance.
|
|
340
|
+
* @param args - The deployment arguments used for the rollup.
|
|
341
|
+
* @param addresses - The L1 contract addresses.
|
|
342
|
+
* @param extendedClient - The extended viem wallet client.
|
|
343
|
+
* @param logger - The logger.
|
|
344
|
+
*/ async function generateRollupVerificationRecords(rollup, deployer, args, addresses, extendedClient, logger) {
|
|
345
|
+
try {
|
|
346
|
+
// Add Inbox / Outbox verification records (constructor args are created inside RollupCore)
|
|
347
|
+
const rollupAddr = rollup.address;
|
|
348
|
+
const rollupAddresses = await rollup.getRollupAddresses();
|
|
349
|
+
const inboxAddr = rollupAddresses.inboxAddress.toString();
|
|
350
|
+
const outboxAddr = rollupAddresses.outboxAddress.toString();
|
|
351
|
+
const feeAsset = rollupAddresses.feeJuiceAddress.toString();
|
|
352
|
+
const version = await rollup.getVersion();
|
|
353
|
+
const inboxCtor = encodeAbiParameters([
|
|
354
|
+
{
|
|
355
|
+
type: 'address'
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
type: 'address'
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
type: 'uint256'
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
type: 'uint256'
|
|
365
|
+
}
|
|
366
|
+
], [
|
|
367
|
+
rollupAddr,
|
|
368
|
+
feeAsset,
|
|
369
|
+
version,
|
|
370
|
+
BigInt(L1_TO_L2_MSG_SUBTREE_HEIGHT)
|
|
371
|
+
]);
|
|
372
|
+
const outboxCtor = encodeAbiParameters([
|
|
373
|
+
{
|
|
374
|
+
type: 'address'
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
type: 'uint256'
|
|
378
|
+
}
|
|
379
|
+
], [
|
|
380
|
+
rollupAddr,
|
|
381
|
+
version
|
|
382
|
+
]);
|
|
383
|
+
deployer.verificationRecords.push({
|
|
384
|
+
name: 'Inbox',
|
|
385
|
+
address: inboxAddr,
|
|
386
|
+
constructorArgsHex: inboxCtor,
|
|
387
|
+
libraries: []
|
|
388
|
+
}, {
|
|
389
|
+
name: 'Outbox',
|
|
390
|
+
address: outboxAddr,
|
|
391
|
+
constructorArgsHex: outboxCtor,
|
|
392
|
+
libraries: []
|
|
393
|
+
});
|
|
394
|
+
// Include Slasher and SlashingProposer (if deployed) in verification data
|
|
395
|
+
try {
|
|
396
|
+
const slasherAddrHex = await rollup.getSlasherAddress();
|
|
397
|
+
const slasherAddr = EthAddress.fromString(slasherAddrHex);
|
|
398
|
+
if (!slasherAddr.isZero()) {
|
|
399
|
+
// Slasher constructor: (address _vetoer, address _governance)
|
|
400
|
+
const slasherCtor = encodeAbiParameters([
|
|
401
|
+
{
|
|
402
|
+
type: 'address'
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
type: 'address'
|
|
406
|
+
}
|
|
407
|
+
], [
|
|
408
|
+
args.slashingVetoer.toString(),
|
|
409
|
+
extendedClient.account.address
|
|
410
|
+
]);
|
|
411
|
+
deployer.verificationRecords.push({
|
|
412
|
+
name: 'Slasher',
|
|
413
|
+
address: slasherAddr.toString(),
|
|
414
|
+
constructorArgsHex: slasherCtor,
|
|
415
|
+
libraries: []
|
|
416
|
+
});
|
|
417
|
+
// Proposer address is stored in Slasher.PROPOSER()
|
|
418
|
+
const proposerAddr = (await rollup.getSlashingProposerAddress()).toString();
|
|
419
|
+
// Compute constructor args matching deployment path in RollupCore
|
|
420
|
+
const computedRoundSize = BigInt(args.slashingRoundSizeInEpochs * args.aztecEpochDuration);
|
|
421
|
+
const computedQuorum = BigInt(args.slashingQuorum ?? args.slashingRoundSizeInEpochs * args.aztecEpochDuration / 2 + 1);
|
|
422
|
+
const lifetimeInRounds = BigInt(args.slashingLifetimeInRounds);
|
|
423
|
+
const executionDelayInRounds = BigInt(args.slashingExecutionDelayInRounds);
|
|
424
|
+
if (args.slasherFlavor === 'tally') {
|
|
425
|
+
const slashAmounts = [
|
|
426
|
+
args.slashAmountSmall,
|
|
427
|
+
args.slashAmountMedium,
|
|
428
|
+
args.slashAmountLarge
|
|
429
|
+
];
|
|
430
|
+
const committeeSize = BigInt(args.aztecTargetCommitteeSize);
|
|
431
|
+
const epochDuration = BigInt(args.aztecEpochDuration);
|
|
432
|
+
const slashOffsetInRounds = BigInt(args.slashingOffsetInRounds);
|
|
433
|
+
const proposerCtor = encodeAbiParameters([
|
|
434
|
+
{
|
|
435
|
+
type: 'address'
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
type: 'address'
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
type: 'uint256'
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
type: 'uint256'
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
type: 'uint256'
|
|
448
|
+
},
|
|
449
|
+
{
|
|
450
|
+
type: 'uint256'
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
type: 'uint256[3]'
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
type: 'uint256'
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
type: 'uint256'
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
type: 'uint256'
|
|
463
|
+
}
|
|
464
|
+
], [
|
|
465
|
+
rollup.address,
|
|
466
|
+
slasherAddr.toString(),
|
|
467
|
+
computedQuorum,
|
|
468
|
+
computedRoundSize,
|
|
469
|
+
lifetimeInRounds,
|
|
470
|
+
executionDelayInRounds,
|
|
471
|
+
slashAmounts,
|
|
472
|
+
committeeSize,
|
|
473
|
+
epochDuration,
|
|
474
|
+
slashOffsetInRounds
|
|
475
|
+
]);
|
|
476
|
+
deployer.verificationRecords.push({
|
|
477
|
+
name: 'TallySlashingProposer',
|
|
478
|
+
address: proposerAddr,
|
|
479
|
+
constructorArgsHex: proposerCtor,
|
|
480
|
+
libraries: []
|
|
481
|
+
});
|
|
482
|
+
} else if (args.slasherFlavor === 'empire') {
|
|
483
|
+
const proposerCtor = encodeAbiParameters([
|
|
484
|
+
{
|
|
485
|
+
type: 'address'
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
type: 'address'
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
type: 'uint256'
|
|
492
|
+
},
|
|
493
|
+
{
|
|
494
|
+
type: 'uint256'
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
type: 'uint256'
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
type: 'uint256'
|
|
501
|
+
}
|
|
502
|
+
], [
|
|
503
|
+
rollup.address,
|
|
504
|
+
slasherAddr.toString(),
|
|
505
|
+
computedQuorum,
|
|
506
|
+
computedRoundSize,
|
|
507
|
+
lifetimeInRounds,
|
|
508
|
+
executionDelayInRounds
|
|
509
|
+
]);
|
|
510
|
+
deployer.verificationRecords.push({
|
|
511
|
+
name: 'EmpireSlashingProposer',
|
|
512
|
+
address: proposerAddr,
|
|
513
|
+
constructorArgsHex: proposerCtor,
|
|
514
|
+
libraries: []
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
} catch (e) {
|
|
519
|
+
logger.warn(`Failed to add Slasher/Proposer verification records: ${String(e)}`);
|
|
520
|
+
}
|
|
521
|
+
} catch (e) {
|
|
522
|
+
throw new Error(`Failed to generate rollup verification records: ${String(e)}`);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Writes verification records to a JSON file for later forge verify.
|
|
527
|
+
* @param deployer - The L1 deployer containing verification records.
|
|
528
|
+
* @param outputDirectory - The directory to write the verification file to.
|
|
529
|
+
* @param chainId - The chain ID.
|
|
530
|
+
* @param filenameSuffix - Optional suffix for the filename (e.g., 'upgrade').
|
|
531
|
+
* @param logger - The logger.
|
|
532
|
+
*/ async function writeVerificationJson(deployer, outputDirectory, chainId, filenameSuffix = '', logger) {
|
|
533
|
+
try {
|
|
534
|
+
const date = new Date();
|
|
535
|
+
const formattedDate = date.toISOString().slice(2, 19).replace(/[-T:]/g, '');
|
|
536
|
+
// Ensure the verification output directory exists
|
|
537
|
+
await mkdir(outputDirectory, {
|
|
538
|
+
recursive: true
|
|
539
|
+
});
|
|
540
|
+
const suffix = filenameSuffix ? `-${filenameSuffix}` : '';
|
|
541
|
+
const verificationOutputPath = `${outputDirectory}/l1-verify${suffix}-${chainId}-${formattedDate.slice(0, 6)}-${formattedDate.slice(6)}.json`;
|
|
542
|
+
const networkName = getActiveNetworkName();
|
|
543
|
+
const verificationData = {
|
|
544
|
+
chainId: chainId,
|
|
545
|
+
network: networkName,
|
|
546
|
+
records: deployer.verificationRecords
|
|
547
|
+
};
|
|
548
|
+
await writeFile(verificationOutputPath, JSON.stringify(verificationData, null, 2));
|
|
549
|
+
logger.info(`Wrote L1 verification data to ${verificationOutputPath}`);
|
|
550
|
+
} catch (e) {
|
|
551
|
+
logger.warn(`Failed to write L1 verification data file: ${String(e)}`);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
236
554
|
/**
|
|
237
555
|
* Deploys a new rollup, using the existing canonical version to derive certain values (addresses of assets etc).
|
|
238
556
|
* @param clients - The L1 clients.
|
|
@@ -240,28 +558,34 @@ const getZkPassportVerifierAddress = async (deployer, args)=>{
|
|
|
240
558
|
* @param registryAddress - The address of the registry.
|
|
241
559
|
* @param logger - The logger.
|
|
242
560
|
* @param txUtilsConfig - The L1 tx utils config.
|
|
243
|
-
|
|
244
|
-
|
|
561
|
+
* @param createVerificationJson - Optional path to write verification data for forge verify.
|
|
562
|
+
*/ export const deployRollupForUpgrade = async (extendedClient, args, registryAddress, logger, txUtilsConfig, createVerificationJson = false)=>{
|
|
563
|
+
const deployer = new L1Deployer(extendedClient, args.salt, undefined, args.acceleratedTestDeployments, logger, txUtilsConfig, !!createVerificationJson);
|
|
245
564
|
const addresses = await RegistryContract.collectAddresses(extendedClient, registryAddress, 'canonical');
|
|
246
565
|
const { rollup, slashFactoryAddress } = await deployRollup(extendedClient, deployer, args, addresses, logger);
|
|
247
566
|
await deployer.waitForDeployments();
|
|
567
|
+
// Write verification data (constructor args + linked libraries) to file for later forge verify
|
|
568
|
+
if (createVerificationJson) {
|
|
569
|
+
await generateRollupVerificationRecords(rollup, deployer, args, addresses, extendedClient, logger);
|
|
570
|
+
await writeVerificationJson(deployer, createVerificationJson, extendedClient.chain.id, 'upgrade', logger);
|
|
571
|
+
}
|
|
248
572
|
return {
|
|
249
573
|
rollup,
|
|
250
574
|
slashFactoryAddress
|
|
251
575
|
};
|
|
252
576
|
};
|
|
253
577
|
export const deploySlashFactory = async (deployer, rollupAddress, logger)=>{
|
|
254
|
-
const slashFactoryAddress = await deployer.deploy(SlashFactoryArtifact, [
|
|
578
|
+
const slashFactoryAddress = (await deployer.deploy(SlashFactoryArtifact, [
|
|
255
579
|
rollupAddress
|
|
256
|
-
]);
|
|
580
|
+
])).address;
|
|
257
581
|
logger.verbose(`Deployed SlashFactory at ${slashFactoryAddress}`);
|
|
258
582
|
return slashFactoryAddress;
|
|
259
583
|
};
|
|
260
584
|
export const deployUpgradePayload = async (deployer, addresses)=>{
|
|
261
|
-
const payloadAddress = await deployer.deploy(RegisterNewRollupVersionPayloadArtifact, [
|
|
585
|
+
const payloadAddress = (await deployer.deploy(RegisterNewRollupVersionPayloadArtifact, [
|
|
262
586
|
addresses.registryAddress.toString(),
|
|
263
587
|
addresses.rollupAddress.toString()
|
|
264
|
-
]);
|
|
588
|
+
])).address;
|
|
265
589
|
return payloadAddress;
|
|
266
590
|
};
|
|
267
591
|
function slasherFlavorToSolidityEnum(flavor) {
|
|
@@ -285,14 +609,15 @@ function slasherFlavorToSolidityEnum(flavor) {
|
|
|
285
609
|
if (!addresses.gseAddress) {
|
|
286
610
|
throw new Error('GSE address is required when deploying');
|
|
287
611
|
}
|
|
612
|
+
const networkName = getActiveNetworkName();
|
|
288
613
|
logger.info(`Deploying rollup using network configuration: ${networkName}`);
|
|
289
614
|
const txHashes = [];
|
|
290
615
|
let epochProofVerifier = EthAddress.ZERO;
|
|
291
616
|
if (args.realVerifier) {
|
|
292
|
-
epochProofVerifier = await deployer.deploy(l1ArtifactsVerifiers.honkVerifier);
|
|
617
|
+
epochProofVerifier = (await deployer.deploy(l1ArtifactsVerifiers.honkVerifier)).address;
|
|
293
618
|
logger.verbose(`Rollup will use the real verifier at ${epochProofVerifier}`);
|
|
294
619
|
} else {
|
|
295
|
-
epochProofVerifier = await deployer.deploy(mockVerifiers.mockVerifier);
|
|
620
|
+
epochProofVerifier = (await deployer.deploy(mockVerifiers.mockVerifier)).address;
|
|
296
621
|
logger.verbose(`Rollup will use the mock verifier at ${epochProofVerifier}`);
|
|
297
622
|
}
|
|
298
623
|
const rewardConfig = {
|
|
@@ -303,6 +628,7 @@ function slasherFlavorToSolidityEnum(flavor) {
|
|
|
303
628
|
aztecSlotDuration: BigInt(args.aztecSlotDuration),
|
|
304
629
|
aztecEpochDuration: BigInt(args.aztecEpochDuration),
|
|
305
630
|
targetCommitteeSize: BigInt(args.aztecTargetCommitteeSize),
|
|
631
|
+
lagInEpochs: BigInt(args.lagInEpochs),
|
|
306
632
|
aztecProofSubmissionEpochs: BigInt(args.aztecProofSubmissionEpochs),
|
|
307
633
|
slashingQuorum: BigInt(args.slashingQuorum ?? args.slashingRoundSizeInEpochs * args.aztecEpochDuration / 2 + 1),
|
|
308
634
|
slashingRoundSize: BigInt(args.slashingRoundSizeInEpochs * args.aztecEpochDuration),
|
|
@@ -313,7 +639,7 @@ function slasherFlavorToSolidityEnum(flavor) {
|
|
|
313
639
|
provingCostPerMana: args.provingCostPerMana,
|
|
314
640
|
rewardConfig: rewardConfig,
|
|
315
641
|
version: 0,
|
|
316
|
-
rewardBoostConfig: getRewardBoostConfig(
|
|
642
|
+
rewardBoostConfig: getRewardBoostConfig(),
|
|
317
643
|
stakingQueueConfig: getEntryQueueConfig(networkName),
|
|
318
644
|
exitDelaySeconds: BigInt(args.exitDelaySeconds),
|
|
319
645
|
slasherFlavor: slasherFlavorToSolidityEnum(args.slasherFlavor),
|
|
@@ -322,11 +648,14 @@ function slasherFlavorToSolidityEnum(flavor) {
|
|
|
322
648
|
args.slashAmountSmall,
|
|
323
649
|
args.slashAmountMedium,
|
|
324
650
|
args.slashAmountLarge
|
|
325
|
-
]
|
|
651
|
+
],
|
|
652
|
+
localEjectionThreshold: args.localEjectionThreshold,
|
|
653
|
+
slashingDisableDuration: BigInt(args.slashingDisableDuration ?? 0n),
|
|
654
|
+
earliestRewardsClaimableTimestamp: 0n
|
|
326
655
|
};
|
|
327
656
|
const genesisStateArgs = {
|
|
328
657
|
vkTreeRoot: args.vkTreeRoot.toString(),
|
|
329
|
-
|
|
658
|
+
protocolContractsHash: args.protocolContractsHash.toString(),
|
|
330
659
|
genesisArchiveRoot: args.genesisArchiveRoot.toString()
|
|
331
660
|
};
|
|
332
661
|
// Until there is an actual chain-id for the version, we will just draw a random value.
|
|
@@ -345,33 +674,38 @@ function slasherFlavorToSolidityEnum(flavor) {
|
|
|
345
674
|
genesisStateArgs,
|
|
346
675
|
rollupConfigArgs
|
|
347
676
|
];
|
|
348
|
-
const rollupAddress = await deployer.deploy(RollupArtifact, rollupArgs, {
|
|
677
|
+
const { address: rollupAddress, existed: rollupExisted } = await deployer.deploy(RollupArtifact, rollupArgs, {
|
|
349
678
|
gasLimit: 15_000_000n
|
|
350
679
|
});
|
|
351
|
-
logger.verbose(`Deployed Rollup at ${rollupAddress}`, rollupConfigArgs);
|
|
680
|
+
logger.verbose(`Deployed Rollup at ${rollupAddress}, already existed: ${rollupExisted}`, rollupConfigArgs);
|
|
352
681
|
const rollupContract = new RollupContract(extendedClient, rollupAddress);
|
|
353
682
|
await deployer.waitForDeployments();
|
|
354
683
|
logger.verbose(`All core contracts have been deployed`);
|
|
355
684
|
if (args.feeJuicePortalInitialBalance && args.feeJuicePortalInitialBalance > 0n) {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
to
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
args
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
685
|
+
// Skip funding when using an external token, as we likely don't have mint permissions
|
|
686
|
+
if (!('existingTokenAddress' in args) || !args.existingTokenAddress) {
|
|
687
|
+
const feeJuicePortalAddress = await rollupContract.getFeeJuicePortal();
|
|
688
|
+
// In fast mode, use the L1TxUtils to send transactions with nonce management
|
|
689
|
+
const { txHash: mintTxHash } = await deployer.sendTransaction({
|
|
690
|
+
to: addresses.feeJuiceAddress.toString(),
|
|
691
|
+
data: encodeFunctionData({
|
|
692
|
+
abi: FeeAssetArtifact.contractAbi,
|
|
693
|
+
functionName: 'mint',
|
|
694
|
+
args: [
|
|
695
|
+
feeJuicePortalAddress.toString(),
|
|
696
|
+
args.feeJuicePortalInitialBalance
|
|
697
|
+
]
|
|
698
|
+
})
|
|
699
|
+
});
|
|
700
|
+
logger.verbose(`Funding fee juice portal with ${args.feeJuicePortalInitialBalance} fee juice in ${mintTxHash} (accelerated test deployments)`);
|
|
701
|
+
txHashes.push(mintTxHash);
|
|
702
|
+
} else {
|
|
703
|
+
logger.verbose('Skipping fee juice portal funding due to external token usage');
|
|
704
|
+
}
|
|
371
705
|
}
|
|
372
|
-
const slashFactoryAddress = await deployer.deploy(SlashFactoryArtifact, [
|
|
706
|
+
const slashFactoryAddress = (await deployer.deploy(SlashFactoryArtifact, [
|
|
373
707
|
rollupAddress.toString()
|
|
374
|
-
]);
|
|
708
|
+
])).address;
|
|
375
709
|
logger.verbose(`Deployed SlashFactory at ${slashFactoryAddress}`);
|
|
376
710
|
// We need to call a function on the registry to set the various contract addresses.
|
|
377
711
|
const registryContract = getContract({
|
|
@@ -435,7 +769,11 @@ function slasherFlavorToSolidityEnum(flavor) {
|
|
|
435
769
|
} else {
|
|
436
770
|
logger.verbose(`Not the owner of the gse, skipping rollup addition`);
|
|
437
771
|
}
|
|
438
|
-
|
|
772
|
+
const activeAttestorCount = await rollupContract.getActiveAttesterCount();
|
|
773
|
+
const queuedAttestorCount = await rollupContract.getEntryQueueLength();
|
|
774
|
+
logger.info(`Rollup has ${activeAttestorCount} active attestors and ${queuedAttestorCount} queued attestors`);
|
|
775
|
+
const shouldAddValidators = activeAttestorCount === 0n && queuedAttestorCount === 0n;
|
|
776
|
+
if (args.initialValidators && shouldAddValidators && await gseContract.read.isRollupRegistered([
|
|
439
777
|
rollupContract.address
|
|
440
778
|
])) {
|
|
441
779
|
await addMultipleValidators(extendedClient, deployer, addresses.gseAddress.toString(), rollupAddress.toString(), addresses.stakingAssetAddress.toString(), args.initialValidators, args.acceleratedTestDeployments, logger);
|
|
@@ -467,7 +805,7 @@ function slasherFlavorToSolidityEnum(flavor) {
|
|
|
467
805
|
slashFactoryAddress
|
|
468
806
|
};
|
|
469
807
|
};
|
|
470
|
-
export const handoverToGovernance = async (extendedClient, deployer, registryAddress, gseAddress, coinIssuerAddress, feeAssetAddress, governanceAddress, logger, acceleratedTestDeployments)=>{
|
|
808
|
+
export const handoverToGovernance = async (extendedClient, deployer, registryAddress, gseAddress, coinIssuerAddress, feeAssetAddress, governanceAddress, logger, acceleratedTestDeployments, useExternalToken = false)=>{
|
|
471
809
|
// We need to call a function on the registry to set the various contract addresses.
|
|
472
810
|
const registryContract = getContract({
|
|
473
811
|
address: getAddress(registryAddress.toString()),
|
|
@@ -522,7 +860,7 @@ export const handoverToGovernance = async (extendedClient, deployer, registryAdd
|
|
|
522
860
|
logger.verbose(`Transferring the ownership of the gse contract at ${gseAddress} to the Governance ${governanceAddress} in tx ${transferOwnershipTxHash}`);
|
|
523
861
|
txHashes.push(transferOwnershipTxHash);
|
|
524
862
|
}
|
|
525
|
-
if (acceleratedTestDeployments || await feeAsset.read.owner() !== coinIssuerAddress.toString()) {
|
|
863
|
+
if (!useExternalToken && (acceleratedTestDeployments || await feeAsset.read.owner() !== coinIssuerAddress.toString())) {
|
|
526
864
|
const { txHash } = await deployer.sendTransaction({
|
|
527
865
|
to: feeAssetAddress.toString(),
|
|
528
866
|
data: encodeFunctionData({
|
|
@@ -548,20 +886,27 @@ export const handoverToGovernance = async (extendedClient, deployer, registryAdd
|
|
|
548
886
|
});
|
|
549
887
|
logger.verbose(`Accept ownership of fee asset in ${acceptTokenOwnershipTxHash}`);
|
|
550
888
|
txHashes.push(acceptTokenOwnershipTxHash);
|
|
889
|
+
} else if (useExternalToken) {
|
|
890
|
+
logger.verbose('Skipping fee asset ownership transfer due to external token usage');
|
|
551
891
|
}
|
|
892
|
+
// Either deploy or at least predict the address of the date gated relayer
|
|
893
|
+
const dateGatedRelayer = await deployer.deploy(DateGatedRelayerArtifact, [
|
|
894
|
+
governanceAddress.toString(),
|
|
895
|
+
1798761600n
|
|
896
|
+
]);
|
|
552
897
|
// If the owner is not the Governance contract, transfer ownership to the Governance contract
|
|
553
|
-
if (acceleratedTestDeployments || await coinIssuerContract.read.owner()
|
|
898
|
+
if (acceleratedTestDeployments || await coinIssuerContract.read.owner() === deployer.client.account.address) {
|
|
554
899
|
const { txHash: transferOwnershipTxHash } = await deployer.sendTransaction({
|
|
555
900
|
to: coinIssuerContract.address,
|
|
556
901
|
data: encodeFunctionData({
|
|
557
902
|
abi: CoinIssuerArtifact.contractAbi,
|
|
558
903
|
functionName: 'transferOwnership',
|
|
559
904
|
args: [
|
|
560
|
-
getAddress(
|
|
905
|
+
getAddress(dateGatedRelayer.address.toString())
|
|
561
906
|
]
|
|
562
907
|
})
|
|
563
908
|
});
|
|
564
|
-
logger.verbose(`Transferring the ownership of the coin issuer contract at ${coinIssuerAddress} to the
|
|
909
|
+
logger.verbose(`Transferring the ownership of the coin issuer contract at ${coinIssuerAddress} to the DateGatedRelayer ${dateGatedRelayer.address} in tx ${transferOwnershipTxHash}`);
|
|
565
910
|
txHashes.push(transferOwnershipTxHash);
|
|
566
911
|
}
|
|
567
912
|
// Wait for all actions to be mined
|
|
@@ -569,6 +914,9 @@ export const handoverToGovernance = async (extendedClient, deployer, registryAdd
|
|
|
569
914
|
await Promise.all(txHashes.map((txHash)=>extendedClient.waitForTransactionReceipt({
|
|
570
915
|
hash: txHash
|
|
571
916
|
})));
|
|
917
|
+
return {
|
|
918
|
+
dateGatedRelayerAddress: dateGatedRelayer.address
|
|
919
|
+
};
|
|
572
920
|
};
|
|
573
921
|
/*
|
|
574
922
|
* Adds multiple validators to the rollup
|
|
@@ -596,85 +944,94 @@ export const handoverToGovernance = async (extendedClient, deployer, registryAdd
|
|
|
596
944
|
}
|
|
597
945
|
validators = enrichedValidators.filter((v)=>v.status === 0).map((v)=>v.operator);
|
|
598
946
|
}
|
|
599
|
-
if (validators.length
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
947
|
+
if (validators.length === 0) {
|
|
948
|
+
logger.warn('No validators to add. Skipping.');
|
|
949
|
+
return;
|
|
950
|
+
}
|
|
951
|
+
const gseContract = new GSEContract(extendedClient, gseAddress);
|
|
952
|
+
const multiAdder = (await deployer.deploy(MultiAdderArtifact, [
|
|
953
|
+
rollupAddress,
|
|
954
|
+
deployer.client.account.address
|
|
955
|
+
])).address;
|
|
956
|
+
const makeValidatorTuples = async (validator)=>{
|
|
957
|
+
const registrationTuple = await gseContract.makeRegistrationTuple(validator.bn254SecretKey.getValue());
|
|
958
|
+
return {
|
|
959
|
+
attester: getAddress(validator.attester.toString()),
|
|
960
|
+
withdrawer: getAddress(validator.withdrawer.toString()),
|
|
961
|
+
...registrationTuple
|
|
612
962
|
};
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
963
|
+
};
|
|
964
|
+
const validatorsTuples = await Promise.all(validators.map(makeValidatorTuples));
|
|
965
|
+
// Mint tokens, approve them, use cheat code to initialize validator set without setting up the epoch.
|
|
966
|
+
const stakeNeeded = activationThreshold * BigInt(validators.length);
|
|
967
|
+
await deployer.l1TxUtils.sendAndMonitorTransaction({
|
|
968
|
+
to: stakingAssetAddress,
|
|
969
|
+
data: encodeFunctionData({
|
|
970
|
+
abi: StakingAssetArtifact.contractAbi,
|
|
971
|
+
functionName: 'mint',
|
|
972
|
+
args: [
|
|
973
|
+
multiAdder.toString(),
|
|
974
|
+
stakeNeeded
|
|
975
|
+
]
|
|
976
|
+
})
|
|
977
|
+
});
|
|
978
|
+
const entryQueueLengthBefore = await rollup.getEntryQueueLength();
|
|
979
|
+
const validatorCountBefore = await rollup.getActiveAttesterCount();
|
|
980
|
+
logger.info(`Adding ${validators.length} validators to the rollup`);
|
|
981
|
+
const chunkSize = 16;
|
|
982
|
+
// We will add `chunkSize` validators to the queue until we have covered all of our validators.
|
|
983
|
+
// The `chunkSize` needs to be small enough to fit inside a single tx, therefore 16.
|
|
984
|
+
for (const c of chunk(validatorsTuples, chunkSize)){
|
|
616
985
|
await deployer.l1TxUtils.sendAndMonitorTransaction({
|
|
617
|
-
to:
|
|
986
|
+
to: multiAdder.toString(),
|
|
618
987
|
data: encodeFunctionData({
|
|
619
|
-
abi:
|
|
620
|
-
functionName: '
|
|
988
|
+
abi: MultiAdderArtifact.contractAbi,
|
|
989
|
+
functionName: 'addValidators',
|
|
621
990
|
args: [
|
|
622
|
-
|
|
623
|
-
|
|
991
|
+
c,
|
|
992
|
+
BigInt(0)
|
|
624
993
|
]
|
|
625
994
|
})
|
|
995
|
+
}, {
|
|
996
|
+
gasLimit: 16_000_000n
|
|
626
997
|
});
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
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
|
-
});
|
|
998
|
+
}
|
|
999
|
+
// After adding to the queue, we will now try to flush from it.
|
|
1000
|
+
// We are explicitly doing this as a second step instead of as part of adding to benefit
|
|
1001
|
+
// from the accounting used to speed the process up.
|
|
1002
|
+
// As the queue computes the amount of possible flushes in an epoch when told to flush,
|
|
1003
|
+
// waiting until we have added all we want allows us to benefit in the case were we added
|
|
1004
|
+
// enough to pass the bootstrap set size without needing to wait another epoch.
|
|
1005
|
+
// This is useful when we are testing as it speeds up the tests slightly.
|
|
1006
|
+
while(true){
|
|
1007
|
+
// If the queue is empty, we can break
|
|
1008
|
+
if (await rollup.getEntryQueueLength() == 0n) {
|
|
1009
|
+
break;
|
|
670
1010
|
}
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
throw new Error(`Failed to add ${validators.length} validators. Active validators: ${validatorCountBefore} -> ${validatorCountAfter}. Queue: ${entryQueueLengthBefore} -> ${entryQueueLengthAfter}`);
|
|
1011
|
+
// If there are no available validator flushes, no need to even try
|
|
1012
|
+
if (await rollup.getAvailableValidatorFlushes() == 0n) {
|
|
1013
|
+
break;
|
|
675
1014
|
}
|
|
676
|
-
|
|
1015
|
+
// Note that we are flushing at most `chunkSize` at each call
|
|
1016
|
+
await deployer.l1TxUtils.sendAndMonitorTransaction({
|
|
1017
|
+
to: rollup.address,
|
|
1018
|
+
data: encodeFunctionData({
|
|
1019
|
+
abi: RollupArtifact.contractAbi,
|
|
1020
|
+
functionName: 'flushEntryQueue',
|
|
1021
|
+
args: [
|
|
1022
|
+
BigInt(chunkSize)
|
|
1023
|
+
]
|
|
1024
|
+
})
|
|
1025
|
+
}, {
|
|
1026
|
+
gasLimit: 16_000_000n
|
|
1027
|
+
});
|
|
677
1028
|
}
|
|
1029
|
+
const entryQueueLengthAfter = await rollup.getEntryQueueLength();
|
|
1030
|
+
const validatorCountAfter = await rollup.getActiveAttesterCount();
|
|
1031
|
+
if (entryQueueLengthAfter + validatorCountAfter < entryQueueLengthBefore + validatorCountBefore + BigInt(validators.length)) {
|
|
1032
|
+
throw new Error(`Failed to add ${validators.length} validators. Active validators: ${validatorCountBefore} -> ${validatorCountAfter}. Queue: ${entryQueueLengthBefore} -> ${entryQueueLengthAfter}. A likely issue is the bootstrap size.`);
|
|
1033
|
+
}
|
|
1034
|
+
logger.info(`Added ${validators.length} validators. Active validators: ${validatorCountBefore} -> ${validatorCountAfter}. Queue: ${entryQueueLengthBefore} -> ${entryQueueLengthAfter}`);
|
|
678
1035
|
}
|
|
679
1036
|
};
|
|
680
1037
|
/**
|
|
@@ -687,11 +1044,11 @@ export const handoverToGovernance = async (extendedClient, deployer, registryAdd
|
|
|
687
1044
|
* @param logger - The logger.
|
|
688
1045
|
*/ // eslint-disable-next-line camelcase
|
|
689
1046
|
export const cheat_initializeFeeAssetHandler = async (extendedClient, deployer, feeAssetAddress, logger)=>{
|
|
690
|
-
const feeAssetHandlerAddress = await deployer.deploy(FeeAssetHandlerArtifact, [
|
|
1047
|
+
const feeAssetHandlerAddress = (await deployer.deploy(FeeAssetHandlerArtifact, [
|
|
691
1048
|
extendedClient.account.address,
|
|
692
1049
|
feeAssetAddress.toString(),
|
|
693
1050
|
BigInt(1e18)
|
|
694
|
-
]);
|
|
1051
|
+
])).address;
|
|
695
1052
|
logger.verbose(`Deployed FeeAssetHandler at ${feeAssetHandlerAddress}`);
|
|
696
1053
|
const { txHash } = await deployer.sendTransaction({
|
|
697
1054
|
to: feeAssetAddress.toString(),
|
|
@@ -720,6 +1077,9 @@ export const cheat_initializeFeeAssetHandler = async (extendedClient, deployer,
|
|
|
720
1077
|
*/ export const deployL1Contracts = async (rpcUrls, account, chain, logger, args, txUtilsConfig = getL1TxUtilsConfigEnvVars(), createVerificationJson = false)=>{
|
|
721
1078
|
logger.info(`Deploying L1 contracts with config: ${jsonStringify(args)}`);
|
|
722
1079
|
validateConfig(args);
|
|
1080
|
+
if (args.initialValidators && args.initialValidators.length > 0 && args.existingTokenAddress) {
|
|
1081
|
+
throw new Error('Cannot deploy with both initialValidators and existingTokenAddress. ' + 'Initial validator funding requires minting tokens, which is not possible with an external token.');
|
|
1082
|
+
}
|
|
723
1083
|
const l1Client = createExtendedL1Client(rpcUrls, account, chain);
|
|
724
1084
|
// Deploy multicall3 if it does not exist in this network
|
|
725
1085
|
await deployMulticall3(l1Client, logger);
|
|
@@ -757,205 +1117,15 @@ export const cheat_initializeFeeAssetHandler = async (extendedClient, deployer,
|
|
|
757
1117
|
logger.verbose('Waiting for rollup and slash factory to be deployed');
|
|
758
1118
|
await deployer.waitForDeployments();
|
|
759
1119
|
// 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);
|
|
1120
|
+
const { dateGatedRelayerAddress } = await handoverToGovernance(l1Client, deployer, registryAddress, gseAddress, coinIssuerAddress, feeAssetAddress, governanceAddress, logger, args.acceleratedTestDeployments, !!args.existingTokenAddress);
|
|
761
1121
|
logger.info(`Handing over to governance complete`);
|
|
762
1122
|
logger.verbose(`All transactions for L1 deployment have been mined`);
|
|
763
1123
|
const l1Contracts = await RegistryContract.collectAddresses(l1Client, registryAddress, 'canonical');
|
|
764
1124
|
logger.info(`Aztec L1 contracts initialized`, l1Contracts);
|
|
765
1125
|
// Write verification data (constructor args + linked libraries) to file for later forge verify
|
|
766
1126
|
if (createVerificationJson) {
|
|
767
|
-
|
|
768
|
-
|
|
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
|
-
}
|
|
1127
|
+
await generateRollupVerificationRecords(rollup, deployer, args, l1Contracts, l1Client, logger);
|
|
1128
|
+
await writeVerificationJson(deployer, createVerificationJson, chain.id, '', logger);
|
|
959
1129
|
}
|
|
960
1130
|
if (isAnvilTestChain(chain.id)) {
|
|
961
1131
|
// @note We make a time jump PAST the very first slot to not have to deal with the edge case of the first slot.
|
|
@@ -990,7 +1160,8 @@ export const cheat_initializeFeeAssetHandler = async (extendedClient, deployer,
|
|
|
990
1160
|
feeAssetHandlerAddress,
|
|
991
1161
|
stakingAssetHandlerAddress,
|
|
992
1162
|
zkPassportVerifierAddress,
|
|
993
|
-
coinIssuerAddress
|
|
1163
|
+
coinIssuerAddress,
|
|
1164
|
+
dateGatedRelayerAddress
|
|
994
1165
|
}
|
|
995
1166
|
};
|
|
996
1167
|
};
|
|
@@ -1015,14 +1186,20 @@ export class L1Deployer {
|
|
|
1015
1186
|
this.salt = maybeSalt ? padHex(numberToHex(maybeSalt), {
|
|
1016
1187
|
size: 32
|
|
1017
1188
|
}) : undefined;
|
|
1018
|
-
this.l1TxUtils = createL1TxUtilsFromViemWallet(this.client,
|
|
1189
|
+
this.l1TxUtils = createL1TxUtilsFromViemWallet(this.client, {
|
|
1190
|
+
logger: this.logger,
|
|
1191
|
+
dateProvider
|
|
1192
|
+
}, {
|
|
1193
|
+
...this.txUtilsConfig,
|
|
1194
|
+
debugMaxGasLimit: acceleratedTestDeployments
|
|
1195
|
+
});
|
|
1019
1196
|
}
|
|
1020
1197
|
async deploy(params, args, opts = {}) {
|
|
1021
1198
|
this.logger.debug(`Deploying ${params.name} contract`, {
|
|
1022
1199
|
args
|
|
1023
1200
|
});
|
|
1024
1201
|
try {
|
|
1025
|
-
const { txHash, address, deployedLibraries } = await deployL1Contract(this.client, params.contractAbi, params.contractBytecode, args ?? [], {
|
|
1202
|
+
const { txHash, address, deployedLibraries, existed } = await deployL1Contract(this.client, params.contractAbi, params.contractBytecode, args ?? [], {
|
|
1026
1203
|
salt: this.salt,
|
|
1027
1204
|
libraries: params.libraries,
|
|
1028
1205
|
logger: this.logger,
|
|
@@ -1053,7 +1230,10 @@ export class L1Deployer {
|
|
|
1053
1230
|
libraries: deployedLibraries ?? []
|
|
1054
1231
|
});
|
|
1055
1232
|
}
|
|
1056
|
-
return
|
|
1233
|
+
return {
|
|
1234
|
+
address,
|
|
1235
|
+
existed
|
|
1236
|
+
};
|
|
1057
1237
|
} catch (error) {
|
|
1058
1238
|
throw new Error(`Failed to deploy ${params.name}`, {
|
|
1059
1239
|
cause: formatViemError(error)
|
|
@@ -1083,10 +1263,13 @@ export class L1Deployer {
|
|
|
1083
1263
|
});
|
|
1084
1264
|
}
|
|
1085
1265
|
sendTransaction(tx, options) {
|
|
1086
|
-
return this.l1TxUtils.sendTransaction(tx, options)
|
|
1266
|
+
return this.l1TxUtils.sendTransaction(tx, options).then(({ txHash, state })=>({
|
|
1267
|
+
txHash,
|
|
1268
|
+
gasLimit: state.gasLimit,
|
|
1269
|
+
gasPrice: state.gasPrice
|
|
1270
|
+
}));
|
|
1087
1271
|
}
|
|
1088
1272
|
}
|
|
1089
|
-
// docs:start:deployL1Contract
|
|
1090
1273
|
/**
|
|
1091
1274
|
* Helper function to deploy ETH contracts.
|
|
1092
1275
|
* @param walletClient - A viem WalletClient.
|
|
@@ -1104,7 +1287,12 @@ export class L1Deployer {
|
|
|
1104
1287
|
let { l1TxUtils } = opts;
|
|
1105
1288
|
if (!l1TxUtils) {
|
|
1106
1289
|
const config = getL1TxUtilsConfigEnvVars();
|
|
1107
|
-
l1TxUtils = createL1TxUtilsFromViemWallet(extendedClient,
|
|
1290
|
+
l1TxUtils = createL1TxUtilsFromViemWallet(extendedClient, {
|
|
1291
|
+
logger
|
|
1292
|
+
}, {
|
|
1293
|
+
...config,
|
|
1294
|
+
debugMaxGasLimit: acceleratedTestDeployments
|
|
1295
|
+
});
|
|
1108
1296
|
}
|
|
1109
1297
|
if (libraries) {
|
|
1110
1298
|
// Note that this does NOT work well for linked libraries having linked libraries.
|
|
@@ -1179,6 +1367,7 @@ export class L1Deployer {
|
|
|
1179
1367
|
logger?.verbose(`Skipping waiting for linked libraries to be deployed ${acceleratedTestDeployments ? '(accelerated test deployments)' : ''}`);
|
|
1180
1368
|
}
|
|
1181
1369
|
}
|
|
1370
|
+
let existed = false;
|
|
1182
1371
|
if (saltFromOpts) {
|
|
1183
1372
|
logger?.info(`Deploying contract with salt ${saltFromOpts}`);
|
|
1184
1373
|
const { address, paddedSalt: salt, calldata } = getExpectedAddress(abi, bytecode, args, saltFromOpts);
|
|
@@ -1193,9 +1382,8 @@ export class L1Deployer {
|
|
|
1193
1382
|
data: concatHex([
|
|
1194
1383
|
salt,
|
|
1195
1384
|
calldata
|
|
1196
|
-
])
|
|
1197
|
-
|
|
1198
|
-
gasLimit
|
|
1385
|
+
]),
|
|
1386
|
+
gas: gasLimit
|
|
1199
1387
|
});
|
|
1200
1388
|
} catch (err) {
|
|
1201
1389
|
logger?.error(`Failed to simulate deployment tx using universal deployer`, err);
|
|
@@ -1205,7 +1393,8 @@ export class L1Deployer {
|
|
|
1205
1393
|
abi,
|
|
1206
1394
|
bytecode,
|
|
1207
1395
|
args
|
|
1208
|
-
})
|
|
1396
|
+
}),
|
|
1397
|
+
gas: gasLimit
|
|
1209
1398
|
});
|
|
1210
1399
|
}
|
|
1211
1400
|
const res = await l1TxUtils.sendTransaction({
|
|
@@ -1221,6 +1410,7 @@ export class L1Deployer {
|
|
|
1221
1410
|
logger?.verbose(`Deployed contract with salt ${salt} to address ${resultingAddress} in tx ${txHash}.`);
|
|
1222
1411
|
} else {
|
|
1223
1412
|
logger?.verbose(`Skipping existing deployment of contract with salt ${salt} to address ${resultingAddress}`);
|
|
1413
|
+
existed = true;
|
|
1224
1414
|
}
|
|
1225
1415
|
} else {
|
|
1226
1416
|
const deployData = encodeDeployData({
|
|
@@ -1231,6 +1421,8 @@ export class L1Deployer {
|
|
|
1231
1421
|
const { receipt } = await l1TxUtils.sendAndMonitorTransaction({
|
|
1232
1422
|
to: null,
|
|
1233
1423
|
data: deployData
|
|
1424
|
+
}, {
|
|
1425
|
+
gasLimit
|
|
1234
1426
|
});
|
|
1235
1427
|
txHash = receipt.transactionHash;
|
|
1236
1428
|
resultingAddress = receipt.contractAddress;
|
|
@@ -1241,7 +1433,8 @@ export class L1Deployer {
|
|
|
1241
1433
|
return {
|
|
1242
1434
|
address: EthAddress.fromString(resultingAddress),
|
|
1243
1435
|
txHash,
|
|
1244
|
-
deployedLibraries
|
|
1436
|
+
deployedLibraries,
|
|
1437
|
+
existed
|
|
1245
1438
|
};
|
|
1246
1439
|
}
|
|
1247
1440
|
export function getExpectedAddress(abi, bytecode, args, salt) {
|
|
@@ -1264,4 +1457,4 @@ export function getExpectedAddress(abi, bytecode, args, salt) {
|
|
|
1264
1457
|
paddedSalt,
|
|
1265
1458
|
calldata
|
|
1266
1459
|
};
|
|
1267
|
-
}
|
|
1460
|
+
}
|