Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions src/bots/kleros-liquid.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,16 @@ module.exports = async (web3, batchedSend) => {
try {
let disputeID = process.env.STARTING_DISPUTE_ID || 0;
while (true) {
console.debug(`Processing dispute ${disputeID}`);
if (!executedDisputeIDs[disputeID]) {
let dispute;
try {
dispute = await klerosLiquid.methods.disputes(disputeID).call();
} catch (_) {
//console.log(e);
} catch (e) {
// We are in a disputeID that doesn't exist.
// console.error(
// `Error trying to read dispute ${disputeID}: ${e.message}`
// );
break;
}
const dispute2 = await klerosLiquid.methods
Expand All @@ -55,6 +59,9 @@ module.exports = async (web3, batchedSend) => {
.call();
} catch (_) {
// Look it up manually if numberOfChoices is too high for loop
console.debug(
`Looking up vote counter manually for dispute ${disputeID}, choice ${i}`
);
Comment on lines +62 to +64
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix fallback path: missing .call() and shape mismatch cause runtime errors.

  • getVote requires .call(); without it, the await resolves to a method object, not data.
  • The manual voteCounter lacks counts, but later logic indexes v.counts[winningChoice], leading to TypeError.

Apply:

-                  const vote = await klerosLiquid.methods.getVote(
-                    disputeID,
-                    i,
-                    j
-                  );
+                  const vote = await klerosLiquid.methods
+                    .getVote(disputeID, i, j)
+                    .call();

And return a compatible structure with counts (stringified), ensuring the winner exists:

-                voteCounter = {
-                  tied,
-                  winningChoice,
-                };
+                const counts = Object.fromEntries(
+                  Object.entries(_voteCounters).map(([k, v]) => [String(k), String(v)])
+                );
+                if (counts[winningChoice] === undefined) counts[winningChoice] = "0";
+                voteCounter = { tied, winningChoice, counts };

Also applies to: 69-73, 95-99, 106-111

🤖 Prompt for AI Agents
In src/bots/kleros-liquid.js around lines 61-63 (and similarly at 69-73, 95-99,
106-111), the fallback path for fetching vote counters is incorrect: it calls
the contract method without .call(), which returns a method object instead of
data, and it returns an object lacking a counts array so later indexing
v.counts[winningChoice] throws. Fix by invoking the contract getter with .call()
and by returning a structure matching the expected shape: an object with counts
as an array of strings (stringify numeric values) and a winner index validated
to exist (if winner not present, set to a safe default or throw/handle
accordingly); ensure the returned counts length matches numberOfChoices to avoid
out-of-bounds indexing.

let tied = true;
let winningChoice = "0";
const _voteCounters = {};
Expand All @@ -65,6 +72,11 @@ module.exports = async (web3, batchedSend) => {
i,
j
);
console.debug(
`Vote for dispute ${disputeID}, choice ${i}, index ${j}: ${JSON.stringify(
vote
)}`
);
if (vote.voted) {
// increment vote count
_voteCounters[vote.choice] = _voteCounters[vote.choice]
Expand Down Expand Up @@ -95,13 +107,17 @@ module.exports = async (web3, batchedSend) => {
return voteCounter;
})
);
console.debug(`Vote counter has ${voteCounters.length} entries`);

const notTieAndNoOneCoherent = voteCounters.map(
(v) =>
!voteCounters[voteCounters.length - 1].tied &&
v.counts[voteCounters[voteCounters.length - 1].winningChoice] ===
"0"
);
console.debug(
`No tie and no coherent votes for dispute ${disputeID}: ${notTieAndNoOneCoherent}`
);
if (
!dispute.ruled ||
dispute2.votesLengths.some(
Expand Down Expand Up @@ -148,6 +164,8 @@ module.exports = async (web3, batchedSend) => {
executedDisputeIDs[disputeID] = true; // The dispute is finalized, cache it.
console.log("Dispute %s is finalized, caching it.", disputeID);
}
} else {
console.debug(`Dispute ${disputeID} is already executed.`);
}
disputeID++;
}
Expand All @@ -163,22 +181,26 @@ module.exports = async (web3, batchedSend) => {
const disputesWithoutJurors = await klerosLiquid.methods
.disputesWithoutJurors()
.call();
console.log(`Checking if reay to move phase`);
if (phase == PhaseEnum.staking) {
const minStakingTime = await klerosLiquid.methods.minStakingTime().call();
if (
Date.now() - lastPhaseChange * 1000 >= minStakingTime * 1000 &&
disputesWithoutJurors > 0
) {
console.debug(`Ready to move from staking to generating`);
readyForNextPhase = true;
}
} else if (phase == PhaseEnum.generating) {
console.debug(`Ready to move from generating to drawing`);
readyForNextPhase = true;
} else if (phase == PhaseEnum.drawing) {
const maxDrawingTime = await klerosLiquid.methods.maxDrawingTime().call();
if (
Date.now() - lastPhaseChange * 1000 >= maxDrawingTime * 1000 ||
disputesWithoutJurors == 0
) {
console.debug(`Ready to move from drawing to staking`);
readyForNextPhase = true;
}
}
Expand Down