@aztec/ethereum 2.0.0-nightly.20250903 → 3.0.0-canary.a9708bd
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +61 -54
- package/dest/contracts/fee_asset_handler.d.ts +3 -2
- package/dest/contracts/fee_asset_handler.d.ts.map +1 -1
- package/dest/contracts/fee_asset_handler.js +14 -0
- package/dest/contracts/fee_juice.d.ts +2 -1
- package/dest/contracts/fee_juice.d.ts.map +1 -1
- package/dest/contracts/fee_juice.js +6 -0
- package/dest/contracts/governance.d.ts +1 -1
- package/dest/contracts/governance.d.ts.map +1 -1
- package/dest/contracts/governance.js +3 -0
- package/dest/contracts/governance_proposer.d.ts +1 -1
- package/dest/contracts/governance_proposer.d.ts.map +1 -1
- package/dest/contracts/governance_proposer.js +3 -0
- package/dest/contracts/gse.d.ts +2 -0
- package/dest/contracts/gse.d.ts.map +1 -1
- package/dest/contracts/gse.js +6 -0
- package/dest/deploy_l1_contracts.d.ts +2 -2
- package/dest/deploy_l1_contracts.d.ts.map +1 -1
- package/dest/deploy_l1_contracts.js +133 -53
- package/dest/l1_artifacts.d.ts +39210 -39196
- package/dest/l1_artifacts.d.ts.map +1 -1
- package/dest/test/eth_cheat_codes.d.ts +3 -2
- package/dest/test/eth_cheat_codes.d.ts.map +1 -1
- package/dest/test/eth_cheat_codes.js +11 -0
- package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
- package/dest/test/rollup_cheat_codes.js +2 -1
- package/dest/test/tx_delayer.d.ts +2 -2
- package/dest/test/tx_delayer.d.ts.map +1 -1
- package/dest/test/tx_delayer.js +4 -4
- package/package.json +5 -5
- package/src/config.ts +81 -72
- package/src/contracts/fee_asset_handler.ts +17 -2
- package/src/contracts/fee_juice.ts +8 -1
- package/src/contracts/governance.ts +4 -1
- package/src/contracts/governance_proposer.ts +4 -1
- package/src/contracts/gse.ts +8 -0
- package/src/deploy_l1_contracts.ts +151 -50
- package/src/test/eth_cheat_codes.ts +12 -2
- package/src/test/rollup_cheat_codes.ts +5 -1
- package/src/test/tx_delayer.ts +14 -4
package/src/config.ts
CHANGED
|
@@ -423,78 +423,7 @@ export function validateConfig(config: Omit<L1ContractsConfig, keyof L1TxUtilsCo
|
|
|
423
423
|
|
|
424
424
|
// TallySlashingProposer constructor validations
|
|
425
425
|
if (config.slasherFlavor === 'tally') {
|
|
426
|
-
|
|
427
|
-
if (config.slashingOffsetInRounds <= 0) {
|
|
428
|
-
errors.push(`slashingOffsetInRounds (${config.slashingOffsetInRounds}) must be greater than 0`);
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
// From: require(ROUND_SIZE_IN_EPOCHS * _epochDuration == ROUND_SIZE, Errors.TallySlashingProposer__RoundSizeMustBeMultipleOfEpochDuration(...));
|
|
432
|
-
const roundSizeInSlots = config.slashingRoundSizeInEpochs * config.aztecEpochDuration;
|
|
433
|
-
|
|
434
|
-
// From: require(QUORUM > 0, Errors.TallySlashingProposer__QuorumMustBeGreaterThanZero());
|
|
435
|
-
if (slashingQuorum !== undefined && slashingQuorum <= 0) {
|
|
436
|
-
errors.push(`slashingQuorum (${slashingQuorum}) must be greater than 0`);
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
// From: require(ROUND_SIZE > 1, Errors.TallySlashingProposer__InvalidQuorumAndRoundSize(QUORUM, ROUND_SIZE));
|
|
440
|
-
if (roundSizeInSlots <= 1) {
|
|
441
|
-
errors.push(`slashing round size in slots (${roundSizeInSlots}) must be greater than 1`);
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
// From: require(_slashAmounts[0] <= _slashAmounts[1], Errors.TallySlashingProposer__InvalidSlashAmounts(_slashAmounts));
|
|
445
|
-
if (config.slashAmountSmall > config.slashAmountMedium) {
|
|
446
|
-
errors.push(
|
|
447
|
-
`slashAmountSmall (${config.slashAmountSmall}) must be less than or equal to slashAmountMedium (${config.slashAmountMedium})`,
|
|
448
|
-
);
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
// From: require(_slashAmounts[1] <= _slashAmounts[2], Errors.TallySlashingProposer__InvalidSlashAmounts(_slashAmounts));
|
|
452
|
-
if (config.slashAmountMedium > config.slashAmountLarge) {
|
|
453
|
-
errors.push(
|
|
454
|
-
`slashAmountMedium (${config.slashAmountMedium}) must be less than or equal to slashAmountLarge (${config.slashAmountLarge})`,
|
|
455
|
-
);
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
// From: require(LIFETIME_IN_ROUNDS < ROUNDABOUT_SIZE, Errors.TallySlashingProposer__LifetimeMustBeLessThanRoundabout(...));
|
|
459
|
-
const ROUNDABOUT_SIZE = 128; // Constant from TallySlashingProposer
|
|
460
|
-
if (config.slashingLifetimeInRounds >= ROUNDABOUT_SIZE) {
|
|
461
|
-
errors.push(`slashingLifetimeInRounds (${config.slashingLifetimeInRounds}) must be less than ${ROUNDABOUT_SIZE}`);
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
// From: require(ROUND_SIZE_IN_EPOCHS > 0, Errors.TallySlashingProposer__RoundSizeInEpochsMustBeGreaterThanZero(...));
|
|
465
|
-
if (config.slashingRoundSizeInEpochs <= 0) {
|
|
466
|
-
errors.push(`slashingRoundSizeInEpochs (${config.slashingRoundSizeInEpochs}) must be greater than 0`);
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
// From: require(ROUND_SIZE < MAX_ROUND_SIZE, Errors.TallySlashingProposer__RoundSizeTooLarge(ROUND_SIZE, MAX_ROUND_SIZE));
|
|
470
|
-
const MAX_ROUND_SIZE = 1024; // Constant from TallySlashingProposer
|
|
471
|
-
if (roundSizeInSlots >= MAX_ROUND_SIZE) {
|
|
472
|
-
errors.push(`slashing round size in slots (${roundSizeInSlots}) must be less than ${MAX_ROUND_SIZE}`);
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
// From: require(COMMITTEE_SIZE > 0, Errors.TallySlashingProposer__CommitteeSizeMustBeGreaterThanZero(COMMITTEE_SIZE));
|
|
476
|
-
if (config.aztecTargetCommitteeSize <= 0) {
|
|
477
|
-
errors.push(`aztecTargetCommitteeSize (${config.aztecTargetCommitteeSize}) must be greater than 0`);
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
// From: require(voteSize <= 128, Errors.TallySlashingProposer__VoteSizeTooBig(voteSize, 128));
|
|
481
|
-
// voteSize = COMMITTEE_SIZE * ROUND_SIZE_IN_EPOCHS / 4
|
|
482
|
-
const voteSize = (config.aztecTargetCommitteeSize * config.slashingRoundSizeInEpochs) / 4;
|
|
483
|
-
if (voteSize > 128) {
|
|
484
|
-
errors.push(`vote size (${voteSize}) must be <= 128 (committee size * round size in epochs / 4)`);
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
// From: require(COMMITTEE_SIZE * ROUND_SIZE_IN_EPOCHS % 4 == 0, Errors.TallySlashingProposer__InvalidCommitteeAndRoundSize(...));
|
|
488
|
-
if ((config.aztecTargetCommitteeSize * config.slashingRoundSizeInEpochs) % 4 !== 0) {
|
|
489
|
-
errors.push(
|
|
490
|
-
`aztecTargetCommitteeSize * slashingRoundSizeInEpochs (${config.aztecTargetCommitteeSize * config.slashingRoundSizeInEpochs}) must be divisible by 4`,
|
|
491
|
-
);
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
// Slashing offset validation: should be positive to allow proper slashing timing
|
|
495
|
-
if (config.slashingOffsetInRounds < 0) {
|
|
496
|
-
errors.push('slashingOffsetInRounds cannot be negative');
|
|
497
|
-
}
|
|
426
|
+
validateTallySlasherConfig(config, errors);
|
|
498
427
|
}
|
|
499
428
|
|
|
500
429
|
// Epoch and slot duration validations
|
|
@@ -541,3 +470,83 @@ export function validateConfig(config: Omit<L1ContractsConfig, keyof L1TxUtilsCo
|
|
|
541
470
|
);
|
|
542
471
|
}
|
|
543
472
|
}
|
|
473
|
+
|
|
474
|
+
function validateTallySlasherConfig(config: L1ContractsConfig, errors: string[]) {
|
|
475
|
+
if (config.slasherFlavor !== 'tally') {
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// From: require(SLASH_OFFSET_IN_ROUNDS > 0, Errors.TallySlashingProposer__SlashOffsetMustBeGreaterThanZero(...));
|
|
480
|
+
if (config.slashingOffsetInRounds <= 0) {
|
|
481
|
+
errors.push(`slashingOffsetInRounds (${config.slashingOffsetInRounds}) must be greater than 0`);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// From: require(ROUND_SIZE_IN_EPOCHS * _epochDuration == ROUND_SIZE, Errors.TallySlashingProposer__RoundSizeMustBeMultipleOfEpochDuration(...));
|
|
485
|
+
const roundSizeInSlots = config.slashingRoundSizeInEpochs * config.aztecEpochDuration;
|
|
486
|
+
|
|
487
|
+
// From: require(QUORUM > 0, Errors.TallySlashingProposer__QuorumMustBeGreaterThanZero());
|
|
488
|
+
const { slashingQuorum } = config;
|
|
489
|
+
if (slashingQuorum !== undefined && slashingQuorum <= 0) {
|
|
490
|
+
errors.push(`slashingQuorum (${slashingQuorum}) must be greater than 0`);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// From: require(ROUND_SIZE > 1, Errors.TallySlashingProposer__InvalidQuorumAndRoundSize(QUORUM, ROUND_SIZE));
|
|
494
|
+
if (roundSizeInSlots <= 1) {
|
|
495
|
+
errors.push(`slashing round size in slots (${roundSizeInSlots}) must be greater than 1`);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// From: require(_slashAmounts[0] <= _slashAmounts[1], Errors.TallySlashingProposer__InvalidSlashAmounts(_slashAmounts));
|
|
499
|
+
if (config.slashAmountSmall > config.slashAmountMedium) {
|
|
500
|
+
errors.push(
|
|
501
|
+
`slashAmountSmall (${config.slashAmountSmall}) must be less than or equal to slashAmountMedium (${config.slashAmountMedium})`,
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// From: require(_slashAmounts[1] <= _slashAmounts[2], Errors.TallySlashingProposer__InvalidSlashAmounts(_slashAmounts));
|
|
506
|
+
if (config.slashAmountMedium > config.slashAmountLarge) {
|
|
507
|
+
errors.push(
|
|
508
|
+
`slashAmountMedium (${config.slashAmountMedium}) must be less than or equal to slashAmountLarge (${config.slashAmountLarge})`,
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// From: require(LIFETIME_IN_ROUNDS < ROUNDABOUT_SIZE, Errors.TallySlashingProposer__LifetimeMustBeLessThanRoundabout(...));
|
|
513
|
+
const ROUNDABOUT_SIZE = 128; // Constant from TallySlashingProposer
|
|
514
|
+
if (config.slashingLifetimeInRounds >= ROUNDABOUT_SIZE) {
|
|
515
|
+
errors.push(`slashingLifetimeInRounds (${config.slashingLifetimeInRounds}) must be less than ${ROUNDABOUT_SIZE}`);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// From: require(ROUND_SIZE_IN_EPOCHS > 0, Errors.TallySlashingProposer__RoundSizeInEpochsMustBeGreaterThanZero(...));
|
|
519
|
+
if (config.slashingRoundSizeInEpochs <= 0) {
|
|
520
|
+
errors.push(`slashingRoundSizeInEpochs (${config.slashingRoundSizeInEpochs}) must be greater than 0`);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// From: require(ROUND_SIZE < MAX_ROUND_SIZE, Errors.TallySlashingProposer__RoundSizeTooLarge(ROUND_SIZE, MAX_ROUND_SIZE));
|
|
524
|
+
const MAX_ROUND_SIZE = 1024; // Constant from TallySlashingProposer
|
|
525
|
+
if (roundSizeInSlots >= MAX_ROUND_SIZE) {
|
|
526
|
+
errors.push(`slashing round size in slots (${roundSizeInSlots}) must be less than ${MAX_ROUND_SIZE}`);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// From: require(COMMITTEE_SIZE > 0, Errors.TallySlashingProposer__CommitteeSizeMustBeGreaterThanZero(COMMITTEE_SIZE));
|
|
530
|
+
if (config.aztecTargetCommitteeSize <= 0) {
|
|
531
|
+
errors.push(`aztecTargetCommitteeSize (${config.aztecTargetCommitteeSize}) must be greater than 0`);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// From: require(voteSize <= 128, Errors.TallySlashingProposer__VoteSizeTooBig(voteSize, 128));
|
|
535
|
+
// voteSize = COMMITTEE_SIZE * ROUND_SIZE_IN_EPOCHS / 4
|
|
536
|
+
const voteSize = (config.aztecTargetCommitteeSize * config.slashingRoundSizeInEpochs) / 4;
|
|
537
|
+
if (voteSize > 128) {
|
|
538
|
+
errors.push(`vote size (${voteSize}) must be <= 128 (committee size * round size in epochs / 4)`);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// From: require(COMMITTEE_SIZE * ROUND_SIZE_IN_EPOCHS % 4 == 0, Errors.TallySlashingProposer__InvalidCommitteeAndRoundSize(...));
|
|
542
|
+
if ((config.aztecTargetCommitteeSize * config.slashingRoundSizeInEpochs) % 4 !== 0) {
|
|
543
|
+
errors.push(
|
|
544
|
+
`aztecTargetCommitteeSize * slashingRoundSizeInEpochs (${config.aztecTargetCommitteeSize * config.slashingRoundSizeInEpochs}) must be divisible by 4`,
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// Slashing offset validation: should be positive to allow proper slashing timing
|
|
549
|
+
if (config.slashingOffsetInRounds < 0) {
|
|
550
|
+
errors.push('slashingOffsetInRounds cannot be negative');
|
|
551
|
+
}
|
|
552
|
+
}
|
|
@@ -9,12 +9,24 @@ export class FeeAssetHandlerContract {
|
|
|
9
9
|
public address: EthAddress;
|
|
10
10
|
|
|
11
11
|
constructor(
|
|
12
|
-
address: Hex,
|
|
12
|
+
address: Hex | EthAddress,
|
|
13
13
|
public readonly txUtils: L1TxUtils,
|
|
14
14
|
) {
|
|
15
|
+
if (address instanceof EthAddress) {
|
|
16
|
+
address = address.toString();
|
|
17
|
+
}
|
|
15
18
|
this.address = EthAddress.fromString(address);
|
|
16
19
|
}
|
|
17
20
|
|
|
21
|
+
public async getOwner(): Promise<EthAddress> {
|
|
22
|
+
const contract = getContract({
|
|
23
|
+
abi: FeeAssetHandlerAbi,
|
|
24
|
+
address: this.address.toString(),
|
|
25
|
+
client: this.txUtils.client,
|
|
26
|
+
});
|
|
27
|
+
return EthAddress.fromString(await contract.read.owner());
|
|
28
|
+
}
|
|
29
|
+
|
|
18
30
|
public getMintAmount() {
|
|
19
31
|
const contract = getContract({
|
|
20
32
|
abi: FeeAssetHandlerAbi,
|
|
@@ -24,7 +36,10 @@ export class FeeAssetHandlerContract {
|
|
|
24
36
|
return contract.read.mintAmount();
|
|
25
37
|
}
|
|
26
38
|
|
|
27
|
-
public mint(recipient: Hex) {
|
|
39
|
+
public mint(recipient: Hex | EthAddress) {
|
|
40
|
+
if (recipient instanceof EthAddress) {
|
|
41
|
+
recipient = recipient.toString();
|
|
42
|
+
}
|
|
28
43
|
return this.txUtils.sendAndMonitorTransaction({
|
|
29
44
|
to: this.address.toString(),
|
|
30
45
|
data: encodeFunctionData({
|
|
@@ -9,9 +9,12 @@ export class FeeJuiceContract {
|
|
|
9
9
|
private readonly feeJuiceContract: GetContractReturnType<typeof FeeJuiceAbi, ViemClient>;
|
|
10
10
|
|
|
11
11
|
constructor(
|
|
12
|
-
address: Hex,
|
|
12
|
+
address: Hex | EthAddress,
|
|
13
13
|
public readonly client: ViemClient,
|
|
14
14
|
) {
|
|
15
|
+
if (address instanceof EthAddress) {
|
|
16
|
+
address = address.toString();
|
|
17
|
+
}
|
|
15
18
|
this.feeJuiceContract = getContract({ address, abi: FeeJuiceAbi, client });
|
|
16
19
|
}
|
|
17
20
|
|
|
@@ -19,6 +22,10 @@ export class FeeJuiceContract {
|
|
|
19
22
|
return EthAddress.fromString(this.feeJuiceContract.address);
|
|
20
23
|
}
|
|
21
24
|
|
|
25
|
+
public async getOwner(): Promise<EthAddress> {
|
|
26
|
+
return EthAddress.fromString(await this.feeJuiceContract.read.owner());
|
|
27
|
+
}
|
|
28
|
+
|
|
22
29
|
private assertWalletFeeJuice(): GetContractReturnType<typeof FeeJuiceAbi, ExtendedViemWalletClient> {
|
|
23
30
|
if (!isExtendedClient(this.client)) {
|
|
24
31
|
throw new Error('Wallet client is required for this operation');
|
|
@@ -136,9 +136,12 @@ export class GovernanceContract extends ReadOnlyGovernanceContract {
|
|
|
136
136
|
protected override readonly governanceContract: GetContractReturnType<typeof GovernanceAbi, ExtendedViemWalletClient>;
|
|
137
137
|
|
|
138
138
|
constructor(
|
|
139
|
-
address: Hex,
|
|
139
|
+
address: Hex | EthAddress,
|
|
140
140
|
public override readonly client: ExtendedViemWalletClient,
|
|
141
141
|
) {
|
|
142
|
+
if (address instanceof EthAddress) {
|
|
143
|
+
address = address.toString();
|
|
144
|
+
}
|
|
142
145
|
super(address, client);
|
|
143
146
|
if (!isExtendedClient(client)) {
|
|
144
147
|
throw new Error('GovernanceContract has to be instantiated with a wallet client.');
|
|
@@ -21,8 +21,11 @@ export class GovernanceProposerContract implements IEmpireBase {
|
|
|
21
21
|
|
|
22
22
|
constructor(
|
|
23
23
|
public readonly client: ViemClient,
|
|
24
|
-
address: Hex,
|
|
24
|
+
address: Hex | EthAddress,
|
|
25
25
|
) {
|
|
26
|
+
if (address instanceof EthAddress) {
|
|
27
|
+
address = address.toString();
|
|
28
|
+
}
|
|
26
29
|
this.proposer = getContract({ address, abi: GovernanceProposerAbi, client });
|
|
27
30
|
}
|
|
28
31
|
|
package/src/contracts/gse.ts
CHANGED
|
@@ -39,6 +39,14 @@ export class GSEContract {
|
|
|
39
39
|
this.gse = getContract({ address, abi: GSEAbi, client });
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
public async getOwner(): Promise<EthAddress> {
|
|
43
|
+
return EthAddress.fromString(await this.gse.read.owner());
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public async getGovernance(): Promise<EthAddress> {
|
|
47
|
+
return EthAddress.fromString(await this.gse.read.getGovernance());
|
|
48
|
+
}
|
|
49
|
+
|
|
42
50
|
getAttestersFromIndicesAtTime(instance: Hex | EthAddress, ts: bigint, indices: bigint[]) {
|
|
43
51
|
if (instance instanceof EthAddress) {
|
|
44
52
|
instance = instance.toString();
|
|
@@ -263,37 +263,14 @@ export const deploySharedContracts = async (
|
|
|
263
263
|
|
|
264
264
|
const coinIssuerAddress = await deployer.deploy(CoinIssuerArtifact, [
|
|
265
265
|
feeAssetAddress.toString(),
|
|
266
|
-
|
|
267
|
-
|
|
266
|
+
1_000_000n * 10n ** 18n, // @todo #8084
|
|
267
|
+
l1Client.account.address,
|
|
268
268
|
]);
|
|
269
269
|
logger.verbose(`Deployed CoinIssuer at ${coinIssuerAddress}`);
|
|
270
270
|
|
|
271
|
-
const feeAsset = getContract({
|
|
272
|
-
address: feeAssetAddress.toString(),
|
|
273
|
-
abi: FeeAssetArtifact.contractAbi,
|
|
274
|
-
client: l1Client,
|
|
275
|
-
});
|
|
276
|
-
|
|
277
271
|
logger.verbose(`Waiting for deployments to complete`);
|
|
278
272
|
await deployer.waitForDeployments();
|
|
279
273
|
|
|
280
|
-
if (args.acceleratedTestDeployments || !(await feeAsset.read.minters([coinIssuerAddress.toString()]))) {
|
|
281
|
-
const { txHash } = await deployer.sendTransaction(
|
|
282
|
-
{
|
|
283
|
-
to: feeAssetAddress.toString(),
|
|
284
|
-
data: encodeFunctionData({
|
|
285
|
-
abi: FeeAssetArtifact.contractAbi,
|
|
286
|
-
functionName: 'addMinter',
|
|
287
|
-
args: [coinIssuerAddress.toString()],
|
|
288
|
-
}),
|
|
289
|
-
},
|
|
290
|
-
{ gasLimit: 100_000n },
|
|
291
|
-
);
|
|
292
|
-
|
|
293
|
-
logger.verbose(`Added coin issuer ${coinIssuerAddress} as minter on fee asset in ${txHash}`);
|
|
294
|
-
txHashes.push(txHash);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
274
|
// Registry ownership will be transferred to governance later, after rollup is added
|
|
298
275
|
|
|
299
276
|
let feeAssetHandlerAddress: EthAddress | undefined = undefined;
|
|
@@ -309,20 +286,23 @@ export const deploySharedContracts = async (
|
|
|
309
286
|
feeAssetHandlerAddress = await deployer.deploy(FeeAssetHandlerArtifact, [
|
|
310
287
|
l1Client.account.address,
|
|
311
288
|
feeAssetAddress.toString(),
|
|
312
|
-
BigInt(
|
|
289
|
+
BigInt(1000n * 10n ** 18n),
|
|
313
290
|
]);
|
|
314
291
|
logger.verbose(`Deployed FeeAssetHandler at ${feeAssetHandlerAddress}`);
|
|
315
292
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
293
|
+
// Only if we are "fresh" will we be adding as a minter, otherwise above will simply get same address
|
|
294
|
+
if (needToSetGovernance) {
|
|
295
|
+
const { txHash } = await deployer.sendTransaction({
|
|
296
|
+
to: feeAssetAddress.toString(),
|
|
297
|
+
data: encodeFunctionData({
|
|
298
|
+
abi: FeeAssetArtifact.contractAbi,
|
|
299
|
+
functionName: 'addMinter',
|
|
300
|
+
args: [feeAssetHandlerAddress.toString()],
|
|
301
|
+
}),
|
|
302
|
+
});
|
|
303
|
+
logger.verbose(`Added fee asset handler ${feeAssetHandlerAddress} as minter on fee asset in ${txHash}`);
|
|
304
|
+
txHashes.push(txHash);
|
|
305
|
+
}
|
|
326
306
|
|
|
327
307
|
// Only if on sepolia will we deploy the staking asset handler
|
|
328
308
|
// Should not be deployed to devnet since it would cause caos with sequencers there etc.
|
|
@@ -517,7 +497,12 @@ export const deployRollup = async (
|
|
|
517
497
|
>,
|
|
518
498
|
addresses: Pick<
|
|
519
499
|
L1ContractAddresses,
|
|
520
|
-
|
|
500
|
+
| 'feeJuiceAddress'
|
|
501
|
+
| 'registryAddress'
|
|
502
|
+
| 'rewardDistributorAddress'
|
|
503
|
+
| 'stakingAssetAddress'
|
|
504
|
+
| 'gseAddress'
|
|
505
|
+
| 'governanceAddress'
|
|
521
506
|
>,
|
|
522
507
|
logger: Logger,
|
|
523
508
|
) => {
|
|
@@ -695,6 +680,24 @@ export const deployRollup = async (
|
|
|
695
680
|
);
|
|
696
681
|
}
|
|
697
682
|
|
|
683
|
+
// If the owner is not the Governance contract, transfer ownership to the Governance contract
|
|
684
|
+
logger.verbose(addresses.governanceAddress.toString());
|
|
685
|
+
if (getAddress(await rollupContract.getOwner()) !== getAddress(addresses.governanceAddress.toString())) {
|
|
686
|
+
// TODO(md): add send transaction to the deployer such that we do not need to manage tx hashes here
|
|
687
|
+
const { txHash: transferOwnershipTxHash } = await deployer.sendTransaction({
|
|
688
|
+
to: rollupContract.address,
|
|
689
|
+
data: encodeFunctionData({
|
|
690
|
+
abi: RegistryArtifact.contractAbi,
|
|
691
|
+
functionName: 'transferOwnership',
|
|
692
|
+
args: [getAddress(addresses.governanceAddress.toString())],
|
|
693
|
+
}),
|
|
694
|
+
});
|
|
695
|
+
logger.verbose(
|
|
696
|
+
`Transferring the ownership of the rollup contract at ${rollupContract.address} to the Governance ${addresses.governanceAddress} in tx ${transferOwnershipTxHash}`,
|
|
697
|
+
);
|
|
698
|
+
txHashes.push(transferOwnershipTxHash);
|
|
699
|
+
}
|
|
700
|
+
|
|
698
701
|
await deployer.waitForDeployments();
|
|
699
702
|
await Promise.all(txHashes.map(txHash => extendedClient.waitForTransactionReceipt({ hash: txHash })));
|
|
700
703
|
logger.verbose(`Rollup deployed`);
|
|
@@ -707,6 +710,8 @@ export const handoverToGovernance = async (
|
|
|
707
710
|
deployer: L1Deployer,
|
|
708
711
|
registryAddress: EthAddress,
|
|
709
712
|
gseAddress: EthAddress,
|
|
713
|
+
coinIssuerAddress: EthAddress,
|
|
714
|
+
feeAssetAddress: EthAddress,
|
|
710
715
|
governanceAddress: EthAddress,
|
|
711
716
|
logger: Logger,
|
|
712
717
|
acceleratedTestDeployments: boolean | undefined,
|
|
@@ -724,6 +729,18 @@ export const handoverToGovernance = async (
|
|
|
724
729
|
client: extendedClient,
|
|
725
730
|
});
|
|
726
731
|
|
|
732
|
+
const coinIssuerContract = getContract({
|
|
733
|
+
address: getAddress(coinIssuerAddress.toString()),
|
|
734
|
+
abi: CoinIssuerArtifact.contractAbi,
|
|
735
|
+
client: extendedClient,
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
const feeAsset = getContract({
|
|
739
|
+
address: getAddress(feeAssetAddress.toString()),
|
|
740
|
+
abi: FeeAssetArtifact.contractAbi,
|
|
741
|
+
client: extendedClient,
|
|
742
|
+
});
|
|
743
|
+
|
|
727
744
|
const txHashes: Hex[] = [];
|
|
728
745
|
|
|
729
746
|
// If the owner is not the Governance contract, transfer ownership to the Governance contract
|
|
@@ -763,6 +780,54 @@ export const handoverToGovernance = async (
|
|
|
763
780
|
txHashes.push(transferOwnershipTxHash);
|
|
764
781
|
}
|
|
765
782
|
|
|
783
|
+
if (acceleratedTestDeployments || (await feeAsset.read.owner()) !== coinIssuerAddress.toString()) {
|
|
784
|
+
const { txHash } = await deployer.sendTransaction(
|
|
785
|
+
{
|
|
786
|
+
to: feeAssetAddress.toString(),
|
|
787
|
+
data: encodeFunctionData({
|
|
788
|
+
abi: FeeAssetArtifact.contractAbi,
|
|
789
|
+
functionName: 'transferOwnership',
|
|
790
|
+
args: [coinIssuerAddress.toString()],
|
|
791
|
+
}),
|
|
792
|
+
},
|
|
793
|
+
{ gasLimit: 500_000n },
|
|
794
|
+
);
|
|
795
|
+
logger.verbose(`Transfer ownership of fee asset to coin issuer ${coinIssuerAddress} in ${txHash}`);
|
|
796
|
+
txHashes.push(txHash);
|
|
797
|
+
|
|
798
|
+
const { txHash: acceptTokenOwnershipTxHash } = await deployer.sendTransaction(
|
|
799
|
+
{
|
|
800
|
+
to: coinIssuerAddress.toString(),
|
|
801
|
+
data: encodeFunctionData({
|
|
802
|
+
abi: CoinIssuerArtifact.contractAbi,
|
|
803
|
+
functionName: 'acceptTokenOwnership',
|
|
804
|
+
}),
|
|
805
|
+
},
|
|
806
|
+
{ gasLimit: 500_000n },
|
|
807
|
+
);
|
|
808
|
+
logger.verbose(`Accept ownership of fee asset in ${acceptTokenOwnershipTxHash}`);
|
|
809
|
+
txHashes.push(acceptTokenOwnershipTxHash);
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
// If the owner is not the Governance contract, transfer ownership to the Governance contract
|
|
813
|
+
if (
|
|
814
|
+
acceleratedTestDeployments ||
|
|
815
|
+
(await coinIssuerContract.read.owner()) !== getAddress(governanceAddress.toString())
|
|
816
|
+
) {
|
|
817
|
+
const { txHash: transferOwnershipTxHash } = await deployer.sendTransaction({
|
|
818
|
+
to: coinIssuerContract.address,
|
|
819
|
+
data: encodeFunctionData({
|
|
820
|
+
abi: CoinIssuerArtifact.contractAbi,
|
|
821
|
+
functionName: 'transferOwnership',
|
|
822
|
+
args: [getAddress(governanceAddress.toString())],
|
|
823
|
+
}),
|
|
824
|
+
});
|
|
825
|
+
logger.verbose(
|
|
826
|
+
`Transferring the ownership of the coin issuer contract at ${coinIssuerAddress} to the Governance ${governanceAddress} in tx ${transferOwnershipTxHash}`,
|
|
827
|
+
);
|
|
828
|
+
txHashes.push(transferOwnershipTxHash);
|
|
829
|
+
}
|
|
830
|
+
|
|
766
831
|
// Wait for all actions to be mined
|
|
767
832
|
await deployer.waitForDeployments();
|
|
768
833
|
await Promise.all(txHashes.map(txHash => extendedClient.waitForTransactionReceipt({ hash: txHash })));
|
|
@@ -844,19 +909,51 @@ export const addMultipleValidators = async (
|
|
|
844
909
|
|
|
845
910
|
logger.info(`Adding ${validators.length} validators to the rollup`);
|
|
846
911
|
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
912
|
+
// Adding to the queue and flushing need to be done in two transactions
|
|
913
|
+
// if we are adding many validators.
|
|
914
|
+
if (validatorsTuples.length > 10) {
|
|
915
|
+
await deployer.l1TxUtils.sendAndMonitorTransaction(
|
|
916
|
+
{
|
|
917
|
+
to: multiAdder.toString(),
|
|
918
|
+
data: encodeFunctionData({
|
|
919
|
+
abi: MultiAdderArtifact.contractAbi,
|
|
920
|
+
functionName: 'addValidators',
|
|
921
|
+
args: [validatorsTuples, true],
|
|
922
|
+
}),
|
|
923
|
+
},
|
|
924
|
+
{
|
|
925
|
+
gasLimit: 40_000_000n,
|
|
926
|
+
},
|
|
927
|
+
);
|
|
928
|
+
|
|
929
|
+
await deployer.l1TxUtils.sendAndMonitorTransaction(
|
|
930
|
+
{
|
|
931
|
+
to: rollupAddress,
|
|
932
|
+
data: encodeFunctionData({
|
|
933
|
+
abi: RollupArtifact.contractAbi,
|
|
934
|
+
functionName: 'flushEntryQueue',
|
|
935
|
+
args: [],
|
|
936
|
+
}),
|
|
937
|
+
},
|
|
938
|
+
{
|
|
939
|
+
gasLimit: 40_000_000n,
|
|
940
|
+
},
|
|
941
|
+
);
|
|
942
|
+
} else {
|
|
943
|
+
await deployer.l1TxUtils.sendAndMonitorTransaction(
|
|
944
|
+
{
|
|
945
|
+
to: multiAdder.toString(),
|
|
946
|
+
data: encodeFunctionData({
|
|
947
|
+
abi: MultiAdderArtifact.contractAbi,
|
|
948
|
+
functionName: 'addValidators',
|
|
949
|
+
args: [validatorsTuples, false],
|
|
950
|
+
}),
|
|
951
|
+
},
|
|
952
|
+
{
|
|
953
|
+
gasLimit: 45_000_000n,
|
|
954
|
+
},
|
|
955
|
+
);
|
|
956
|
+
}
|
|
860
957
|
|
|
861
958
|
const entryQueueLengthAfter = await rollup.getEntryQueueLength();
|
|
862
959
|
const validatorCountAfter = await rollup.getActiveAttesterCount();
|
|
@@ -933,6 +1030,7 @@ export const deployL1Contracts = async (
|
|
|
933
1030
|
txUtilsConfig: L1TxUtilsConfig = getL1TxUtilsConfigEnvVars(),
|
|
934
1031
|
createVerificationJson: string | false = false,
|
|
935
1032
|
): Promise<DeployL1ContractsReturnType> => {
|
|
1033
|
+
logger.info(`Deploying L1 contracts with config: ${jsonStringify(args)}`);
|
|
936
1034
|
validateConfig(args);
|
|
937
1035
|
|
|
938
1036
|
const l1Client = createExtendedL1Client(rpcUrls, account, chain);
|
|
@@ -995,6 +1093,7 @@ export const deployL1Contracts = async (
|
|
|
995
1093
|
gseAddress,
|
|
996
1094
|
rewardDistributorAddress,
|
|
997
1095
|
stakingAssetAddress,
|
|
1096
|
+
governanceAddress,
|
|
998
1097
|
},
|
|
999
1098
|
logger,
|
|
1000
1099
|
);
|
|
@@ -1008,6 +1107,8 @@ export const deployL1Contracts = async (
|
|
|
1008
1107
|
deployer,
|
|
1009
1108
|
registryAddress,
|
|
1010
1109
|
gseAddress,
|
|
1110
|
+
coinIssuerAddress,
|
|
1111
|
+
feeAssetAddress,
|
|
1011
1112
|
governanceAddress,
|
|
1012
1113
|
logger,
|
|
1013
1114
|
args.acceleratedTestDeployments,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { toBigIntBE, toHex } from '@aztec/foundation/bigint-buffer';
|
|
2
2
|
import { keccak256 } from '@aztec/foundation/crypto';
|
|
3
|
-
import
|
|
3
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
4
4
|
import { jsonStringify } from '@aztec/foundation/json-rpc';
|
|
5
5
|
import { createLogger } from '@aztec/foundation/log';
|
|
6
6
|
import type { TestDateProvider } from '@aztec/foundation/timer';
|
|
@@ -112,7 +112,7 @@ export class EthCheatCodes {
|
|
|
112
112
|
* @param account - The account to set the balance for
|
|
113
113
|
* @param balance - The balance to set
|
|
114
114
|
*/
|
|
115
|
-
public async setBalance(account: EthAddress, balance: bigint): Promise<void> {
|
|
115
|
+
public async setBalance(account: EthAddress | Hex, balance: bigint): Promise<void> {
|
|
116
116
|
try {
|
|
117
117
|
await this.rpcCall('anvil_setBalance', [account.toString(), toHex(balance)]);
|
|
118
118
|
} catch (err) {
|
|
@@ -121,6 +121,11 @@ export class EthCheatCodes {
|
|
|
121
121
|
this.logger.warn(`Set balance for ${account} to ${balance}`);
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
public async getBalance(account: EthAddress | Hex): Promise<bigint> {
|
|
125
|
+
const res = await this.rpcCall('eth_getBalance', [account.toString(), 'latest']);
|
|
126
|
+
return BigInt(res);
|
|
127
|
+
}
|
|
128
|
+
|
|
124
129
|
/**
|
|
125
130
|
* Set the interval between successive blocks (block time). This does NOT enable interval mining.
|
|
126
131
|
* @param interval - The interval to use between blocks
|
|
@@ -300,6 +305,11 @@ export class EthCheatCodes {
|
|
|
300
305
|
*/
|
|
301
306
|
public async startImpersonating(who: EthAddress | Hex): Promise<void> {
|
|
302
307
|
try {
|
|
308
|
+
// Since the `who` impersonated will sometimes be a contract without funds, we fund it if needed.
|
|
309
|
+
if ((await this.getBalance(who)) === 0n) {
|
|
310
|
+
await this.setBalance(who, 10n * 10n ** 18n);
|
|
311
|
+
}
|
|
312
|
+
|
|
303
313
|
await this.rpcCall('hardhat_impersonateAccount', [who.toString()]);
|
|
304
314
|
} catch (err) {
|
|
305
315
|
throw new Error(`Error impersonating ${who}: ${err}`);
|
|
@@ -258,7 +258,11 @@ export class RollupCheatCodes {
|
|
|
258
258
|
*/
|
|
259
259
|
public async setProvingCostPerMana(ethValue: bigint) {
|
|
260
260
|
await this.asOwner(async (account, rollup) => {
|
|
261
|
-
const hash = await rollup.write.setProvingCostPerMana([ethValue], {
|
|
261
|
+
const hash = await rollup.write.setProvingCostPerMana([ethValue], {
|
|
262
|
+
account,
|
|
263
|
+
chain: this.client.chain,
|
|
264
|
+
gasLimit: 1000000n,
|
|
265
|
+
});
|
|
262
266
|
await this.client.waitForTransactionReceipt({ hash });
|
|
263
267
|
this.logger.warn(`Updated proving cost per mana to ${ethValue}`);
|
|
264
268
|
});
|
package/src/test/tx_delayer.ts
CHANGED
|
@@ -18,7 +18,12 @@ import {
|
|
|
18
18
|
|
|
19
19
|
import { type ViemClient, isExtendedClient } from '../types.js';
|
|
20
20
|
|
|
21
|
-
export function waitUntilBlock<T extends Client>(
|
|
21
|
+
export function waitUntilBlock<T extends Client>(
|
|
22
|
+
client: T,
|
|
23
|
+
blockNumber: number | bigint,
|
|
24
|
+
logger?: Logger,
|
|
25
|
+
timeout?: number,
|
|
26
|
+
) {
|
|
22
27
|
const publicClient =
|
|
23
28
|
'getBlockNumber' in client && typeof client.getBlockNumber === 'function'
|
|
24
29
|
? (client as unknown as PublicClient)
|
|
@@ -31,12 +36,17 @@ export function waitUntilBlock<T extends Client>(client: T, blockNumber: number
|
|
|
31
36
|
return currentBlockNumber >= BigInt(blockNumber);
|
|
32
37
|
},
|
|
33
38
|
`Wait until L1 block ${blockNumber}`,
|
|
34
|
-
120,
|
|
39
|
+
timeout ?? 120,
|
|
35
40
|
0.1,
|
|
36
41
|
);
|
|
37
42
|
}
|
|
38
43
|
|
|
39
|
-
export function waitUntilL1Timestamp<T extends Client>(
|
|
44
|
+
export function waitUntilL1Timestamp<T extends Client>(
|
|
45
|
+
client: T,
|
|
46
|
+
timestamp: number | bigint,
|
|
47
|
+
logger?: Logger,
|
|
48
|
+
timeout?: number,
|
|
49
|
+
) {
|
|
40
50
|
const publicClient =
|
|
41
51
|
'getBlockNumber' in client && typeof client.getBlockNumber === 'function'
|
|
42
52
|
? (client as unknown as PublicClient)
|
|
@@ -56,7 +66,7 @@ export function waitUntilL1Timestamp<T extends Client>(client: T, timestamp: num
|
|
|
56
66
|
return currentTs >= BigInt(timestamp);
|
|
57
67
|
},
|
|
58
68
|
`Wait until L1 timestamp ${timestamp}`,
|
|
59
|
-
120,
|
|
69
|
+
timeout ?? 120,
|
|
60
70
|
0.1,
|
|
61
71
|
);
|
|
62
72
|
}
|