@aztec/ethereum 0.72.1 → 0.74.0
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/{ethereum_chain.d.ts → chain.d.ts} +1 -1
- package/dest/chain.d.ts.map +1 -0
- package/dest/{ethereum_chain.js → chain.js} +1 -1
- package/dest/client.d.ts +16 -0
- package/dest/client.d.ts.map +1 -0
- package/dest/client.js +35 -0
- package/dest/contracts/empire_base.d.ts +13 -0
- package/dest/contracts/empire_base.d.ts.map +1 -0
- package/dest/contracts/empire_base.js +10 -0
- package/dest/contracts/forwarder.d.ts +24 -0
- package/dest/contracts/forwarder.d.ts.map +1 -0
- package/dest/contracts/forwarder.js +81 -0
- package/dest/contracts/governance.d.ts +14 -0
- package/dest/contracts/governance.d.ts.map +1 -0
- package/dest/contracts/governance.js +31 -0
- package/dest/contracts/governance_proposer.d.ts +28 -0
- package/dest/contracts/governance_proposer.d.ts.map +1 -0
- package/dest/contracts/governance_proposer.js +71 -0
- package/dest/contracts/index.d.ts +5 -0
- package/dest/contracts/index.d.ts.map +1 -1
- package/dest/contracts/index.js +6 -1
- package/dest/contracts/rollup.d.ts +96 -5
- package/dest/contracts/rollup.d.ts.map +1 -1
- package/dest/contracts/rollup.js +188 -17
- package/dest/contracts/slashing_proposer.d.ts +21 -0
- package/dest/contracts/slashing_proposer.d.ts.map +1 -0
- package/dest/contracts/slashing_proposer.js +37 -0
- package/dest/deploy_l1_contracts.d.ts +2337 -1081
- package/dest/deploy_l1_contracts.d.ts.map +1 -1
- package/dest/deploy_l1_contracts.js +48 -22
- package/dest/index.d.ts +4 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +5 -2
- package/dest/l1_reader.d.ts.map +1 -1
- package/dest/l1_reader.js +2 -3
- package/dest/l1_tx_utils.d.ts +80 -18
- package/dest/l1_tx_utils.d.ts.map +1 -1
- package/dest/l1_tx_utils.js +171 -20
- package/dest/l1_tx_utils_with_blobs.d.ts +12 -0
- package/dest/l1_tx_utils_with_blobs.d.ts.map +1 -0
- package/dest/l1_tx_utils_with_blobs.js +61 -0
- package/dest/queries.d.ts +15 -0
- package/dest/queries.d.ts.map +1 -0
- package/dest/queries.js +48 -0
- package/dest/test/delayed_tx_utils.d.ts +8 -0
- package/dest/test/delayed_tx_utils.d.ts.map +1 -0
- package/dest/test/delayed_tx_utils.js +21 -0
- package/dest/test/index.d.ts +2 -1
- package/dest/test/index.d.ts.map +1 -1
- package/dest/test/index.js +3 -2
- package/dest/types.d.ts +3 -1
- package/dest/types.d.ts.map +1 -1
- package/dest/utils.d.ts +1 -0
- package/dest/utils.d.ts.map +1 -1
- package/dest/utils.js +40 -4
- package/package.json +7 -4
- package/src/client.ts +56 -0
- package/src/contracts/empire_base.ts +19 -0
- package/src/contracts/forwarder.ts +136 -0
- package/src/contracts/governance.ts +50 -0
- package/src/contracts/governance_proposer.ts +91 -0
- package/src/contracts/index.ts +5 -0
- package/src/contracts/rollup.ts +277 -17
- package/src/contracts/slashing_proposer.ts +58 -0
- package/src/deploy_l1_contracts.ts +74 -26
- package/src/index.ts +4 -1
- package/src/l1_reader.ts +1 -2
- package/src/l1_tx_utils.ts +245 -35
- package/src/l1_tx_utils_with_blobs.ts +86 -0
- package/src/queries.ts +77 -0
- package/src/test/delayed_tx_utils.ts +24 -0
- package/src/test/index.ts +2 -1
- package/src/types.ts +4 -0
- package/src/utils.ts +44 -3
- package/dest/ethereum_chain.d.ts.map +0 -1
- /package/src/{ethereum_chain.ts → chain.ts} +0 -0
package/src/contracts/rollup.ts
CHANGED
|
@@ -1,31 +1,89 @@
|
|
|
1
|
-
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
2
1
|
import { memoize } from '@aztec/foundation/decorators';
|
|
3
|
-
import {
|
|
2
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
|
+
import type { ViemSignature } from '@aztec/foundation/eth-signature';
|
|
4
|
+
import { RollupAbi, RollupStorage, SlasherAbi } from '@aztec/l1-artifacts';
|
|
4
5
|
|
|
5
6
|
import {
|
|
7
|
+
type Account,
|
|
6
8
|
type Chain,
|
|
7
9
|
type GetContractReturnType,
|
|
8
10
|
type Hex,
|
|
9
11
|
type HttpTransport,
|
|
10
12
|
type PublicClient,
|
|
11
13
|
createPublicClient,
|
|
14
|
+
getAddress,
|
|
12
15
|
getContract,
|
|
13
16
|
http,
|
|
14
17
|
} from 'viem';
|
|
15
18
|
|
|
19
|
+
import { createEthereumChain } from '../chain.js';
|
|
16
20
|
import { type DeployL1Contracts } from '../deploy_l1_contracts.js';
|
|
17
|
-
import {
|
|
21
|
+
import { type L1ContractAddresses } from '../l1_contract_addresses.js';
|
|
18
22
|
import { type L1ReaderConfig } from '../l1_reader.js';
|
|
23
|
+
import { formatViemError } from '../utils.js';
|
|
24
|
+
import { SlashingProposerContract } from './slashing_proposer.js';
|
|
25
|
+
|
|
26
|
+
export type L1RollupContractAddresses = Pick<
|
|
27
|
+
L1ContractAddresses,
|
|
28
|
+
| 'rollupAddress'
|
|
29
|
+
| 'inboxAddress'
|
|
30
|
+
| 'outboxAddress'
|
|
31
|
+
| 'feeJuicePortalAddress'
|
|
32
|
+
| 'feeJuiceAddress'
|
|
33
|
+
| 'stakingAssetAddress'
|
|
34
|
+
| 'rewardDistributorAddress'
|
|
35
|
+
>;
|
|
36
|
+
|
|
37
|
+
export type EpochProofQuoteViemArgs = {
|
|
38
|
+
epochToProve: bigint;
|
|
39
|
+
validUntilSlot: bigint;
|
|
40
|
+
bondAmount: bigint;
|
|
41
|
+
prover: `0x${string}`;
|
|
42
|
+
basisPointFee: number;
|
|
43
|
+
};
|
|
19
44
|
|
|
20
45
|
export class RollupContract {
|
|
21
46
|
private readonly rollup: GetContractReturnType<typeof RollupAbi, PublicClient<HttpTransport, Chain>>;
|
|
22
47
|
|
|
48
|
+
static get checkBlobStorageSlot(): bigint {
|
|
49
|
+
const asString = RollupStorage.find(storage => storage.label === 'checkBlob')?.slot;
|
|
50
|
+
if (asString === undefined) {
|
|
51
|
+
throw new Error('checkBlobStorageSlot not found');
|
|
52
|
+
}
|
|
53
|
+
return BigInt(asString);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
static getFromL1ContractsValues(deployL1ContractsValues: DeployL1Contracts) {
|
|
57
|
+
const {
|
|
58
|
+
publicClient,
|
|
59
|
+
l1ContractAddresses: { rollupAddress },
|
|
60
|
+
} = deployL1ContractsValues;
|
|
61
|
+
return new RollupContract(publicClient, rollupAddress.toString());
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
static getFromConfig(config: L1ReaderConfig) {
|
|
65
|
+
const client = createPublicClient({
|
|
66
|
+
transport: http(config.l1RpcUrl),
|
|
67
|
+
chain: createEthereumChain(config.l1RpcUrl, config.l1ChainId).chainInfo,
|
|
68
|
+
});
|
|
69
|
+
const address = config.l1Contracts.rollupAddress.toString();
|
|
70
|
+
return new RollupContract(client, address);
|
|
71
|
+
}
|
|
72
|
+
|
|
23
73
|
constructor(public readonly client: PublicClient<HttpTransport, Chain>, address: Hex) {
|
|
24
74
|
this.rollup = getContract({ address, abi: RollupAbi, client });
|
|
25
75
|
}
|
|
26
76
|
|
|
27
77
|
public get address() {
|
|
28
|
-
return
|
|
78
|
+
return this.rollup.address;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@memoize
|
|
82
|
+
public async getSlashingProposer() {
|
|
83
|
+
const slasherAddress = await this.rollup.read.getSlasher();
|
|
84
|
+
const slasher = getContract({ address: slasherAddress, abi: SlasherAbi, client: this.client });
|
|
85
|
+
const proposerAddress = await slasher.read.PROPOSER();
|
|
86
|
+
return new SlashingProposerContract(this.client, proposerAddress);
|
|
29
87
|
}
|
|
30
88
|
|
|
31
89
|
@memoize
|
|
@@ -35,7 +93,42 @@ export class RollupContract {
|
|
|
35
93
|
|
|
36
94
|
@memoize
|
|
37
95
|
getL1GenesisTime() {
|
|
38
|
-
return this.rollup.read.
|
|
96
|
+
return this.rollup.read.getGenesisTime();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@memoize
|
|
100
|
+
getClaimDurationInL2Slots() {
|
|
101
|
+
return this.rollup.read.CLAIM_DURATION_IN_L2_SLOTS();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
@memoize
|
|
105
|
+
getEpochDuration() {
|
|
106
|
+
return this.rollup.read.getEpochDuration();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@memoize
|
|
110
|
+
getSlotDuration() {
|
|
111
|
+
return this.rollup.read.getSlotDuration();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@memoize
|
|
115
|
+
getTargetCommitteeSize() {
|
|
116
|
+
return this.rollup.read.TARGET_COMMITTEE_SIZE();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@memoize
|
|
120
|
+
getMinimumStake() {
|
|
121
|
+
return this.rollup.read.getMinimumStake();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
public async getSlashingProposerAddress() {
|
|
125
|
+
const slasherAddress = await this.rollup.read.getSlasher();
|
|
126
|
+
const slasher = getContract({
|
|
127
|
+
address: getAddress(slasherAddress.toString()),
|
|
128
|
+
abi: SlasherAbi,
|
|
129
|
+
client: this.client,
|
|
130
|
+
});
|
|
131
|
+
return EthAddress.fromString(await slasher.read.PROPOSER());
|
|
39
132
|
}
|
|
40
133
|
|
|
41
134
|
getBlockNumber() {
|
|
@@ -70,25 +163,192 @@ export class RollupContract {
|
|
|
70
163
|
return this.rollup.read.getCurrentProposer();
|
|
71
164
|
}
|
|
72
165
|
|
|
166
|
+
getProposerAt(timestamp: bigint) {
|
|
167
|
+
return this.rollup.read.getProposerAt([timestamp]);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
getBlock(blockNumber: bigint) {
|
|
171
|
+
return this.rollup.read.getBlock([blockNumber]);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
getProofCommitmentEscrow() {
|
|
175
|
+
return this.rollup.read.PROOF_COMMITMENT_ESCROW();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
getTips() {
|
|
179
|
+
return this.rollup.read.getTips();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
getTimestampForSlot(slot: bigint) {
|
|
183
|
+
return this.rollup.read.getTimestampForSlot([slot]);
|
|
184
|
+
}
|
|
185
|
+
|
|
73
186
|
async getEpochNumber(blockNumber?: bigint) {
|
|
74
187
|
blockNumber ??= await this.getBlockNumber();
|
|
75
188
|
return this.rollup.read.getEpochForBlock([BigInt(blockNumber)]);
|
|
76
189
|
}
|
|
77
190
|
|
|
78
|
-
|
|
191
|
+
async getRollupAddresses(): Promise<L1RollupContractAddresses> {
|
|
192
|
+
const [
|
|
193
|
+
inboxAddress,
|
|
194
|
+
outboxAddress,
|
|
195
|
+
feeJuicePortalAddress,
|
|
196
|
+
rewardDistributorAddress,
|
|
197
|
+
feeJuiceAddress,
|
|
198
|
+
stakingAssetAddress,
|
|
199
|
+
] = (
|
|
200
|
+
await Promise.all([
|
|
201
|
+
this.rollup.read.INBOX(),
|
|
202
|
+
this.rollup.read.OUTBOX(),
|
|
203
|
+
this.rollup.read.FEE_JUICE_PORTAL(),
|
|
204
|
+
this.rollup.read.REWARD_DISTRIBUTOR(),
|
|
205
|
+
this.rollup.read.ASSET(),
|
|
206
|
+
this.rollup.read.getStakingAsset(),
|
|
207
|
+
] as const)
|
|
208
|
+
).map(EthAddress.fromString);
|
|
209
|
+
|
|
210
|
+
return {
|
|
211
|
+
rollupAddress: EthAddress.fromString(this.address),
|
|
212
|
+
inboxAddress,
|
|
213
|
+
outboxAddress,
|
|
214
|
+
feeJuicePortalAddress,
|
|
215
|
+
feeJuiceAddress,
|
|
216
|
+
stakingAssetAddress,
|
|
217
|
+
rewardDistributorAddress,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
public async getEpochNumberForSlotNumber(slotNumber: bigint): Promise<bigint> {
|
|
222
|
+
return await this.rollup.read.getEpochAtSlot([slotNumber]);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
getEpochProofPublicInputs(
|
|
226
|
+
args: readonly [
|
|
227
|
+
bigint,
|
|
228
|
+
readonly [
|
|
229
|
+
`0x${string}`,
|
|
230
|
+
`0x${string}`,
|
|
231
|
+
`0x${string}`,
|
|
232
|
+
`0x${string}`,
|
|
233
|
+
`0x${string}`,
|
|
234
|
+
`0x${string}`,
|
|
235
|
+
`0x${string}`,
|
|
236
|
+
],
|
|
237
|
+
readonly `0x${string}`[],
|
|
238
|
+
`0x${string}`,
|
|
239
|
+
`0x${string}`,
|
|
240
|
+
],
|
|
241
|
+
) {
|
|
242
|
+
return this.rollup.read.getEpochProofPublicInputs(args);
|
|
243
|
+
}
|
|
244
|
+
public async getProofClaim() {
|
|
79
245
|
const {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
246
|
+
epochToProve,
|
|
247
|
+
basisPointFee,
|
|
248
|
+
bondAmount,
|
|
249
|
+
bondProvider: bondProviderHex,
|
|
250
|
+
proposerClaimant: proposerClaimantHex,
|
|
251
|
+
} = await this.rollup.read.getProofClaim();
|
|
252
|
+
|
|
253
|
+
const bondProvider = EthAddress.fromString(bondProviderHex);
|
|
254
|
+
const proposerClaimant = EthAddress.fromString(proposerClaimantHex);
|
|
255
|
+
|
|
256
|
+
if (bondProvider.isZero() && proposerClaimant.isZero() && epochToProve === 0n) {
|
|
257
|
+
return undefined;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return {
|
|
261
|
+
epochToProve,
|
|
262
|
+
basisPointFee,
|
|
263
|
+
bondAmount,
|
|
264
|
+
bondProvider,
|
|
265
|
+
proposerClaimant,
|
|
266
|
+
};
|
|
84
267
|
}
|
|
85
268
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
269
|
+
async getClaimableEpoch(): Promise<bigint | undefined> {
|
|
270
|
+
try {
|
|
271
|
+
return await this.rollup.read.getClaimableEpoch();
|
|
272
|
+
} catch (err: unknown) {
|
|
273
|
+
throw formatViemError(err);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
public async getEpochToProve(): Promise<bigint | undefined> {
|
|
278
|
+
try {
|
|
279
|
+
return await this.rollup.read.getEpochToProve();
|
|
280
|
+
} catch (err: unknown) {
|
|
281
|
+
throw formatViemError(err);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
public async validateProofQuote(
|
|
286
|
+
quote: {
|
|
287
|
+
quote: EpochProofQuoteViemArgs;
|
|
288
|
+
signature: ViemSignature;
|
|
289
|
+
},
|
|
290
|
+
account: `0x${string}` | Account,
|
|
291
|
+
slotDuration: bigint | number,
|
|
292
|
+
): Promise<void> {
|
|
293
|
+
if (typeof slotDuration === 'number') {
|
|
294
|
+
slotDuration = BigInt(slotDuration);
|
|
295
|
+
}
|
|
296
|
+
const timeOfNextL1Slot = BigInt((await this.client.getBlock()).timestamp + slotDuration);
|
|
297
|
+
const args = [timeOfNextL1Slot, quote] as const;
|
|
298
|
+
try {
|
|
299
|
+
await this.rollup.read.validateEpochProofRightClaimAtTime(args, { account });
|
|
300
|
+
} catch (err) {
|
|
301
|
+
throw formatViemError(err);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
public async validateHeader(
|
|
306
|
+
args: readonly [
|
|
307
|
+
`0x${string}`,
|
|
308
|
+
ViemSignature[],
|
|
309
|
+
`0x${string}`,
|
|
310
|
+
bigint,
|
|
311
|
+
`0x${string}`,
|
|
312
|
+
{
|
|
313
|
+
ignoreDA: boolean;
|
|
314
|
+
ignoreSignatures: boolean;
|
|
315
|
+
},
|
|
316
|
+
],
|
|
317
|
+
account: `0x${string}` | Account,
|
|
318
|
+
): Promise<void> {
|
|
319
|
+
try {
|
|
320
|
+
await this.rollup.read.validateHeader(args, { account });
|
|
321
|
+
} catch (error: unknown) {
|
|
322
|
+
throw formatViemError(error);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* @notice Calls `canProposeAtTime` with the time of the next Ethereum block and the sender address
|
|
328
|
+
*
|
|
329
|
+
* @dev Throws if unable to propose
|
|
330
|
+
*
|
|
331
|
+
* @param archive - The archive that we expect to be current state
|
|
332
|
+
* @return [slot, blockNumber] - If you can propose, the L2 slot number and L2 block number of the next Ethereum block,
|
|
333
|
+
* @throws otherwise
|
|
334
|
+
*/
|
|
335
|
+
public async canProposeAtNextEthBlock(
|
|
336
|
+
archive: Buffer,
|
|
337
|
+
account: `0x${string}` | Account,
|
|
338
|
+
slotDuration: bigint | number,
|
|
339
|
+
): Promise<[bigint, bigint]> {
|
|
340
|
+
if (typeof slotDuration === 'number') {
|
|
341
|
+
slotDuration = BigInt(slotDuration);
|
|
342
|
+
}
|
|
343
|
+
const timeOfNextL1Slot = (await this.client.getBlock()).timestamp + slotDuration;
|
|
344
|
+
try {
|
|
345
|
+
const [slot, blockNumber] = await this.rollup.read.canProposeAtTime(
|
|
346
|
+
[timeOfNextL1Slot, `0x${archive.toString('hex')}`],
|
|
347
|
+
{ account },
|
|
348
|
+
);
|
|
349
|
+
return [slot, blockNumber];
|
|
350
|
+
} catch (err: unknown) {
|
|
351
|
+
throw formatViemError(err);
|
|
352
|
+
}
|
|
93
353
|
}
|
|
94
354
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
2
|
+
import { SlashingProposerAbi } from '@aztec/l1-artifacts';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
type Chain,
|
|
6
|
+
type GetContractReturnType,
|
|
7
|
+
type Hex,
|
|
8
|
+
type HttpTransport,
|
|
9
|
+
type PublicClient,
|
|
10
|
+
getContract,
|
|
11
|
+
} from 'viem';
|
|
12
|
+
|
|
13
|
+
import type { L1Clients } from '../deploy_l1_contracts.js';
|
|
14
|
+
import type { L1TxRequest } from '../l1_tx_utils.js';
|
|
15
|
+
import { type IEmpireBase, encodeVote } from './empire_base.js';
|
|
16
|
+
|
|
17
|
+
export class SlashingProposerContract implements IEmpireBase {
|
|
18
|
+
private readonly proposer: GetContractReturnType<typeof SlashingProposerAbi, PublicClient<HttpTransport, Chain>>;
|
|
19
|
+
|
|
20
|
+
constructor(public readonly client: L1Clients['publicClient'], address: Hex) {
|
|
21
|
+
this.proposer = getContract({ address, abi: SlashingProposerAbi, client });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public get address() {
|
|
25
|
+
return EthAddress.fromString(this.proposer.address);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public getQuorumSize() {
|
|
29
|
+
return this.proposer.read.N();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public getRoundSize() {
|
|
33
|
+
return this.proposer.read.M();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public computeRound(slot: bigint): Promise<bigint> {
|
|
37
|
+
return this.proposer.read.computeRound([slot]);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public async getRoundInfo(
|
|
41
|
+
rollupAddress: Hex,
|
|
42
|
+
round: bigint,
|
|
43
|
+
): Promise<{ lastVote: bigint; leader: Hex; executed: boolean }> {
|
|
44
|
+
const roundInfo = await this.proposer.read.rounds([rollupAddress, round]);
|
|
45
|
+
return {
|
|
46
|
+
lastVote: roundInfo[0],
|
|
47
|
+
leader: roundInfo[1],
|
|
48
|
+
executed: roundInfo[2],
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public createVoteRequest(payload: Hex): L1TxRequest {
|
|
53
|
+
return {
|
|
54
|
+
to: this.address.toString(),
|
|
55
|
+
data: encodeVote(payload),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -9,14 +9,14 @@ import {
|
|
|
9
9
|
ExtRollupLibBytecode,
|
|
10
10
|
FeeJuicePortalAbi,
|
|
11
11
|
FeeJuicePortalBytecode,
|
|
12
|
+
ForwarderAbi,
|
|
13
|
+
ForwarderBytecode,
|
|
12
14
|
GovernanceAbi,
|
|
13
15
|
GovernanceBytecode,
|
|
14
16
|
GovernanceProposerAbi,
|
|
15
17
|
GovernanceProposerBytecode,
|
|
16
18
|
InboxAbi,
|
|
17
19
|
InboxBytecode,
|
|
18
|
-
LeonidasLibAbi,
|
|
19
|
-
LeonidasLibBytecode,
|
|
20
20
|
OutboxAbi,
|
|
21
21
|
OutboxBytecode,
|
|
22
22
|
RegistryAbi,
|
|
@@ -28,18 +28,27 @@ import {
|
|
|
28
28
|
RollupLinkReferences,
|
|
29
29
|
SlashFactoryAbi,
|
|
30
30
|
SlashFactoryBytecode,
|
|
31
|
+
StakingLibAbi,
|
|
32
|
+
StakingLibBytecode,
|
|
31
33
|
TestERC20Abi,
|
|
32
34
|
TestERC20Bytecode,
|
|
35
|
+
ValidatorSelectionLibAbi,
|
|
36
|
+
ValidatorSelectionLibBytecode,
|
|
33
37
|
} from '@aztec/l1-artifacts';
|
|
34
38
|
|
|
35
39
|
import type { Abi, Narrow } from 'abitype';
|
|
36
40
|
import {
|
|
37
41
|
type Account,
|
|
38
42
|
type Chain,
|
|
43
|
+
type Client,
|
|
39
44
|
type Hex,
|
|
40
45
|
type HttpTransport,
|
|
46
|
+
type PublicActions,
|
|
41
47
|
type PublicClient,
|
|
48
|
+
type PublicRpcSchema,
|
|
49
|
+
type WalletActions,
|
|
42
50
|
type WalletClient,
|
|
51
|
+
type WalletRpcSchema,
|
|
43
52
|
concatHex,
|
|
44
53
|
createPublicClient,
|
|
45
54
|
createWalletClient,
|
|
@@ -50,15 +59,18 @@ import {
|
|
|
50
59
|
http,
|
|
51
60
|
numberToHex,
|
|
52
61
|
padHex,
|
|
62
|
+
publicActions,
|
|
53
63
|
} from 'viem';
|
|
54
64
|
import { type HDAccount, type PrivateKeyAccount, mnemonicToAccount, privateKeyToAccount } from 'viem/accounts';
|
|
55
65
|
import { foundry } from 'viem/chains';
|
|
56
66
|
|
|
67
|
+
import { isAnvilTestChain } from './chain.js';
|
|
57
68
|
import { type L1ContractsConfig } from './config.js';
|
|
58
|
-
import { isAnvilTestChain } from './ethereum_chain.js';
|
|
59
69
|
import { type L1ContractAddresses } from './l1_contract_addresses.js';
|
|
60
70
|
import { L1TxUtils } from './l1_tx_utils.js';
|
|
61
71
|
|
|
72
|
+
export const DEPLOYER_ADDRESS: Hex = '0x4e59b44847b379578588920cA78FbF26c0B4956C';
|
|
73
|
+
|
|
62
74
|
/**
|
|
63
75
|
* Return type of the deployL1Contract function.
|
|
64
76
|
*/
|
|
@@ -128,14 +140,18 @@ export const l1Artifacts = {
|
|
|
128
140
|
libraries: {
|
|
129
141
|
linkReferences: RollupLinkReferences,
|
|
130
142
|
libraryCode: {
|
|
131
|
-
|
|
132
|
-
contractAbi:
|
|
133
|
-
contractBytecode:
|
|
143
|
+
ValidatorSelectionLib: {
|
|
144
|
+
contractAbi: ValidatorSelectionLibAbi,
|
|
145
|
+
contractBytecode: ValidatorSelectionLibBytecode as Hex,
|
|
134
146
|
},
|
|
135
147
|
ExtRollupLib: {
|
|
136
148
|
contractAbi: ExtRollupLibAbi,
|
|
137
149
|
contractBytecode: ExtRollupLibBytecode as Hex,
|
|
138
150
|
},
|
|
151
|
+
StakingLib: {
|
|
152
|
+
contractAbi: StakingLibAbi,
|
|
153
|
+
contractBytecode: StakingLibBytecode as Hex,
|
|
154
|
+
},
|
|
139
155
|
},
|
|
140
156
|
},
|
|
141
157
|
},
|
|
@@ -190,7 +206,13 @@ export interface DeployL1ContractsArgs extends L1ContractsConfig {
|
|
|
190
206
|
|
|
191
207
|
export type L1Clients = {
|
|
192
208
|
publicClient: PublicClient<HttpTransport, Chain>;
|
|
193
|
-
walletClient:
|
|
209
|
+
walletClient: Client<
|
|
210
|
+
HttpTransport,
|
|
211
|
+
Chain,
|
|
212
|
+
PrivateKeyAccount,
|
|
213
|
+
[...WalletRpcSchema, ...PublicRpcSchema],
|
|
214
|
+
PublicActions<HttpTransport, Chain> & WalletActions<Chain, PrivateKeyAccount>
|
|
215
|
+
>;
|
|
194
216
|
};
|
|
195
217
|
|
|
196
218
|
/**
|
|
@@ -212,18 +234,25 @@ export function createL1Clients(
|
|
|
212
234
|
: mnemonicToAccount(mnemonicOrPrivateKeyOrHdAccount)
|
|
213
235
|
: mnemonicOrPrivateKeyOrHdAccount;
|
|
214
236
|
|
|
237
|
+
// From what I can see, this is the difference between the HDAccount and the PrivateKeyAccount
|
|
238
|
+
// and we don't need it for anything. This lets us use the same type for both.
|
|
239
|
+
// eslint-disable-next-line camelcase
|
|
240
|
+
hdAccount.experimental_signAuthorization ??= () => {
|
|
241
|
+
throw new Error('experimental_signAuthorization not implemented for HDAccount');
|
|
242
|
+
};
|
|
243
|
+
|
|
215
244
|
const walletClient = createWalletClient({
|
|
216
245
|
account: hdAccount,
|
|
217
246
|
chain,
|
|
218
247
|
transport: http(rpcUrl),
|
|
219
|
-
});
|
|
248
|
+
}).extend(publicActions);
|
|
220
249
|
const publicClient = createPublicClient({
|
|
221
250
|
chain,
|
|
222
251
|
transport: http(rpcUrl),
|
|
223
252
|
pollingInterval: 100,
|
|
224
253
|
});
|
|
225
254
|
|
|
226
|
-
return { walletClient, publicClient };
|
|
255
|
+
return { walletClient, publicClient } as L1Clients;
|
|
227
256
|
}
|
|
228
257
|
|
|
229
258
|
/**
|
|
@@ -414,18 +443,18 @@ export const deployL1Contracts = async (
|
|
|
414
443
|
].map(txHash => publicClient.waitForTransactionReceipt({ hash: txHash })),
|
|
415
444
|
);
|
|
416
445
|
|
|
417
|
-
const
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
]);
|
|
446
|
+
const validators = newValidatorsAddresses.map(v => ({
|
|
447
|
+
attester: v,
|
|
448
|
+
proposer: getExpectedAddress(ForwarderAbi, ForwarderBytecode, [v], v).address,
|
|
449
|
+
withdrawer: v,
|
|
450
|
+
amount: args.minimumStake,
|
|
451
|
+
}));
|
|
452
|
+
const initiateValidatorSetTxHash = await rollup.write.cheat__InitialiseValidatorSet([validators]);
|
|
425
453
|
txHashes.push(initiateValidatorSetTxHash);
|
|
426
|
-
logger.info(
|
|
427
|
-
|
|
428
|
-
|
|
454
|
+
logger.info(`Initialized validator set`, {
|
|
455
|
+
validators,
|
|
456
|
+
txHash: initiateValidatorSetTxHash,
|
|
457
|
+
});
|
|
429
458
|
}
|
|
430
459
|
}
|
|
431
460
|
|
|
@@ -663,15 +692,12 @@ export async function deployL1Contract(
|
|
|
663
692
|
}
|
|
664
693
|
|
|
665
694
|
if (maybeSalt) {
|
|
666
|
-
const salt =
|
|
667
|
-
|
|
668
|
-
const calldata = encodeDeployData({ abi, bytecode, args });
|
|
669
|
-
resultingAddress = getContractAddress({ from: deployer, salt, bytecode: calldata, opcode: 'CREATE2' });
|
|
695
|
+
const { address, paddedSalt: salt, calldata } = getExpectedAddress(abi, bytecode, args, maybeSalt);
|
|
696
|
+
resultingAddress = address;
|
|
670
697
|
const existing = await publicClient.getBytecode({ address: resultingAddress });
|
|
671
|
-
|
|
672
698
|
if (existing === undefined || existing === '0x') {
|
|
673
699
|
const res = await l1TxUtils.sendTransaction({
|
|
674
|
-
to:
|
|
700
|
+
to: DEPLOYER_ADDRESS,
|
|
675
701
|
data: concatHex([salt, calldata]),
|
|
676
702
|
});
|
|
677
703
|
txHash = res.txHash;
|
|
@@ -701,4 +727,26 @@ export async function deployL1Contract(
|
|
|
701
727
|
|
|
702
728
|
return { address: EthAddress.fromString(resultingAddress!), txHash };
|
|
703
729
|
}
|
|
730
|
+
|
|
731
|
+
export function getExpectedAddress(
|
|
732
|
+
abi: Narrow<Abi | readonly unknown[]>,
|
|
733
|
+
bytecode: Hex,
|
|
734
|
+
args: readonly unknown[],
|
|
735
|
+
salt: Hex,
|
|
736
|
+
) {
|
|
737
|
+
const paddedSalt = padHex(salt, { size: 32 });
|
|
738
|
+
const calldata = encodeDeployData({ abi, bytecode, args });
|
|
739
|
+
const address = getContractAddress({
|
|
740
|
+
from: DEPLOYER_ADDRESS,
|
|
741
|
+
salt: paddedSalt,
|
|
742
|
+
bytecode: calldata,
|
|
743
|
+
opcode: 'CREATE2',
|
|
744
|
+
});
|
|
745
|
+
return {
|
|
746
|
+
address,
|
|
747
|
+
paddedSalt,
|
|
748
|
+
calldata,
|
|
749
|
+
};
|
|
750
|
+
}
|
|
751
|
+
|
|
704
752
|
// docs:end:deployL1Contract
|
package/src/index.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
export * from './constants.js';
|
|
2
2
|
export * from './deploy_l1_contracts.js';
|
|
3
|
-
export * from './
|
|
3
|
+
export * from './chain.js';
|
|
4
4
|
export * from './eth_cheat_codes.js';
|
|
5
5
|
export * from './l1_tx_utils.js';
|
|
6
|
+
export * from './l1_tx_utils_with_blobs.js';
|
|
6
7
|
export * from './l1_contract_addresses.js';
|
|
7
8
|
export * from './l1_reader.js';
|
|
8
9
|
export * from './utils.js';
|
|
9
10
|
export * from './config.js';
|
|
10
11
|
export * from './types.js';
|
|
11
12
|
export * from './contracts/index.js';
|
|
13
|
+
export * from './queries.js';
|
|
14
|
+
export * from './client.js';
|
package/src/l1_reader.ts
CHANGED
|
@@ -25,10 +25,9 @@ export const l1ReaderConfigMappings: ConfigMappingsType<L1ReaderConfig> = {
|
|
|
25
25
|
defaultValue: 31337,
|
|
26
26
|
description: 'The chain ID of the ethereum host.',
|
|
27
27
|
},
|
|
28
|
-
// NOTE: Special case for l1Contracts
|
|
29
28
|
l1Contracts: {
|
|
30
29
|
description: 'The deployed L1 contract addresses',
|
|
31
|
-
|
|
30
|
+
nested: l1ContractAddressesMapping,
|
|
32
31
|
},
|
|
33
32
|
viemPollingIntervalMS: {
|
|
34
33
|
env: 'L1_READER_VIEM_POLLING_INTERVAL_MS',
|