@aztec/ethereum 0.86.0 → 0.87.0-nightly.20250521
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/client.d.ts +1 -1
- package/dest/client.d.ts.map +1 -1
- package/dest/client.js +1 -1
- package/dest/contracts/errors.d.ts +4 -0
- package/dest/contracts/errors.d.ts.map +1 -0
- package/dest/contracts/errors.js +6 -0
- package/dest/contracts/fee_asset_handler.d.ts.map +1 -1
- package/dest/contracts/fee_juice.d.ts.map +1 -1
- package/dest/contracts/forwarder.d.ts.map +1 -1
- package/dest/contracts/governance.d.ts.map +1 -1
- package/dest/contracts/governance.js +1 -0
- package/dest/contracts/governance_proposer.d.ts.map +1 -1
- package/dest/contracts/inbox.d.ts +26 -0
- package/dest/contracts/inbox.d.ts.map +1 -0
- package/dest/contracts/inbox.js +45 -0
- package/dest/contracts/index.d.ts +2 -0
- package/dest/contracts/index.d.ts.map +1 -1
- package/dest/contracts/index.js +2 -0
- package/dest/contracts/registry.d.ts.map +1 -1
- package/dest/contracts/registry.js +2 -2
- package/dest/contracts/rollup.d.ts +6 -2
- package/dest/contracts/rollup.d.ts.map +1 -1
- package/dest/contracts/rollup.js +13 -2
- package/dest/contracts/slashing_proposer.d.ts.map +1 -1
- package/dest/contracts/utils.d.ts +3 -0
- package/dest/contracts/utils.d.ts.map +1 -0
- package/dest/contracts/utils.js +11 -0
- package/dest/deploy_l1_contracts.d.ts +1275 -634
- package/dest/deploy_l1_contracts.d.ts.map +1 -1
- package/dest/deploy_l1_contracts.js +22 -25
- package/dest/eth_cheat_codes.d.ts.map +1 -1
- package/dest/eth_cheat_codes.js +8 -1
- package/dest/index.d.ts +1 -0
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -0
- package/dest/l1_tx_utils.d.ts +12 -11
- package/dest/l1_tx_utils.d.ts.map +1 -1
- package/dest/l1_tx_utils.js +1 -1
- package/dest/l1_types.d.ts +6 -0
- package/dest/l1_types.d.ts.map +1 -0
- package/dest/l1_types.js +1 -0
- package/dest/test/chain_monitor.d.ts +6 -3
- package/dest/test/chain_monitor.d.ts.map +1 -1
- package/dest/test/chain_monitor.js +27 -5
- package/dest/test/tx_delayer.d.ts +6 -2
- package/dest/test/tx_delayer.d.ts.map +1 -1
- package/dest/test/tx_delayer.js +41 -9
- package/dest/utils.js +2 -2
- package/package.json +7 -7
- package/src/client.ts +2 -2
- package/src/contracts/errors.ts +6 -0
- package/src/contracts/fee_asset_handler.ts +4 -1
- package/src/contracts/fee_juice.ts +4 -1
- package/src/contracts/forwarder.ts +5 -1
- package/src/contracts/governance.ts +9 -2
- package/src/contracts/governance_proposer.ts +4 -1
- package/src/contracts/inbox.ts +63 -0
- package/src/contracts/index.ts +2 -0
- package/src/contracts/registry.ts +6 -3
- package/src/contracts/rollup.ts +17 -3
- package/src/contracts/slashing_proposer.ts +4 -1
- package/src/contracts/utils.ts +14 -0
- package/src/deploy_l1_contracts.ts +23 -19
- package/src/eth_cheat_codes.ts +8 -1
- package/src/index.ts +1 -0
- package/src/l1_tx_utils.ts +2 -1
- package/src/l1_types.ts +6 -0
- package/src/test/chain_monitor.ts +26 -4
- package/src/test/tx_delayer.ts +55 -13
- package/src/utils.ts +2 -2
package/dest/utils.js
CHANGED
|
@@ -101,7 +101,7 @@ function getNestedErrorData(error) {
|
|
|
101
101
|
return new FormattedViemError(`${errorName}${args}`, error?.metaMessages);
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
|
-
} catch
|
|
104
|
+
} catch {
|
|
105
105
|
// If decoding fails, we fall back to the original formatting
|
|
106
106
|
}
|
|
107
107
|
// Strip ABI from the error object before formatting
|
|
@@ -309,7 +309,7 @@ export function tryGetCustomErrorName(err) {
|
|
|
309
309
|
return revertError.data?.errorName;
|
|
310
310
|
}
|
|
311
311
|
}
|
|
312
|
-
} catch
|
|
312
|
+
} catch {
|
|
313
313
|
return undefined;
|
|
314
314
|
}
|
|
315
315
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/ethereum",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.87.0-nightly.20250521",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
"../package.common.json"
|
|
33
33
|
],
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@aztec/blob-lib": "0.
|
|
36
|
-
"@aztec/foundation": "0.
|
|
37
|
-
"@aztec/l1-artifacts": "0.
|
|
35
|
+
"@aztec/blob-lib": "0.87.0-nightly.20250521",
|
|
36
|
+
"@aztec/foundation": "0.87.0-nightly.20250521",
|
|
37
|
+
"@aztec/l1-artifacts": "0.87.0-nightly.20250521",
|
|
38
38
|
"@viem/anvil": "^0.0.10",
|
|
39
39
|
"dotenv": "^16.0.3",
|
|
40
40
|
"tslib": "^2.4.0",
|
|
@@ -44,13 +44,13 @@
|
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@jest/globals": "^29.5.0",
|
|
46
46
|
"@types/jest": "^29.5.0",
|
|
47
|
-
"@types/node": "^
|
|
47
|
+
"@types/node": "^22.15.17",
|
|
48
48
|
"@viem/anvil": "^0.0.10",
|
|
49
49
|
"get-port": "^7.1.0",
|
|
50
50
|
"jest": "^29.5.0",
|
|
51
51
|
"lodash.omit": "^4.5.0",
|
|
52
52
|
"ts-node": "^10.9.1",
|
|
53
|
-
"typescript": "^5.
|
|
53
|
+
"typescript": "^5.3.3"
|
|
54
54
|
},
|
|
55
55
|
"files": [
|
|
56
56
|
"dest",
|
|
@@ -92,6 +92,6 @@
|
|
|
92
92
|
]
|
|
93
93
|
},
|
|
94
94
|
"engines": {
|
|
95
|
-
"node": ">=
|
|
95
|
+
"node": ">=20.10"
|
|
96
96
|
}
|
|
97
97
|
}
|
package/src/client.ts
CHANGED
|
@@ -54,7 +54,7 @@ async function waitForRpc(client: ViemPublicClient, config: Config, logger?: Log
|
|
|
54
54
|
let chainId = 0;
|
|
55
55
|
try {
|
|
56
56
|
chainId = await client.getChainId();
|
|
57
|
-
} catch
|
|
57
|
+
} catch {
|
|
58
58
|
logger?.warn(`Failed to connect to Ethereum node at ${config.l1RpcUrls.join(', ')}. Retrying...`);
|
|
59
59
|
}
|
|
60
60
|
return chainId;
|
|
@@ -73,7 +73,7 @@ async function waitForRpc(client: ViemPublicClient, config: Config, logger?: Log
|
|
|
73
73
|
|
|
74
74
|
export function createExtendedL1Client(
|
|
75
75
|
rpcUrls: string[],
|
|
76
|
-
mnemonicOrPrivateKeyOrHdAccount: string |
|
|
76
|
+
mnemonicOrPrivateKeyOrHdAccount: string | HDAccount | PrivateKeyAccount | LocalAccount,
|
|
77
77
|
chain: Chain = foundry,
|
|
78
78
|
pollingIntervalMS?: number,
|
|
79
79
|
addressIndex?: number,
|
|
@@ -8,7 +8,10 @@ import type { L1TxUtils } from '../l1_tx_utils.js';
|
|
|
8
8
|
export class FeeAssetHandlerContract {
|
|
9
9
|
public address: EthAddress;
|
|
10
10
|
|
|
11
|
-
constructor(
|
|
11
|
+
constructor(
|
|
12
|
+
address: Hex,
|
|
13
|
+
public readonly txUtils: L1TxUtils,
|
|
14
|
+
) {
|
|
12
15
|
this.address = EthAddress.fromString(address);
|
|
13
16
|
}
|
|
14
17
|
|
|
@@ -8,7 +8,10 @@ import { type ExtendedViemWalletClient, type ViemClient, isExtendedClient } from
|
|
|
8
8
|
export class FeeJuiceContract {
|
|
9
9
|
private readonly feeJuiceContract: GetContractReturnType<typeof FeeJuiceAbi, ViemClient>;
|
|
10
10
|
|
|
11
|
-
constructor(
|
|
11
|
+
constructor(
|
|
12
|
+
address: Hex,
|
|
13
|
+
public readonly client: ViemClient,
|
|
14
|
+
) {
|
|
12
15
|
this.feeJuiceContract = getContract({ address, abi: FeeJuiceAbi, client });
|
|
13
16
|
}
|
|
14
17
|
|
|
@@ -19,7 +19,11 @@ import { RollupContract } from './rollup.js';
|
|
|
19
19
|
export class ForwarderContract {
|
|
20
20
|
private readonly forwarder: GetContractReturnType<typeof ForwarderAbi, ViemClient>;
|
|
21
21
|
|
|
22
|
-
constructor(
|
|
22
|
+
constructor(
|
|
23
|
+
public readonly client: ExtendedViemWalletClient,
|
|
24
|
+
address: Hex,
|
|
25
|
+
public readonly rollupAddress: Hex,
|
|
26
|
+
) {
|
|
23
27
|
this.forwarder = getContract({ address, abi: ForwarderAbi, client });
|
|
24
28
|
}
|
|
25
29
|
|
|
@@ -50,7 +50,10 @@ export function extractProposalIdFromLogs(logs: Log[]): bigint {
|
|
|
50
50
|
export class ReadOnlyGovernanceContract {
|
|
51
51
|
protected readonly governanceContract: GetContractReturnType<typeof GovernanceAbi, ViemClient>;
|
|
52
52
|
|
|
53
|
-
constructor(
|
|
53
|
+
constructor(
|
|
54
|
+
address: Hex,
|
|
55
|
+
public readonly client: ViemClient,
|
|
56
|
+
) {
|
|
54
57
|
this.governanceContract = getContract({ address, abi: GovernanceAbi, client: client });
|
|
55
58
|
}
|
|
56
59
|
|
|
@@ -72,6 +75,7 @@ export class ReadOnlyGovernanceContract {
|
|
|
72
75
|
|
|
73
76
|
public async getProposalState(proposalId: bigint): Promise<ProposalState> {
|
|
74
77
|
const state = await this.governanceContract.read.getProposalState([proposalId]);
|
|
78
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
|
|
75
79
|
if (state < 0 || state > ProposalState.Expired) {
|
|
76
80
|
throw new Error(`Invalid proposal state: ${state}`);
|
|
77
81
|
}
|
|
@@ -131,7 +135,10 @@ export class ReadOnlyGovernanceContract {
|
|
|
131
135
|
export class GovernanceContract extends ReadOnlyGovernanceContract {
|
|
132
136
|
protected override readonly governanceContract: GetContractReturnType<typeof GovernanceAbi, ExtendedViemWalletClient>;
|
|
133
137
|
|
|
134
|
-
constructor(
|
|
138
|
+
constructor(
|
|
139
|
+
address: Hex,
|
|
140
|
+
public override readonly client: ExtendedViemWalletClient,
|
|
141
|
+
) {
|
|
135
142
|
super(address, client);
|
|
136
143
|
if (!isExtendedClient(client)) {
|
|
137
144
|
throw new Error('GovernanceContract has to be instantiated with a wallet client.');
|
|
@@ -12,7 +12,10 @@ import { extractProposalIdFromLogs } from './governance.js';
|
|
|
12
12
|
export class GovernanceProposerContract implements IEmpireBase {
|
|
13
13
|
private readonly proposer: GetContractReturnType<typeof GovernanceProposerAbi, ViemClient>;
|
|
14
14
|
|
|
15
|
-
constructor(
|
|
15
|
+
constructor(
|
|
16
|
+
public readonly client: ViemClient,
|
|
17
|
+
address: Hex,
|
|
18
|
+
) {
|
|
16
19
|
this.proposer = getContract({ address, abi: GovernanceProposerAbi, client });
|
|
17
20
|
}
|
|
18
21
|
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Buffer16 } from '@aztec/foundation/buffer';
|
|
2
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
|
+
import { InboxAbi } from '@aztec/l1-artifacts/InboxAbi';
|
|
4
|
+
|
|
5
|
+
import { type BlockTag, type GetContractReturnType, type Hex, getContract } from 'viem';
|
|
6
|
+
|
|
7
|
+
import { getPublicClient } from '../client.js';
|
|
8
|
+
import type { DeployL1ContractsReturnType } from '../deploy_l1_contracts.js';
|
|
9
|
+
import type { L1ReaderConfig } from '../l1_reader.js';
|
|
10
|
+
import type { ViemClient } from '../types.js';
|
|
11
|
+
import { checkBlockTag } from './utils.js';
|
|
12
|
+
|
|
13
|
+
export class InboxContract {
|
|
14
|
+
private readonly inbox: GetContractReturnType<typeof InboxAbi, ViemClient>;
|
|
15
|
+
|
|
16
|
+
static getFromL1ContractsValues(deployL1ContractsValues: DeployL1ContractsReturnType) {
|
|
17
|
+
const {
|
|
18
|
+
l1Client,
|
|
19
|
+
l1ContractAddresses: { inboxAddress },
|
|
20
|
+
} = deployL1ContractsValues;
|
|
21
|
+
return new InboxContract(l1Client, inboxAddress.toString());
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static getFromConfig(config: L1ReaderConfig) {
|
|
25
|
+
const client = getPublicClient(config);
|
|
26
|
+
const address = config.l1Contracts.inboxAddress.toString();
|
|
27
|
+
return new InboxContract(client, address);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
constructor(
|
|
31
|
+
public readonly client: ViemClient,
|
|
32
|
+
address: Hex | EthAddress,
|
|
33
|
+
) {
|
|
34
|
+
if (address instanceof EthAddress) {
|
|
35
|
+
address = address.toString();
|
|
36
|
+
}
|
|
37
|
+
this.inbox = getContract({ address, abi: InboxAbi, client });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public get address() {
|
|
41
|
+
return this.inbox.address;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public getContract(): GetContractReturnType<typeof InboxAbi, ViemClient> {
|
|
45
|
+
return this.inbox;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public async getState(opts: { blockTag?: BlockTag; blockNumber?: bigint } = {}): Promise<InboxContractState> {
|
|
49
|
+
await checkBlockTag(opts.blockNumber, this.client);
|
|
50
|
+
const state = await this.inbox.read.getState(opts);
|
|
51
|
+
return {
|
|
52
|
+
totalMessagesInserted: state.totalMessagesInserted,
|
|
53
|
+
messagesRollingHash: Buffer16.fromString(state.rollingHash),
|
|
54
|
+
treeInProgress: state.inProgress,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export type InboxContractState = {
|
|
60
|
+
totalMessagesInserted: bigint;
|
|
61
|
+
messagesRollingHash: Buffer16;
|
|
62
|
+
treeInProgress: bigint;
|
|
63
|
+
};
|
package/src/contracts/index.ts
CHANGED
|
@@ -4,6 +4,8 @@ export * from './fee_juice.js';
|
|
|
4
4
|
export * from './forwarder.js';
|
|
5
5
|
export * from './governance.js';
|
|
6
6
|
export * from './governance_proposer.js';
|
|
7
|
+
export * from './inbox.js';
|
|
7
8
|
export * from './registry.js';
|
|
8
9
|
export * from './rollup.js';
|
|
9
10
|
export * from './slashing_proposer.js';
|
|
11
|
+
export * from './errors.js';
|
|
@@ -16,7 +16,10 @@ export class RegistryContract {
|
|
|
16
16
|
private readonly log = createLogger('ethereum:contracts:registry');
|
|
17
17
|
private readonly registry: GetContractReturnType<typeof RegistryAbi, ViemClient>;
|
|
18
18
|
|
|
19
|
-
constructor(
|
|
19
|
+
constructor(
|
|
20
|
+
public readonly client: ViemClient,
|
|
21
|
+
address: Hex | EthAddress,
|
|
22
|
+
) {
|
|
20
23
|
if (address instanceof EthAddress) {
|
|
21
24
|
address = address.toString();
|
|
22
25
|
}
|
|
@@ -40,7 +43,7 @@ export class RegistryContract {
|
|
|
40
43
|
|
|
41
44
|
try {
|
|
42
45
|
return EthAddress.fromString(await this.registry.read.getRollup([version]));
|
|
43
|
-
} catch
|
|
46
|
+
} catch {
|
|
44
47
|
this.log.warn(`Failed fetching rollup address for version ${version}. Retrying as index.`);
|
|
45
48
|
}
|
|
46
49
|
|
|
@@ -48,7 +51,7 @@ export class RegistryContract {
|
|
|
48
51
|
const actualVersion = await this.registry.read.getVersion([version]);
|
|
49
52
|
const rollupAddress = await this.registry.read.getRollup([actualVersion]);
|
|
50
53
|
return EthAddress.fromString(rollupAddress);
|
|
51
|
-
} catch
|
|
54
|
+
} catch {
|
|
52
55
|
throw new Error('Rollup address is undefined');
|
|
53
56
|
}
|
|
54
57
|
}
|
package/src/contracts/rollup.ts
CHANGED
|
@@ -14,6 +14,7 @@ import type { L1ReaderConfig } from '../l1_reader.js';
|
|
|
14
14
|
import type { ViemClient } from '../types.js';
|
|
15
15
|
import { formatViemError } from '../utils.js';
|
|
16
16
|
import { SlashingProposerContract } from './slashing_proposer.js';
|
|
17
|
+
import { checkBlockTag } from './utils.js';
|
|
17
18
|
|
|
18
19
|
export type L1RollupContractAddresses = Pick<
|
|
19
20
|
L1ContractAddresses,
|
|
@@ -60,7 +61,10 @@ export class RollupContract {
|
|
|
60
61
|
return new RollupContract(client, address);
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
constructor(
|
|
64
|
+
constructor(
|
|
65
|
+
public readonly client: ViemClient,
|
|
66
|
+
address: Hex | EthAddress,
|
|
67
|
+
) {
|
|
64
68
|
if (address instanceof EthAddress) {
|
|
65
69
|
address = address.toString();
|
|
66
70
|
}
|
|
@@ -175,6 +179,14 @@ export class RollupContract {
|
|
|
175
179
|
return this.rollup.read.getCurrentSlot();
|
|
176
180
|
}
|
|
177
181
|
|
|
182
|
+
getL1FeesAt(timestamp: bigint) {
|
|
183
|
+
return this.rollup.read.getL1FeesAt([timestamp]);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
getFeeAssetPerEth() {
|
|
187
|
+
return this.rollup.read.getFeeAssetPerEth();
|
|
188
|
+
}
|
|
189
|
+
|
|
178
190
|
async getCommitteeAt(timestamp: bigint) {
|
|
179
191
|
const { result } = await this.client.simulateContract({
|
|
180
192
|
address: this.address,
|
|
@@ -381,11 +393,13 @@ export class RollupContract {
|
|
|
381
393
|
return this.rollup.read.getSlotAt([timestamp]);
|
|
382
394
|
}
|
|
383
395
|
|
|
384
|
-
status(blockNumber: bigint, options?: { blockNumber?: bigint }) {
|
|
396
|
+
async status(blockNumber: bigint, options?: { blockNumber?: bigint }) {
|
|
397
|
+
await checkBlockTag(options?.blockNumber, this.client);
|
|
385
398
|
return this.rollup.read.status([blockNumber], options);
|
|
386
399
|
}
|
|
387
400
|
|
|
388
|
-
canPruneAtTime(timestamp: bigint, options?: { blockNumber?: bigint }) {
|
|
401
|
+
async canPruneAtTime(timestamp: bigint, options?: { blockNumber?: bigint }) {
|
|
402
|
+
await checkBlockTag(options?.blockNumber, this.client);
|
|
389
403
|
return this.rollup.read.canPruneAtTime([timestamp], options);
|
|
390
404
|
}
|
|
391
405
|
|
|
@@ -10,7 +10,10 @@ import { type IEmpireBase, encodeVote } from './empire_base.js';
|
|
|
10
10
|
export class SlashingProposerContract implements IEmpireBase {
|
|
11
11
|
private readonly proposer: GetContractReturnType<typeof SlashingProposerAbi, ViemClient>;
|
|
12
12
|
|
|
13
|
-
constructor(
|
|
13
|
+
constructor(
|
|
14
|
+
public readonly client: ViemClient,
|
|
15
|
+
address: Hex,
|
|
16
|
+
) {
|
|
14
17
|
this.proposer = getContract({ address, abi: SlashingProposerAbi, client });
|
|
15
18
|
}
|
|
16
19
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ViemClient } from '../types.js';
|
|
2
|
+
import { BlockTagTooOldError } from './errors.js';
|
|
3
|
+
|
|
4
|
+
const L1_NON_ARCHIVE_BLOCK_HISTORY_LENGTH = 128n;
|
|
5
|
+
|
|
6
|
+
export async function checkBlockTag(block: bigint | undefined, publicClient: ViemClient) {
|
|
7
|
+
if (block === undefined) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
const latestBlock = await publicClient.getBlockNumber();
|
|
11
|
+
if (block < latestBlock - L1_NON_ARCHIVE_BLOCK_HISTORY_LENGTH) {
|
|
12
|
+
throw new BlockTagTooOldError(block, latestBlock);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -18,6 +18,8 @@ import {
|
|
|
18
18
|
GovernanceProposerBytecode,
|
|
19
19
|
InboxAbi,
|
|
20
20
|
InboxBytecode,
|
|
21
|
+
MultiAdderAbi,
|
|
22
|
+
MultiAdderBytecode,
|
|
21
23
|
OutboxAbi,
|
|
22
24
|
OutboxBytecode,
|
|
23
25
|
RegisterNewRollupVersionPayloadAbi,
|
|
@@ -193,6 +195,10 @@ export const l1Artifacts = {
|
|
|
193
195
|
contractAbi: StakingAssetHandlerAbi,
|
|
194
196
|
contractBytecode: StakingAssetHandlerBytecode as Hex,
|
|
195
197
|
},
|
|
198
|
+
multiAdder: {
|
|
199
|
+
contractAbi: MultiAdderAbi,
|
|
200
|
+
contractBytecode: MultiAdderBytecode as Hex,
|
|
201
|
+
},
|
|
196
202
|
};
|
|
197
203
|
|
|
198
204
|
export interface DeployL1ContractsArgs extends L1ContractsConfig {
|
|
@@ -550,7 +556,7 @@ export const deployRollup = async (
|
|
|
550
556
|
try {
|
|
551
557
|
const retrievedRollupAddress = await registryContract.read.getRollup([version]);
|
|
552
558
|
logger.verbose(`Rollup ${retrievedRollupAddress} already exists in registry`);
|
|
553
|
-
} catch
|
|
559
|
+
} catch {
|
|
554
560
|
const { txHash: addRollupTxHash } = await deployer.sendTransaction({
|
|
555
561
|
to: addresses.registryAddress.toString(),
|
|
556
562
|
data: encodeFunctionData({
|
|
@@ -664,6 +670,18 @@ export const cheat_initializeValidatorSet = async (
|
|
|
664
670
|
}
|
|
665
671
|
|
|
666
672
|
if (validators.length > 0) {
|
|
673
|
+
const multiAdder = await deployer.deploy(l1Artifacts.multiAdder, [
|
|
674
|
+
rollupAddress,
|
|
675
|
+
deployer.client.account.address,
|
|
676
|
+
]);
|
|
677
|
+
|
|
678
|
+
const validatorsTuples = validators.map(v => ({
|
|
679
|
+
attester: v,
|
|
680
|
+
proposer: getExpectedAddress(ForwarderAbi, ForwarderBytecode, [v], v).address,
|
|
681
|
+
withdrawer: v,
|
|
682
|
+
amount: minimumStake,
|
|
683
|
+
}));
|
|
684
|
+
|
|
667
685
|
// Mint tokens, approve them, use cheat code to initialise validator set without setting up the epoch.
|
|
668
686
|
const stakeNeeded = minimumStake * BigInt(validators.length);
|
|
669
687
|
await Promise.all(
|
|
@@ -673,30 +691,16 @@ export const cheat_initializeValidatorSet = async (
|
|
|
673
691
|
data: encodeFunctionData({
|
|
674
692
|
abi: l1Artifacts.stakingAsset.contractAbi,
|
|
675
693
|
functionName: 'mint',
|
|
676
|
-
args: [
|
|
677
|
-
}),
|
|
678
|
-
}),
|
|
679
|
-
await deployer.sendTransaction({
|
|
680
|
-
to: stakingAssetAddress,
|
|
681
|
-
data: encodeFunctionData({
|
|
682
|
-
abi: l1Artifacts.stakingAsset.contractAbi,
|
|
683
|
-
functionName: 'approve',
|
|
684
|
-
args: [rollupAddress, stakeNeeded],
|
|
694
|
+
args: [multiAdder.toString(), stakeNeeded],
|
|
685
695
|
}),
|
|
686
696
|
}),
|
|
687
697
|
].map(tx => extendedClient.waitForTransactionReceipt({ hash: tx.txHash })),
|
|
688
698
|
);
|
|
689
699
|
|
|
690
|
-
const validatorsTuples = validators.map(v => ({
|
|
691
|
-
attester: v,
|
|
692
|
-
proposer: getExpectedAddress(ForwarderAbi, ForwarderBytecode, [v], v).address,
|
|
693
|
-
withdrawer: v,
|
|
694
|
-
amount: minimumStake,
|
|
695
|
-
}));
|
|
696
700
|
const initiateValidatorSetTxHash = await deployer.client.writeContract({
|
|
697
|
-
address:
|
|
698
|
-
abi: l1Artifacts.
|
|
699
|
-
functionName: '
|
|
701
|
+
address: multiAdder.toString(),
|
|
702
|
+
abi: l1Artifacts.multiAdder.contractAbi,
|
|
703
|
+
functionName: 'addValidators',
|
|
700
704
|
args: [validatorsTuples],
|
|
701
705
|
});
|
|
702
706
|
await extendedClient.waitForTransactionReceipt({ hash: initiateValidatorSetTxHash });
|
package/src/eth_cheat_codes.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { 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
|
|
|
7
|
-
import { type Hex, createPublicClient, fallback, http } from 'viem';
|
|
7
|
+
import { type Hex, createPublicClient, fallback, http, parseTransaction } from 'viem';
|
|
8
8
|
|
|
9
9
|
import type { ViemPublicClient } from './types.js';
|
|
10
10
|
|
|
@@ -336,6 +336,13 @@ export class EthCheatCodes {
|
|
|
336
336
|
depth: number,
|
|
337
337
|
newBlocks: (Hex | { to: EthAddress | Hex; input?: Hex; from?: EthAddress | Hex; value?: number | bigint })[][] = [],
|
|
338
338
|
): Promise<void> {
|
|
339
|
+
this.logger.verbose(`Preparing L1 reorg with depth ${depth}`);
|
|
340
|
+
for (const tx of newBlocks.flat()) {
|
|
341
|
+
const isBlobTx = typeof tx === 'string' ? parseTransaction(tx).type === 'eip4844' : 'blobVersionedHashes' in tx;
|
|
342
|
+
if (isBlobTx) {
|
|
343
|
+
throw new Error(`Anvil does not support blob transactions in anvil_reorg`);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
339
346
|
try {
|
|
340
347
|
await this.rpcCall('anvil_reorg', [
|
|
341
348
|
depth,
|
package/src/index.ts
CHANGED
package/src/l1_tx_utils.ts
CHANGED
|
@@ -167,6 +167,7 @@ export interface L1TxRequest {
|
|
|
167
167
|
to: Address | null;
|
|
168
168
|
data?: Hex;
|
|
169
169
|
value?: bigint;
|
|
170
|
+
abi?: Abi;
|
|
170
171
|
}
|
|
171
172
|
|
|
172
173
|
export type L1GasConfig = Partial<L1TxUtilsConfig> & { gasLimit?: bigint; txTimeoutAt?: Date };
|
|
@@ -595,7 +596,7 @@ export class L1TxUtils extends ReadOnlyL1TxUtils {
|
|
|
595
596
|
|
|
596
597
|
return { txHash, gasLimit, gasPrice };
|
|
597
598
|
} catch (err: any) {
|
|
598
|
-
const viemError = formatViemError(err);
|
|
599
|
+
const viemError = formatViemError(err, request.abi);
|
|
599
600
|
this.logger?.error(`Failed to send L1 transaction`, viemError.message, {
|
|
600
601
|
metaMessages: viemError.metaMessages,
|
|
601
602
|
});
|
package/src/l1_types.ts
ADDED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { InboxContract, type RollupContract } from '@aztec/ethereum/contracts';
|
|
2
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
3
|
|
|
4
4
|
import { EventEmitter } from 'events';
|
|
@@ -8,6 +8,7 @@ import type { ViemClient } from '../types.js';
|
|
|
8
8
|
/** Utility class that polls the chain on quick intervals and logs new L1 blocks, L2 blocks, and L2 proofs. */
|
|
9
9
|
export class ChainMonitor extends EventEmitter {
|
|
10
10
|
private readonly l1Client: ViemClient;
|
|
11
|
+
private inbox: InboxContract | undefined;
|
|
11
12
|
private handle: NodeJS.Timeout | undefined;
|
|
12
13
|
|
|
13
14
|
/** Current L1 block number */
|
|
@@ -20,6 +21,8 @@ export class ChainMonitor extends EventEmitter {
|
|
|
20
21
|
public l2BlockTimestamp!: bigint;
|
|
21
22
|
/** L1 timestamp for the proven L2 block */
|
|
22
23
|
public l2ProvenBlockTimestamp!: bigint;
|
|
24
|
+
/** Total number of L2 messages pushed into the Inbox */
|
|
25
|
+
public totalL2Messages: number = 0;
|
|
23
26
|
|
|
24
27
|
constructor(
|
|
25
28
|
private readonly rollup: RollupContract,
|
|
@@ -46,16 +49,24 @@ export class ChainMonitor extends EventEmitter {
|
|
|
46
49
|
}
|
|
47
50
|
}
|
|
48
51
|
|
|
52
|
+
private async getInbox() {
|
|
53
|
+
if (!this.inbox) {
|
|
54
|
+
const { inboxAddress } = await this.rollup.getRollupAddresses();
|
|
55
|
+
this.inbox = new InboxContract(this.l1Client, inboxAddress);
|
|
56
|
+
}
|
|
57
|
+
return this.inbox;
|
|
58
|
+
}
|
|
59
|
+
|
|
49
60
|
private safeRun() {
|
|
50
61
|
void this.run().catch(error => {
|
|
51
62
|
this.logger.error('Error in chain monitor loop', error);
|
|
52
63
|
});
|
|
53
64
|
}
|
|
54
65
|
|
|
55
|
-
async run() {
|
|
66
|
+
async run(force = false) {
|
|
56
67
|
const newL1BlockNumber = Number(await this.l1Client.getBlockNumber({ cacheTime: 0 }));
|
|
57
|
-
if (this.l1BlockNumber === newL1BlockNumber) {
|
|
58
|
-
return;
|
|
68
|
+
if (!force && this.l1BlockNumber === newL1BlockNumber) {
|
|
69
|
+
return this;
|
|
59
70
|
}
|
|
60
71
|
this.l1BlockNumber = newL1BlockNumber;
|
|
61
72
|
|
|
@@ -88,12 +99,23 @@ export class ChainMonitor extends EventEmitter {
|
|
|
88
99
|
});
|
|
89
100
|
}
|
|
90
101
|
|
|
102
|
+
const inbox = await this.getInbox();
|
|
103
|
+
const newTotalL2Messages = await inbox.getState().then(s => Number(s.totalMessagesInserted));
|
|
104
|
+
if (this.totalL2Messages !== newTotalL2Messages) {
|
|
105
|
+
msg += ` with ${newTotalL2Messages - this.totalL2Messages} new L2 messages (total ${newTotalL2Messages})`;
|
|
106
|
+
this.totalL2Messages = newTotalL2Messages;
|
|
107
|
+
this.emit('l2-messages', { totalL2Messages: newTotalL2Messages, l1BlockNumber: newL1BlockNumber });
|
|
108
|
+
}
|
|
109
|
+
|
|
91
110
|
this.logger.info(msg, {
|
|
92
111
|
l1Timestamp: timestamp,
|
|
93
112
|
l1BlockNumber: this.l1BlockNumber,
|
|
94
113
|
l2SlotNumber: await this.rollup.getSlotNumber(),
|
|
95
114
|
l2BlockNumber: this.l2BlockNumber,
|
|
96
115
|
l2ProvenBlockNumber: this.l2ProvenBlockNumber,
|
|
116
|
+
totalL2Messages: this.totalL2Messages,
|
|
97
117
|
});
|
|
118
|
+
|
|
119
|
+
return this;
|
|
98
120
|
}
|
|
99
121
|
}
|