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