Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit bfaefd2

Browse files
committedJun 19, 2024·
chore: keeper bot script
1 parent a22ade0 commit bfaefd2

File tree

6 files changed

+76
-71
lines changed

6 files changed

+76
-71
lines changed
 

‎contracts/scripts/deploy.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ async function main() {
1717
const ConstantRNG = await ethers.getContractFactory("ConstantNG");
1818
const constantRNG = await ConstantRNG.deploy(42);
1919

20-
await constantRNG.deployed();
20+
await constantRNG.deploymentTransaction();
2121

22-
console.log("ConstantRNG deployed to:", constantRNG.address);
22+
console.log("ConstantRNG deployed to:", constantRNG.target);
2323
}
2424

2525
// We recommend this pattern to be able to use async/await everywhere

‎contracts/scripts/disputeCreatorBot.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import env from "./utils/env";
22
import loggerFactory from "./utils/logger";
33
import hre = require("hardhat");
44
import { KlerosCore, DisputeResolver } from "../typechain-types";
5-
import { BigNumber } from "ethers";
5+
66
const { ethers } = hre;
77

88
const HEARTBEAT_URL = env.optionalNoDefault("HEARTBEAT_URL_DISPUTOR_BOT");
@@ -43,7 +43,7 @@ export default async function main() {
4343
];
4444
const randomTemplate = templates[Math.floor(Math.random() * templates.length)];
4545
const nbOfChoices = 2;
46-
const cost = (await core.functions["arbitrationCost(bytes)"](extraData)).cost;
46+
const cost = await core["arbitrationCost(bytes)"](extraData);
4747
const tx = await resolver.createDisputeForTemplate(
4848
extraData,
4949
randomTemplate,
@@ -55,10 +55,10 @@ export default async function main() {
5555
);
5656

5757
logger.info(`Dispute creation tx: ${tx.hash}`);
58-
const blockNumber = await tx.wait().then((receipt) => receipt.blockNumber);
58+
const blockNumber = await tx.wait().then((receipt) => receipt?.blockNumber);
5959
const disputeId = await resolver
6060
.queryFilter(resolver.filters.DisputeRequest(), blockNumber, blockNumber)
61-
.then((events) => BigNumber.from(events[0].args[1]));
61+
.then((events) => ethers.toBigInt(events[0].args[1]));
6262
logger.info(`Dispute created with disputeId ${disputeId.toString()}`);
6363

6464
logger.info("Shutting down");

‎contracts/scripts/getCourtsV1.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const configByChain = new Map<number, Config>([
3737

3838
async function main() {
3939
const chainId = Number(await hre.getChainId());
40-
const courtAddress = configByChain.get(chainId)?.courtAddress ?? hre.ethers.constants.AddressZero;
40+
const courtAddress = configByChain.get(chainId)?.courtAddress ?? hre.ethers.ZeroAddress;
4141
const courtsV1 = (await ethers.getContractAt("IKlerosLiquid", courtAddress)) as IKlerosLiquid;
4242

4343
const courts: Court[] = [];
@@ -47,7 +47,7 @@ async function main() {
4747
(result) =>
4848
({
4949
id: courtId,
50-
parent: result.parent.toNumber(),
50+
parent: ethers.getNumber(result.parent),
5151
hiddenVotes: result.hiddenVotes,
5252
minStake: result.minStake.toString(),
5353
alpha: result.alpha.toString(),
@@ -58,7 +58,7 @@ async function main() {
5858
);
5959

6060
court.timesPerPeriod = await courtsV1.getSubcourt(courtId).then((result) => {
61-
return result.timesPerPeriod.map((bn) => bn.toNumber());
61+
return result.timesPerPeriod.map((bn) => ethers.getNumber(bn));
6262
});
6363

6464
court.id = courtId;

‎contracts/scripts/getPoliciesV1.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const policyRegistryByChain = new Map<number, string>([
1818

1919
async function main() {
2020
const chainId = Number(await hre.getChainId());
21-
const policyRegistryAddress = policyRegistryByChain.get(chainId) ?? hre.ethers.constants.AddressZero;
21+
const policyRegistryAddress = policyRegistryByChain.get(chainId) ?? hre.ethers.ZeroAddress;
2222
const policyRegistryV1 = await ethers.getContractAt("PolicyRegistry", policyRegistryAddress);
2323

2424
const fetchPolicy = (url: string): Promise<Policy> => {

‎contracts/scripts/keeperBot.ts

Lines changed: 65 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { DisputeKitClassic, KlerosCore, PNK, RandomizerRNG, BlockHashRNG, Sortit
22
import request from "graphql-request";
33
import env from "./utils/env";
44
import loggerFactory from "./utils/logger";
5-
import { BigNumber } from "ethers";
5+
import { toBigInt, BigNumberish, getNumber } from "ethers";
66
import hre = require("hardhat");
77

88
const { ethers } = hre;
@@ -153,8 +153,8 @@ const handleError = (e: any) => {
153153
const isRngReady = async () => {
154154
const { randomizerRng, blockHashRNG, sortition } = await getContracts();
155155
const currentRng = await sortition.rng();
156-
if (currentRng === randomizerRng.address) {
157-
const requesterID = await randomizerRng.requesterToID(sortition.address);
156+
if (currentRng === randomizerRng.target) {
157+
const requesterID = await randomizerRng.requesterToID(sortition.target);
158158
const n = await randomizerRng.randomNumbers(requesterID);
159159
if (Number(n) === 0) {
160160
logger.info("RandomizerRNG is NOT ready yet");
@@ -163,10 +163,10 @@ const isRngReady = async () => {
163163
logger.info(`RandomizerRNG is ready: ${n.toString()}`);
164164
return true;
165165
}
166-
} else if (currentRng === blockHashRNG.address) {
166+
} else if (currentRng === blockHashRNG.target) {
167167
const requestBlock = await sortition.randomNumberRequestBlock();
168168
const lookahead = await sortition.rngLookahead();
169-
const n = await blockHashRNG.callStatic.receiveRandomness(requestBlock.add(lookahead));
169+
const n = await blockHashRNG.receiveRandomness.staticCall(requestBlock + lookahead);
170170
if (Number(n) === 0) {
171171
logger.info("BlockHashRNG is NOT ready yet");
172172
return false;
@@ -184,21 +184,21 @@ const passPhase = async () => {
184184
const { sortition } = await getContracts();
185185
let success = false;
186186
try {
187-
await sortition.callStatic.passPhase();
187+
await sortition.passPhase.staticCall();
188188
} catch (e) {
189189
const error = e as CustomError;
190190
logger.info(`passPhase: not ready yet because of ${error?.reason ?? error?.errorName ?? error?.code}`);
191191
return success;
192192
}
193-
const before = await sortition.phase();
193+
const before = getNumber(await sortition.phase());
194194
try {
195-
const gas = (await sortition.estimateGas.passPhase()).mul(150).div(100); // 50% extra gas
195+
const gas = ((await sortition.passPhase.estimateGas()) * toBigInt(150)) / toBigInt(100); // 50% extra gas
196196
const tx = await (await sortition.passPhase({ gasLimit: gas })).wait();
197-
logger.info(`passPhase txID: ${tx?.transactionHash}`);
197+
logger.info(`passPhase txID: ${tx?.hash}`);
198198
} catch (e) {
199199
handleError(e);
200200
} finally {
201-
const after = await sortition.phase();
201+
const after = getNumber(await sortition.phase());
202202
logger.info(`passPhase: ${PHASES[before]} -> ${PHASES[after]}`);
203203
success = before !== after; // true if successful
204204
}
@@ -209,7 +209,7 @@ const passPeriod = async (dispute: { id: string }) => {
209209
const { core } = await getContracts();
210210
let success = false;
211211
try {
212-
await core.callStatic.passPeriod(dispute.id);
212+
await core.passPeriod.staticCall(dispute.id);
213213
} catch (e) {
214214
const error = e as CustomError;
215215
logger.info(
@@ -221,9 +221,9 @@ const passPeriod = async (dispute: { id: string }) => {
221221
}
222222
const before = (await core.disputes(dispute.id)).period;
223223
try {
224-
const gas = (await core.estimateGas.passPeriod(dispute.id)).mul(150).div(100); // 50% extra gas
224+
const gas = ((await core.passPeriod.estimateGas(dispute.id)) * toBigInt(150)) / toBigInt(100); // 50% extra gas
225225
const tx = await (await core.passPeriod(dispute.id, { gasLimit: gas })).wait();
226-
logger.info(`passPeriod txID: ${tx?.transactionHash}`);
226+
logger.info(`passPeriod txID: ${tx?.hash}`);
227227
} catch (e) {
228228
handleError(e);
229229
} finally {
@@ -238,14 +238,14 @@ const drawJurors = async (dispute: { id: string; currentRoundIndex: string }, it
238238
const { core } = await getContracts();
239239
let success = false;
240240
try {
241-
await core.callStatic.draw(dispute.id, iterations, HIGH_GAS_LIMIT);
241+
await core.draw.staticCall(dispute.id, iterations, HIGH_GAS_LIMIT);
242242
} catch (e) {
243243
logger.error(`Draw: will fail for ${dispute.id}, skipping`);
244244
return success;
245245
}
246246
try {
247247
const tx = await (await core.draw(dispute.id, iterations, HIGH_GAS_LIMIT)).wait();
248-
logger.info(`Draw txID: ${tx?.transactionHash}`);
248+
logger.info(`Draw txID: ${tx?.hash}`);
249249
success = true;
250250
} catch (e) {
251251
handleError(e);
@@ -260,14 +260,14 @@ const executeRepartitions = async (dispute: { id: string; currentRoundIndex: str
260260
const { core } = await getContracts();
261261
let success = false;
262262
try {
263-
await core.callStatic.execute(dispute.id, dispute.currentRoundIndex, iterations, HIGH_GAS_LIMIT);
263+
await core.execute.staticCall(dispute.id, dispute.currentRoundIndex, iterations, HIGH_GAS_LIMIT);
264264
} catch (e) {
265265
logger.error(`Execute: will fail for ${dispute.id}, skipping`);
266266
return success;
267267
}
268268
try {
269269
const tx = await (await core.execute(dispute.id, dispute.currentRoundIndex, iterations, HIGH_GAS_LIMIT)).wait();
270-
logger.info(`Execute txID: ${tx?.transactionHash}`);
270+
logger.info(`Execute txID: ${tx?.hash}`);
271271
success = true;
272272
} catch (e) {
273273
handleError(e);
@@ -279,15 +279,15 @@ const executeRuling = async (dispute: { id: string }) => {
279279
const { core } = await getContracts();
280280
let success = false;
281281
try {
282-
await core.callStatic.executeRuling(dispute.id);
282+
await core.executeRuling.staticCall(dispute.id);
283283
} catch (e) {
284284
logger.error(`ExecuteRuling: will fail for ${dispute.id}, skipping`);
285285
return success;
286286
}
287287
try {
288-
const gas = (await core.estimateGas.executeRuling(dispute.id)).mul(150).div(100); // 50% extra gas
288+
const gas = ((await core.executeRuling.estimateGas(dispute.id)) * toBigInt(150)) / toBigInt(100); // 50% extra gas
289289
const tx = await (await core.executeRuling(dispute.id, { gasLimit: gas })).wait();
290-
logger.info(`ExecuteRuling txID: ${tx?.transactionHash}`);
290+
logger.info(`ExecuteRuling txID: ${tx?.hash}`);
291291
success = true;
292292
} catch (e) {
293293
handleError(e);
@@ -302,9 +302,9 @@ const withdrawAppealContribution = async (
302302
): Promise<boolean> => {
303303
const { disputeKitClassic: kit } = await getContracts();
304304
let success = false;
305-
let amountWithdrawn = BigNumber.from(0);
305+
let amountWithdrawn = toBigInt(0);
306306
try {
307-
amountWithdrawn = await kit.callStatic.withdrawFeesAndRewards(
307+
amountWithdrawn = await kit.withdrawFeesAndRewards.staticCall(
308308
disputeId,
309309
contribution.contributor.id,
310310
roundId,
@@ -316,7 +316,7 @@ const withdrawAppealContribution = async (
316316
);
317317
return success;
318318
}
319-
if (amountWithdrawn.isZero()) {
319+
if (amountWithdrawn === toBigInt(0)) {
320320
logger.debug(
321321
`WithdrawFeesAndRewards: no fees or rewards to withdraw for dispute #${disputeId}, round #${roundId}, choice ${contribution.choice} and beneficiary ${contribution.contributor.id}, skipping`
322322
);
@@ -326,17 +326,21 @@ const withdrawAppealContribution = async (
326326
logger.info(
327327
`WithdrawFeesAndRewards: appeal contribution for dispute #${disputeId}, round #${roundId}, choice ${contribution.choice} and beneficiary ${contribution.contributor.id}`
328328
);
329-
const gas = (
330-
await kit.estimateGas.withdrawFeesAndRewards(disputeId, contribution.contributor.id, roundId, contribution.choice)
331-
)
332-
.mul(150)
333-
.div(100); // 50% extra gas
329+
const gas =
330+
((await kit.withdrawFeesAndRewards.estimateGas(
331+
disputeId,
332+
contribution.contributor.id,
333+
roundId,
334+
contribution.choice
335+
)) *
336+
toBigInt(150)) /
337+
toBigInt(100); // 50% extra gas
334338
const tx = await (
335339
await kit.withdrawFeesAndRewards(disputeId, contribution.contributor.id, roundId, contribution.choice, {
336340
gasLimit: gas,
337341
})
338342
).wait();
339-
logger.info(`WithdrawFeesAndRewards txID: ${tx?.transactionHash}`);
343+
logger.info(`WithdrawFeesAndRewards txID: ${tx?.hash}`);
340344
success = true;
341345
} catch (e) {
342346
handleError(e);
@@ -348,30 +352,30 @@ const executeDelayedStakes = async () => {
348352
const { sortition } = await getContracts();
349353

350354
// delayedStakes = 1 + delayedStakeWriteIndex - delayedStakeReadIndex
351-
const delayedStakesRemaining = BigNumber.from(1)
352-
.add(await sortition.delayedStakeWriteIndex())
353-
.sub(await sortition.delayedStakeReadIndex());
355+
const delayedStakesRemaining =
356+
toBigInt(1) + (await sortition.delayedStakeWriteIndex()) - (await sortition.delayedStakeReadIndex());
354357

355-
const delayedStakes = delayedStakesRemaining.lt(MAX_DELAYED_STAKES_ITERATIONS)
356-
? delayedStakesRemaining
357-
: BigNumber.from(MAX_DELAYED_STAKES_ITERATIONS);
358+
const delayedStakes =
359+
delayedStakesRemaining < MAX_DELAYED_STAKES_ITERATIONS
360+
? delayedStakesRemaining
361+
: toBigInt(MAX_DELAYED_STAKES_ITERATIONS);
358362

359-
if (delayedStakes.eq(0)) {
363+
if (delayedStakes === toBigInt(0)) {
360364
logger.info("No delayed stakes to execute");
361365
return true;
362366
}
363367
logger.info(`Executing ${delayedStakes} delayed stakes, ${delayedStakesRemaining} remaining`);
364368
let success = false;
365369
try {
366-
await sortition.callStatic.executeDelayedStakes(delayedStakes);
370+
await sortition.executeDelayedStakes.staticCall(delayedStakes);
367371
} catch (e) {
368372
logger.error(`executeDelayedStakes: will fail because of ${JSON.stringify(e)}`);
369373
return success;
370374
}
371375
try {
372-
const gas = (await sortition.estimateGas.executeDelayedStakes(delayedStakes)).mul(150).div(100); // 50% extra gas
376+
const gas = ((await sortition.executeDelayedStakes.estimateGas(delayedStakes)) * toBigInt(150)) / toBigInt(100); // 50% extra gas
373377
const tx = await (await sortition.executeDelayedStakes(delayedStakes, { gasLimit: gas })).wait();
374-
logger.info(`executeDelayedStakes txID: ${tx?.transactionHash}`);
378+
logger.info(`executeDelayedStakes txID: ${tx?.hash}`);
375379
} catch (e) {
376380
handleError(e);
377381
}
@@ -381,22 +385,22 @@ const executeDelayedStakes = async () => {
381385
const getMissingJurors = async (dispute: { id: string; currentRoundIndex: string }) => {
382386
const { core } = await getContracts();
383387
const { nbVotes, drawnJurors } = await core.getRoundInfo(dispute.id, dispute.currentRoundIndex);
384-
return nbVotes.sub(drawnJurors.length);
388+
return nbVotes - toBigInt(drawnJurors.length);
385389
};
386390

387391
const isDisputeFullyDrawn = async (dispute: { id: string; currentRoundIndex: string }): Promise<boolean> => {
388-
return (await getMissingJurors(dispute)).eq(0);
392+
return (await getMissingJurors(dispute)) === toBigInt(0);
389393
};
390394

391395
const getNumberOfMissingRepartitions = async (
392396
dispute: { id: string; currentRoundIndex: string },
393-
coherentCount: BigNumber
397+
coherentCount: BigNumberish
394398
) => {
395399
const { core } = await getContracts();
396400
const { repartitions, drawnJurors } = await core.getRoundInfo(dispute.id, dispute.currentRoundIndex);
397-
return coherentCount.eq(0)
398-
? drawnJurors.length - repartitions.toNumber()
399-
: 2 * drawnJurors.length - repartitions.toNumber();
401+
return coherentCount === toBigInt(0)
402+
? drawnJurors.length - getNumber(repartitions)
403+
: 2 * drawnJurors.length - getNumber(repartitions);
400404
};
401405

402406
const filterDisputesToSkip = (disputes: Dispute[]) => {
@@ -436,43 +440,44 @@ async function main() {
436440

437441
const getBlockTime = async () => {
438442
return await ethers.provider.getBlock("latest").then((block) => {
439-
return BigNumber.from(block.timestamp);
443+
if (block?.timestamp === undefined) return 0;
444+
return block?.timestamp;
440445
});
441446
};
442447

443448
const hasMinStakingTimePassed = async (): Promise<boolean> => {
444449
const minStakingTime = await sortition.minStakingTime();
445450
const blockTime = await getBlockTime();
446451
return await sortition.lastPhaseChange().then((lastPhaseChange) => {
447-
return blockTime.sub(lastPhaseChange).gt(minStakingTime);
452+
return toBigInt(blockTime) - lastPhaseChange > minStakingTime;
448453
});
449454
};
450455

451456
const hasMaxDrawingTimePassed = async (): Promise<boolean> => {
452457
const maxDrawingTime = await sortition.maxDrawingTime();
453458
const blockTime = await getBlockTime();
454459
return await sortition.lastPhaseChange().then((lastPhaseChange) => {
455-
return blockTime.sub(lastPhaseChange).gt(maxDrawingTime);
460+
return toBigInt(blockTime) - lastPhaseChange > maxDrawingTime;
456461
});
457462
};
458463

459464
const isPhaseStaking = async (): Promise<boolean> => {
460-
return PHASES[await sortition.phase()] === Phase.STAKING;
465+
return PHASES[getNumber(await sortition.phase())] === Phase.STAKING;
461466
};
462467

463468
const isPhaseGenerating = async (): Promise<boolean> => {
464-
return PHASES[await sortition.phase()] === Phase.GENERATING;
469+
return PHASES[getNumber(await sortition.phase())] === Phase.GENERATING;
465470
};
466471

467472
const isPhaseDrawing = async (): Promise<boolean> => {
468-
return PHASES[await sortition.phase()] === Phase.DRAWING;
473+
return PHASES[getNumber(await sortition.phase())] === Phase.DRAWING;
469474
};
470475

471476
logger.info("Starting up");
472477

473478
await sendHeartbeat();
474479

475-
logger.info(`Current phase: ${PHASES[await sortition.phase()]}`);
480+
logger.info(`Current phase: ${PHASES[getNumber(await sortition.phase())]}`);
476481

477482
// Retrieve the disputes which are in a non-final period
478483
let disputes = await getNonFinalDisputes().catch((e) => handleError(e));
@@ -485,7 +490,7 @@ async function main() {
485490

486491
// Just a sanity check
487492
const numberOfDisputesWithoutJurors = await sortition.disputesWithoutJurors();
488-
if (!numberOfDisputesWithoutJurors.eq(disputesWithoutJurors.length)) {
493+
if (!(numberOfDisputesWithoutJurors === toBigInt(disputesWithoutJurors.length))) {
489494
logger.error("Discrepancy between SortitionModule.disputesWithoutJurors and KlerosCore.disputes");
490495
logger.error(`KlerosCore.disputes without jurors = ${disputesWithoutJurors.length}`);
491496
logger.error(`SortitionModule.disputesWithoutJurors = ${numberOfDisputesWithoutJurors}`);
@@ -523,12 +528,12 @@ async function main() {
523528
break;
524529
}
525530
let numberOfMissingJurors = await getMissingJurors(dispute);
526-
if (numberOfMissingJurors.gt(MAX_JURORS_PER_DISPUTE)) {
531+
if (numberOfMissingJurors > MAX_JURORS_PER_DISPUTE) {
527532
logger.warn(`Skipping dispute #${dispute.id} with too many jurors to draw`);
528533
continue;
529534
}
530535
do {
531-
const drawIterations = Math.min(MAX_DRAW_ITERATIONS, numberOfMissingJurors.toNumber());
536+
const drawIterations = Math.min(MAX_DRAW_ITERATIONS, getNumber(numberOfMissingJurors));
532537
logger.info(
533538
`Drawing ${drawIterations} out of ${numberOfMissingJurors} jurors needed for dispute #${dispute.id}`
534539
);
@@ -539,7 +544,7 @@ async function main() {
539544
await delay(ITERATIONS_COOLDOWN_PERIOD); // To avoid spiking the gas price
540545
maxDrawingTimePassed = await hasMaxDrawingTimePassed();
541546
numberOfMissingJurors = await getMissingJurors(dispute);
542-
} while (!numberOfMissingJurors.eq(0) && !maxDrawingTimePassed);
547+
} while (!(numberOfMissingJurors === toBigInt(0)) && !maxDrawingTimePassed);
543548
}
544549
// At this point, either all disputes are fully drawn or max drawing time has passed
545550
}
@@ -554,7 +559,7 @@ async function main() {
554559

555560
await sendHeartbeat();
556561

557-
logger.info(`Current phase: ${PHASES[await sortition.phase()]}`);
562+
logger.info(`Current phase: ${PHASES[getNumber(await sortition.phase())]}`);
558563

559564
for (var dispute of disputes) {
560565
// ----------------------------------------------- //
@@ -583,7 +588,7 @@ async function main() {
583588

584589
for (var dispute of unprocessedDisputesInExecution) {
585590
const { period } = await core.disputes(dispute.id);
586-
if (period !== 4) {
591+
if (period !== toBigInt(4)) {
587592
logger.info(`Skipping dispute #${dispute.id} because it is not in the execution period`);
588593
continue;
589594
}
@@ -636,14 +641,14 @@ async function main() {
636641
contributions = [...new Set(contributions)];
637642
for (let contribution of contributions) {
638643
// Could be improved by pinpointing exactly which round requires a withdrawal, just try all of them for now.
639-
for (let round = BigNumber.from(dispute.currentRoundIndex); round.gte(0); round = round.sub(1)) {
644+
for (let round = toBigInt(dispute.currentRoundIndex); round >= 0; round = round - toBigInt(1)) {
640645
await withdrawAppealContribution(dispute.id, round.toString(), contribution);
641646
await delay(ITERATIONS_COOLDOWN_PERIOD); // To avoid spiking the gas price
642647
}
643648
}
644649
}
645650

646-
logger.info(`Current phase: ${PHASES[await sortition.phase()]}`);
651+
logger.info(`Current phase: ${PHASES[getNumber(await sortition.phase())]}`);
647652

648653
// ----------------------------------------------- //
649654
// EXECUTE DELAYED STAKES //

‎contracts/scripts/viemTest.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const main = async () => {
1212
const disputeKit = getContract({
1313
address: disputeKitClassicConfig.address[arbitrumSepolia.id],
1414
abi: disputeKitClassicConfig.abi,
15-
publicClient: client,
15+
client: client,
1616
});
1717

1818
await disputeKit.read.governor().then(console.log);

0 commit comments

Comments
 (0)
Please sign in to comment.