@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.
Files changed (98) hide show
  1. package/dest/config.d.ts +22 -7
  2. package/dest/config.d.ts.map +1 -1
  3. package/dest/config.js +49 -14
  4. package/dest/contracts/empire_base.d.ts +12 -10
  5. package/dest/contracts/empire_base.d.ts.map +1 -1
  6. package/dest/contracts/empire_base.js +21 -16
  7. package/dest/contracts/governance.d.ts +4 -4
  8. package/dest/contracts/governance.js +2 -2
  9. package/dest/contracts/governance_proposer.d.ts +7 -7
  10. package/dest/contracts/governance_proposer.d.ts.map +1 -1
  11. package/dest/contracts/governance_proposer.js +13 -13
  12. package/dest/contracts/gse.d.ts +29 -0
  13. package/dest/contracts/gse.d.ts.map +1 -0
  14. package/dest/contracts/gse.js +56 -0
  15. package/dest/contracts/index.d.ts +1 -0
  16. package/dest/contracts/index.d.ts.map +1 -1
  17. package/dest/contracts/index.js +1 -0
  18. package/dest/contracts/multicall.d.ts +3 -1
  19. package/dest/contracts/multicall.d.ts.map +1 -1
  20. package/dest/contracts/multicall.js +11 -2
  21. package/dest/contracts/registry.d.ts +1 -0
  22. package/dest/contracts/registry.d.ts.map +1 -1
  23. package/dest/contracts/registry.js +3 -0
  24. package/dest/contracts/rollup.d.ts +39 -5
  25. package/dest/contracts/rollup.d.ts.map +1 -1
  26. package/dest/contracts/rollup.js +92 -14
  27. package/dest/contracts/slashing_proposer.d.ts +21 -10
  28. package/dest/contracts/slashing_proposer.d.ts.map +1 -1
  29. package/dest/contracts/slashing_proposer.js +43 -23
  30. package/dest/deploy_l1_contracts.d.ts +11 -36664
  31. package/dest/deploy_l1_contracts.d.ts.map +1 -1
  32. package/dest/deploy_l1_contracts.js +92 -177
  33. package/dest/index.d.ts +1 -1
  34. package/dest/index.d.ts.map +1 -1
  35. package/dest/index.js +1 -1
  36. package/dest/l1_artifacts.d.ts +51869 -0
  37. package/dest/l1_artifacts.d.ts.map +1 -0
  38. package/dest/l1_artifacts.js +141 -0
  39. package/dest/l1_tx_utils.d.ts +4 -2
  40. package/dest/l1_tx_utils.d.ts.map +1 -1
  41. package/dest/l1_tx_utils.js +46 -21
  42. package/dest/queries.d.ts +1 -8
  43. package/dest/queries.d.ts.map +1 -1
  44. package/dest/queries.js +20 -15
  45. package/dest/test/chain_monitor.d.ts +4 -2
  46. package/dest/test/chain_monitor.d.ts.map +1 -1
  47. package/dest/test/chain_monitor.js +12 -3
  48. package/dest/test/delayed_tx_utils.js +2 -2
  49. package/dest/{eth_cheat_codes.d.ts → test/eth_cheat_codes.d.ts} +8 -4
  50. package/dest/test/eth_cheat_codes.d.ts.map +1 -0
  51. package/dest/{eth_cheat_codes.js → test/eth_cheat_codes.js} +27 -11
  52. package/dest/test/eth_cheat_codes_with_state.d.ts +1 -1
  53. package/dest/test/eth_cheat_codes_with_state.d.ts.map +1 -1
  54. package/dest/test/eth_cheat_codes_with_state.js +1 -1
  55. package/dest/test/index.d.ts +2 -0
  56. package/dest/test/index.d.ts.map +1 -1
  57. package/dest/test/index.js +2 -0
  58. package/dest/test/rollup_cheat_codes.d.ts +81 -0
  59. package/dest/test/rollup_cheat_codes.d.ts.map +1 -0
  60. package/dest/test/rollup_cheat_codes.js +234 -0
  61. package/dest/test/start_anvil.d.ts +1 -0
  62. package/dest/test/start_anvil.d.ts.map +1 -1
  63. package/dest/test/start_anvil.js +6 -1
  64. package/dest/test/tx_delayer.d.ts +8 -1
  65. package/dest/test/tx_delayer.d.ts.map +1 -1
  66. package/dest/test/tx_delayer.js +51 -11
  67. package/dest/test/upgrade_utils.d.ts.map +1 -1
  68. package/dest/test/upgrade_utils.js +1 -1
  69. package/dest/utils.d.ts +1 -0
  70. package/dest/utils.d.ts.map +1 -1
  71. package/dest/utils.js +1 -1
  72. package/package.json +5 -5
  73. package/src/config.ts +62 -18
  74. package/src/contracts/empire_base.ts +28 -19
  75. package/src/contracts/governance.ts +2 -2
  76. package/src/contracts/governance_proposer.ts +23 -15
  77. package/src/contracts/gse.ts +73 -0
  78. package/src/contracts/index.ts +1 -0
  79. package/src/contracts/multicall.ts +8 -1
  80. package/src/contracts/registry.ts +4 -0
  81. package/src/contracts/rollup.ts +115 -9
  82. package/src/contracts/slashing_proposer.ts +55 -27
  83. package/src/deploy_l1_contracts.ts +151 -238
  84. package/src/index.ts +1 -1
  85. package/src/l1_artifacts.ts +216 -0
  86. package/src/l1_tx_utils.ts +52 -26
  87. package/src/queries.ts +20 -31
  88. package/src/test/chain_monitor.ts +9 -2
  89. package/src/test/delayed_tx_utils.ts +2 -2
  90. package/src/{eth_cheat_codes.ts → test/eth_cheat_codes.ts} +20 -14
  91. package/src/test/eth_cheat_codes_with_state.ts +1 -1
  92. package/src/test/index.ts +2 -0
  93. package/src/test/rollup_cheat_codes.ts +257 -0
  94. package/src/test/start_anvil.ts +9 -1
  95. package/src/test/tx_delayer.ts +55 -9
  96. package/src/test/upgrade_utils.ts +1 -1
  97. package/src/utils.ts +1 -1
  98. 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: false,
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).
@@ -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 { type Account, type GetContractReturnType, type Hex, encodeFunctionData, getAddress, getContract } from 'viem';
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
- getMinimumStake() {
174
- return this.rollup.read.getMinimumStake();
188
+ getEjectionThreshold() {
189
+ return this.rollup.read.getEjectionThreshold();
175
190
  }
176
191
 
177
192
  @memoize
178
- getDepositAmount() {
179
- return this.rollup.read.getDepositAmount();
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: 'validateHeader',
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, encodeVote, encodeVoteWithSignature, signVoteWithSig } from './empire_base.js';
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.N();
44
+ return this.proposer.read.QUORUM_SIZE();
42
45
  }
43
46
 
44
47
  public getRoundSize() {
45
- return this.proposer.read.M();
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<{ lastVote: bigint; leader: Hex; executed: boolean }> {
74
+ ): Promise<{ lastSignalSlot: bigint; payloadWithMostSignals: Hex; executed: boolean }> {
60
75
  return await this.proposer.read.getRoundData([rollupAddress, round]);
61
76
  }
62
77
 
63
- public getProposalVotes(rollupAddress: Hex, round: bigint, proposal: Hex): Promise<bigint> {
64
- return this.proposer.read.yeaCount([rollupAddress, round, proposal]);
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 createVoteRequest(payload: Hex): L1TxRequest {
82
+ public createSignalRequest(payload: Hex): L1TxRequest {
68
83
  return {
69
84
  to: this.address.toString(),
70
- data: encodeVote(payload),
85
+ data: encodeSignal(payload),
71
86
  };
72
87
  }
73
88
 
74
- public async createVoteRequestWithSignature(
89
+ public async createSignalRequestWithSignature(
75
90
  payload: Hex,
91
+ round: bigint,
76
92
  chainId: number,
77
93
  signerAddress: Hex,
78
- signer: (msg: Hex) => Promise<Hex>,
94
+ signer: (msg: TypedDataDefinition) => Promise<Hex>,
79
95
  ): Promise<L1TxRequest> {
80
96
  const nonce = await this.getNonce(signerAddress);
81
- const signature = await signVoteWithSig(signer, payload, nonce, this.address.toString(), chainId);
97
+ const signature = await signSignalWithSig(signer, payload, nonce, round, this.address.toString(), chainId);
82
98
  return {
83
99
  to: this.address.toString(),
84
- data: encodeVoteWithSignature(payload, signature),
100
+ data: encodeSignalWithSignature(payload, signature),
85
101
  };
86
102
  }
87
103
 
88
- public listenToExecutableProposals(callback: (args: { proposal: `0x${string}`; round: bigint }) => unknown) {
89
- return this.proposer.watchEvent.ProposalExecutable(
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.proposal && args.round) {
111
+ if (args.payload && args.round) {
96
112
  // why compiler can't figure it out? no one knows
97
- callback(args as { proposal: `0x${string}`; round: bigint });
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 listenToProposalExecuted(callback: (args: { round: bigint; proposal: `0x${string}` }) => unknown) {
106
- return this.proposer.watchEvent.ProposalExecuted(
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.proposal) {
113
- callback(args as { round: bigint; proposal: `0x${string}` });
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
- public waitForRound(round: bigint, pollingIntervalSeconds: number = 1) {
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
- return currentRound >= round;
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, 'executeProposal'> = {
166
+ const args: EncodeFunctionDataParameters<typeof SlashingProposerAbi, 'submitRoundWinner'> = {
141
167
  abi: SlashingProposerAbi,
142
- functionName: 'executeProposal',
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: ${error ?? 'Unknown 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;