@aztec/ethereum 1.0.0-nightly.20250708 → 1.0.0-nightly.20250709
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/empire_base.d.ts +3 -4
- package/dest/contracts/empire_base.d.ts.map +1 -1
- package/dest/contracts/empire_base.js +4 -8
- package/dest/contracts/governance_proposer.d.ts +2 -2
- package/dest/contracts/governance_proposer.d.ts.map +1 -1
- package/dest/contracts/governance_proposer.js +3 -3
- package/dest/contracts/slashing_proposer.d.ts +10 -2
- package/dest/contracts/slashing_proposer.d.ts.map +1 -1
- package/dest/contracts/slashing_proposer.js +19 -8
- package/dest/test/start_anvil.d.ts +2 -0
- package/dest/test/start_anvil.d.ts.map +1 -1
- package/dest/test/start_anvil.js +4 -1
- package/package.json +4 -4
- package/src/contracts/empire_base.ts +10 -16
- package/src/contracts/governance_proposer.ts +9 -4
- package/src/contracts/slashing_proposer.ts +25 -8
- package/src/test/start_anvil.ts +7 -3
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Signature } from '@aztec/foundation/eth-signature';
|
|
2
|
-
import { type Hex
|
|
2
|
+
import { type Hex } from 'viem';
|
|
3
3
|
import type { L1TxRequest } from '../l1_tx_utils.js';
|
|
4
|
-
import type { ExtendedViemWalletClient } from '../types.js';
|
|
5
4
|
export interface IEmpireBase {
|
|
6
5
|
getRoundInfo(rollupAddress: Hex, round: bigint): Promise<{
|
|
7
6
|
lastVote: bigint;
|
|
@@ -10,7 +9,7 @@ export interface IEmpireBase {
|
|
|
10
9
|
}>;
|
|
11
10
|
computeRound(slot: bigint): Promise<bigint>;
|
|
12
11
|
createVoteRequest(payload: Hex): L1TxRequest;
|
|
13
|
-
createVoteRequestWithSignature(payload: Hex,
|
|
12
|
+
createVoteRequestWithSignature(payload: Hex, chainId: number, signerAddress: Hex, signer: (msg: Hex) => Promise<Hex>): Promise<L1TxRequest>;
|
|
14
13
|
}
|
|
15
14
|
export declare function encodeVote(payload: Hex): Hex;
|
|
16
15
|
export declare function encodeVoteWithSignature(payload: Hex, signature: Signature): `0x${string}`;
|
|
@@ -23,5 +22,5 @@ export declare function encodeVoteWithSignature(payload: Hex, signature: Signatu
|
|
|
23
22
|
* @param account - The account to sign with (optional if hoisted on wallet client)
|
|
24
23
|
* @returns The EIP-712 signature
|
|
25
24
|
*/
|
|
26
|
-
export declare function signVoteWithSig(
|
|
25
|
+
export declare function signVoteWithSig(signer: (msg: Hex) => Promise<Hex>, proposal: Hex, nonce: bigint, verifyingContract: Hex, chainId: number): Promise<Signature>;
|
|
27
26
|
//# sourceMappingURL=empire_base.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"empire_base.d.ts","sourceRoot":"","sources":["../../src/contracts/empire_base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAG5D,OAAO,EAAE,KAAK,GAAG,
|
|
1
|
+
{"version":3,"file":"empire_base.d.ts","sourceRoot":"","sources":["../../src/contracts/empire_base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAG5D,OAAO,EAAE,KAAK,GAAG,EAAqC,MAAM,MAAM,CAAC;AAEnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,aAAa,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,GAAG,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC/G,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,iBAAiB,CAAC,OAAO,EAAE,GAAG,GAAG,WAAW,CAAC;IAC7C,8BAA8B,CAC5B,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,GAAG,EAClB,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,GACjC,OAAO,CAAC,WAAW,CAAC,CAAC;CACzB;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,GAAG,GAAG,GAAG,CAM5C;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,iBAMzE;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,EAClC,QAAQ,EAAE,GAAG,EACb,KAAK,EAAE,MAAM,EACb,iBAAiB,EAAE,GAAG,EACtB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,SAAS,CAAC,CAsBpB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Signature } from '@aztec/foundation/eth-signature';
|
|
2
2
|
import { EmpireBaseAbi } from '@aztec/l1-artifacts/EmpireBaseAbi';
|
|
3
|
-
import { encodeFunctionData } from 'viem';
|
|
3
|
+
import { encodeFunctionData, hashTypedData } from 'viem';
|
|
4
4
|
export function encodeVote(payload) {
|
|
5
5
|
return encodeFunctionData({
|
|
6
6
|
abi: EmpireBaseAbi,
|
|
@@ -28,7 +28,7 @@ export function encodeVoteWithSignature(payload, signature) {
|
|
|
28
28
|
* @param chainId - The chain ID where the contract is deployed
|
|
29
29
|
* @param account - The account to sign with (optional if hoisted on wallet client)
|
|
30
30
|
* @returns The EIP-712 signature
|
|
31
|
-
*/ export async function signVoteWithSig(
|
|
31
|
+
*/ export async function signVoteWithSig(signer, proposal, nonce, verifyingContract, chainId) {
|
|
32
32
|
const domain = {
|
|
33
33
|
name: 'EmpireBase',
|
|
34
34
|
version: '1',
|
|
@@ -51,15 +51,11 @@ export function encodeVoteWithSignature(payload, signature) {
|
|
|
51
51
|
proposal,
|
|
52
52
|
nonce
|
|
53
53
|
};
|
|
54
|
-
|
|
55
|
-
throw new Error('Wallet client must be connected to an account');
|
|
56
|
-
}
|
|
57
|
-
const signatureHex = await walletClient.signTypedData({
|
|
58
|
-
account: walletClient.account.address,
|
|
54
|
+
const msg = hashTypedData({
|
|
59
55
|
domain,
|
|
60
56
|
types,
|
|
61
57
|
primaryType: 'Vote',
|
|
62
58
|
message
|
|
63
59
|
});
|
|
64
|
-
return Signature.fromString(
|
|
60
|
+
return Signature.fromString(await signer(msg));
|
|
65
61
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
2
2
|
import { type Hex, type TransactionReceipt } from 'viem';
|
|
3
3
|
import type { GasPrice, L1TxRequest, L1TxUtils } from '../l1_tx_utils.js';
|
|
4
|
-
import type {
|
|
4
|
+
import type { ViemClient } from '../types.js';
|
|
5
5
|
import { type IEmpireBase } from './empire_base.js';
|
|
6
6
|
export declare class GovernanceProposerContract implements IEmpireBase {
|
|
7
7
|
readonly client: ViemClient;
|
|
@@ -21,7 +21,7 @@ export declare class GovernanceProposerContract implements IEmpireBase {
|
|
|
21
21
|
}>;
|
|
22
22
|
getProposalVotes(rollupAddress: Hex, round: bigint, proposal: Hex): Promise<bigint>;
|
|
23
23
|
createVoteRequest(payload: Hex): L1TxRequest;
|
|
24
|
-
createVoteRequestWithSignature(payload: Hex,
|
|
24
|
+
createVoteRequestWithSignature(payload: Hex, chainId: number, signerAddress: Hex, signer: (msg: Hex) => Promise<Hex>): Promise<L1TxRequest>;
|
|
25
25
|
executeProposal(round: bigint, l1TxUtils: L1TxUtils): Promise<{
|
|
26
26
|
receipt: TransactionReceipt;
|
|
27
27
|
gasPrice: GasPrice;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"governance_proposer.d.ts","sourceRoot":"","sources":["../../src/contracts/governance_proposer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAG3D,OAAO,EAA8B,KAAK,GAAG,EAAE,KAAK,kBAAkB,EAAmC,MAAM,MAAM,CAAC;AAEtH,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"governance_proposer.d.ts","sourceRoot":"","sources":["../../src/contracts/governance_proposer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAG3D,OAAO,EAA8B,KAAK,GAAG,EAAE,KAAK,kBAAkB,EAAmC,MAAM,MAAM,CAAC;AAEtH,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,KAAK,WAAW,EAAwD,MAAM,kBAAkB,CAAC;AAG1G,qBAAa,0BAA2B,YAAW,WAAW;aAI1C,MAAM,EAAE,UAAU;IAHpC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkE;gBAGzE,MAAM,EAAE,UAAU,EAClC,OAAO,EAAE,GAAG;IAKd,IAAW,OAAO,eAEjB;IAEY,gBAAgB;IAKhB,kBAAkB;IAIxB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAIhC,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAI/B,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI3C,QAAQ,CAAC,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC;IAIlC,YAAY,CACvB,aAAa,EAAE,GAAG,EAClB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,GAAG,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IAIzD,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC;IAInF,iBAAiB,CAAC,OAAO,EAAE,GAAG,GAAG,WAAW;IAOtC,8BAA8B,CACzC,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,GAAG,EAClB,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,GACjC,OAAO,CAAC,WAAW,CAAC;IASV,eAAe,CAC1B,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC;QACT,OAAO,EAAE,kBAAkB,CAAC;QAC5B,QAAQ,EAAE,QAAQ,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CAYH"}
|
|
@@ -65,9 +65,9 @@ export class GovernanceProposerContract {
|
|
|
65
65
|
data: encodeVote(payload)
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
|
-
async createVoteRequestWithSignature(payload,
|
|
69
|
-
const nonce = await this.getNonce(
|
|
70
|
-
const signature = await signVoteWithSig(
|
|
68
|
+
async createVoteRequestWithSignature(payload, chainId, signerAddress, signer) {
|
|
69
|
+
const nonce = await this.getNonce(signerAddress);
|
|
70
|
+
const signature = await signVoteWithSig(signer, payload, nonce, this.address.toString(), chainId);
|
|
71
71
|
return {
|
|
72
72
|
to: this.address.toString(),
|
|
73
73
|
data: encodeVoteWithSignature(payload, signature)
|
|
@@ -2,13 +2,14 @@ import { EthAddress } from '@aztec/foundation/eth-address';
|
|
|
2
2
|
import EventEmitter from 'events';
|
|
3
3
|
import { type Hex } from 'viem';
|
|
4
4
|
import type { L1TxRequest, L1TxUtils } from '../l1_tx_utils.js';
|
|
5
|
-
import type {
|
|
5
|
+
import type { ViemClient } from '../types.js';
|
|
6
6
|
import { type IEmpireBase } from './empire_base.js';
|
|
7
7
|
export declare class ProposalAlreadyExecutedError extends Error {
|
|
8
8
|
constructor(round: bigint);
|
|
9
9
|
}
|
|
10
10
|
export declare class SlashingProposerContract extends EventEmitter implements IEmpireBase {
|
|
11
11
|
readonly client: ViemClient;
|
|
12
|
+
private readonly logger;
|
|
12
13
|
private readonly proposer;
|
|
13
14
|
constructor(client: ViemClient, address: Hex);
|
|
14
15
|
get address(): EthAddress;
|
|
@@ -23,7 +24,7 @@ export declare class SlashingProposerContract extends EventEmitter implements IE
|
|
|
23
24
|
}>;
|
|
24
25
|
getProposalVotes(rollupAddress: Hex, round: bigint, proposal: Hex): Promise<bigint>;
|
|
25
26
|
createVoteRequest(payload: Hex): L1TxRequest;
|
|
26
|
-
createVoteRequestWithSignature(payload: Hex,
|
|
27
|
+
createVoteRequestWithSignature(payload: Hex, chainId: number, signerAddress: Hex, signer: (msg: Hex) => Promise<Hex>): Promise<L1TxRequest>;
|
|
27
28
|
listenToExecutableProposals(callback: (args: {
|
|
28
29
|
proposal: `0x${string}`;
|
|
29
30
|
round: bigint;
|
|
@@ -32,6 +33,13 @@ export declare class SlashingProposerContract extends EventEmitter implements IE
|
|
|
32
33
|
round: bigint;
|
|
33
34
|
proposal: `0x${string}`;
|
|
34
35
|
}) => unknown): import("viem").WatchContractEventReturnType;
|
|
36
|
+
/**
|
|
37
|
+
* Wait for a round to be reached.
|
|
38
|
+
*
|
|
39
|
+
* @param round - The round to wait for.
|
|
40
|
+
* @param pollingIntervalSeconds - The interval in seconds to poll for the round.
|
|
41
|
+
* @returns True if the round was reached, false otherwise.
|
|
42
|
+
*/
|
|
35
43
|
waitForRound(round: bigint, pollingIntervalSeconds?: number): Promise<boolean>;
|
|
36
44
|
executeRound(txUtils: L1TxUtils, round: bigint | number): ReturnType<typeof txUtils.sendAndMonitorTransaction>;
|
|
37
45
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slashing_proposer.d.ts","sourceRoot":"","sources":["../../src/contracts/slashing_proposer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"slashing_proposer.d.ts","sourceRoot":"","sources":["../../src/contracts/slashing_proposer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAK3D,OAAO,YAAY,MAAM,QAAQ,CAAC;AAClC,OAAO,EAGL,KAAK,GAAG,EAGT,MAAM,MAAM,CAAC;AAEd,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAE,KAAK,WAAW,EAAwD,MAAM,kBAAkB,CAAC;AAE1G,qBAAa,4BAA6B,SAAQ,KAAK;gBACzC,KAAK,EAAE,MAAM;CAG1B;AAED,qBAAa,wBAAyB,SAAQ,YAAa,YAAW,WAAW;aAK7D,MAAM,EAAE,UAAU;IAJpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4C;IACnE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgE;gBAGvE,MAAM,EAAE,UAAU,EAClC,OAAO,EAAE,GAAG;IAMd,IAAW,OAAO,eAEjB;IAEM,aAAa;IAIb,YAAY;IAIZ,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI3C,QAAQ,CAAC,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC;IAIlC,YAAY,CACvB,aAAa,EAAE,GAAG,EAClB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,GAAG,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IAIzD,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC;IAInF,iBAAiB,CAAC,OAAO,EAAE,GAAG,GAAG,WAAW;IAOtC,8BAA8B,CACzC,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,GAAG,EAClB,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,GACjC,OAAO,CAAC,WAAW,CAAC;IAShB,2BAA2B,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,KAAK,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO;IAiBnG,wBAAwB,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,KAAK,MAAM,EAAE,CAAA;KAAE,KAAK,OAAO;IAgBvG;;;;;;OAMG;IACI,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,sBAAsB,GAAE,MAAU,GAAG,OAAO,CAAC,OAAO,CAAC;IAe3E,YAAY,CACvB,OAAO,EAAE,SAAS,EAClB,KAAK,EAAE,MAAM,GAAG,MAAM,GACrB,UAAU,CAAC,OAAO,OAAO,CAAC,yBAAyB,CAAC;CA+CxD"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
2
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
2
3
|
import { retryUntil } from '@aztec/foundation/retry';
|
|
3
4
|
import { SlashingProposerAbi } from '@aztec/l1-artifacts/SlashingProposerAbi';
|
|
4
5
|
import EventEmitter from 'events';
|
|
@@ -12,9 +13,10 @@ export class ProposalAlreadyExecutedError extends Error {
|
|
|
12
13
|
}
|
|
13
14
|
export class SlashingProposerContract extends EventEmitter {
|
|
14
15
|
client;
|
|
16
|
+
logger;
|
|
15
17
|
proposer;
|
|
16
18
|
constructor(client, address){
|
|
17
|
-
super(), this.client = client;
|
|
19
|
+
super(), this.client = client, this.logger = createLogger('SlashingProposerContract');
|
|
18
20
|
this.proposer = getContract({
|
|
19
21
|
address,
|
|
20
22
|
abi: SlashingProposerAbi,
|
|
@@ -59,9 +61,9 @@ export class SlashingProposerContract extends EventEmitter {
|
|
|
59
61
|
data: encodeVote(payload)
|
|
60
62
|
};
|
|
61
63
|
}
|
|
62
|
-
async createVoteRequestWithSignature(payload,
|
|
63
|
-
const nonce = await this.getNonce(
|
|
64
|
-
const signature = await signVoteWithSig(
|
|
64
|
+
async createVoteRequestWithSignature(payload, chainId, signerAddress, signer) {
|
|
65
|
+
const nonce = await this.getNonce(signerAddress);
|
|
66
|
+
const signature = await signVoteWithSig(signer, payload, nonce, this.address.toString(), chainId);
|
|
65
67
|
return {
|
|
66
68
|
to: this.address.toString(),
|
|
67
69
|
data: encodeVoteWithSignature(payload, signature)
|
|
@@ -92,11 +94,20 @@ export class SlashingProposerContract extends EventEmitter {
|
|
|
92
94
|
}
|
|
93
95
|
});
|
|
94
96
|
}
|
|
95
|
-
|
|
97
|
+
/**
|
|
98
|
+
* Wait for a round to be reached.
|
|
99
|
+
*
|
|
100
|
+
* @param round - The round to wait for.
|
|
101
|
+
* @param pollingIntervalSeconds - The interval in seconds to poll for the round.
|
|
102
|
+
* @returns True if the round was reached, false otherwise.
|
|
103
|
+
*/ waitForRound(round, pollingIntervalSeconds = 1) {
|
|
96
104
|
return retryUntil(async ()=>{
|
|
97
|
-
const currentRound = await this.proposer.read.getCurrentRound()
|
|
98
|
-
|
|
99
|
-
|
|
105
|
+
const currentRound = await this.proposer.read.getCurrentRound().catch((e)=>{
|
|
106
|
+
this.logger.error('Error getting current round', e);
|
|
107
|
+
return undefined;
|
|
108
|
+
});
|
|
109
|
+
return currentRound !== undefined && currentRound >= round;
|
|
110
|
+
}, `Waiting for round ${round} to be reached`, 0, pollingIntervalSeconds).catch(()=>false);
|
|
100
111
|
}
|
|
101
112
|
async executeRound(txUtils, round) {
|
|
102
113
|
if (typeof round === 'number') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start_anvil.d.ts","sourceRoot":"","sources":["../../src/test/start_anvil.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,KAAK,EAAe,MAAM,aAAa,CAAC;AAGtD;;GAEG;AACH,wBAAsB,UAAU,CAC9B,IAAI,GAAE;IACJ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"start_anvil.d.ts","sourceRoot":"","sources":["../../src/test/start_anvil.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,KAAK,EAAe,MAAM,aAAa,CAAC;AAGtD;;GAEG;AACH,wBAAsB,UAAU,CAC9B,IAAI,GAAE;IACJ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,kBAAkB,CAAC,EAAE,OAAO,CAAC;CACzB,GACL,OAAO,CAAC;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CA8C9F"}
|
package/dest/test/start_anvil.js
CHANGED
|
@@ -8,6 +8,7 @@ import { dirname, resolve } from 'path';
|
|
|
8
8
|
*/ export async function startAnvil(opts = {}) {
|
|
9
9
|
const anvilBinary = resolve(dirname(fileURLToPath(import.meta.url)), '../../', 'scripts/anvil_kill_wrapper.sh');
|
|
10
10
|
const logger = opts.log ? createLogger('ethereum:anvil') : undefined;
|
|
11
|
+
const methodCalls = opts.captureMethodCalls ? [] : undefined;
|
|
11
12
|
let port;
|
|
12
13
|
// Start anvil.
|
|
13
14
|
// We go via a wrapper script to ensure if the parent dies, anvil dies.
|
|
@@ -22,12 +23,13 @@ import { dirname, resolve } from 'path';
|
|
|
22
23
|
// Listen to the anvil output to get the port.
|
|
23
24
|
const removeHandler = anvil.on('message', (message)=>{
|
|
24
25
|
logger?.debug(message);
|
|
26
|
+
methodCalls?.push(...message.match(/eth_[^\s]+/g) || []);
|
|
25
27
|
if (port === undefined && message.includes('Listening on')) {
|
|
26
28
|
port = parseInt(message.match(/Listening on ([^:]+):(\d+)/)[2]);
|
|
27
29
|
}
|
|
28
30
|
});
|
|
29
31
|
await anvil.start();
|
|
30
|
-
if (!logger) {
|
|
32
|
+
if (!logger && !opts.captureMethodCalls) {
|
|
31
33
|
removeHandler();
|
|
32
34
|
}
|
|
33
35
|
return anvil;
|
|
@@ -43,6 +45,7 @@ import { dirname, resolve } from 'path';
|
|
|
43
45
|
// Object.defineProperty(anvil, 'port', { value: port, writable: false });
|
|
44
46
|
return {
|
|
45
47
|
anvil,
|
|
48
|
+
methodCalls,
|
|
46
49
|
stop: ()=>anvil.stop(),
|
|
47
50
|
rpcUrl: `http://127.0.0.1:${port}`
|
|
48
51
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/ethereum",
|
|
3
|
-
"version": "1.0.0-nightly.
|
|
3
|
+
"version": "1.0.0-nightly.20250709",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"../package.common.json"
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@aztec/blob-lib": "1.0.0-nightly.
|
|
35
|
-
"@aztec/foundation": "1.0.0-nightly.
|
|
36
|
-
"@aztec/l1-artifacts": "1.0.0-nightly.
|
|
34
|
+
"@aztec/blob-lib": "1.0.0-nightly.20250709",
|
|
35
|
+
"@aztec/foundation": "1.0.0-nightly.20250709",
|
|
36
|
+
"@aztec/l1-artifacts": "1.0.0-nightly.20250709",
|
|
37
37
|
"@viem/anvil": "^0.0.10",
|
|
38
38
|
"dotenv": "^16.0.3",
|
|
39
39
|
"tslib": "^2.4.0",
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { Signature } from '@aztec/foundation/eth-signature';
|
|
2
2
|
import { EmpireBaseAbi } from '@aztec/l1-artifacts/EmpireBaseAbi';
|
|
3
3
|
|
|
4
|
-
import { type Hex,
|
|
4
|
+
import { type Hex, encodeFunctionData, hashTypedData } from 'viem';
|
|
5
5
|
|
|
6
6
|
import type { L1TxRequest } from '../l1_tx_utils.js';
|
|
7
|
-
import type { ExtendedViemWalletClient } from '../types.js';
|
|
8
7
|
|
|
9
8
|
export interface IEmpireBase {
|
|
10
9
|
getRoundInfo(rollupAddress: Hex, round: bigint): Promise<{ lastVote: bigint; leader: Hex; executed: boolean }>;
|
|
11
10
|
computeRound(slot: bigint): Promise<bigint>;
|
|
12
11
|
createVoteRequest(payload: Hex): L1TxRequest;
|
|
13
|
-
createVoteRequestWithSignature(
|
|
12
|
+
createVoteRequestWithSignature(
|
|
13
|
+
payload: Hex,
|
|
14
|
+
chainId: number,
|
|
15
|
+
signerAddress: Hex,
|
|
16
|
+
signer: (msg: Hex) => Promise<Hex>,
|
|
17
|
+
): Promise<L1TxRequest>;
|
|
14
18
|
}
|
|
15
19
|
|
|
16
20
|
export function encodeVote(payload: Hex): Hex {
|
|
@@ -39,7 +43,7 @@ export function encodeVoteWithSignature(payload: Hex, signature: Signature) {
|
|
|
39
43
|
* @returns The EIP-712 signature
|
|
40
44
|
*/
|
|
41
45
|
export async function signVoteWithSig(
|
|
42
|
-
|
|
46
|
+
signer: (msg: Hex) => Promise<Hex>,
|
|
43
47
|
proposal: Hex,
|
|
44
48
|
nonce: bigint,
|
|
45
49
|
verifyingContract: Hex,
|
|
@@ -64,16 +68,6 @@ export async function signVoteWithSig(
|
|
|
64
68
|
nonce,
|
|
65
69
|
};
|
|
66
70
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const signatureHex = await walletClient.signTypedData({
|
|
72
|
-
account: walletClient.account.address,
|
|
73
|
-
domain,
|
|
74
|
-
types,
|
|
75
|
-
primaryType: 'Vote',
|
|
76
|
-
message,
|
|
77
|
-
});
|
|
78
|
-
return Signature.fromString(signatureHex);
|
|
71
|
+
const msg = hashTypedData({ domain, types, primaryType: 'Vote', message });
|
|
72
|
+
return Signature.fromString(await signer(msg));
|
|
79
73
|
}
|
|
@@ -5,7 +5,7 @@ import { GovernanceProposerAbi } from '@aztec/l1-artifacts/GovernanceProposerAbi
|
|
|
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
|
-
import type {
|
|
8
|
+
import type { ViemClient } from '../types.js';
|
|
9
9
|
import { type IEmpireBase, encodeVote, encodeVoteWithSignature, signVoteWithSig } from './empire_base.js';
|
|
10
10
|
import { extractProposalIdFromLogs } from './governance.js';
|
|
11
11
|
|
|
@@ -66,9 +66,14 @@ export class GovernanceProposerContract implements IEmpireBase {
|
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
public async createVoteRequestWithSignature(
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
public async createVoteRequestWithSignature(
|
|
70
|
+
payload: Hex,
|
|
71
|
+
chainId: number,
|
|
72
|
+
signerAddress: Hex,
|
|
73
|
+
signer: (msg: Hex) => Promise<Hex>,
|
|
74
|
+
): Promise<L1TxRequest> {
|
|
75
|
+
const nonce = await this.getNonce(signerAddress);
|
|
76
|
+
const signature = await signVoteWithSig(signer, payload, nonce, this.address.toString(), chainId);
|
|
72
77
|
return {
|
|
73
78
|
to: this.address.toString(),
|
|
74
79
|
data: encodeVoteWithSignature(payload, signature),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
2
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
2
3
|
import { retryUntil } from '@aztec/foundation/retry';
|
|
3
4
|
import { SlashingProposerAbi } from '@aztec/l1-artifacts/SlashingProposerAbi';
|
|
4
5
|
|
|
@@ -12,7 +13,7 @@ import {
|
|
|
12
13
|
} from 'viem';
|
|
13
14
|
|
|
14
15
|
import type { L1TxRequest, L1TxUtils } from '../l1_tx_utils.js';
|
|
15
|
-
import type {
|
|
16
|
+
import type { ViemClient } from '../types.js';
|
|
16
17
|
import { FormattedViemError } from '../utils.js';
|
|
17
18
|
import { type IEmpireBase, encodeVote, encodeVoteWithSignature, signVoteWithSig } from './empire_base.js';
|
|
18
19
|
|
|
@@ -23,6 +24,7 @@ export class ProposalAlreadyExecutedError extends Error {
|
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export class SlashingProposerContract extends EventEmitter implements IEmpireBase {
|
|
27
|
+
private readonly logger = createLogger('SlashingProposerContract');
|
|
26
28
|
private readonly proposer: GetContractReturnType<typeof SlashingProposerAbi, ViemClient>;
|
|
27
29
|
|
|
28
30
|
constructor(
|
|
@@ -71,9 +73,14 @@ export class SlashingProposerContract extends EventEmitter implements IEmpireBas
|
|
|
71
73
|
};
|
|
72
74
|
}
|
|
73
75
|
|
|
74
|
-
public async createVoteRequestWithSignature(
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
public async createVoteRequestWithSignature(
|
|
77
|
+
payload: Hex,
|
|
78
|
+
chainId: number,
|
|
79
|
+
signerAddress: Hex,
|
|
80
|
+
signer: (msg: Hex) => Promise<Hex>,
|
|
81
|
+
): Promise<L1TxRequest> {
|
|
82
|
+
const nonce = await this.getNonce(signerAddress);
|
|
83
|
+
const signature = await signVoteWithSig(signer, payload, nonce, this.address.toString(), chainId);
|
|
77
84
|
return {
|
|
78
85
|
to: this.address.toString(),
|
|
79
86
|
data: encodeVoteWithSignature(payload, signature),
|
|
@@ -113,16 +120,26 @@ export class SlashingProposerContract extends EventEmitter implements IEmpireBas
|
|
|
113
120
|
);
|
|
114
121
|
}
|
|
115
122
|
|
|
116
|
-
|
|
123
|
+
/**
|
|
124
|
+
* Wait for a round to be reached.
|
|
125
|
+
*
|
|
126
|
+
* @param round - The round to wait for.
|
|
127
|
+
* @param pollingIntervalSeconds - The interval in seconds to poll for the round.
|
|
128
|
+
* @returns True if the round was reached, false otherwise.
|
|
129
|
+
*/
|
|
130
|
+
public waitForRound(round: bigint, pollingIntervalSeconds: number = 1): Promise<boolean> {
|
|
117
131
|
return retryUntil(
|
|
118
132
|
async () => {
|
|
119
|
-
const currentRound = await this.proposer.read.getCurrentRound()
|
|
120
|
-
|
|
133
|
+
const currentRound = await this.proposer.read.getCurrentRound().catch(e => {
|
|
134
|
+
this.logger.error('Error getting current round', e);
|
|
135
|
+
return undefined;
|
|
136
|
+
});
|
|
137
|
+
return currentRound !== undefined && currentRound >= round;
|
|
121
138
|
},
|
|
122
139
|
`Waiting for round ${round} to be reached`,
|
|
123
140
|
0, // no timeout
|
|
124
141
|
pollingIntervalSeconds,
|
|
125
|
-
);
|
|
142
|
+
).catch(() => false);
|
|
126
143
|
}
|
|
127
144
|
|
|
128
145
|
public async executeRound(
|
package/src/test/start_anvil.ts
CHANGED
|
@@ -13,10 +13,12 @@ export async function startAnvil(
|
|
|
13
13
|
port?: number;
|
|
14
14
|
l1BlockTime?: number;
|
|
15
15
|
log?: boolean;
|
|
16
|
+
captureMethodCalls?: boolean;
|
|
16
17
|
} = {},
|
|
17
|
-
): Promise<{ anvil: Anvil; rpcUrl: string; stop: () => Promise<void> }> {
|
|
18
|
+
): Promise<{ anvil: Anvil; methodCalls?: string[]; rpcUrl: string; stop: () => Promise<void> }> {
|
|
18
19
|
const anvilBinary = resolve(dirname(fileURLToPath(import.meta.url)), '../../', 'scripts/anvil_kill_wrapper.sh');
|
|
19
20
|
const logger = opts.log ? createLogger('ethereum:anvil') : undefined;
|
|
21
|
+
const methodCalls = opts.captureMethodCalls ? ([] as string[]) : undefined;
|
|
20
22
|
|
|
21
23
|
let port: number | undefined;
|
|
22
24
|
|
|
@@ -35,12 +37,14 @@ export async function startAnvil(
|
|
|
35
37
|
// Listen to the anvil output to get the port.
|
|
36
38
|
const removeHandler = anvil.on('message', (message: string) => {
|
|
37
39
|
logger?.debug(message);
|
|
40
|
+
|
|
41
|
+
methodCalls?.push(...(message.match(/eth_[^\s]+/g) || []));
|
|
38
42
|
if (port === undefined && message.includes('Listening on')) {
|
|
39
43
|
port = parseInt(message.match(/Listening on ([^:]+):(\d+)/)![2]);
|
|
40
44
|
}
|
|
41
45
|
});
|
|
42
46
|
await anvil.start();
|
|
43
|
-
if (!logger) {
|
|
47
|
+
if (!logger && !opts.captureMethodCalls) {
|
|
44
48
|
removeHandler();
|
|
45
49
|
}
|
|
46
50
|
|
|
@@ -56,5 +60,5 @@ export async function startAnvil(
|
|
|
56
60
|
|
|
57
61
|
// Monkeypatch the anvil instance to include the actually assigned port
|
|
58
62
|
// Object.defineProperty(anvil, 'port', { value: port, writable: false });
|
|
59
|
-
return { anvil, stop: () => anvil.stop(), rpcUrl: `http://127.0.0.1:${port}` };
|
|
63
|
+
return { anvil, methodCalls, stop: () => anvil.stop(), rpcUrl: `http://127.0.0.1:${port}` };
|
|
60
64
|
}
|