@aztec/ethereum 0.74.0 → 0.75.0-commit.c03ba01a2a4122e43e90d5133ba017e54b90e9d2
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/chain.js +17 -18
- package/dest/client.js +5 -9
- package/dest/config.js +13 -14
- package/dest/constants.js +0 -1
- package/dest/contracts/empire_base.js +3 -2
- package/dest/contracts/forwarder.js +46 -26
- package/dest/contracts/governance.js +11 -6
- package/dest/contracts/governance_proposer.js +78 -67
- package/dest/contracts/index.js +0 -1
- package/dest/contracts/rollup.js +270 -243
- package/dest/contracts/slashing_proposer.js +18 -8
- package/dest/deploy_l1_contracts.js +201 -126
- package/dest/eth_cheat_codes.js +144 -127
- package/dest/index.js +0 -1
- package/dest/l1_contract_addresses.js +17 -19
- package/dest/l1_reader.js +6 -7
- package/dest/l1_tx_utils.js +227 -186
- package/dest/l1_tx_utils_with_blobs.js +25 -22
- package/dest/queries.js +6 -9
- package/dest/test/delayed_tx_utils.js +3 -3
- package/dest/test/eth_cheat_codes_with_state.js +10 -12
- package/dest/test/index.js +0 -1
- package/dest/test/start_anvil.js +17 -9
- package/dest/test/tx_delayer.js +77 -74
- package/dest/types.js +1 -2
- package/dest/utils.js +35 -36
- package/package.json +5 -4
- package/src/contracts/rollup.ts +1 -1
- package/src/l1_tx_utils_with_blobs.ts +1 -1
- package/dest/chain.d.ts +0 -25
- package/dest/chain.d.ts.map +0 -1
- package/dest/client.d.ts +0 -16
- package/dest/client.d.ts.map +0 -1
- package/dest/config.d.ts +0 -38
- package/dest/config.d.ts.map +0 -1
- package/dest/constants.d.ts +0 -4
- package/dest/constants.d.ts.map +0 -1
- package/dest/contracts/empire_base.d.ts +0 -13
- package/dest/contracts/empire_base.d.ts.map +0 -1
- package/dest/contracts/forwarder.d.ts +0 -24
- package/dest/contracts/forwarder.d.ts.map +0 -1
- package/dest/contracts/governance.d.ts +0 -14
- package/dest/contracts/governance.d.ts.map +0 -1
- package/dest/contracts/governance_proposer.d.ts +0 -28
- package/dest/contracts/governance_proposer.d.ts.map +0 -1
- package/dest/contracts/index.d.ts +0 -7
- package/dest/contracts/index.d.ts.map +0 -1
- package/dest/contracts/rollup.d.ts +0 -115
- package/dest/contracts/rollup.d.ts.map +0 -1
- package/dest/contracts/slashing_proposer.d.ts +0 -21
- package/dest/contracts/slashing_proposer.d.ts.map +0 -1
- package/dest/deploy_l1_contracts.d.ts +0 -21118
- package/dest/deploy_l1_contracts.d.ts.map +0 -1
- package/dest/eth_cheat_codes.d.ts +0 -146
- package/dest/eth_cheat_codes.d.ts.map +0 -1
- package/dest/index.d.ts +0 -15
- package/dest/index.d.ts.map +0 -1
- package/dest/l1_contract_addresses.d.ts +0 -55
- package/dest/l1_contract_addresses.d.ts.map +0 -1
- package/dest/l1_reader.d.ts +0 -16
- package/dest/l1_reader.d.ts.map +0 -1
- package/dest/l1_tx_utils.d.ts +0 -194
- package/dest/l1_tx_utils.d.ts.map +0 -1
- package/dest/l1_tx_utils_with_blobs.d.ts +0 -12
- package/dest/l1_tx_utils_with_blobs.d.ts.map +0 -1
- package/dest/queries.d.ts +0 -15
- package/dest/queries.d.ts.map +0 -1
- package/dest/test/delayed_tx_utils.d.ts +0 -8
- package/dest/test/delayed_tx_utils.d.ts.map +0 -1
- package/dest/test/eth_cheat_codes_with_state.d.ts +0 -18
- package/dest/test/eth_cheat_codes_with_state.d.ts.map +0 -1
- package/dest/test/index.d.ts +0 -5
- package/dest/test/index.d.ts.map +0 -1
- package/dest/test/start_anvil.d.ts +0 -9
- package/dest/test/start_anvil.d.ts.map +0 -1
- package/dest/test/tx_delayer.d.ts +0 -24
- package/dest/test/tx_delayer.d.ts.map +0 -1
- package/dest/types.d.ts +0 -12
- package/dest/types.d.ts.map +0 -1
- package/dest/utils.d.ts +0 -24
- package/dest/utils.d.ts.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
2
|
-
import { CoinIssuerAbi, CoinIssuerBytecode, ExtRollupLibAbi, ExtRollupLibBytecode, FeeJuicePortalAbi, FeeJuicePortalBytecode, ForwarderAbi, ForwarderBytecode, GovernanceAbi, GovernanceBytecode, GovernanceProposerAbi, GovernanceProposerBytecode, InboxAbi, InboxBytecode, OutboxAbi, OutboxBytecode, RegistryAbi, RegistryBytecode, RewardDistributorAbi, RewardDistributorBytecode, RollupAbi, RollupBytecode, RollupLinkReferences, SlashFactoryAbi, SlashFactoryBytecode, StakingLibAbi, StakingLibBytecode, TestERC20Abi, TestERC20Bytecode, ValidatorSelectionLibAbi, ValidatorSelectionLibBytecode
|
|
3
|
-
import { concatHex, createPublicClient, createWalletClient, encodeDeployData, getAddress, getContract, getContractAddress, http, numberToHex, padHex, publicActions
|
|
2
|
+
import { CoinIssuerAbi, CoinIssuerBytecode, ExtRollupLibAbi, ExtRollupLibBytecode, FeeJuicePortalAbi, FeeJuicePortalBytecode, ForwarderAbi, ForwarderBytecode, GovernanceAbi, GovernanceBytecode, GovernanceProposerAbi, GovernanceProposerBytecode, InboxAbi, InboxBytecode, OutboxAbi, OutboxBytecode, RegistryAbi, RegistryBytecode, RewardDistributorAbi, RewardDistributorBytecode, RollupAbi, RollupBytecode, RollupLinkReferences, SlashFactoryAbi, SlashFactoryBytecode, StakingLibAbi, StakingLibBytecode, TestERC20Abi, TestERC20Bytecode, ValidatorSelectionLibAbi, ValidatorSelectionLibBytecode } from '@aztec/l1-artifacts';
|
|
3
|
+
import { concatHex, createPublicClient, createWalletClient, encodeDeployData, getAddress, getContract, getContractAddress, http, numberToHex, padHex, publicActions } from 'viem';
|
|
4
4
|
import { mnemonicToAccount, privateKeyToAccount } from 'viem/accounts';
|
|
5
5
|
import { foundry } from 'viem/chains';
|
|
6
6
|
import { isAnvilTestChain } from './chain.js';
|
|
@@ -9,15 +9,15 @@ export const DEPLOYER_ADDRESS = '0x4e59b44847b379578588920cA78FbF26c0B4956C';
|
|
|
9
9
|
export const l1Artifacts = {
|
|
10
10
|
registry: {
|
|
11
11
|
contractAbi: RegistryAbi,
|
|
12
|
-
contractBytecode: RegistryBytecode
|
|
12
|
+
contractBytecode: RegistryBytecode
|
|
13
13
|
},
|
|
14
14
|
inbox: {
|
|
15
15
|
contractAbi: InboxAbi,
|
|
16
|
-
contractBytecode: InboxBytecode
|
|
16
|
+
contractBytecode: InboxBytecode
|
|
17
17
|
},
|
|
18
18
|
outbox: {
|
|
19
19
|
contractAbi: OutboxAbi,
|
|
20
|
-
contractBytecode: OutboxBytecode
|
|
20
|
+
contractBytecode: OutboxBytecode
|
|
21
21
|
},
|
|
22
22
|
rollup: {
|
|
23
23
|
contractAbi: RollupAbi,
|
|
@@ -27,51 +27,51 @@ export const l1Artifacts = {
|
|
|
27
27
|
libraryCode: {
|
|
28
28
|
ValidatorSelectionLib: {
|
|
29
29
|
contractAbi: ValidatorSelectionLibAbi,
|
|
30
|
-
contractBytecode: ValidatorSelectionLibBytecode
|
|
30
|
+
contractBytecode: ValidatorSelectionLibBytecode
|
|
31
31
|
},
|
|
32
32
|
ExtRollupLib: {
|
|
33
33
|
contractAbi: ExtRollupLibAbi,
|
|
34
|
-
contractBytecode: ExtRollupLibBytecode
|
|
34
|
+
contractBytecode: ExtRollupLibBytecode
|
|
35
35
|
},
|
|
36
36
|
StakingLib: {
|
|
37
37
|
contractAbi: StakingLibAbi,
|
|
38
|
-
contractBytecode: StakingLibBytecode
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
38
|
+
contractBytecode: StakingLibBytecode
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
42
|
},
|
|
43
43
|
stakingAsset: {
|
|
44
44
|
contractAbi: TestERC20Abi,
|
|
45
|
-
contractBytecode: TestERC20Bytecode
|
|
45
|
+
contractBytecode: TestERC20Bytecode
|
|
46
46
|
},
|
|
47
47
|
feeAsset: {
|
|
48
48
|
contractAbi: TestERC20Abi,
|
|
49
|
-
contractBytecode: TestERC20Bytecode
|
|
49
|
+
contractBytecode: TestERC20Bytecode
|
|
50
50
|
},
|
|
51
51
|
feeJuicePortal: {
|
|
52
52
|
contractAbi: FeeJuicePortalAbi,
|
|
53
|
-
contractBytecode: FeeJuicePortalBytecode
|
|
53
|
+
contractBytecode: FeeJuicePortalBytecode
|
|
54
54
|
},
|
|
55
55
|
rewardDistributor: {
|
|
56
56
|
contractAbi: RewardDistributorAbi,
|
|
57
|
-
contractBytecode: RewardDistributorBytecode
|
|
57
|
+
contractBytecode: RewardDistributorBytecode
|
|
58
58
|
},
|
|
59
59
|
coinIssuer: {
|
|
60
60
|
contractAbi: CoinIssuerAbi,
|
|
61
|
-
contractBytecode: CoinIssuerBytecode
|
|
61
|
+
contractBytecode: CoinIssuerBytecode
|
|
62
62
|
},
|
|
63
63
|
governanceProposer: {
|
|
64
64
|
contractAbi: GovernanceProposerAbi,
|
|
65
|
-
contractBytecode: GovernanceProposerBytecode
|
|
65
|
+
contractBytecode: GovernanceProposerBytecode
|
|
66
66
|
},
|
|
67
67
|
governance: {
|
|
68
68
|
contractAbi: GovernanceAbi,
|
|
69
|
-
contractBytecode: GovernanceBytecode
|
|
69
|
+
contractBytecode: GovernanceBytecode
|
|
70
70
|
},
|
|
71
71
|
slashFactory: {
|
|
72
72
|
contractAbi: SlashFactoryAbi,
|
|
73
|
-
contractBytecode: SlashFactoryBytecode
|
|
74
|
-
}
|
|
73
|
+
contractBytecode: SlashFactoryBytecode
|
|
74
|
+
}
|
|
75
75
|
};
|
|
76
76
|
/**
|
|
77
77
|
* Creates a wallet and a public viem client for interacting with L1.
|
|
@@ -79,30 +79,28 @@ export const l1Artifacts = {
|
|
|
79
79
|
* @param mnemonicOrPrivateKeyOrHdAccount - Mnemonic or account for the wallet client.
|
|
80
80
|
* @param chain - Optional chain spec (defaults to local foundry).
|
|
81
81
|
* @returns - A wallet and a public client.
|
|
82
|
-
*/
|
|
83
|
-
|
|
84
|
-
const hdAccount = typeof mnemonicOrPrivateKeyOrHdAccount === 'string'
|
|
85
|
-
? mnemonicOrPrivateKeyOrHdAccount.startsWith('0x')
|
|
86
|
-
? privateKeyToAccount(mnemonicOrPrivateKeyOrHdAccount)
|
|
87
|
-
: mnemonicToAccount(mnemonicOrPrivateKeyOrHdAccount)
|
|
88
|
-
: mnemonicOrPrivateKeyOrHdAccount;
|
|
82
|
+
*/ export function createL1Clients(rpcUrl, mnemonicOrPrivateKeyOrHdAccount, chain = foundry) {
|
|
83
|
+
const hdAccount = typeof mnemonicOrPrivateKeyOrHdAccount === 'string' ? mnemonicOrPrivateKeyOrHdAccount.startsWith('0x') ? privateKeyToAccount(mnemonicOrPrivateKeyOrHdAccount) : mnemonicToAccount(mnemonicOrPrivateKeyOrHdAccount) : mnemonicOrPrivateKeyOrHdAccount;
|
|
89
84
|
// From what I can see, this is the difference between the HDAccount and the PrivateKeyAccount
|
|
90
85
|
// and we don't need it for anything. This lets us use the same type for both.
|
|
91
86
|
// eslint-disable-next-line camelcase
|
|
92
|
-
hdAccount.experimental_signAuthorization
|
|
87
|
+
hdAccount.experimental_signAuthorization ??= ()=>{
|
|
93
88
|
throw new Error('experimental_signAuthorization not implemented for HDAccount');
|
|
94
|
-
}
|
|
89
|
+
};
|
|
95
90
|
const walletClient = createWalletClient({
|
|
96
91
|
account: hdAccount,
|
|
97
92
|
chain,
|
|
98
|
-
transport: http(rpcUrl)
|
|
93
|
+
transport: http(rpcUrl)
|
|
99
94
|
}).extend(publicActions);
|
|
100
95
|
const publicClient = createPublicClient({
|
|
101
96
|
chain,
|
|
102
97
|
transport: http(rpcUrl),
|
|
103
|
-
pollingInterval: 100
|
|
98
|
+
pollingInterval: 100
|
|
104
99
|
});
|
|
105
|
-
return {
|
|
100
|
+
return {
|
|
101
|
+
walletClient,
|
|
102
|
+
publicClient
|
|
103
|
+
};
|
|
106
104
|
}
|
|
107
105
|
/**
|
|
108
106
|
* Deploys the aztec L1 contracts; Rollup & (optionally) Decoder Helper.
|
|
@@ -112,69 +110,81 @@ export function createL1Clients(rpcUrl, mnemonicOrPrivateKeyOrHdAccount, chain =
|
|
|
112
110
|
* @param logger - A logger object.
|
|
113
111
|
* @param args - Arguments for initialization of L1 contracts
|
|
114
112
|
* @returns A list of ETH addresses of the deployed contracts.
|
|
115
|
-
*/
|
|
116
|
-
export const deployL1Contracts = async (rpcUrl, account, chain, logger, args) => {
|
|
113
|
+
*/ export const deployL1Contracts = async (rpcUrl, account, chain, logger, args)=>{
|
|
117
114
|
// We are assuming that you are running this on a local anvil node which have 1s block times
|
|
118
115
|
// To align better with actual deployment, we update the block interval to 12s
|
|
119
116
|
// The code is same as `setBlockInterval` in `cheat_codes.ts`
|
|
120
|
-
const rpcCall = async (method, params)
|
|
117
|
+
const rpcCall = async (method, params)=>{
|
|
121
118
|
const paramsString = JSON.stringify(params);
|
|
122
119
|
const content = {
|
|
123
120
|
body: `{"jsonrpc":"2.0", "method": "${method}", "params": ${paramsString}, "id": 1}`,
|
|
124
121
|
method: 'POST',
|
|
125
|
-
headers: {
|
|
122
|
+
headers: {
|
|
123
|
+
'Content-Type': 'application/json'
|
|
124
|
+
}
|
|
126
125
|
};
|
|
127
126
|
return await (await fetch(rpcUrl, content)).json();
|
|
128
127
|
};
|
|
129
128
|
if (isAnvilTestChain(chain.id)) {
|
|
130
|
-
const res = await rpcCall('anvil_setBlockTimestampInterval', [
|
|
129
|
+
const res = await rpcCall('anvil_setBlockTimestampInterval', [
|
|
130
|
+
args.ethereumSlotDuration
|
|
131
|
+
]);
|
|
131
132
|
if (res.error) {
|
|
132
133
|
throw new Error(`Error setting block interval: ${res.error.message}`);
|
|
133
134
|
}
|
|
134
135
|
logger.warn(`Set block interval to ${args.ethereumSlotDuration}`);
|
|
135
136
|
}
|
|
136
137
|
logger.verbose(`Deploying contracts from ${account.address.toString()}`);
|
|
137
|
-
const walletClient = createWalletClient({
|
|
138
|
-
|
|
138
|
+
const walletClient = createWalletClient({
|
|
139
|
+
account,
|
|
140
|
+
chain,
|
|
141
|
+
transport: http(rpcUrl)
|
|
142
|
+
});
|
|
143
|
+
const publicClient = createPublicClient({
|
|
144
|
+
chain,
|
|
145
|
+
transport: http(rpcUrl)
|
|
146
|
+
});
|
|
139
147
|
// Governance stuff
|
|
140
148
|
const govDeployer = new L1Deployer(walletClient, publicClient, args.salt, logger);
|
|
141
|
-
const registryAddress = await govDeployer.deploy(l1Artifacts.registry, [
|
|
149
|
+
const registryAddress = await govDeployer.deploy(l1Artifacts.registry, [
|
|
150
|
+
account.address.toString()
|
|
151
|
+
]);
|
|
142
152
|
logger.verbose(`Deployed Registry at ${registryAddress}`);
|
|
143
153
|
const feeAssetAddress = await govDeployer.deploy(l1Artifacts.feeAsset, [
|
|
144
154
|
'FeeJuice',
|
|
145
155
|
'FEE',
|
|
146
|
-
account.address.toString()
|
|
156
|
+
account.address.toString()
|
|
147
157
|
]);
|
|
148
158
|
logger.verbose(`Deployed Fee Juice at ${feeAssetAddress}`);
|
|
149
159
|
const stakingAssetAddress = await govDeployer.deploy(l1Artifacts.stakingAsset, [
|
|
150
160
|
'Staking',
|
|
151
161
|
'STK',
|
|
152
|
-
account.address.toString()
|
|
162
|
+
account.address.toString()
|
|
153
163
|
]);
|
|
154
164
|
logger.verbose(`Deployed Staking Asset at ${stakingAssetAddress}`);
|
|
155
165
|
const governanceProposerAddress = await govDeployer.deploy(l1Artifacts.governanceProposer, [
|
|
156
166
|
registryAddress.toString(),
|
|
157
167
|
args.governanceProposerQuorum,
|
|
158
|
-
args.governanceProposerRoundSize
|
|
168
|
+
args.governanceProposerRoundSize
|
|
159
169
|
]);
|
|
160
170
|
logger.verbose(`Deployed GovernanceProposer at ${governanceProposerAddress}`);
|
|
161
171
|
// @note @LHerskind the assets are expected to be the same at some point, but for better
|
|
162
172
|
// configurability they are different for now.
|
|
163
173
|
const governanceAddress = await govDeployer.deploy(l1Artifacts.governance, [
|
|
164
174
|
feeAssetAddress.toString(),
|
|
165
|
-
governanceProposerAddress.toString()
|
|
175
|
+
governanceProposerAddress.toString()
|
|
166
176
|
]);
|
|
167
177
|
logger.verbose(`Deployed Governance at ${governanceAddress}`);
|
|
168
178
|
const coinIssuerAddress = await govDeployer.deploy(l1Artifacts.coinIssuer, [
|
|
169
179
|
feeAssetAddress.toString(),
|
|
170
|
-
1n * 10n ** 18n,
|
|
171
|
-
governanceAddress.toString()
|
|
180
|
+
1n * 10n ** 18n,
|
|
181
|
+
governanceAddress.toString()
|
|
172
182
|
]);
|
|
173
183
|
logger.verbose(`Deployed CoinIssuer at ${coinIssuerAddress}`);
|
|
174
184
|
const rewardDistributorAddress = await govDeployer.deploy(l1Artifacts.rewardDistributor, [
|
|
175
185
|
feeAssetAddress.toString(),
|
|
176
186
|
registryAddress.toString(),
|
|
177
|
-
governanceAddress.toString()
|
|
187
|
+
governanceAddress.toString()
|
|
178
188
|
]);
|
|
179
189
|
logger.verbose(`Deployed RewardDistributor at ${rewardDistributorAddress}`);
|
|
180
190
|
logger.verbose(`Waiting for governance contracts to be deployed`);
|
|
@@ -184,7 +194,7 @@ export const deployL1Contracts = async (rpcUrl, account, chain, logger, args) =>
|
|
|
184
194
|
const feeJuicePortalAddress = await deployer.deploy(l1Artifacts.feeJuicePortal, [
|
|
185
195
|
registryAddress.toString(),
|
|
186
196
|
feeAssetAddress.toString(),
|
|
187
|
-
args.l2FeeJuiceAddress.toString()
|
|
197
|
+
args.l2FeeJuiceAddress.toString()
|
|
188
198
|
]);
|
|
189
199
|
logger.verbose(`Deployed Fee Juice Portal at ${feeJuicePortalAddress}`);
|
|
190
200
|
const rollupConfigArgs = {
|
|
@@ -194,7 +204,7 @@ export const deployL1Contracts = async (rpcUrl, account, chain, logger, args) =>
|
|
|
194
204
|
aztecEpochProofClaimWindowInL2Slots: args.aztecEpochProofClaimWindowInL2Slots,
|
|
195
205
|
minimumStake: args.minimumStake,
|
|
196
206
|
slashingQuorum: args.slashingQuorum,
|
|
197
|
-
slashingRoundSize: args.slashingRoundSize
|
|
207
|
+
slashingRoundSize: args.slashingRoundSize
|
|
198
208
|
};
|
|
199
209
|
const rollupArgs = [
|
|
200
210
|
feeJuicePortalAddress.toString(),
|
|
@@ -203,68 +213,89 @@ export const deployL1Contracts = async (rpcUrl, account, chain, logger, args) =>
|
|
|
203
213
|
args.vkTreeRoot.toString(),
|
|
204
214
|
args.protocolContractTreeRoot.toString(),
|
|
205
215
|
account.address.toString(),
|
|
206
|
-
rollupConfigArgs
|
|
216
|
+
rollupConfigArgs
|
|
207
217
|
];
|
|
208
218
|
await deployer.waitForDeployments();
|
|
209
219
|
const rollupAddress = await deployer.deploy(l1Artifacts.rollup, rollupArgs);
|
|
210
220
|
logger.verbose(`Deployed Rollup at ${rollupAddress}`, rollupConfigArgs);
|
|
211
|
-
const slashFactoryAddress = await deployer.deploy(l1Artifacts.slashFactory, [
|
|
221
|
+
const slashFactoryAddress = await deployer.deploy(l1Artifacts.slashFactory, [
|
|
222
|
+
rollupAddress.toString()
|
|
223
|
+
]);
|
|
212
224
|
logger.verbose(`Deployed SlashFactory at ${slashFactoryAddress}`);
|
|
213
225
|
await deployer.waitForDeployments();
|
|
214
226
|
logger.verbose(`All core contracts have been deployed`);
|
|
215
227
|
const feeJuicePortal = getContract({
|
|
216
228
|
address: feeJuicePortalAddress.toString(),
|
|
217
229
|
abi: l1Artifacts.feeJuicePortal.contractAbi,
|
|
218
|
-
client: walletClient
|
|
230
|
+
client: walletClient
|
|
219
231
|
});
|
|
220
232
|
const feeAsset = getContract({
|
|
221
233
|
address: feeAssetAddress.toString(),
|
|
222
234
|
abi: l1Artifacts.feeAsset.contractAbi,
|
|
223
|
-
client: walletClient
|
|
235
|
+
client: walletClient
|
|
224
236
|
});
|
|
225
237
|
const stakingAsset = getContract({
|
|
226
238
|
address: stakingAssetAddress.toString(),
|
|
227
239
|
abi: l1Artifacts.stakingAsset.contractAbi,
|
|
228
|
-
client: walletClient
|
|
240
|
+
client: walletClient
|
|
229
241
|
});
|
|
230
242
|
const rollup = getContract({
|
|
231
243
|
address: getAddress(rollupAddress.toString()),
|
|
232
244
|
abi: l1Artifacts.rollup.contractAbi,
|
|
233
|
-
client: walletClient
|
|
245
|
+
client: walletClient
|
|
234
246
|
});
|
|
235
247
|
// Transaction hashes to await
|
|
236
248
|
const txHashes = [];
|
|
237
249
|
{
|
|
238
|
-
const txHash = await feeAsset.write.setFreeForAll([
|
|
250
|
+
const txHash = await feeAsset.write.setFreeForAll([
|
|
251
|
+
true
|
|
252
|
+
], {});
|
|
239
253
|
logger.verbose(`Fee asset set to free for all in ${txHash}`);
|
|
240
254
|
txHashes.push(txHash);
|
|
241
255
|
}
|
|
242
256
|
if (args.initialValidators && args.initialValidators.length > 0) {
|
|
243
257
|
// Check if some of the initial validators are already registered, so we support idempotent deployments
|
|
244
|
-
const validatorsInfo = await Promise.all(args.initialValidators.map(async (address)
|
|
245
|
-
|
|
258
|
+
const validatorsInfo = await Promise.all(args.initialValidators.map(async (address)=>({
|
|
259
|
+
address,
|
|
260
|
+
...await rollup.read.getInfo([
|
|
261
|
+
address.toString()
|
|
262
|
+
])
|
|
263
|
+
})));
|
|
264
|
+
const existingValidators = validatorsInfo.filter((v)=>v.status !== 0);
|
|
246
265
|
if (existingValidators.length > 0) {
|
|
247
|
-
logger.warn(`Validators ${existingValidators.map(v
|
|
266
|
+
logger.warn(`Validators ${existingValidators.map((v)=>v.address).join(', ')} already exist. Skipping from initialization.`);
|
|
248
267
|
}
|
|
249
|
-
const newValidatorsAddresses = validatorsInfo.filter(v
|
|
268
|
+
const newValidatorsAddresses = validatorsInfo.filter((v)=>v.status === 0).map((v)=>v.address.toString());
|
|
250
269
|
if (newValidatorsAddresses.length > 0) {
|
|
251
270
|
// Mint tokens, approve them, use cheat code to initialise validator set without setting up the epoch.
|
|
252
271
|
const stakeNeeded = args.minimumStake * BigInt(newValidatorsAddresses.length);
|
|
253
272
|
await Promise.all([
|
|
254
|
-
await stakingAsset.write.mint([
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
273
|
+
await stakingAsset.write.mint([
|
|
274
|
+
walletClient.account.address,
|
|
275
|
+
stakeNeeded
|
|
276
|
+
], {}),
|
|
277
|
+
await stakingAsset.write.approve([
|
|
278
|
+
rollupAddress.toString(),
|
|
279
|
+
stakeNeeded
|
|
280
|
+
], {})
|
|
281
|
+
].map((txHash)=>publicClient.waitForTransactionReceipt({
|
|
282
|
+
hash: txHash
|
|
283
|
+
})));
|
|
284
|
+
const validators = newValidatorsAddresses.map((v)=>({
|
|
285
|
+
attester: v,
|
|
286
|
+
proposer: getExpectedAddress(ForwarderAbi, ForwarderBytecode, [
|
|
287
|
+
v
|
|
288
|
+
], v).address,
|
|
289
|
+
withdrawer: v,
|
|
290
|
+
amount: args.minimumStake
|
|
291
|
+
}));
|
|
292
|
+
const initiateValidatorSetTxHash = await rollup.write.cheat__InitialiseValidatorSet([
|
|
293
|
+
validators
|
|
294
|
+
]);
|
|
264
295
|
txHashes.push(initiateValidatorSetTxHash);
|
|
265
296
|
logger.info(`Initialized validator set`, {
|
|
266
297
|
validators,
|
|
267
|
-
txHash: initiateValidatorSetTxHash
|
|
298
|
+
txHash: initiateValidatorSetTxHash
|
|
268
299
|
});
|
|
269
300
|
}
|
|
270
301
|
}
|
|
@@ -273,17 +304,21 @@ export const deployL1Contracts = async (rpcUrl, account, chain, logger, args) =>
|
|
|
273
304
|
// @todo #8084
|
|
274
305
|
// fund the portal contract with Fee Juice
|
|
275
306
|
const FEE_JUICE_INITIAL_MINT = 200000000000000000000000n;
|
|
276
|
-
const mintTxHash = await feeAsset.write.mint([
|
|
307
|
+
const mintTxHash = await feeAsset.write.mint([
|
|
308
|
+
feeJuicePortalAddress.toString(),
|
|
309
|
+
FEE_JUICE_INITIAL_MINT
|
|
310
|
+
], {});
|
|
277
311
|
// @note This is used to ensure we fully wait for the transaction when running against a real chain
|
|
278
312
|
// otherwise we execute subsequent transactions too soon
|
|
279
|
-
await publicClient.waitForTransactionReceipt({
|
|
313
|
+
await publicClient.waitForTransactionReceipt({
|
|
314
|
+
hash: mintTxHash
|
|
315
|
+
});
|
|
280
316
|
logger.verbose(`Funding fee juice portal contract with fee juice in ${mintTxHash}`);
|
|
281
|
-
if (!
|
|
317
|
+
if (!await feeJuicePortal.read.initialized()) {
|
|
282
318
|
const initPortalTxHash = await feeJuicePortal.write.initialize();
|
|
283
319
|
txHashes.push(initPortalTxHash);
|
|
284
320
|
logger.verbose(`Fee juice portal initializing in tx ${initPortalTxHash}`);
|
|
285
|
-
}
|
|
286
|
-
else {
|
|
321
|
+
} else {
|
|
287
322
|
logger.verbose(`Fee juice portal is already initialized`);
|
|
288
323
|
}
|
|
289
324
|
logger.verbose(`Initialized Fee Juice Portal at ${feeJuicePortalAddress} to bridge between L1 ${feeAssetAddress} to L2 ${args.l2FeeJuiceAddress}`);
|
|
@@ -292,56 +327,74 @@ export const deployL1Contracts = async (rpcUrl, account, chain, logger, args) =>
|
|
|
292
327
|
// The edge case being that the genesis block is already occupying slot 0, so we cannot have another block.
|
|
293
328
|
try {
|
|
294
329
|
// Need to get the time
|
|
295
|
-
const currentSlot =
|
|
330
|
+
const currentSlot = await rollup.read.getCurrentSlot();
|
|
296
331
|
if (BigInt(currentSlot) === 0n) {
|
|
297
|
-
const ts = Number(await rollup.read.getTimestampForSlot([
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
332
|
+
const ts = Number(await rollup.read.getTimestampForSlot([
|
|
333
|
+
1n
|
|
334
|
+
]));
|
|
335
|
+
await rpcCall('evm_setNextBlockTimestamp', [
|
|
336
|
+
ts
|
|
337
|
+
]);
|
|
338
|
+
await rpcCall('hardhat_mine', [
|
|
339
|
+
1
|
|
340
|
+
]);
|
|
341
|
+
const currentSlot = await rollup.read.getCurrentSlot();
|
|
301
342
|
if (BigInt(currentSlot) !== 1n) {
|
|
302
343
|
throw new Error(`Error jumping time: current slot is ${currentSlot}`);
|
|
303
344
|
}
|
|
304
345
|
logger.info(`Jumped to slot 1`);
|
|
305
346
|
}
|
|
306
|
-
}
|
|
307
|
-
catch (e) {
|
|
347
|
+
} catch (e) {
|
|
308
348
|
throw new Error(`Error jumping time: ${e}`);
|
|
309
349
|
}
|
|
310
350
|
}
|
|
311
351
|
// Set initial blocks as proven if requested
|
|
312
352
|
if (args.assumeProvenThrough && args.assumeProvenThrough > 0) {
|
|
313
|
-
await rollup.write.setAssumeProvenThroughBlockNumber([
|
|
353
|
+
await rollup.write.setAssumeProvenThroughBlockNumber([
|
|
354
|
+
BigInt(args.assumeProvenThrough)
|
|
355
|
+
], {
|
|
356
|
+
account
|
|
357
|
+
});
|
|
314
358
|
logger.warn(`Rollup set to assumedProvenUntil to ${args.assumeProvenThrough}`);
|
|
315
359
|
}
|
|
316
360
|
// Inbox and Outbox are immutable and are deployed from Rollup's constructor so we just fetch them from the contract.
|
|
317
|
-
const inboxAddress = EthAddress.fromString(
|
|
361
|
+
const inboxAddress = EthAddress.fromString(await rollup.read.INBOX());
|
|
318
362
|
logger.verbose(`Inbox available at ${inboxAddress}`);
|
|
319
|
-
const outboxAddress = EthAddress.fromString(
|
|
363
|
+
const outboxAddress = EthAddress.fromString(await rollup.read.OUTBOX());
|
|
320
364
|
logger.verbose(`Outbox available at ${outboxAddress}`);
|
|
321
365
|
// We need to call a function on the registry to set the various contract addresses.
|
|
322
366
|
const registryContract = getContract({
|
|
323
367
|
address: getAddress(registryAddress.toString()),
|
|
324
368
|
abi: l1Artifacts.registry.contractAbi,
|
|
325
|
-
client: walletClient
|
|
369
|
+
client: walletClient
|
|
326
370
|
});
|
|
327
|
-
if (!
|
|
328
|
-
|
|
371
|
+
if (!await registryContract.read.isRollupRegistered([
|
|
372
|
+
getAddress(rollupAddress.toString())
|
|
373
|
+
])) {
|
|
374
|
+
const upgradeTxHash = await registryContract.write.upgrade([
|
|
375
|
+
getAddress(rollupAddress.toString())
|
|
376
|
+
], {
|
|
377
|
+
account
|
|
378
|
+
});
|
|
329
379
|
logger.verbose(`Upgrading registry contract at ${registryAddress} to rollup ${rollupAddress} in tx ${upgradeTxHash}`);
|
|
330
380
|
txHashes.push(upgradeTxHash);
|
|
331
|
-
}
|
|
332
|
-
else {
|
|
381
|
+
} else {
|
|
333
382
|
logger.verbose(`Registry ${registryAddress} has already registered rollup ${rollupAddress}`);
|
|
334
383
|
}
|
|
335
384
|
// If the owner is not the Governance contract, transfer ownership to the Governance contract
|
|
336
|
-
if (
|
|
337
|
-
const transferOwnershipTxHash = await registryContract.write.transferOwnership([
|
|
338
|
-
|
|
385
|
+
if (await registryContract.read.owner() !== getAddress(governanceAddress.toString())) {
|
|
386
|
+
const transferOwnershipTxHash = await registryContract.write.transferOwnership([
|
|
387
|
+
getAddress(governanceAddress.toString())
|
|
388
|
+
], {
|
|
389
|
+
account
|
|
339
390
|
});
|
|
340
391
|
logger.verbose(`Transferring the ownership of the registry contract at ${registryAddress} to the Governance ${governanceAddress} in tx ${transferOwnershipTxHash}`);
|
|
341
392
|
txHashes.push(transferOwnershipTxHash);
|
|
342
393
|
}
|
|
343
394
|
// Wait for all actions to be mined
|
|
344
|
-
await Promise.all(txHashes.map(txHash
|
|
395
|
+
await Promise.all(txHashes.map((txHash)=>publicClient.waitForTransactionReceipt({
|
|
396
|
+
hash: txHash
|
|
397
|
+
})));
|
|
345
398
|
logger.verbose(`All transactions for L1 deployment have been mined`);
|
|
346
399
|
const l1Contracts = {
|
|
347
400
|
rollupAddress,
|
|
@@ -355,22 +408,29 @@ export const deployL1Contracts = async (rpcUrl, account, chain, logger, args) =>
|
|
|
355
408
|
rewardDistributorAddress,
|
|
356
409
|
governanceProposerAddress,
|
|
357
410
|
governanceAddress,
|
|
358
|
-
slashFactoryAddress
|
|
411
|
+
slashFactoryAddress
|
|
359
412
|
};
|
|
360
413
|
logger.info(`Aztec L1 contracts initialized`, l1Contracts);
|
|
361
414
|
return {
|
|
362
415
|
walletClient,
|
|
363
416
|
publicClient,
|
|
364
|
-
l1ContractAddresses: l1Contracts
|
|
417
|
+
l1ContractAddresses: l1Contracts
|
|
365
418
|
};
|
|
366
419
|
};
|
|
367
420
|
class L1Deployer {
|
|
368
|
-
|
|
421
|
+
walletClient;
|
|
422
|
+
publicClient;
|
|
423
|
+
logger;
|
|
424
|
+
salt;
|
|
425
|
+
txHashes;
|
|
426
|
+
constructor(walletClient, publicClient, maybeSalt, logger){
|
|
369
427
|
this.walletClient = walletClient;
|
|
370
428
|
this.publicClient = publicClient;
|
|
371
429
|
this.logger = logger;
|
|
372
430
|
this.txHashes = [];
|
|
373
|
-
this.salt = maybeSalt ? padHex(numberToHex(maybeSalt), {
|
|
431
|
+
this.salt = maybeSalt ? padHex(numberToHex(maybeSalt), {
|
|
432
|
+
size: 32
|
|
433
|
+
}) : undefined;
|
|
374
434
|
}
|
|
375
435
|
async deploy(params, args = []) {
|
|
376
436
|
const { txHash, address } = await deployL1Contract(this.walletClient, this.publicClient, params.contractAbi, params.contractBytecode, args, this.salt, params.libraries, this.logger);
|
|
@@ -380,7 +440,9 @@ class L1Deployer {
|
|
|
380
440
|
return address;
|
|
381
441
|
}
|
|
382
442
|
async waitForDeployments() {
|
|
383
|
-
await Promise.all(this.txHashes.map(txHash
|
|
443
|
+
await Promise.all(this.txHashes.map((txHash)=>this.publicClient.waitForTransactionReceipt({
|
|
444
|
+
hash: txHash
|
|
445
|
+
})));
|
|
384
446
|
}
|
|
385
447
|
}
|
|
386
448
|
// docs:start:deployL1Contract
|
|
@@ -393,27 +455,26 @@ class L1Deployer {
|
|
|
393
455
|
* @param args - Constructor arguments for the contract.
|
|
394
456
|
* @param maybeSalt - Optional salt for CREATE2 deployment (does not wait for deployment tx to be mined if set, does not send tx if contract already exists).
|
|
395
457
|
* @returns The ETH address the contract was deployed to.
|
|
396
|
-
*/
|
|
397
|
-
export async function deployL1Contract(walletClient, publicClient, abi, bytecode, args = [], maybeSalt, libraries, logger) {
|
|
458
|
+
*/ export async function deployL1Contract(walletClient, publicClient, abi, bytecode, args = [], maybeSalt, libraries, logger) {
|
|
398
459
|
let txHash = undefined;
|
|
399
460
|
let resultingAddress = undefined;
|
|
400
461
|
const l1TxUtils = new L1TxUtils(publicClient, walletClient, logger);
|
|
401
462
|
if (libraries) {
|
|
402
463
|
// Note that this does NOT work well for linked libraries having linked libraries.
|
|
403
464
|
// Verify that all link references have corresponding code
|
|
404
|
-
for
|
|
405
|
-
for
|
|
465
|
+
for(const linkRef in libraries.linkReferences){
|
|
466
|
+
for(const contractName in libraries.linkReferences[linkRef]){
|
|
406
467
|
if (!libraries.libraryCode[contractName]) {
|
|
407
468
|
throw new Error(`Missing library code for ${contractName}`);
|
|
408
469
|
}
|
|
409
470
|
}
|
|
410
471
|
}
|
|
411
472
|
const replacements = {};
|
|
412
|
-
for
|
|
473
|
+
for(const libraryName in libraries?.libraryCode){
|
|
413
474
|
const lib = libraries.libraryCode[libraryName];
|
|
414
475
|
const { address } = await deployL1Contract(walletClient, publicClient, lib.contractAbi, lib.contractBytecode, [], maybeSalt, undefined, logger);
|
|
415
|
-
for
|
|
416
|
-
for
|
|
476
|
+
for(const linkRef in libraries.linkReferences){
|
|
477
|
+
for(const contractName in libraries.linkReferences[linkRef]){
|
|
417
478
|
// If the library name matches the one we just deployed, we replace it.
|
|
418
479
|
if (contractName !== libraryName) {
|
|
419
480
|
continue;
|
|
@@ -426,10 +487,10 @@ export async function deployL1Contract(walletClient, publicClient, abi, bytecode
|
|
|
426
487
|
}
|
|
427
488
|
}
|
|
428
489
|
}
|
|
429
|
-
const escapeRegExp = (s)
|
|
490
|
+
const escapeRegExp = (s)=>{
|
|
430
491
|
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // Escape special characters
|
|
431
492
|
};
|
|
432
|
-
for
|
|
493
|
+
for(const toReplace in replacements){
|
|
433
494
|
const replacement = replacements[toReplace].toString().slice(2);
|
|
434
495
|
bytecode = bytecode.replace(new RegExp(escapeRegExp(toReplace), 'g'), replacement);
|
|
435
496
|
}
|
|
@@ -437,48 +498,62 @@ export async function deployL1Contract(walletClient, publicClient, abi, bytecode
|
|
|
437
498
|
if (maybeSalt) {
|
|
438
499
|
const { address, paddedSalt: salt, calldata } = getExpectedAddress(abi, bytecode, args, maybeSalt);
|
|
439
500
|
resultingAddress = address;
|
|
440
|
-
const existing = await publicClient.getBytecode({
|
|
501
|
+
const existing = await publicClient.getBytecode({
|
|
502
|
+
address: resultingAddress
|
|
503
|
+
});
|
|
441
504
|
if (existing === undefined || existing === '0x') {
|
|
442
505
|
const res = await l1TxUtils.sendTransaction({
|
|
443
506
|
to: DEPLOYER_ADDRESS,
|
|
444
|
-
data: concatHex([
|
|
507
|
+
data: concatHex([
|
|
508
|
+
salt,
|
|
509
|
+
calldata
|
|
510
|
+
])
|
|
445
511
|
});
|
|
446
512
|
txHash = res.txHash;
|
|
447
513
|
logger?.verbose(`Deployed contract with salt ${salt} to address ${resultingAddress} in tx ${txHash}.`);
|
|
448
|
-
}
|
|
449
|
-
else {
|
|
514
|
+
} else {
|
|
450
515
|
logger?.verbose(`Skipping existing deployment of contract with salt ${salt} to address ${resultingAddress}`);
|
|
451
516
|
}
|
|
452
|
-
}
|
|
453
|
-
else {
|
|
517
|
+
} else {
|
|
454
518
|
// Regular deployment path
|
|
455
|
-
const deployData = encodeDeployData({
|
|
519
|
+
const deployData = encodeDeployData({
|
|
520
|
+
abi,
|
|
521
|
+
bytecode,
|
|
522
|
+
args
|
|
523
|
+
});
|
|
456
524
|
const { receipt } = await l1TxUtils.sendAndMonitorTransaction({
|
|
457
525
|
to: null,
|
|
458
|
-
data: deployData
|
|
526
|
+
data: deployData
|
|
459
527
|
});
|
|
460
528
|
txHash = receipt.transactionHash;
|
|
461
529
|
resultingAddress = receipt.contractAddress;
|
|
462
530
|
if (!resultingAddress) {
|
|
463
|
-
throw new Error(`No contract address found in receipt: ${JSON.stringify(receipt, (_, val)
|
|
531
|
+
throw new Error(`No contract address found in receipt: ${JSON.stringify(receipt, (_, val)=>typeof val === 'bigint' ? String(val) : val)}`);
|
|
464
532
|
}
|
|
465
533
|
}
|
|
466
|
-
return {
|
|
534
|
+
return {
|
|
535
|
+
address: EthAddress.fromString(resultingAddress),
|
|
536
|
+
txHash
|
|
537
|
+
};
|
|
467
538
|
}
|
|
468
539
|
export function getExpectedAddress(abi, bytecode, args, salt) {
|
|
469
|
-
const paddedSalt = padHex(salt, {
|
|
470
|
-
|
|
540
|
+
const paddedSalt = padHex(salt, {
|
|
541
|
+
size: 32
|
|
542
|
+
});
|
|
543
|
+
const calldata = encodeDeployData({
|
|
544
|
+
abi,
|
|
545
|
+
bytecode,
|
|
546
|
+
args
|
|
547
|
+
});
|
|
471
548
|
const address = getContractAddress({
|
|
472
549
|
from: DEPLOYER_ADDRESS,
|
|
473
550
|
salt: paddedSalt,
|
|
474
551
|
bytecode: calldata,
|
|
475
|
-
opcode: 'CREATE2'
|
|
552
|
+
opcode: 'CREATE2'
|
|
476
553
|
});
|
|
477
554
|
return {
|
|
478
555
|
address,
|
|
479
556
|
paddedSalt,
|
|
480
|
-
calldata
|
|
557
|
+
calldata
|
|
481
558
|
};
|
|
482
|
-
}
|
|
483
|
-
// docs:end:deployL1Contract
|
|
484
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95X2wxX2NvbnRyYWN0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9kZXBsb3lfbDFfY29udHJhY3RzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUczRCxPQUFPLEVBQ0wsYUFBYSxFQUNiLGtCQUFrQixFQUNsQixlQUFlLEVBQ2Ysb0JBQW9CLEVBQ3BCLGlCQUFpQixFQUNqQixzQkFBc0IsRUFDdEIsWUFBWSxFQUNaLGlCQUFpQixFQUNqQixhQUFhLEVBQ2Isa0JBQWtCLEVBQ2xCLHFCQUFxQixFQUNyQiwwQkFBMEIsRUFDMUIsUUFBUSxFQUNSLGFBQWEsRUFDYixTQUFTLEVBQ1QsY0FBYyxFQUNkLFdBQVcsRUFDWCxnQkFBZ0IsRUFDaEIsb0JBQW9CLEVBQ3BCLHlCQUF5QixFQUN6QixTQUFTLEVBQ1QsY0FBYyxFQUNkLG9CQUFvQixFQUNwQixlQUFlLEVBQ2Ysb0JBQW9CLEVBQ3BCLGFBQWEsRUFDYixrQkFBa0IsRUFDbEIsWUFBWSxFQUNaLGlCQUFpQixFQUNqQix3QkFBd0IsRUFDeEIsNkJBQTZCLEdBQzlCLE1BQU0scUJBQXFCLENBQUM7QUFHN0IsT0FBTyxFQVlMLFNBQVMsRUFDVCxrQkFBa0IsRUFDbEIsa0JBQWtCLEVBQ2xCLGdCQUFnQixFQUNoQixVQUFVLEVBQ1YsV0FBVyxFQUNYLGtCQUFrQixFQUNsQixJQUFJLEVBQ0osV0FBVyxFQUNYLE1BQU0sRUFDTixhQUFhLEdBQ2QsTUFBTSxNQUFNLENBQUM7QUFDZCxPQUFPLEVBQTBDLGlCQUFpQixFQUFFLG1CQUFtQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQy9HLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFdEMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRzlDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztB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
|
|
559
|
+
} // docs:end:deployL1Contract
|