@aztec/ethereum 0.78.1 → 0.80.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/contracts/fee_juice.js +1 -1
- package/dest/contracts/forwarder.d.ts.map +1 -1
- package/dest/contracts/forwarder.js +2 -1
- package/dest/contracts/governance.d.ts +17 -5
- package/dest/contracts/governance.d.ts.map +1 -1
- package/dest/contracts/governance.js +18 -20
- package/dest/contracts/governance_proposer.d.ts +1 -0
- package/dest/contracts/governance_proposer.d.ts.map +1 -1
- package/dest/contracts/governance_proposer.js +10 -3
- package/dest/contracts/registry.d.ts +1 -0
- package/dest/contracts/registry.d.ts.map +1 -1
- package/dest/contracts/registry.js +6 -2
- package/dest/contracts/rollup.d.ts.map +1 -1
- package/dest/contracts/rollup.js +3 -1
- package/dest/contracts/slashing_proposer.js +1 -1
- package/dest/deploy_l1_contracts.d.ts +181 -325
- package/dest/deploy_l1_contracts.d.ts.map +1 -1
- package/dest/deploy_l1_contracts.js +48 -26
- package/dest/l1_tx_utils.d.ts +1 -0
- package/dest/l1_tx_utils.d.ts.map +1 -1
- package/dest/l1_tx_utils.js +4 -1
- package/dest/queries.d.ts +7 -0
- package/dest/queries.d.ts.map +1 -1
- package/dest/queries.js +14 -2
- package/dest/test/chain_monitor.d.ts +25 -0
- package/dest/test/chain_monitor.d.ts.map +1 -0
- package/dest/test/chain_monitor.js +74 -0
- package/dest/test/index.d.ts +1 -0
- package/dest/test/index.d.ts.map +1 -1
- package/dest/test/index.js +1 -0
- package/dest/test/upgrade_utils.d.ts.map +1 -1
- package/dest/test/upgrade_utils.js +1 -1
- package/dest/utils.js +1 -1
- package/package.json +5 -5
- package/src/contracts/fee_juice.ts +1 -1
- package/src/contracts/forwarder.ts +2 -1
- package/src/contracts/governance.ts +22 -21
- package/src/contracts/governance_proposer.ts +7 -3
- package/src/contracts/registry.ts +7 -2
- package/src/contracts/rollup.ts +3 -1
- package/src/contracts/slashing_proposer.ts +1 -1
- package/src/deploy_l1_contracts.ts +66 -28
- package/src/l1_tx_utils.ts +5 -0
- package/src/queries.ts +29 -2
- package/src/test/chain_monitor.ts +88 -0
- package/src/test/index.ts +1 -0
- package/src/test/upgrade_utils.ts +1 -1
- package/src/utils.ts +1 -1
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
2
2
|
import type { Logger } from '@aztec/foundation/log';
|
|
3
3
|
import { sleep } from '@aztec/foundation/sleep';
|
|
4
|
-
import { GovernanceAbi } from '@aztec/l1-artifacts';
|
|
4
|
+
import { GovernanceAbi } from '@aztec/l1-artifacts/GovernanceAbi';
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
7
|
type EncodeFunctionDataParameters,
|
|
8
8
|
type GetContractReturnType,
|
|
9
9
|
type Hex,
|
|
10
|
+
type Log,
|
|
10
11
|
encodeFunctionData,
|
|
11
12
|
getContract,
|
|
13
|
+
parseEventLogs,
|
|
12
14
|
} from 'viem';
|
|
13
15
|
|
|
14
16
|
import type { L1ContractAddresses } from '../l1_contract_addresses.js';
|
|
15
17
|
import { L1TxUtils } from '../l1_tx_utils.js';
|
|
16
18
|
import type { ViemPublicClient, ViemWalletClient } from '../types.js';
|
|
17
|
-
import { GovernanceProposerContract } from './governance_proposer.js';
|
|
18
19
|
|
|
19
20
|
export type L1GovernanceContractAddresses = Pick<
|
|
20
21
|
L1ContractAddresses,
|
|
@@ -33,6 +34,19 @@ export enum ProposalState {
|
|
|
33
34
|
Expired,
|
|
34
35
|
}
|
|
35
36
|
|
|
37
|
+
export function extractProposalIdFromLogs(logs: Log[]): bigint {
|
|
38
|
+
const parsedLogs = parseEventLogs({
|
|
39
|
+
abi: GovernanceAbi,
|
|
40
|
+
logs: logs,
|
|
41
|
+
eventName: 'Proposed',
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
if (parsedLogs.length === 0) {
|
|
45
|
+
throw new Error('Proposal log not found');
|
|
46
|
+
}
|
|
47
|
+
return parsedLogs[0].args.proposalId;
|
|
48
|
+
}
|
|
49
|
+
|
|
36
50
|
export class GovernanceContract {
|
|
37
51
|
private readonly publicGovernance: GetContractReturnType<typeof GovernanceAbi, ViemPublicClient>;
|
|
38
52
|
private readonly walletGovernance: GetContractReturnType<typeof GovernanceAbi, ViemWalletClient> | undefined;
|
|
@@ -52,23 +66,12 @@ export class GovernanceContract {
|
|
|
52
66
|
return EthAddress.fromString(this.publicGovernance.address);
|
|
53
67
|
}
|
|
54
68
|
|
|
55
|
-
public async
|
|
56
|
-
|
|
57
|
-
return new GovernanceProposerContract(this.publicClient, governanceProposerAddress.toString());
|
|
69
|
+
public async getGovernanceProposerAddress() {
|
|
70
|
+
return EthAddress.fromString(await this.publicGovernance.read.governanceProposer());
|
|
58
71
|
}
|
|
59
72
|
|
|
60
|
-
public
|
|
61
|
-
|
|
62
|
-
const [rollupAddress, registryAddress] = await Promise.all([
|
|
63
|
-
governanceProposer.getRollupAddress(),
|
|
64
|
-
governanceProposer.getRegistryAddress(),
|
|
65
|
-
]);
|
|
66
|
-
return {
|
|
67
|
-
governanceAddress: this.address,
|
|
68
|
-
rollupAddress,
|
|
69
|
-
registryAddress,
|
|
70
|
-
governanceProposerAddress: governanceProposer.address,
|
|
71
|
-
};
|
|
73
|
+
public getConfiguration() {
|
|
74
|
+
return this.publicGovernance.read.getConfiguration();
|
|
72
75
|
}
|
|
73
76
|
|
|
74
77
|
public getProposal(proposalId: bigint) {
|
|
@@ -102,16 +105,14 @@ export class GovernanceContract {
|
|
|
102
105
|
}: {
|
|
103
106
|
payloadAddress: Hex;
|
|
104
107
|
withdrawAddress: Hex;
|
|
105
|
-
}): Promise<
|
|
108
|
+
}): Promise<bigint> {
|
|
106
109
|
const walletGovernance = this.assertWalletGovernance();
|
|
107
110
|
const proposeTx = await walletGovernance.write.proposeWithLock([payloadAddress, withdrawAddress]);
|
|
108
111
|
const receipt = await this.publicClient.waitForTransactionReceipt({ hash: proposeTx });
|
|
109
112
|
if (receipt.status !== 'success') {
|
|
110
113
|
throw new Error(`Proposal failed: ${receipt.status}`);
|
|
111
114
|
}
|
|
112
|
-
|
|
113
|
-
const proposalId = Number(receipt.logs[1].topics[1]);
|
|
114
|
-
return proposalId;
|
|
115
|
+
return extractProposalIdFromLogs(receipt.logs);
|
|
115
116
|
}
|
|
116
117
|
|
|
117
118
|
public async awaitProposalActive({ proposalId, logger }: { proposalId: bigint; logger: Logger }) {
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { memoize } from '@aztec/foundation/decorators';
|
|
2
2
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
|
-
import { GovernanceProposerAbi } from '@aztec/l1-artifacts';
|
|
3
|
+
import { GovernanceProposerAbi } from '@aztec/l1-artifacts/GovernanceProposerAbi';
|
|
4
4
|
|
|
5
5
|
import { type GetContractReturnType, type Hex, type TransactionReceipt, encodeFunctionData, getContract } from 'viem';
|
|
6
6
|
|
|
7
7
|
import type { GasPrice, L1TxRequest, L1TxUtils } from '../l1_tx_utils.js';
|
|
8
8
|
import type { ViemPublicClient } from '../types.js';
|
|
9
9
|
import { type IEmpireBase, encodeVote } from './empire_base.js';
|
|
10
|
+
import { extractProposalIdFromLogs } from './governance.js';
|
|
10
11
|
|
|
11
12
|
export class GovernanceProposerContract implements IEmpireBase {
|
|
12
13
|
private readonly proposer: GetContractReturnType<typeof GovernanceProposerAbi, ViemPublicClient>;
|
|
@@ -63,14 +64,15 @@ export class GovernanceProposerContract implements IEmpireBase {
|
|
|
63
64
|
};
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
public executeProposal(
|
|
67
|
+
public async executeProposal(
|
|
67
68
|
round: bigint,
|
|
68
69
|
l1TxUtils: L1TxUtils,
|
|
69
70
|
): Promise<{
|
|
70
71
|
receipt: TransactionReceipt;
|
|
71
72
|
gasPrice: GasPrice;
|
|
73
|
+
proposalId: bigint;
|
|
72
74
|
}> {
|
|
73
|
-
|
|
75
|
+
const { receipt, gasPrice } = await l1TxUtils.sendAndMonitorTransaction({
|
|
74
76
|
to: this.address.toString(),
|
|
75
77
|
data: encodeFunctionData({
|
|
76
78
|
abi: this.proposer.abi,
|
|
@@ -78,5 +80,7 @@ export class GovernanceProposerContract implements IEmpireBase {
|
|
|
78
80
|
args: [round],
|
|
79
81
|
}),
|
|
80
82
|
});
|
|
83
|
+
const proposalId = extractProposalIdFromLogs(receipt.logs);
|
|
84
|
+
return { receipt, gasPrice, proposalId };
|
|
81
85
|
}
|
|
82
86
|
}
|
|
@@ -68,10 +68,10 @@ export class RegistryContract {
|
|
|
68
68
|
> {
|
|
69
69
|
const governanceAddress = await this.registry.read.getGovernance();
|
|
70
70
|
const governance = new GovernanceContract(governanceAddress, this.client, undefined);
|
|
71
|
-
const
|
|
71
|
+
const governanceProposerAddress = await governance.getGovernanceProposerAddress();
|
|
72
72
|
return {
|
|
73
73
|
governanceAddress: governance.address,
|
|
74
|
-
governanceProposerAddress:
|
|
74
|
+
governanceProposerAddress: governanceProposerAddress,
|
|
75
75
|
};
|
|
76
76
|
}
|
|
77
77
|
|
|
@@ -103,4 +103,9 @@ export class RegistryContract {
|
|
|
103
103
|
coinIssuerAddress: EthAddress.fromString(coinIssuer),
|
|
104
104
|
};
|
|
105
105
|
}
|
|
106
|
+
|
|
107
|
+
public async getNumberOfVersions(): Promise<number> {
|
|
108
|
+
const version = await this.registry.read.numberOfVersions();
|
|
109
|
+
return Number(version);
|
|
110
|
+
}
|
|
106
111
|
}
|
package/src/contracts/rollup.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { memoize } from '@aztec/foundation/decorators';
|
|
2
2
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
3
|
import type { ViemSignature } from '@aztec/foundation/eth-signature';
|
|
4
|
-
import { RollupAbi
|
|
4
|
+
import { RollupAbi } from '@aztec/l1-artifacts/RollupAbi';
|
|
5
|
+
import { RollupStorage } from '@aztec/l1-artifacts/RollupStorage';
|
|
6
|
+
import { SlasherAbi } from '@aztec/l1-artifacts/SlasherAbi';
|
|
5
7
|
|
|
6
8
|
import { type Account, type GetContractReturnType, type Hex, getAddress, getContract } from 'viem';
|
|
7
9
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
2
|
-
import { SlashingProposerAbi } from '@aztec/l1-artifacts';
|
|
2
|
+
import { SlashingProposerAbi } from '@aztec/l1-artifacts/SlashingProposerAbi';
|
|
3
3
|
|
|
4
4
|
import { type GetContractReturnType, type Hex, getContract } from 'viem';
|
|
5
5
|
|
|
@@ -66,7 +66,7 @@ import {
|
|
|
66
66
|
type L1TxRequest,
|
|
67
67
|
L1TxUtils,
|
|
68
68
|
type L1TxUtilsConfig,
|
|
69
|
-
|
|
69
|
+
getL1TxUtilsConfigEnvVars,
|
|
70
70
|
} from './l1_tx_utils.js';
|
|
71
71
|
import type { L1Clients, ViemPublicClient, ViemWalletClient } from './types.js';
|
|
72
72
|
|
|
@@ -257,7 +257,15 @@ export function createL1Clients(
|
|
|
257
257
|
return { walletClient, publicClient } as L1Clients;
|
|
258
258
|
}
|
|
259
259
|
|
|
260
|
-
|
|
260
|
+
/**
|
|
261
|
+
* Deploys the rollup, slash factory, and the payload which can be used to make the rollup the canonical version.
|
|
262
|
+
* @param clients - The L1 clients.
|
|
263
|
+
* @param args - The deployment arguments.
|
|
264
|
+
* @param registryAddress - The address of the registry.
|
|
265
|
+
* @param logger - The logger.
|
|
266
|
+
* @param txUtilsConfig - The L1 tx utils config.
|
|
267
|
+
*/
|
|
268
|
+
export const deployRollupForUpgrade = async (
|
|
261
269
|
clients: L1Clients,
|
|
262
270
|
args: DeployL1ContractsArgs,
|
|
263
271
|
registryAddress: EthAddress,
|
|
@@ -343,22 +351,56 @@ export const deployRollup = async (
|
|
|
343
351
|
await deployer.waitForDeployments();
|
|
344
352
|
logger.verbose(`All core contracts have been deployed`);
|
|
345
353
|
|
|
354
|
+
if (args.initialValidators) {
|
|
355
|
+
await cheat_initializeValidatorSet(
|
|
356
|
+
clients,
|
|
357
|
+
deployer,
|
|
358
|
+
rollupAddress.toString(),
|
|
359
|
+
addresses.stakingAssetAddress.toString(),
|
|
360
|
+
args.initialValidators.map(v => v.toString()),
|
|
361
|
+
args.acceleratedTestDeployments,
|
|
362
|
+
logger,
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
return new RollupContract(clients.publicClient, rollupAddress);
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Initialize the validator set for the rollup using a cheat function.
|
|
371
|
+
* @note This function will only be used when the chain is local anvil node soon (#12050)
|
|
372
|
+
*
|
|
373
|
+
* @param clients - The L1 clients.
|
|
374
|
+
* @param deployer - The L1 deployer.
|
|
375
|
+
* @param rollupAddress - The address of the rollup.
|
|
376
|
+
* @param stakingAssetAddress - The address of the staking asset.
|
|
377
|
+
* @param validators - The validators to initialize.
|
|
378
|
+
* @param acceleratedTestDeployments - Whether to use accelerated test deployments.
|
|
379
|
+
* @param logger - The logger.
|
|
380
|
+
*/
|
|
381
|
+
// eslint-disable-next-line camelcase
|
|
382
|
+
export const cheat_initializeValidatorSet = async (
|
|
383
|
+
clients: L1Clients,
|
|
384
|
+
deployer: L1Deployer,
|
|
385
|
+
rollupAddress: Hex,
|
|
386
|
+
stakingAssetAddress: Hex,
|
|
387
|
+
validators: Hex[],
|
|
388
|
+
acceleratedTestDeployments: boolean | undefined,
|
|
389
|
+
logger: Logger,
|
|
390
|
+
) => {
|
|
346
391
|
const rollup = getContract({
|
|
347
392
|
address: getAddress(rollupAddress.toString()),
|
|
348
393
|
abi: l1Artifacts.rollup.contractAbi,
|
|
349
394
|
client: clients.walletClient,
|
|
350
395
|
});
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
if (args.initialValidators && args.initialValidators.length > 0) {
|
|
396
|
+
const minimumStake = await rollup.read.getMinimumStake();
|
|
397
|
+
if (validators && validators.length > 0) {
|
|
355
398
|
// Check if some of the initial validators are already registered, so we support idempotent deployments
|
|
356
|
-
|
|
357
|
-
if (!args.acceleratedTestDeployments) {
|
|
399
|
+
if (!acceleratedTestDeployments) {
|
|
358
400
|
const validatorsInfo = await Promise.all(
|
|
359
|
-
|
|
401
|
+
validators.map(async address => ({
|
|
360
402
|
address,
|
|
361
|
-
...(await rollup.read.getInfo([address
|
|
403
|
+
...(await rollup.read.getInfo([address])),
|
|
362
404
|
})),
|
|
363
405
|
);
|
|
364
406
|
const existingValidators = validatorsInfo.filter(v => v.status !== 0);
|
|
@@ -370,16 +412,16 @@ export const deployRollup = async (
|
|
|
370
412
|
);
|
|
371
413
|
}
|
|
372
414
|
|
|
373
|
-
|
|
415
|
+
validators = validatorsInfo.filter(v => v.status === 0).map(v => v.address);
|
|
374
416
|
}
|
|
375
417
|
|
|
376
|
-
if (
|
|
418
|
+
if (validators.length > 0) {
|
|
377
419
|
// Mint tokens, approve them, use cheat code to initialise validator set without setting up the epoch.
|
|
378
|
-
const stakeNeeded =
|
|
420
|
+
const stakeNeeded = minimumStake * BigInt(validators.length);
|
|
379
421
|
await Promise.all(
|
|
380
422
|
[
|
|
381
423
|
await deployer.sendTransaction({
|
|
382
|
-
to:
|
|
424
|
+
to: stakingAssetAddress,
|
|
383
425
|
data: encodeFunctionData({
|
|
384
426
|
abi: l1Artifacts.stakingAsset.contractAbi,
|
|
385
427
|
functionName: 'mint',
|
|
@@ -387,40 +429,35 @@ export const deployRollup = async (
|
|
|
387
429
|
}),
|
|
388
430
|
}),
|
|
389
431
|
await deployer.sendTransaction({
|
|
390
|
-
to:
|
|
432
|
+
to: stakingAssetAddress,
|
|
391
433
|
data: encodeFunctionData({
|
|
392
434
|
abi: l1Artifacts.stakingAsset.contractAbi,
|
|
393
435
|
functionName: 'approve',
|
|
394
|
-
args: [rollupAddress
|
|
436
|
+
args: [rollupAddress, stakeNeeded],
|
|
395
437
|
}),
|
|
396
438
|
}),
|
|
397
439
|
].map(tx => clients.publicClient.waitForTransactionReceipt({ hash: tx.txHash })),
|
|
398
440
|
);
|
|
399
441
|
|
|
400
|
-
const
|
|
442
|
+
const validatorsTuples = validators.map(v => ({
|
|
401
443
|
attester: v,
|
|
402
444
|
proposer: getExpectedAddress(ForwarderAbi, ForwarderBytecode, [v], v).address,
|
|
403
445
|
withdrawer: v,
|
|
404
|
-
amount:
|
|
446
|
+
amount: minimumStake,
|
|
405
447
|
}));
|
|
406
|
-
// const initiateValidatorSetTxHash = await rollup.write.cheat__InitialiseValidatorSet([validators]);
|
|
407
448
|
const initiateValidatorSetTxHash = await deployer.walletClient.writeContract({
|
|
408
|
-
address: rollupAddress
|
|
449
|
+
address: rollupAddress,
|
|
409
450
|
abi: l1Artifacts.rollup.contractAbi,
|
|
410
451
|
functionName: 'cheat__InitialiseValidatorSet',
|
|
411
|
-
args: [
|
|
452
|
+
args: [validatorsTuples],
|
|
412
453
|
});
|
|
413
|
-
|
|
454
|
+
await clients.publicClient.waitForTransactionReceipt({ hash: initiateValidatorSetTxHash });
|
|
414
455
|
logger.info(`Initialized validator set`, {
|
|
415
456
|
validators,
|
|
416
457
|
txHash: initiateValidatorSetTxHash,
|
|
417
458
|
});
|
|
418
459
|
}
|
|
419
460
|
}
|
|
420
|
-
|
|
421
|
-
await Promise.all(txHashes.map(txHash => clients.publicClient.waitForTransactionReceipt({ hash: txHash })));
|
|
422
|
-
|
|
423
|
-
return new RollupContract(clients.publicClient, rollupAddress);
|
|
424
461
|
};
|
|
425
462
|
|
|
426
463
|
/**
|
|
@@ -438,7 +475,7 @@ export const deployL1Contracts = async (
|
|
|
438
475
|
chain: Chain,
|
|
439
476
|
logger: Logger,
|
|
440
477
|
args: DeployL1ContractsArgs,
|
|
441
|
-
txUtilsConfig: L1TxUtilsConfig =
|
|
478
|
+
txUtilsConfig: L1TxUtilsConfig = getL1TxUtilsConfigEnvVars(),
|
|
442
479
|
): Promise<DeployL1ContractsReturnType> => {
|
|
443
480
|
const clients = createL1Clients(rpcUrls, account, chain);
|
|
444
481
|
const { walletClient, publicClient } = clients;
|
|
@@ -809,7 +846,8 @@ export async function deployL1Contract(
|
|
|
809
846
|
let resultingAddress: Hex | null | undefined = undefined;
|
|
810
847
|
|
|
811
848
|
if (!l1TxUtils) {
|
|
812
|
-
|
|
849
|
+
const config = getL1TxUtilsConfigEnvVars();
|
|
850
|
+
l1TxUtils = new L1TxUtils(publicClient, walletClient, logger, config, acceleratedTestDeployments);
|
|
813
851
|
}
|
|
814
852
|
|
|
815
853
|
if (libraries) {
|
package/src/l1_tx_utils.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { compactArray, times } from '@aztec/foundation/collection';
|
|
|
2
2
|
import {
|
|
3
3
|
type ConfigMappingsType,
|
|
4
4
|
bigintConfigHelper,
|
|
5
|
+
getConfigFromMappings,
|
|
5
6
|
getDefaultConfig,
|
|
6
7
|
numberConfigHelper,
|
|
7
8
|
} from '@aztec/foundation/config';
|
|
@@ -158,6 +159,10 @@ export const l1TxUtilsConfigMappings: ConfigMappingsType<L1TxUtilsConfig> = {
|
|
|
158
159
|
|
|
159
160
|
export const defaultL1TxUtilsConfig = getDefaultConfig<L1TxUtilsConfig>(l1TxUtilsConfigMappings);
|
|
160
161
|
|
|
162
|
+
export function getL1TxUtilsConfigEnvVars(): L1TxUtilsConfig {
|
|
163
|
+
return getConfigFromMappings(l1TxUtilsConfigMappings);
|
|
164
|
+
}
|
|
165
|
+
|
|
161
166
|
export interface L1TxRequest {
|
|
162
167
|
to: Address | null;
|
|
163
168
|
data?: Hex;
|
package/src/queries.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
2
|
+
import { RollupAbi } from '@aztec/l1-artifacts/RollupAbi';
|
|
3
|
+
|
|
4
|
+
import type { Hex } from 'viem';
|
|
2
5
|
|
|
3
6
|
import type { L1ContractsConfig } from './config.js';
|
|
4
7
|
import { GovernanceContract } from './contracts/governance.js';
|
|
8
|
+
import { GovernanceProposerContract } from './contracts/governance_proposer.js';
|
|
5
9
|
import { RollupContract } from './contracts/rollup.js';
|
|
6
10
|
import type { ViemPublicClient } from './types.js';
|
|
7
11
|
|
|
@@ -11,8 +15,9 @@ export async function getL1ContractsConfig(
|
|
|
11
15
|
addresses: { governanceAddress: EthAddress; rollupAddress?: EthAddress },
|
|
12
16
|
): Promise<Omit<L1ContractsConfig, 'ethereumSlotDuration'> & { l1StartBlock: bigint; l1GenesisTime: bigint }> {
|
|
13
17
|
const governance = new GovernanceContract(addresses.governanceAddress.toString(), publicClient, undefined);
|
|
14
|
-
const
|
|
15
|
-
const
|
|
18
|
+
const governanceProposerAddress = await governance.getGovernanceProposerAddress();
|
|
19
|
+
const governanceProposer = new GovernanceProposerContract(publicClient, governanceProposerAddress.toString());
|
|
20
|
+
const rollupAddress = addresses.rollupAddress ?? (await governanceProposer.getRollupAddress());
|
|
16
21
|
const rollup = new RollupContract(publicClient, rollupAddress.toString());
|
|
17
22
|
const slasherProposer = await rollup.getSlashingProposer();
|
|
18
23
|
|
|
@@ -56,3 +61,25 @@ export async function getL1ContractsConfig(
|
|
|
56
61
|
slashingRoundSize: Number(slashingRoundSize),
|
|
57
62
|
};
|
|
58
63
|
}
|
|
64
|
+
|
|
65
|
+
export type L2BlockProposedEvent = {
|
|
66
|
+
versionedBlobHashes: readonly Hex[];
|
|
67
|
+
archive: Hex;
|
|
68
|
+
blockNumber: bigint;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export async function getL2BlockProposalEvents(
|
|
72
|
+
client: ViemPublicClient,
|
|
73
|
+
blockId: Hex,
|
|
74
|
+
rollupAddress?: EthAddress,
|
|
75
|
+
): Promise<L2BlockProposedEvent[]> {
|
|
76
|
+
return (
|
|
77
|
+
await client.getContractEvents({
|
|
78
|
+
abi: RollupAbi,
|
|
79
|
+
address: rollupAddress?.toString(),
|
|
80
|
+
blockHash: blockId,
|
|
81
|
+
eventName: 'L2BlockProposed',
|
|
82
|
+
strict: true,
|
|
83
|
+
})
|
|
84
|
+
).map(log => log.args);
|
|
85
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { RollupContract } from '@aztec/ethereum/contracts';
|
|
2
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
3
|
+
|
|
4
|
+
import type { PublicClient } from 'viem';
|
|
5
|
+
|
|
6
|
+
/** Utility class that polls the chain on quick intervals and logs new L1 blocks, L2 blocks, and L2 proofs. */
|
|
7
|
+
export class ChainMonitor {
|
|
8
|
+
private readonly l1Client: PublicClient;
|
|
9
|
+
private handle: NodeJS.Timeout | undefined;
|
|
10
|
+
|
|
11
|
+
/** Current L1 block number */
|
|
12
|
+
public l1BlockNumber!: number;
|
|
13
|
+
/** Current L2 block number */
|
|
14
|
+
public l2BlockNumber!: number;
|
|
15
|
+
/** Current L2 proven block number */
|
|
16
|
+
public l2ProvenBlockNumber!: number;
|
|
17
|
+
/** L1 timestamp for the current L2 block */
|
|
18
|
+
public l2BlockTimestamp!: bigint;
|
|
19
|
+
/** L1 timestamp for the proven L2 block */
|
|
20
|
+
public l2ProvenBlockTimestamp!: bigint;
|
|
21
|
+
|
|
22
|
+
constructor(
|
|
23
|
+
private readonly rollup: RollupContract,
|
|
24
|
+
private logger = createLogger('aztecjs:utils:chain_monitor'),
|
|
25
|
+
private readonly intervalMs = 200,
|
|
26
|
+
) {
|
|
27
|
+
this.l1Client = rollup.client;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
start() {
|
|
31
|
+
if (this.handle) {
|
|
32
|
+
throw new Error('Chain monitor already started');
|
|
33
|
+
}
|
|
34
|
+
this.handle = setInterval(this.safeRun.bind(this), this.intervalMs);
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
stop() {
|
|
39
|
+
if (this.handle) {
|
|
40
|
+
clearInterval(this.handle!);
|
|
41
|
+
this.handle = undefined;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private safeRun() {
|
|
46
|
+
void this.run().catch(error => {
|
|
47
|
+
this.logger.error('Error in chain monitor loop', error);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async run() {
|
|
52
|
+
const newL1BlockNumber = Number(await this.l1Client.getBlockNumber({ cacheTime: 0 }));
|
|
53
|
+
if (this.l1BlockNumber === newL1BlockNumber) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
this.l1BlockNumber = newL1BlockNumber;
|
|
57
|
+
|
|
58
|
+
const block = await this.l1Client.getBlock({ blockNumber: BigInt(newL1BlockNumber), includeTransactions: false });
|
|
59
|
+
const timestamp = block.timestamp;
|
|
60
|
+
const timestampString = new Date(Number(timestamp) * 1000).toTimeString().split(' ')[0];
|
|
61
|
+
|
|
62
|
+
let msg = `L1 block ${newL1BlockNumber} mined at ${timestampString}`;
|
|
63
|
+
|
|
64
|
+
const newL2BlockNumber = Number(await this.rollup.getBlockNumber());
|
|
65
|
+
if (this.l2BlockNumber !== newL2BlockNumber) {
|
|
66
|
+
const epochNumber = await this.rollup.getEpochNumber(BigInt(newL2BlockNumber));
|
|
67
|
+
msg += ` with new L2 block ${newL2BlockNumber} for epoch ${epochNumber}`;
|
|
68
|
+
this.l2BlockNumber = newL2BlockNumber;
|
|
69
|
+
this.l2BlockTimestamp = timestamp;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const newL2ProvenBlockNumber = Number(await this.rollup.getProvenBlockNumber());
|
|
73
|
+
if (this.l2ProvenBlockNumber !== newL2ProvenBlockNumber) {
|
|
74
|
+
const epochNumber = await this.rollup.getEpochNumber(BigInt(newL2ProvenBlockNumber));
|
|
75
|
+
msg += ` with proof up to L2 block ${newL2ProvenBlockNumber} for epoch ${epochNumber}`;
|
|
76
|
+
this.l2ProvenBlockNumber = newL2ProvenBlockNumber;
|
|
77
|
+
this.l2ProvenBlockTimestamp = timestamp;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
this.logger.info(msg, {
|
|
81
|
+
l1Timestamp: timestamp,
|
|
82
|
+
l1BlockNumber: this.l1BlockNumber,
|
|
83
|
+
l2SlotNumber: await this.rollup.getSlotNumber(),
|
|
84
|
+
l2BlockNumber: this.l2BlockNumber,
|
|
85
|
+
l2ProvenBlockNumber: this.l2ProvenBlockNumber,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
package/src/test/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Logger } from '@aztec/foundation/log';
|
|
2
|
-
import { TestERC20Abi as FeeJuiceAbi } from '@aztec/l1-artifacts';
|
|
3
2
|
import { GovernanceAbi } from '@aztec/l1-artifacts/GovernanceAbi';
|
|
3
|
+
import { TestERC20Abi as FeeJuiceAbi } from '@aztec/l1-artifacts/TestERC20Abi';
|
|
4
4
|
|
|
5
5
|
import { type GetContractReturnType, type PrivateKeyAccount, getContract } from 'viem';
|
|
6
6
|
|
package/src/utils.ts
CHANGED