@aztec/ethereum 2.0.3 → 2.1.0-rc.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/config.d.ts +10 -5
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +27 -39
- 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 +1 -1
- package/dest/contracts/empire_slashing_proposer.d.ts.map +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 +13 -14
- package/dest/contracts/rollup.d.ts.map +1 -1
- package/dest/contracts/rollup.js +25 -67
- 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/deploy_l1_contracts.d.ts +18 -4
- package/dest/deploy_l1_contracts.d.ts.map +1 -1
- package/dest/deploy_l1_contracts.js +316 -159
- 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 +8019 -5948
- package/dest/l1_artifacts.d.ts.map +1 -1
- package/dest/l1_artifacts.js +6 -1
- 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 +2 -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 +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 +8 -2
- package/dest/test/chain_monitor.js +2 -2
- 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 +18 -1
- package/dest/test/eth_cheat_codes.d.ts.map +1 -1
- package/dest/test/eth_cheat_codes.js +101 -22
- package/dest/test/rollup_cheat_codes.d.ts +3 -1
- package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
- package/dest/test/rollup_cheat_codes.js +2 -2
- package/dest/test/upgrade_utils.js +1 -1
- package/package.json +6 -6
- package/src/config.ts +34 -44
- package/src/contracts/empire_base.ts +1 -1
- package/src/contracts/empire_slashing_proposer.ts +1 -1
- 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 +31 -86
- package/src/contracts/slasher_contract.ts +22 -0
- package/src/deploy_l1_contracts.ts +351 -178
- package/src/index.ts +1 -1
- package/src/l1_artifacts.ts +8 -0
- package/src/l1_contract_addresses.ts +3 -1
- 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 +10 -1
- package/src/test/chain_monitor.ts +2 -2
- package/src/test/delayed_tx_utils.ts +2 -2
- package/src/test/eth_cheat_codes.ts +120 -20
- package/src/test/rollup_cheat_codes.ts +5 -2
- package/src/test/upgrade_utils.ts +1 -1
- package/dest/l1_tx_utils.d.ts +0 -252
- package/dest/l1_tx_utils.d.ts.map +0 -1
- package/dest/l1_tx_utils.js +0 -834
- package/dest/l1_tx_utils_with_blobs.d.ts +0 -20
- package/dest/l1_tx_utils_with_blobs.d.ts.map +0 -1
- package/dest/l1_tx_utils_with_blobs.js +0 -87
- package/src/l1_tx_utils.ts +0 -1124
- package/src/l1_tx_utils_with_blobs.ts +0 -150
|
@@ -6,50 +6,144 @@ 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)=>{
|
|
108
|
+
const networkName = getActiveNetworkName();
|
|
25
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
|
+
}
|
|
134
|
+
const gseAddress = (await deployer.deploy(GSEArtifact, [
|
|
41
135
|
l1Client.account.address,
|
|
42
136
|
stakingAssetAddress.toString(),
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
]);
|
|
137
|
+
args.activationThreshold,
|
|
138
|
+
args.ejectionThreshold
|
|
139
|
+
])).address;
|
|
46
140
|
logger.verbose(`Deployed GSE at ${gseAddress}`);
|
|
47
|
-
const registryAddress = await deployer.deploy(RegistryArtifact, [
|
|
141
|
+
const { address: registryAddress } = await deployer.deploy(RegistryArtifact, [
|
|
48
142
|
l1Client.account.address,
|
|
49
143
|
feeAssetAddress.toString()
|
|
50
144
|
]);
|
|
51
145
|
logger.verbose(`Deployed Registry at ${registryAddress}`);
|
|
52
|
-
const governanceProposerAddress = await deployer.deploy(GovernanceProposerArtifact, [
|
|
146
|
+
const { address: governanceProposerAddress } = await deployer.deploy(GovernanceProposerArtifact, [
|
|
53
147
|
registryAddress.toString(),
|
|
54
148
|
gseAddress.toString(),
|
|
55
149
|
BigInt(args.governanceProposerQuorum ?? args.governanceProposerRoundSize / 2 + 1),
|
|
@@ -58,7 +152,7 @@ export const deploySharedContracts = async (l1Client, deployer, args, logger)=>{
|
|
|
58
152
|
logger.verbose(`Deployed GovernanceProposer at ${governanceProposerAddress}`);
|
|
59
153
|
// @note @LHerskind the assets are expected to be the same at some point, but for better
|
|
60
154
|
// configurability they are different for now.
|
|
61
|
-
const governanceAddress = await deployer.deploy(GovernanceArtifact, [
|
|
155
|
+
const { address: governanceAddress } = await deployer.deploy(GovernanceArtifact, [
|
|
62
156
|
stakingAssetAddress.toString(),
|
|
63
157
|
governanceProposerAddress.toString(),
|
|
64
158
|
gseAddress.toString(),
|
|
@@ -98,11 +192,11 @@ export const deploySharedContracts = async (l1Client, deployer, args, logger)=>{
|
|
|
98
192
|
logger.verbose(`Set governance on GSE in ${txHash}`);
|
|
99
193
|
txHashes.push(txHash);
|
|
100
194
|
}
|
|
101
|
-
const coinIssuerAddress = await deployer.deploy(CoinIssuerArtifact, [
|
|
195
|
+
const coinIssuerAddress = (await deployer.deploy(CoinIssuerArtifact, [
|
|
102
196
|
feeAssetAddress.toString(),
|
|
103
|
-
|
|
197
|
+
25_000_000_000n * 10n ** 18n / (60n * 60n * 24n * 365n),
|
|
104
198
|
l1Client.account.address
|
|
105
|
-
]);
|
|
199
|
+
])).address;
|
|
106
200
|
logger.verbose(`Deployed CoinIssuer at ${coinIssuerAddress}`);
|
|
107
201
|
logger.verbose(`Waiting for deployments to complete`);
|
|
108
202
|
await deployer.waitForDeployments();
|
|
@@ -110,13 +204,13 @@ export const deploySharedContracts = async (l1Client, deployer, args, logger)=>{
|
|
|
110
204
|
let feeAssetHandlerAddress = undefined;
|
|
111
205
|
let stakingAssetHandlerAddress = undefined;
|
|
112
206
|
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, [
|
|
207
|
+
// Only if not on mainnet will we deploy the handlers, and only when we control the token
|
|
208
|
+
if (l1Client.chain.id !== 1 && !args.existingTokenAddress) {
|
|
209
|
+
/* -------------------------------------------------------------------------- */ /* CHEAT CODES START HERE */ /* -------------------------------------------------------------------------- */ feeAssetHandlerAddress = (await deployer.deploy(FeeAssetHandlerArtifact, [
|
|
116
210
|
l1Client.account.address,
|
|
117
211
|
feeAssetAddress.toString(),
|
|
118
212
|
BigInt(1000n * 10n ** 18n)
|
|
119
|
-
]);
|
|
213
|
+
])).address;
|
|
120
214
|
logger.verbose(`Deployed FeeAssetHandler at ${feeAssetHandlerAddress}`);
|
|
121
215
|
// Only if we are "fresh" will we be adding as a minter, otherwise above will simply get same address
|
|
122
216
|
if (needToSetGovernance) {
|
|
@@ -147,6 +241,7 @@ export const deploySharedContracts = async (l1Client, deployer, args, logger)=>{
|
|
|
147
241
|
stakingAsset: stakingAssetAddress.toString(),
|
|
148
242
|
registry: registryAddress.toString(),
|
|
149
243
|
withdrawer: AMIN.toString(),
|
|
244
|
+
validatorsToFlush: 16n,
|
|
150
245
|
mintInterval: BigInt(60 * 60 * 24),
|
|
151
246
|
depositsPerMint: BigInt(10),
|
|
152
247
|
depositMerkleRoot: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
@@ -161,9 +256,9 @@ export const deploySharedContracts = async (l1Client, deployer, args, logger)=>{
|
|
|
161
256
|
skipBindCheck: args.zkPassportArgs?.mockZkPassportVerifier ?? false,
|
|
162
257
|
skipMerkleCheck: true
|
|
163
258
|
};
|
|
164
|
-
stakingAssetHandlerAddress = await deployer.deploy(StakingAssetHandlerArtifact, [
|
|
259
|
+
stakingAssetHandlerAddress = (await deployer.deploy(StakingAssetHandlerArtifact, [
|
|
165
260
|
stakingAssetHandlerDeployArgs
|
|
166
|
-
]);
|
|
261
|
+
])).address;
|
|
167
262
|
logger.verbose(`Deployed StakingAssetHandler at ${stakingAssetHandlerAddress}`);
|
|
168
263
|
const { txHash: stakingMinterTxHash } = await deployer.sendTransaction({
|
|
169
264
|
to: stakingAssetAddress.toString(),
|
|
@@ -187,20 +282,24 @@ export const deploySharedContracts = async (l1Client, deployer, args, logger)=>{
|
|
|
187
282
|
logger.verbose(`Deployed shared contracts`);
|
|
188
283
|
const registry = new RegistryContract(l1Client, registryAddress);
|
|
189
284
|
/* -------------------------------------------------------------------------- */ /* FUND REWARD DISTRIBUTOR START */ /* -------------------------------------------------------------------------- */ const rewardDistributorAddress = await registry.getRewardDistributor();
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
285
|
+
if (!args.existingTokenAddress) {
|
|
286
|
+
const blockReward = getRewardConfig(networkName).blockReward;
|
|
287
|
+
const funding = blockReward * 200000n;
|
|
288
|
+
const { txHash: fundRewardDistributorTxHash } = await deployer.sendTransaction({
|
|
289
|
+
to: feeAssetAddress.toString(),
|
|
290
|
+
data: encodeFunctionData({
|
|
291
|
+
abi: FeeAssetArtifact.contractAbi,
|
|
292
|
+
functionName: 'mint',
|
|
293
|
+
args: [
|
|
294
|
+
rewardDistributorAddress.toString(),
|
|
295
|
+
funding
|
|
296
|
+
]
|
|
297
|
+
})
|
|
298
|
+
});
|
|
299
|
+
logger.verbose(`Funded reward distributor with ${funding} fee asset in ${fundRewardDistributorTxHash}`);
|
|
300
|
+
} else {
|
|
301
|
+
logger.verbose(`Skipping reward distributor funding as existing token is provided`);
|
|
302
|
+
}
|
|
204
303
|
/* -------------------------------------------------------------------------- */ /* FUND REWARD DISTRIBUTOR STOP */ /* -------------------------------------------------------------------------- */ return {
|
|
205
304
|
feeAssetAddress,
|
|
206
305
|
feeAssetHandlerAddress,
|
|
@@ -217,7 +316,7 @@ export const deploySharedContracts = async (l1Client, deployer, args, logger)=>{
|
|
|
217
316
|
};
|
|
218
317
|
const getZkPassportVerifierAddress = async (deployer, args)=>{
|
|
219
318
|
if (args.zkPassportArgs?.mockZkPassportVerifier) {
|
|
220
|
-
return await deployer.deploy(mockVerifiers.mockZkPassportVerifier);
|
|
319
|
+
return (await deployer.deploy(mockVerifiers.mockZkPassportVerifier)).address;
|
|
221
320
|
}
|
|
222
321
|
return ZK_PASSPORT_VERIFIER_ADDRESS;
|
|
223
322
|
};
|
|
@@ -251,17 +350,17 @@ const getZkPassportVerifierAddress = async (deployer, args)=>{
|
|
|
251
350
|
};
|
|
252
351
|
};
|
|
253
352
|
export const deploySlashFactory = async (deployer, rollupAddress, logger)=>{
|
|
254
|
-
const slashFactoryAddress = await deployer.deploy(SlashFactoryArtifact, [
|
|
353
|
+
const slashFactoryAddress = (await deployer.deploy(SlashFactoryArtifact, [
|
|
255
354
|
rollupAddress
|
|
256
|
-
]);
|
|
355
|
+
])).address;
|
|
257
356
|
logger.verbose(`Deployed SlashFactory at ${slashFactoryAddress}`);
|
|
258
357
|
return slashFactoryAddress;
|
|
259
358
|
};
|
|
260
359
|
export const deployUpgradePayload = async (deployer, addresses)=>{
|
|
261
|
-
const payloadAddress = await deployer.deploy(RegisterNewRollupVersionPayloadArtifact, [
|
|
360
|
+
const payloadAddress = (await deployer.deploy(RegisterNewRollupVersionPayloadArtifact, [
|
|
262
361
|
addresses.registryAddress.toString(),
|
|
263
362
|
addresses.rollupAddress.toString()
|
|
264
|
-
]);
|
|
363
|
+
])).address;
|
|
265
364
|
return payloadAddress;
|
|
266
365
|
};
|
|
267
366
|
function slasherFlavorToSolidityEnum(flavor) {
|
|
@@ -285,14 +384,15 @@ function slasherFlavorToSolidityEnum(flavor) {
|
|
|
285
384
|
if (!addresses.gseAddress) {
|
|
286
385
|
throw new Error('GSE address is required when deploying');
|
|
287
386
|
}
|
|
387
|
+
const networkName = getActiveNetworkName();
|
|
288
388
|
logger.info(`Deploying rollup using network configuration: ${networkName}`);
|
|
289
389
|
const txHashes = [];
|
|
290
390
|
let epochProofVerifier = EthAddress.ZERO;
|
|
291
391
|
if (args.realVerifier) {
|
|
292
|
-
epochProofVerifier = await deployer.deploy(l1ArtifactsVerifiers.honkVerifier);
|
|
392
|
+
epochProofVerifier = (await deployer.deploy(l1ArtifactsVerifiers.honkVerifier)).address;
|
|
293
393
|
logger.verbose(`Rollup will use the real verifier at ${epochProofVerifier}`);
|
|
294
394
|
} else {
|
|
295
|
-
epochProofVerifier = await deployer.deploy(mockVerifiers.mockVerifier);
|
|
395
|
+
epochProofVerifier = (await deployer.deploy(mockVerifiers.mockVerifier)).address;
|
|
296
396
|
logger.verbose(`Rollup will use the mock verifier at ${epochProofVerifier}`);
|
|
297
397
|
}
|
|
298
398
|
const rewardConfig = {
|
|
@@ -303,6 +403,7 @@ function slasherFlavorToSolidityEnum(flavor) {
|
|
|
303
403
|
aztecSlotDuration: BigInt(args.aztecSlotDuration),
|
|
304
404
|
aztecEpochDuration: BigInt(args.aztecEpochDuration),
|
|
305
405
|
targetCommitteeSize: BigInt(args.aztecTargetCommitteeSize),
|
|
406
|
+
lagInEpochs: BigInt(args.lagInEpochs),
|
|
306
407
|
aztecProofSubmissionEpochs: BigInt(args.aztecProofSubmissionEpochs),
|
|
307
408
|
slashingQuorum: BigInt(args.slashingQuorum ?? args.slashingRoundSizeInEpochs * args.aztecEpochDuration / 2 + 1),
|
|
308
409
|
slashingRoundSize: BigInt(args.slashingRoundSizeInEpochs * args.aztecEpochDuration),
|
|
@@ -322,7 +423,9 @@ function slasherFlavorToSolidityEnum(flavor) {
|
|
|
322
423
|
args.slashAmountSmall,
|
|
323
424
|
args.slashAmountMedium,
|
|
324
425
|
args.slashAmountLarge
|
|
325
|
-
]
|
|
426
|
+
],
|
|
427
|
+
localEjectionThreshold: args.localEjectionThreshold,
|
|
428
|
+
slashingDisableDuration: BigInt(args.slashingDisableDuration ?? 0n)
|
|
326
429
|
};
|
|
327
430
|
const genesisStateArgs = {
|
|
328
431
|
vkTreeRoot: args.vkTreeRoot.toString(),
|
|
@@ -345,33 +448,38 @@ function slasherFlavorToSolidityEnum(flavor) {
|
|
|
345
448
|
genesisStateArgs,
|
|
346
449
|
rollupConfigArgs
|
|
347
450
|
];
|
|
348
|
-
const rollupAddress = await deployer.deploy(RollupArtifact, rollupArgs, {
|
|
451
|
+
const { address: rollupAddress, existed: rollupExisted } = await deployer.deploy(RollupArtifact, rollupArgs, {
|
|
349
452
|
gasLimit: 15_000_000n
|
|
350
453
|
});
|
|
351
|
-
logger.verbose(`Deployed Rollup at ${rollupAddress}`, rollupConfigArgs);
|
|
454
|
+
logger.verbose(`Deployed Rollup at ${rollupAddress}, already existed: ${rollupExisted}`, rollupConfigArgs);
|
|
352
455
|
const rollupContract = new RollupContract(extendedClient, rollupAddress);
|
|
353
456
|
await deployer.waitForDeployments();
|
|
354
457
|
logger.verbose(`All core contracts have been deployed`);
|
|
355
458
|
if (args.feeJuicePortalInitialBalance && args.feeJuicePortalInitialBalance > 0n) {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
to
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
args
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
459
|
+
// Skip funding when using an external token, as we likely don't have mint permissions
|
|
460
|
+
if (!('existingTokenAddress' in args) || !args.existingTokenAddress) {
|
|
461
|
+
const feeJuicePortalAddress = await rollupContract.getFeeJuicePortal();
|
|
462
|
+
// In fast mode, use the L1TxUtils to send transactions with nonce management
|
|
463
|
+
const { txHash: mintTxHash } = await deployer.sendTransaction({
|
|
464
|
+
to: addresses.feeJuiceAddress.toString(),
|
|
465
|
+
data: encodeFunctionData({
|
|
466
|
+
abi: FeeAssetArtifact.contractAbi,
|
|
467
|
+
functionName: 'mint',
|
|
468
|
+
args: [
|
|
469
|
+
feeJuicePortalAddress.toString(),
|
|
470
|
+
args.feeJuicePortalInitialBalance
|
|
471
|
+
]
|
|
472
|
+
})
|
|
473
|
+
});
|
|
474
|
+
logger.verbose(`Funding fee juice portal with ${args.feeJuicePortalInitialBalance} fee juice in ${mintTxHash} (accelerated test deployments)`);
|
|
475
|
+
txHashes.push(mintTxHash);
|
|
476
|
+
} else {
|
|
477
|
+
logger.verbose('Skipping fee juice portal funding due to external token usage');
|
|
478
|
+
}
|
|
371
479
|
}
|
|
372
|
-
const slashFactoryAddress = await deployer.deploy(SlashFactoryArtifact, [
|
|
480
|
+
const slashFactoryAddress = (await deployer.deploy(SlashFactoryArtifact, [
|
|
373
481
|
rollupAddress.toString()
|
|
374
|
-
]);
|
|
482
|
+
])).address;
|
|
375
483
|
logger.verbose(`Deployed SlashFactory at ${slashFactoryAddress}`);
|
|
376
484
|
// We need to call a function on the registry to set the various contract addresses.
|
|
377
485
|
const registryContract = getContract({
|
|
@@ -435,7 +543,11 @@ function slasherFlavorToSolidityEnum(flavor) {
|
|
|
435
543
|
} else {
|
|
436
544
|
logger.verbose(`Not the owner of the gse, skipping rollup addition`);
|
|
437
545
|
}
|
|
438
|
-
|
|
546
|
+
const activeAttestorCount = await rollupContract.getActiveAttesterCount();
|
|
547
|
+
const queuedAttestorCount = await rollupContract.getEntryQueueLength();
|
|
548
|
+
logger.info(`Rollup has ${activeAttestorCount} active attestors and ${queuedAttestorCount} queued attestors`);
|
|
549
|
+
const shouldAddValidators = activeAttestorCount === 0n && queuedAttestorCount === 0n;
|
|
550
|
+
if (args.initialValidators && shouldAddValidators && await gseContract.read.isRollupRegistered([
|
|
439
551
|
rollupContract.address
|
|
440
552
|
])) {
|
|
441
553
|
await addMultipleValidators(extendedClient, deployer, addresses.gseAddress.toString(), rollupAddress.toString(), addresses.stakingAssetAddress.toString(), args.initialValidators, args.acceleratedTestDeployments, logger);
|
|
@@ -467,7 +579,7 @@ function slasherFlavorToSolidityEnum(flavor) {
|
|
|
467
579
|
slashFactoryAddress
|
|
468
580
|
};
|
|
469
581
|
};
|
|
470
|
-
export const handoverToGovernance = async (extendedClient, deployer, registryAddress, gseAddress, coinIssuerAddress, feeAssetAddress, governanceAddress, logger, acceleratedTestDeployments)=>{
|
|
582
|
+
export const handoverToGovernance = async (extendedClient, deployer, registryAddress, gseAddress, coinIssuerAddress, feeAssetAddress, governanceAddress, logger, acceleratedTestDeployments, useExternalToken = false)=>{
|
|
471
583
|
// We need to call a function on the registry to set the various contract addresses.
|
|
472
584
|
const registryContract = getContract({
|
|
473
585
|
address: getAddress(registryAddress.toString()),
|
|
@@ -522,7 +634,7 @@ export const handoverToGovernance = async (extendedClient, deployer, registryAdd
|
|
|
522
634
|
logger.verbose(`Transferring the ownership of the gse contract at ${gseAddress} to the Governance ${governanceAddress} in tx ${transferOwnershipTxHash}`);
|
|
523
635
|
txHashes.push(transferOwnershipTxHash);
|
|
524
636
|
}
|
|
525
|
-
if (acceleratedTestDeployments || await feeAsset.read.owner() !== coinIssuerAddress.toString()) {
|
|
637
|
+
if (!useExternalToken && (acceleratedTestDeployments || await feeAsset.read.owner() !== coinIssuerAddress.toString())) {
|
|
526
638
|
const { txHash } = await deployer.sendTransaction({
|
|
527
639
|
to: feeAssetAddress.toString(),
|
|
528
640
|
data: encodeFunctionData({
|
|
@@ -548,20 +660,27 @@ export const handoverToGovernance = async (extendedClient, deployer, registryAdd
|
|
|
548
660
|
});
|
|
549
661
|
logger.verbose(`Accept ownership of fee asset in ${acceptTokenOwnershipTxHash}`);
|
|
550
662
|
txHashes.push(acceptTokenOwnershipTxHash);
|
|
663
|
+
} else if (useExternalToken) {
|
|
664
|
+
logger.verbose('Skipping fee asset ownership transfer due to external token usage');
|
|
551
665
|
}
|
|
666
|
+
// Either deploy or at least predict the address of the date gated relayer
|
|
667
|
+
const dateGatedRelayer = await deployer.deploy(DateGatedRelayerArtifact, [
|
|
668
|
+
governanceAddress.toString(),
|
|
669
|
+
1798761600n
|
|
670
|
+
]);
|
|
552
671
|
// If the owner is not the Governance contract, transfer ownership to the Governance contract
|
|
553
|
-
if (acceleratedTestDeployments || await coinIssuerContract.read.owner()
|
|
672
|
+
if (acceleratedTestDeployments || await coinIssuerContract.read.owner() === deployer.client.account.address) {
|
|
554
673
|
const { txHash: transferOwnershipTxHash } = await deployer.sendTransaction({
|
|
555
674
|
to: coinIssuerContract.address,
|
|
556
675
|
data: encodeFunctionData({
|
|
557
676
|
abi: CoinIssuerArtifact.contractAbi,
|
|
558
677
|
functionName: 'transferOwnership',
|
|
559
678
|
args: [
|
|
560
|
-
getAddress(
|
|
679
|
+
getAddress(dateGatedRelayer.address.toString())
|
|
561
680
|
]
|
|
562
681
|
})
|
|
563
682
|
});
|
|
564
|
-
logger.verbose(`Transferring the ownership of the coin issuer contract at ${coinIssuerAddress} to the
|
|
683
|
+
logger.verbose(`Transferring the ownership of the coin issuer contract at ${coinIssuerAddress} to the DateGatedRelayer ${dateGatedRelayer.address} in tx ${transferOwnershipTxHash}`);
|
|
565
684
|
txHashes.push(transferOwnershipTxHash);
|
|
566
685
|
}
|
|
567
686
|
// Wait for all actions to be mined
|
|
@@ -569,6 +688,9 @@ export const handoverToGovernance = async (extendedClient, deployer, registryAdd
|
|
|
569
688
|
await Promise.all(txHashes.map((txHash)=>extendedClient.waitForTransactionReceipt({
|
|
570
689
|
hash: txHash
|
|
571
690
|
})));
|
|
691
|
+
return {
|
|
692
|
+
dateGatedRelayerAddress: dateGatedRelayer.address
|
|
693
|
+
};
|
|
572
694
|
};
|
|
573
695
|
/*
|
|
574
696
|
* Adds multiple validators to the rollup
|
|
@@ -596,85 +718,94 @@ export const handoverToGovernance = async (extendedClient, deployer, registryAdd
|
|
|
596
718
|
}
|
|
597
719
|
validators = enrichedValidators.filter((v)=>v.status === 0).map((v)=>v.operator);
|
|
598
720
|
}
|
|
599
|
-
if (validators.length
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
721
|
+
if (validators.length === 0) {
|
|
722
|
+
logger.warn('No validators to add. Skipping.');
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
const gseContract = new GSEContract(extendedClient, gseAddress);
|
|
726
|
+
const multiAdder = (await deployer.deploy(MultiAdderArtifact, [
|
|
727
|
+
rollupAddress,
|
|
728
|
+
deployer.client.account.address
|
|
729
|
+
])).address;
|
|
730
|
+
const makeValidatorTuples = async (validator)=>{
|
|
731
|
+
const registrationTuple = await gseContract.makeRegistrationTuple(validator.bn254SecretKey.getValue());
|
|
732
|
+
return {
|
|
733
|
+
attester: getAddress(validator.attester.toString()),
|
|
734
|
+
withdrawer: getAddress(validator.withdrawer.toString()),
|
|
735
|
+
...registrationTuple
|
|
612
736
|
};
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
737
|
+
};
|
|
738
|
+
const validatorsTuples = await Promise.all(validators.map(makeValidatorTuples));
|
|
739
|
+
// Mint tokens, approve them, use cheat code to initialize validator set without setting up the epoch.
|
|
740
|
+
const stakeNeeded = activationThreshold * BigInt(validators.length);
|
|
741
|
+
await deployer.l1TxUtils.sendAndMonitorTransaction({
|
|
742
|
+
to: stakingAssetAddress,
|
|
743
|
+
data: encodeFunctionData({
|
|
744
|
+
abi: StakingAssetArtifact.contractAbi,
|
|
745
|
+
functionName: 'mint',
|
|
746
|
+
args: [
|
|
747
|
+
multiAdder.toString(),
|
|
748
|
+
stakeNeeded
|
|
749
|
+
]
|
|
750
|
+
})
|
|
751
|
+
});
|
|
752
|
+
const entryQueueLengthBefore = await rollup.getEntryQueueLength();
|
|
753
|
+
const validatorCountBefore = await rollup.getActiveAttesterCount();
|
|
754
|
+
logger.info(`Adding ${validators.length} validators to the rollup`);
|
|
755
|
+
const chunkSize = 16;
|
|
756
|
+
// We will add `chunkSize` validators to the queue until we have covered all of our validators.
|
|
757
|
+
// The `chunkSize` needs to be small enough to fit inside a single tx, therefore 16.
|
|
758
|
+
for (const c of chunk(validatorsTuples, chunkSize)){
|
|
616
759
|
await deployer.l1TxUtils.sendAndMonitorTransaction({
|
|
617
|
-
to:
|
|
760
|
+
to: multiAdder.toString(),
|
|
618
761
|
data: encodeFunctionData({
|
|
619
|
-
abi:
|
|
620
|
-
functionName: '
|
|
762
|
+
abi: MultiAdderArtifact.contractAbi,
|
|
763
|
+
functionName: 'addValidators',
|
|
621
764
|
args: [
|
|
622
|
-
|
|
623
|
-
|
|
765
|
+
c,
|
|
766
|
+
BigInt(chunkSize)
|
|
624
767
|
]
|
|
625
768
|
})
|
|
769
|
+
}, {
|
|
770
|
+
gasLimit: 16_000_000n
|
|
626
771
|
});
|
|
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
|
-
});
|
|
772
|
+
}
|
|
773
|
+
// After adding to the queue, we will now try to flush from it.
|
|
774
|
+
// We are explicitly doing this as a second step instead of as part of adding to benefit
|
|
775
|
+
// from the accounting used to speed the process up.
|
|
776
|
+
// As the queue computes the amount of possible flushes in an epoch when told to flush,
|
|
777
|
+
// waiting until we have added all we want allows us to benefit in the case were we added
|
|
778
|
+
// enough to pass the bootstrap set size without needing to wait another epoch.
|
|
779
|
+
// This is useful when we are testing as it speeds up the tests slightly.
|
|
780
|
+
while(true){
|
|
781
|
+
// If the queue is empty, we can break
|
|
782
|
+
if (await rollup.getEntryQueueLength() == 0n) {
|
|
783
|
+
break;
|
|
670
784
|
}
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
throw new Error(`Failed to add ${validators.length} validators. Active validators: ${validatorCountBefore} -> ${validatorCountAfter}. Queue: ${entryQueueLengthBefore} -> ${entryQueueLengthAfter}`);
|
|
785
|
+
// If there are no available validator flushes, no need to even try
|
|
786
|
+
if (await rollup.getAvailableValidatorFlushes() == 0n) {
|
|
787
|
+
break;
|
|
675
788
|
}
|
|
676
|
-
|
|
789
|
+
// Note that we are flushing at most `chunkSize` at each call
|
|
790
|
+
await deployer.l1TxUtils.sendAndMonitorTransaction({
|
|
791
|
+
to: rollup.address,
|
|
792
|
+
data: encodeFunctionData({
|
|
793
|
+
abi: RollupArtifact.contractAbi,
|
|
794
|
+
functionName: 'flushEntryQueue',
|
|
795
|
+
args: [
|
|
796
|
+
BigInt(chunkSize)
|
|
797
|
+
]
|
|
798
|
+
})
|
|
799
|
+
}, {
|
|
800
|
+
gasLimit: 16_000_000n
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
const entryQueueLengthAfter = await rollup.getEntryQueueLength();
|
|
804
|
+
const validatorCountAfter = await rollup.getActiveAttesterCount();
|
|
805
|
+
if (entryQueueLengthAfter + validatorCountAfter < entryQueueLengthBefore + validatorCountBefore + BigInt(validators.length)) {
|
|
806
|
+
throw new Error(`Failed to add ${validators.length} validators. Active validators: ${validatorCountBefore} -> ${validatorCountAfter}. Queue: ${entryQueueLengthBefore} -> ${entryQueueLengthAfter}. A likely issue is the bootstrap size.`);
|
|
677
807
|
}
|
|
808
|
+
logger.info(`Added ${validators.length} validators. Active validators: ${validatorCountBefore} -> ${validatorCountAfter}. Queue: ${entryQueueLengthBefore} -> ${entryQueueLengthAfter}`);
|
|
678
809
|
}
|
|
679
810
|
};
|
|
680
811
|
/**
|
|
@@ -687,11 +818,11 @@ export const handoverToGovernance = async (extendedClient, deployer, registryAdd
|
|
|
687
818
|
* @param logger - The logger.
|
|
688
819
|
*/ // eslint-disable-next-line camelcase
|
|
689
820
|
export const cheat_initializeFeeAssetHandler = async (extendedClient, deployer, feeAssetAddress, logger)=>{
|
|
690
|
-
const feeAssetHandlerAddress = await deployer.deploy(FeeAssetHandlerArtifact, [
|
|
821
|
+
const feeAssetHandlerAddress = (await deployer.deploy(FeeAssetHandlerArtifact, [
|
|
691
822
|
extendedClient.account.address,
|
|
692
823
|
feeAssetAddress.toString(),
|
|
693
824
|
BigInt(1e18)
|
|
694
|
-
]);
|
|
825
|
+
])).address;
|
|
695
826
|
logger.verbose(`Deployed FeeAssetHandler at ${feeAssetHandlerAddress}`);
|
|
696
827
|
const { txHash } = await deployer.sendTransaction({
|
|
697
828
|
to: feeAssetAddress.toString(),
|
|
@@ -720,6 +851,9 @@ export const cheat_initializeFeeAssetHandler = async (extendedClient, deployer,
|
|
|
720
851
|
*/ export const deployL1Contracts = async (rpcUrls, account, chain, logger, args, txUtilsConfig = getL1TxUtilsConfigEnvVars(), createVerificationJson = false)=>{
|
|
721
852
|
logger.info(`Deploying L1 contracts with config: ${jsonStringify(args)}`);
|
|
722
853
|
validateConfig(args);
|
|
854
|
+
if (args.initialValidators && args.initialValidators.length > 0 && args.existingTokenAddress) {
|
|
855
|
+
throw new Error('Cannot deploy with both initialValidators and existingTokenAddress. ' + 'Initial validator funding requires minting tokens, which is not possible with an external token.');
|
|
856
|
+
}
|
|
723
857
|
const l1Client = createExtendedL1Client(rpcUrls, account, chain);
|
|
724
858
|
// Deploy multicall3 if it does not exist in this network
|
|
725
859
|
await deployMulticall3(l1Client, logger);
|
|
@@ -757,7 +891,7 @@ export const cheat_initializeFeeAssetHandler = async (extendedClient, deployer,
|
|
|
757
891
|
logger.verbose('Waiting for rollup and slash factory to be deployed');
|
|
758
892
|
await deployer.waitForDeployments();
|
|
759
893
|
// 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);
|
|
894
|
+
const { dateGatedRelayerAddress } = await handoverToGovernance(l1Client, deployer, registryAddress, gseAddress, coinIssuerAddress, feeAssetAddress, governanceAddress, logger, args.acceleratedTestDeployments, !!args.existingTokenAddress);
|
|
761
895
|
logger.info(`Handing over to governance complete`);
|
|
762
896
|
logger.verbose(`All transactions for L1 deployment have been mined`);
|
|
763
897
|
const l1Contracts = await RegistryContract.collectAddresses(l1Client, registryAddress, 'canonical');
|
|
@@ -946,6 +1080,7 @@ export const cheat_initializeFeeAssetHandler = async (extendedClient, deployer,
|
|
|
946
1080
|
recursive: true
|
|
947
1081
|
});
|
|
948
1082
|
const verificationOutputPath = `${createVerificationJson}/l1-verify-${chain.id}-${formattedDate.slice(0, 6)}-${formattedDate.slice(6)}.json`;
|
|
1083
|
+
const networkName = getActiveNetworkName();
|
|
949
1084
|
const verificationData = {
|
|
950
1085
|
chainId: chain.id,
|
|
951
1086
|
network: networkName,
|
|
@@ -990,7 +1125,8 @@ export const cheat_initializeFeeAssetHandler = async (extendedClient, deployer,
|
|
|
990
1125
|
feeAssetHandlerAddress,
|
|
991
1126
|
stakingAssetHandlerAddress,
|
|
992
1127
|
zkPassportVerifierAddress,
|
|
993
|
-
coinIssuerAddress
|
|
1128
|
+
coinIssuerAddress,
|
|
1129
|
+
dateGatedRelayerAddress
|
|
994
1130
|
}
|
|
995
1131
|
};
|
|
996
1132
|
};
|
|
@@ -1015,14 +1151,20 @@ export class L1Deployer {
|
|
|
1015
1151
|
this.salt = maybeSalt ? padHex(numberToHex(maybeSalt), {
|
|
1016
1152
|
size: 32
|
|
1017
1153
|
}) : undefined;
|
|
1018
|
-
this.l1TxUtils = createL1TxUtilsFromViemWallet(this.client,
|
|
1154
|
+
this.l1TxUtils = createL1TxUtilsFromViemWallet(this.client, {
|
|
1155
|
+
logger: this.logger,
|
|
1156
|
+
dateProvider
|
|
1157
|
+
}, {
|
|
1158
|
+
...this.txUtilsConfig,
|
|
1159
|
+
debugMaxGasLimit: acceleratedTestDeployments
|
|
1160
|
+
});
|
|
1019
1161
|
}
|
|
1020
1162
|
async deploy(params, args, opts = {}) {
|
|
1021
1163
|
this.logger.debug(`Deploying ${params.name} contract`, {
|
|
1022
1164
|
args
|
|
1023
1165
|
});
|
|
1024
1166
|
try {
|
|
1025
|
-
const { txHash, address, deployedLibraries } = await deployL1Contract(this.client, params.contractAbi, params.contractBytecode, args ?? [], {
|
|
1167
|
+
const { txHash, address, deployedLibraries, existed } = await deployL1Contract(this.client, params.contractAbi, params.contractBytecode, args ?? [], {
|
|
1026
1168
|
salt: this.salt,
|
|
1027
1169
|
libraries: params.libraries,
|
|
1028
1170
|
logger: this.logger,
|
|
@@ -1053,7 +1195,10 @@ export class L1Deployer {
|
|
|
1053
1195
|
libraries: deployedLibraries ?? []
|
|
1054
1196
|
});
|
|
1055
1197
|
}
|
|
1056
|
-
return
|
|
1198
|
+
return {
|
|
1199
|
+
address,
|
|
1200
|
+
existed
|
|
1201
|
+
};
|
|
1057
1202
|
} catch (error) {
|
|
1058
1203
|
throw new Error(`Failed to deploy ${params.name}`, {
|
|
1059
1204
|
cause: formatViemError(error)
|
|
@@ -1083,7 +1228,11 @@ export class L1Deployer {
|
|
|
1083
1228
|
});
|
|
1084
1229
|
}
|
|
1085
1230
|
sendTransaction(tx, options) {
|
|
1086
|
-
return this.l1TxUtils.sendTransaction(tx, options)
|
|
1231
|
+
return this.l1TxUtils.sendTransaction(tx, options).then(({ txHash, state })=>({
|
|
1232
|
+
txHash,
|
|
1233
|
+
gasLimit: state.gasLimit,
|
|
1234
|
+
gasPrice: state.gasPrice
|
|
1235
|
+
}));
|
|
1087
1236
|
}
|
|
1088
1237
|
}
|
|
1089
1238
|
// docs:start:deployL1Contract
|
|
@@ -1104,7 +1253,12 @@ export class L1Deployer {
|
|
|
1104
1253
|
let { l1TxUtils } = opts;
|
|
1105
1254
|
if (!l1TxUtils) {
|
|
1106
1255
|
const config = getL1TxUtilsConfigEnvVars();
|
|
1107
|
-
l1TxUtils = createL1TxUtilsFromViemWallet(extendedClient,
|
|
1256
|
+
l1TxUtils = createL1TxUtilsFromViemWallet(extendedClient, {
|
|
1257
|
+
logger
|
|
1258
|
+
}, {
|
|
1259
|
+
...config,
|
|
1260
|
+
debugMaxGasLimit: acceleratedTestDeployments
|
|
1261
|
+
});
|
|
1108
1262
|
}
|
|
1109
1263
|
if (libraries) {
|
|
1110
1264
|
// Note that this does NOT work well for linked libraries having linked libraries.
|
|
@@ -1179,6 +1333,7 @@ export class L1Deployer {
|
|
|
1179
1333
|
logger?.verbose(`Skipping waiting for linked libraries to be deployed ${acceleratedTestDeployments ? '(accelerated test deployments)' : ''}`);
|
|
1180
1334
|
}
|
|
1181
1335
|
}
|
|
1336
|
+
let existed = false;
|
|
1182
1337
|
if (saltFromOpts) {
|
|
1183
1338
|
logger?.info(`Deploying contract with salt ${saltFromOpts}`);
|
|
1184
1339
|
const { address, paddedSalt: salt, calldata } = getExpectedAddress(abi, bytecode, args, saltFromOpts);
|
|
@@ -1221,6 +1376,7 @@ export class L1Deployer {
|
|
|
1221
1376
|
logger?.verbose(`Deployed contract with salt ${salt} to address ${resultingAddress} in tx ${txHash}.`);
|
|
1222
1377
|
} else {
|
|
1223
1378
|
logger?.verbose(`Skipping existing deployment of contract with salt ${salt} to address ${resultingAddress}`);
|
|
1379
|
+
existed = true;
|
|
1224
1380
|
}
|
|
1225
1381
|
} else {
|
|
1226
1382
|
const deployData = encodeDeployData({
|
|
@@ -1241,7 +1397,8 @@ export class L1Deployer {
|
|
|
1241
1397
|
return {
|
|
1242
1398
|
address: EthAddress.fromString(resultingAddress),
|
|
1243
1399
|
txHash,
|
|
1244
|
-
deployedLibraries
|
|
1400
|
+
deployedLibraries,
|
|
1401
|
+
existed
|
|
1245
1402
|
};
|
|
1246
1403
|
}
|
|
1247
1404
|
export function getExpectedAddress(abi, bytecode, args, salt) {
|