@aztec/ethereum 1.2.1 → 2.0.0-nightly.20250813
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 +22 -7
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +49 -14
- package/dest/contracts/empire_base.d.ts +12 -10
- package/dest/contracts/empire_base.d.ts.map +1 -1
- package/dest/contracts/empire_base.js +21 -16
- package/dest/contracts/governance.d.ts +4 -4
- package/dest/contracts/governance.js +2 -2
- package/dest/contracts/governance_proposer.d.ts +7 -7
- package/dest/contracts/governance_proposer.d.ts.map +1 -1
- package/dest/contracts/governance_proposer.js +13 -13
- package/dest/contracts/gse.d.ts +29 -0
- package/dest/contracts/gse.d.ts.map +1 -0
- package/dest/contracts/gse.js +56 -0
- package/dest/contracts/index.d.ts +1 -0
- package/dest/contracts/index.d.ts.map +1 -1
- package/dest/contracts/index.js +1 -0
- package/dest/contracts/multicall.d.ts +3 -1
- package/dest/contracts/multicall.d.ts.map +1 -1
- package/dest/contracts/multicall.js +11 -2
- package/dest/contracts/registry.d.ts +1 -0
- package/dest/contracts/registry.d.ts.map +1 -1
- package/dest/contracts/registry.js +3 -0
- package/dest/contracts/rollup.d.ts +39 -5
- package/dest/contracts/rollup.d.ts.map +1 -1
- package/dest/contracts/rollup.js +92 -14
- package/dest/contracts/slashing_proposer.d.ts +21 -10
- package/dest/contracts/slashing_proposer.d.ts.map +1 -1
- package/dest/contracts/slashing_proposer.js +43 -23
- package/dest/deploy_l1_contracts.d.ts +11 -36664
- package/dest/deploy_l1_contracts.d.ts.map +1 -1
- package/dest/deploy_l1_contracts.js +92 -177
- package/dest/index.d.ts +1 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -1
- package/dest/l1_artifacts.d.ts +51869 -0
- package/dest/l1_artifacts.d.ts.map +1 -0
- package/dest/l1_artifacts.js +141 -0
- package/dest/l1_tx_utils.d.ts +4 -2
- package/dest/l1_tx_utils.d.ts.map +1 -1
- package/dest/l1_tx_utils.js +46 -21
- package/dest/queries.d.ts +1 -8
- package/dest/queries.d.ts.map +1 -1
- package/dest/queries.js +20 -15
- package/dest/test/chain_monitor.d.ts +4 -2
- package/dest/test/chain_monitor.d.ts.map +1 -1
- package/dest/test/chain_monitor.js +12 -3
- package/dest/test/delayed_tx_utils.js +2 -2
- package/dest/{eth_cheat_codes.d.ts → test/eth_cheat_codes.d.ts} +8 -4
- package/dest/test/eth_cheat_codes.d.ts.map +1 -0
- package/dest/{eth_cheat_codes.js → test/eth_cheat_codes.js} +27 -11
- package/dest/test/eth_cheat_codes_with_state.d.ts +1 -1
- package/dest/test/eth_cheat_codes_with_state.d.ts.map +1 -1
- package/dest/test/eth_cheat_codes_with_state.js +1 -1
- package/dest/test/index.d.ts +2 -0
- package/dest/test/index.d.ts.map +1 -1
- package/dest/test/index.js +2 -0
- package/dest/test/rollup_cheat_codes.d.ts +81 -0
- package/dest/test/rollup_cheat_codes.d.ts.map +1 -0
- package/dest/test/rollup_cheat_codes.js +234 -0
- package/dest/test/start_anvil.d.ts +1 -0
- package/dest/test/start_anvil.d.ts.map +1 -1
- package/dest/test/start_anvil.js +6 -1
- package/dest/test/tx_delayer.d.ts +8 -1
- package/dest/test/tx_delayer.d.ts.map +1 -1
- package/dest/test/tx_delayer.js +51 -11
- package/dest/test/upgrade_utils.d.ts.map +1 -1
- package/dest/test/upgrade_utils.js +1 -1
- package/dest/utils.d.ts +1 -0
- package/dest/utils.d.ts.map +1 -1
- package/dest/utils.js +1 -1
- package/package.json +5 -5
- package/src/config.ts +62 -18
- package/src/contracts/empire_base.ts +28 -19
- package/src/contracts/governance.ts +2 -2
- package/src/contracts/governance_proposer.ts +23 -15
- package/src/contracts/gse.ts +73 -0
- package/src/contracts/index.ts +1 -0
- package/src/contracts/multicall.ts +8 -1
- package/src/contracts/registry.ts +4 -0
- package/src/contracts/rollup.ts +115 -9
- package/src/contracts/slashing_proposer.ts +55 -27
- package/src/deploy_l1_contracts.ts +151 -238
- package/src/index.ts +1 -1
- package/src/l1_artifacts.ts +216 -0
- package/src/l1_tx_utils.ts +52 -26
- package/src/queries.ts +20 -31
- package/src/test/chain_monitor.ts +9 -2
- package/src/test/delayed_tx_utils.ts +2 -2
- package/src/{eth_cheat_codes.ts → test/eth_cheat_codes.ts} +20 -14
- package/src/test/eth_cheat_codes_with_state.ts +1 -1
- package/src/test/index.ts +2 -0
- package/src/test/rollup_cheat_codes.ts +257 -0
- package/src/test/start_anvil.ts +9 -1
- package/src/test/tx_delayer.ts +55 -9
- package/src/test/upgrade_utils.ts +1 -1
- package/src/utils.ts +1 -1
- package/dest/eth_cheat_codes.d.ts.map +0 -1
|
@@ -18,12 +18,13 @@ export class Multicall3 {
|
|
|
18
18
|
blobConfig: L1BlobInputs | undefined,
|
|
19
19
|
rollupAddress: Hex,
|
|
20
20
|
logger: Logger,
|
|
21
|
+
opts: { revertOnFailure?: boolean } = {},
|
|
21
22
|
) {
|
|
22
23
|
requests = requests.filter(request => request.to !== null);
|
|
23
24
|
const args = requests.map(r => ({
|
|
24
25
|
target: r.to!,
|
|
25
26
|
callData: r.data!,
|
|
26
|
-
allowFailure:
|
|
27
|
+
allowFailure: !opts.revertOnFailure,
|
|
27
28
|
}));
|
|
28
29
|
const forwarderFunctionData: Required<EncodeFunctionDataParameters<typeof multicall3Abi, 'aggregate3'>> = {
|
|
29
30
|
abi: multicall3Abi,
|
|
@@ -119,6 +120,12 @@ export class Multicall3 {
|
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
export async function deployMulticall3(l1Client: ExtendedViemWalletClient, logger: Logger) {
|
|
123
|
+
const existing = await l1Client.getCode({ address: MULTI_CALL_3_ADDRESS });
|
|
124
|
+
if (existing && existing !== '0x') {
|
|
125
|
+
logger.verbose('Multicall3 already deployed', { address: MULTI_CALL_3_ADDRESS });
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
122
129
|
const deployer = '0x05f32b3cc3888453ff71b01135b34ff8e41263f2';
|
|
123
130
|
const sendEth = await l1Client.sendTransaction({ to: deployer, value: 10n ** 17n });
|
|
124
131
|
logger.info('Sent 0.1 ETH to deployer', { deployer, value: 10n ** 17n });
|
|
@@ -27,6 +27,10 @@ export class RegistryContract {
|
|
|
27
27
|
this.registry = getContract({ address, abi: RegistryAbi, client });
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
public async getOwner(): Promise<EthAddress> {
|
|
31
|
+
return EthAddress.fromString(await this.registry.read.owner());
|
|
32
|
+
}
|
|
33
|
+
|
|
30
34
|
/**
|
|
31
35
|
* Returns the address of the rollup for a given version.
|
|
32
36
|
* @param version - The version of the rollup. 'canonical' can be used to get the canonical address (i.e. the latest version).
|
package/src/contracts/rollup.ts
CHANGED
|
@@ -5,13 +5,23 @@ import { RollupAbi } from '@aztec/l1-artifacts/RollupAbi';
|
|
|
5
5
|
import { RollupStorage } from '@aztec/l1-artifacts/RollupStorage';
|
|
6
6
|
import { SlasherAbi } from '@aztec/l1-artifacts/SlasherAbi';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
type Account,
|
|
10
|
+
type GetContractReturnType,
|
|
11
|
+
type Hex,
|
|
12
|
+
type StateOverride,
|
|
13
|
+
encodeFunctionData,
|
|
14
|
+
getAddress,
|
|
15
|
+
getContract,
|
|
16
|
+
hexToBigInt,
|
|
17
|
+
keccak256,
|
|
18
|
+
} from 'viem';
|
|
9
19
|
|
|
10
20
|
import { getPublicClient } from '../client.js';
|
|
11
21
|
import type { DeployL1ContractsReturnType } from '../deploy_l1_contracts.js';
|
|
12
22
|
import type { L1ContractAddresses } from '../l1_contract_addresses.js';
|
|
13
23
|
import type { L1ReaderConfig } from '../l1_reader.js';
|
|
14
|
-
import type { L1TxUtils } from '../l1_tx_utils.js';
|
|
24
|
+
import type { L1TxRequest, L1TxUtils } from '../l1_tx_utils.js';
|
|
15
25
|
import type { ViemClient } from '../types.js';
|
|
16
26
|
import { formatViemError } from '../utils.js';
|
|
17
27
|
import { SlashingProposerContract } from './slashing_proposer.js';
|
|
@@ -87,6 +97,8 @@ export type ViemAppendOnlyTreeSnapshot = {
|
|
|
87
97
|
export class RollupContract {
|
|
88
98
|
private readonly rollup: GetContractReturnType<typeof RollupAbi, ViemClient>;
|
|
89
99
|
|
|
100
|
+
private static cachedStfStorageSlot: Hex | undefined;
|
|
101
|
+
|
|
90
102
|
static get checkBlobStorageSlot(): bigint {
|
|
91
103
|
const asString = RollupStorage.find(storage => storage.label === 'checkBlob')?.slot;
|
|
92
104
|
if (asString === undefined) {
|
|
@@ -95,6 +107,10 @@ export class RollupContract {
|
|
|
95
107
|
return BigInt(asString);
|
|
96
108
|
}
|
|
97
109
|
|
|
110
|
+
static get stfStorageSlot(): Hex {
|
|
111
|
+
return (RollupContract.cachedStfStorageSlot ??= keccak256(Buffer.from('aztec.stf.storage', 'utf-8')));
|
|
112
|
+
}
|
|
113
|
+
|
|
98
114
|
static getFromL1ContractsValues(deployL1ContractsValues: DeployL1ContractsReturnType) {
|
|
99
115
|
const {
|
|
100
116
|
l1Client,
|
|
@@ -131,7 +147,6 @@ export class RollupContract {
|
|
|
131
147
|
return this.rollup;
|
|
132
148
|
}
|
|
133
149
|
|
|
134
|
-
@memoize
|
|
135
150
|
public async getSlashingProposer() {
|
|
136
151
|
const slasherAddress = await this.rollup.read.getSlasher();
|
|
137
152
|
const slasher = getContract({ address: slasherAddress, abi: SlasherAbi, client: this.client });
|
|
@@ -170,13 +185,13 @@ export class RollupContract {
|
|
|
170
185
|
}
|
|
171
186
|
|
|
172
187
|
@memoize
|
|
173
|
-
|
|
174
|
-
return this.rollup.read.
|
|
188
|
+
getEjectionThreshold() {
|
|
189
|
+
return this.rollup.read.getEjectionThreshold();
|
|
175
190
|
}
|
|
176
191
|
|
|
177
192
|
@memoize
|
|
178
|
-
|
|
179
|
-
return this.rollup.read.
|
|
193
|
+
getActivationThreshold() {
|
|
194
|
+
return this.rollup.read.getActivationThreshold();
|
|
180
195
|
}
|
|
181
196
|
|
|
182
197
|
@memoize
|
|
@@ -219,6 +234,10 @@ export class RollupContract {
|
|
|
219
234
|
return this.rollup.read.getSlasher();
|
|
220
235
|
}
|
|
221
236
|
|
|
237
|
+
getOwner() {
|
|
238
|
+
return this.rollup.read.owner();
|
|
239
|
+
}
|
|
240
|
+
|
|
222
241
|
public async getSlashingProposerAddress() {
|
|
223
242
|
const slasherAddress = await this.getSlasher();
|
|
224
243
|
const slasher = getContract({
|
|
@@ -229,6 +248,10 @@ export class RollupContract {
|
|
|
229
248
|
return EthAddress.fromString(await slasher.read.PROPOSER());
|
|
230
249
|
}
|
|
231
250
|
|
|
251
|
+
getBlockReward() {
|
|
252
|
+
return this.rollup.read.getBlockReward();
|
|
253
|
+
}
|
|
254
|
+
|
|
232
255
|
getBlockNumber() {
|
|
233
256
|
return this.rollup.read.getPendingBlockNumber();
|
|
234
257
|
}
|
|
@@ -387,6 +410,7 @@ export class RollupContract {
|
|
|
387
410
|
args: readonly [
|
|
388
411
|
ViemHeader,
|
|
389
412
|
ViemCommitteeAttestations,
|
|
413
|
+
`0x${string}`[],
|
|
390
414
|
`0x${string}`,
|
|
391
415
|
`0x${string}`,
|
|
392
416
|
{
|
|
@@ -400,7 +424,7 @@ export class RollupContract {
|
|
|
400
424
|
await this.client.simulateContract({
|
|
401
425
|
address: this.address,
|
|
402
426
|
abi: RollupAbi,
|
|
403
|
-
functionName: '
|
|
427
|
+
functionName: 'validateHeaderWithAttestations',
|
|
404
428
|
args,
|
|
405
429
|
account,
|
|
406
430
|
});
|
|
@@ -493,12 +517,14 @@ export class RollupContract {
|
|
|
493
517
|
archive: Buffer,
|
|
494
518
|
account: `0x${string}` | Account,
|
|
495
519
|
slotDuration: bigint | number,
|
|
520
|
+
opts: { forcePendingBlockNumber?: number } = {},
|
|
496
521
|
): Promise<{ slot: bigint; blockNumber: bigint; timeOfNextL1Slot: bigint }> {
|
|
497
522
|
if (typeof slotDuration === 'number') {
|
|
498
523
|
slotDuration = BigInt(slotDuration);
|
|
499
524
|
}
|
|
500
525
|
const latestBlock = await this.client.getBlock();
|
|
501
526
|
const timeOfNextL1Slot = latestBlock.timestamp + slotDuration;
|
|
527
|
+
const who = typeof account === 'string' ? account : account.address;
|
|
502
528
|
|
|
503
529
|
try {
|
|
504
530
|
const {
|
|
@@ -507,8 +533,9 @@ export class RollupContract {
|
|
|
507
533
|
address: this.address,
|
|
508
534
|
abi: RollupAbi,
|
|
509
535
|
functionName: 'canProposeAtTime',
|
|
510
|
-
args: [timeOfNextL1Slot, `0x${archive.toString('hex')}
|
|
536
|
+
args: [timeOfNextL1Slot, `0x${archive.toString('hex')}`, who],
|
|
511
537
|
account,
|
|
538
|
+
stateOverride: await this.makePendingBlockNumberOverride(opts.forcePendingBlockNumber),
|
|
512
539
|
});
|
|
513
540
|
|
|
514
541
|
return { slot, blockNumber, timeOfNextL1Slot };
|
|
@@ -517,6 +544,69 @@ export class RollupContract {
|
|
|
517
544
|
}
|
|
518
545
|
}
|
|
519
546
|
|
|
547
|
+
/**
|
|
548
|
+
* Returns a state override that sets the pending block number to the specified value. Useful for simulations.
|
|
549
|
+
* Requires querying the current state of the contract to get the current proven block number, as they are both
|
|
550
|
+
* stored in the same slot. If the argument is undefined, it returns an empty override.
|
|
551
|
+
*/
|
|
552
|
+
public async makePendingBlockNumberOverride(forcePendingBlockNumber: number | undefined): Promise<StateOverride> {
|
|
553
|
+
if (forcePendingBlockNumber === undefined) {
|
|
554
|
+
return [];
|
|
555
|
+
}
|
|
556
|
+
const slot = RollupContract.stfStorageSlot;
|
|
557
|
+
const currentValue = await this.client.getStorageAt({ address: this.address, slot });
|
|
558
|
+
const currentProvenBlockNumber = currentValue ? hexToBigInt(currentValue) & ((1n << 128n) - 1n) : 0n;
|
|
559
|
+
const newValue = (BigInt(forcePendingBlockNumber) << 128n) | currentProvenBlockNumber;
|
|
560
|
+
return [
|
|
561
|
+
{
|
|
562
|
+
address: this.address,
|
|
563
|
+
stateDiff: [{ slot, value: `0x${newValue.toString(16).padStart(64, '0')}` }],
|
|
564
|
+
},
|
|
565
|
+
];
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/** Creates a request to Rollup#invalidateBadAttestation to be simulated or sent */
|
|
569
|
+
public buildInvalidateBadAttestationRequest(
|
|
570
|
+
blockNumber: number,
|
|
571
|
+
attestations: ViemCommitteeAttestation[],
|
|
572
|
+
committee: EthAddress[],
|
|
573
|
+
invalidIndex: number,
|
|
574
|
+
): L1TxRequest {
|
|
575
|
+
return {
|
|
576
|
+
to: this.address,
|
|
577
|
+
data: encodeFunctionData({
|
|
578
|
+
abi: RollupAbi,
|
|
579
|
+
functionName: 'invalidateBadAttestation',
|
|
580
|
+
args: [
|
|
581
|
+
BigInt(blockNumber),
|
|
582
|
+
RollupContract.packAttestations(attestations),
|
|
583
|
+
committee.map(addr => addr.toString()),
|
|
584
|
+
BigInt(invalidIndex),
|
|
585
|
+
],
|
|
586
|
+
}),
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/** Creates a request to Rollup#invalidateInsufficientAttestations to be simulated or sent */
|
|
591
|
+
public buildInvalidateInsufficientAttestationsRequest(
|
|
592
|
+
blockNumber: number,
|
|
593
|
+
attestations: ViemCommitteeAttestation[],
|
|
594
|
+
committee: EthAddress[],
|
|
595
|
+
): L1TxRequest {
|
|
596
|
+
return {
|
|
597
|
+
to: this.address,
|
|
598
|
+
data: encodeFunctionData({
|
|
599
|
+
abi: RollupAbi,
|
|
600
|
+
functionName: 'invalidateInsufficientAttestations',
|
|
601
|
+
args: [
|
|
602
|
+
BigInt(blockNumber),
|
|
603
|
+
RollupContract.packAttestations(attestations),
|
|
604
|
+
committee.map(addr => addr.toString()),
|
|
605
|
+
],
|
|
606
|
+
}),
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
|
|
520
610
|
/** Calls getHasSubmitted directly. Returns whether the given prover has submitted a proof with the given length for the given epoch. */
|
|
521
611
|
public getHasSubmittedProof(epochNumber: number, numberOfBlocksInEpoch: number, prover: Hex | EthAddress) {
|
|
522
612
|
if (prover instanceof EthAddress) {
|
|
@@ -616,4 +706,20 @@ export class RollupContract {
|
|
|
616
706
|
}),
|
|
617
707
|
});
|
|
618
708
|
}
|
|
709
|
+
|
|
710
|
+
public listenToSlasherChanged(callback: (args: { oldSlasher: `0x${string}`; newSlasher: `0x${string}` }) => unknown) {
|
|
711
|
+
return this.rollup.watchEvent.SlasherUpdated(
|
|
712
|
+
{},
|
|
713
|
+
{
|
|
714
|
+
onLogs: logs => {
|
|
715
|
+
for (const log of logs) {
|
|
716
|
+
const args = log.args;
|
|
717
|
+
if (args.oldSlasher && args.newSlasher) {
|
|
718
|
+
callback(args as { oldSlasher: `0x${string}`; newSlasher: `0x${string}` });
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
},
|
|
722
|
+
},
|
|
723
|
+
);
|
|
724
|
+
}
|
|
619
725
|
}
|
|
@@ -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
|
|
|
@@ -7,6 +8,7 @@ import {
|
|
|
7
8
|
type EncodeFunctionDataParameters,
|
|
8
9
|
type GetContractReturnType,
|
|
9
10
|
type Hex,
|
|
11
|
+
type TypedDataDefinition,
|
|
10
12
|
encodeFunctionData,
|
|
11
13
|
getContract,
|
|
12
14
|
} from 'viem';
|
|
@@ -14,7 +16,7 @@ import {
|
|
|
14
16
|
import type { L1TxRequest, L1TxUtils } from '../l1_tx_utils.js';
|
|
15
17
|
import type { ViemClient } from '../types.js';
|
|
16
18
|
import { FormattedViemError } from '../utils.js';
|
|
17
|
-
import { type IEmpireBase,
|
|
19
|
+
import { type IEmpireBase, encodeSignal, encodeSignalWithSignature, signSignalWithSig } from './empire_base.js';
|
|
18
20
|
|
|
19
21
|
export class ProposalAlreadyExecutedError extends Error {
|
|
20
22
|
constructor(round: bigint) {
|
|
@@ -23,6 +25,7 @@ export class ProposalAlreadyExecutedError extends Error {
|
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
export class SlashingProposerContract extends EventEmitter implements IEmpireBase {
|
|
28
|
+
private readonly logger = createLogger('SlashingProposerContract');
|
|
26
29
|
private readonly proposer: GetContractReturnType<typeof SlashingProposerAbi, ViemClient>;
|
|
27
30
|
|
|
28
31
|
constructor(
|
|
@@ -38,11 +41,23 @@ export class SlashingProposerContract extends EventEmitter implements IEmpireBas
|
|
|
38
41
|
}
|
|
39
42
|
|
|
40
43
|
public getQuorumSize() {
|
|
41
|
-
return this.proposer.read.
|
|
44
|
+
return this.proposer.read.QUORUM_SIZE();
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
public getRoundSize() {
|
|
45
|
-
return this.proposer.read.
|
|
48
|
+
return this.proposer.read.ROUND_SIZE();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public getLifetimeInRounds() {
|
|
52
|
+
return this.proposer.read.LIFETIME_IN_ROUNDS();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public getExecutionDelayInRounds() {
|
|
56
|
+
return this.proposer.read.EXECUTION_DELAY_IN_ROUNDS();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public getCurrentRound() {
|
|
60
|
+
return this.proposer.read.getCurrentRound();
|
|
46
61
|
}
|
|
47
62
|
|
|
48
63
|
public computeRound(slot: bigint): Promise<bigint> {
|
|
@@ -56,45 +71,46 @@ export class SlashingProposerContract extends EventEmitter implements IEmpireBas
|
|
|
56
71
|
public async getRoundInfo(
|
|
57
72
|
rollupAddress: Hex,
|
|
58
73
|
round: bigint,
|
|
59
|
-
): Promise<{
|
|
74
|
+
): Promise<{ lastSignalSlot: bigint; payloadWithMostSignals: Hex; executed: boolean }> {
|
|
60
75
|
return await this.proposer.read.getRoundData([rollupAddress, round]);
|
|
61
76
|
}
|
|
62
77
|
|
|
63
|
-
public
|
|
64
|
-
return this.proposer.read.
|
|
78
|
+
public getPayloadSignals(rollupAddress: Hex, round: bigint, payload: Hex): Promise<bigint> {
|
|
79
|
+
return this.proposer.read.signalCount([rollupAddress, round, payload]);
|
|
65
80
|
}
|
|
66
81
|
|
|
67
|
-
public
|
|
82
|
+
public createSignalRequest(payload: Hex): L1TxRequest {
|
|
68
83
|
return {
|
|
69
84
|
to: this.address.toString(),
|
|
70
|
-
data:
|
|
85
|
+
data: encodeSignal(payload),
|
|
71
86
|
};
|
|
72
87
|
}
|
|
73
88
|
|
|
74
|
-
public async
|
|
89
|
+
public async createSignalRequestWithSignature(
|
|
75
90
|
payload: Hex,
|
|
91
|
+
round: bigint,
|
|
76
92
|
chainId: number,
|
|
77
93
|
signerAddress: Hex,
|
|
78
|
-
signer: (msg:
|
|
94
|
+
signer: (msg: TypedDataDefinition) => Promise<Hex>,
|
|
79
95
|
): Promise<L1TxRequest> {
|
|
80
96
|
const nonce = await this.getNonce(signerAddress);
|
|
81
|
-
const signature = await
|
|
97
|
+
const signature = await signSignalWithSig(signer, payload, nonce, round, this.address.toString(), chainId);
|
|
82
98
|
return {
|
|
83
99
|
to: this.address.toString(),
|
|
84
|
-
data:
|
|
100
|
+
data: encodeSignalWithSignature(payload, signature),
|
|
85
101
|
};
|
|
86
102
|
}
|
|
87
103
|
|
|
88
|
-
public
|
|
89
|
-
return this.proposer.watchEvent.
|
|
104
|
+
public listenToSubmittablePayloads(callback: (args: { payload: `0x${string}`; round: bigint }) => unknown) {
|
|
105
|
+
return this.proposer.watchEvent.PayloadSubmittable(
|
|
90
106
|
{},
|
|
91
107
|
{
|
|
92
108
|
onLogs: logs => {
|
|
93
109
|
for (const payload of logs) {
|
|
94
110
|
const args = payload.args;
|
|
95
|
-
if (args.
|
|
111
|
+
if (args.payload && args.round) {
|
|
96
112
|
// why compiler can't figure it out? no one knows
|
|
97
|
-
callback(args as {
|
|
113
|
+
callback(args as { payload: `0x${string}`; round: bigint });
|
|
98
114
|
}
|
|
99
115
|
}
|
|
100
116
|
},
|
|
@@ -102,15 +118,15 @@ export class SlashingProposerContract extends EventEmitter implements IEmpireBas
|
|
|
102
118
|
);
|
|
103
119
|
}
|
|
104
120
|
|
|
105
|
-
public
|
|
106
|
-
return this.proposer.watchEvent.
|
|
121
|
+
public listenToPayloadSubmitted(callback: (args: { round: bigint; payload: `0x${string}` }) => unknown) {
|
|
122
|
+
return this.proposer.watchEvent.PayloadSubmitted(
|
|
107
123
|
{},
|
|
108
124
|
{
|
|
109
125
|
onLogs: logs => {
|
|
110
126
|
for (const payload of logs) {
|
|
111
127
|
const args = payload.args;
|
|
112
|
-
if (args.round && args.
|
|
113
|
-
callback(args as { round: bigint;
|
|
128
|
+
if (args.round && args.payload) {
|
|
129
|
+
callback(args as { round: bigint; payload: `0x${string}` });
|
|
114
130
|
}
|
|
115
131
|
}
|
|
116
132
|
},
|
|
@@ -118,16 +134,26 @@ export class SlashingProposerContract extends EventEmitter implements IEmpireBas
|
|
|
118
134
|
);
|
|
119
135
|
}
|
|
120
136
|
|
|
121
|
-
|
|
137
|
+
/**
|
|
138
|
+
* Wait for a round to be reached.
|
|
139
|
+
*
|
|
140
|
+
* @param round - The round to wait for.
|
|
141
|
+
* @param pollingIntervalSeconds - The interval in seconds to poll for the round.
|
|
142
|
+
* @returns True if the round was reached, false otherwise.
|
|
143
|
+
*/
|
|
144
|
+
public waitForRound(round: bigint, pollingIntervalSeconds: number = 1): Promise<boolean> {
|
|
122
145
|
return retryUntil(
|
|
123
146
|
async () => {
|
|
124
|
-
const currentRound = await this.proposer.read.getCurrentRound()
|
|
125
|
-
|
|
147
|
+
const currentRound = await this.proposer.read.getCurrentRound().catch(e => {
|
|
148
|
+
this.logger.error('Error getting current round', e);
|
|
149
|
+
return undefined;
|
|
150
|
+
});
|
|
151
|
+
return currentRound !== undefined && currentRound >= round;
|
|
126
152
|
},
|
|
127
153
|
`Waiting for round ${round} to be reached`,
|
|
128
154
|
0, // no timeout
|
|
129
155
|
pollingIntervalSeconds,
|
|
130
|
-
);
|
|
156
|
+
).catch(() => false);
|
|
131
157
|
}
|
|
132
158
|
|
|
133
159
|
public async executeRound(
|
|
@@ -137,9 +163,9 @@ export class SlashingProposerContract extends EventEmitter implements IEmpireBas
|
|
|
137
163
|
if (typeof round === 'number') {
|
|
138
164
|
round = BigInt(round);
|
|
139
165
|
}
|
|
140
|
-
const args: EncodeFunctionDataParameters<typeof SlashingProposerAbi, '
|
|
166
|
+
const args: EncodeFunctionDataParameters<typeof SlashingProposerAbi, 'submitRoundWinner'> = {
|
|
141
167
|
abi: SlashingProposerAbi,
|
|
142
|
-
functionName: '
|
|
168
|
+
functionName: 'submitRoundWinner',
|
|
143
169
|
args: [round],
|
|
144
170
|
};
|
|
145
171
|
const data = encodeFunctionData(args);
|
|
@@ -175,7 +201,9 @@ export class SlashingProposerContract extends EventEmitter implements IEmpireBas
|
|
|
175
201
|
if (error?.includes('ProposalAlreadyExecuted')) {
|
|
176
202
|
throw new ProposalAlreadyExecutedError(round);
|
|
177
203
|
}
|
|
178
|
-
const errorMessage = `Failed to execute round ${round}, TxHash: ${response.receipt.transactionHash}, Error: ${
|
|
204
|
+
const errorMessage = `Failed to execute round ${round}, TxHash: ${response.receipt.transactionHash}, Error: ${
|
|
205
|
+
error ?? 'Unknown error'
|
|
206
|
+
}`;
|
|
179
207
|
throw new Error(errorMessage);
|
|
180
208
|
}
|
|
181
209
|
return response;
|