Skip to content

feat(DK): forking kit#2392

Draft
unknownunknown1 wants to merge 1 commit into
devfrom
feat/forking-kit
Draft

feat(DK): forking kit#2392
unknownunknown1 wants to merge 1 commit into
devfrom
feat/forking-kit

Conversation

@unknownunknown1

@unknownunknown1 unknownunknown1 commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

PR-Codex overview

This PR introduces a new dispute kit, DisputeKitForking, to handle forking logic in the Kleros arbitration system. It adds structures, functions, and events to manage bids and forks, while implementing necessary checks and modifiers for the forking process.

Detailed summary

  • Added DisputeKitForking contract implementing IDisputeKit.
  • Introduced Fork and ForkBid structures for managing bids.
  • Implemented submitBid, searchAndBid, withdraw, and finalize functions for bid management.
  • Added event ForkBidSubmitted for bid submissions.
  • Introduced modifiers like onlyByCore for access control.
  • Added functions for managing forked disputes, including createDispute and currentRuling.
  • Included error handling for various scenarios during the forking process.
  • Marked several functions as unsupported or not used in the contract.

✨ Ask PR-Codex anything about this PR by commenting with /codex {your question}

Summary by CodeRabbit

  • New Features

    • Added forking dispute kit with functionality to submit, withdraw, and finalize bids for fork governance participation.
  • Chores

    • Added implementation notes for future forking integration enhancements.

@netlify

netlify Bot commented Jun 11, 2026

Copy link
Copy Markdown

Deploy Preview for kleros-v2-testnet-devtools failed. Why did it fail? →

Name Link
🔨 Latest commit 344e9d8
🔍 Latest deploy log https://app.netlify.com/projects/kleros-v2-testnet-devtools/deploys/6a2abf7868ff810008bbf193

@netlify

netlify Bot commented Jun 11, 2026

Copy link
Copy Markdown

Deploy Preview for kleros-v2-neo failed. Why did it fail? →

Name Link
🔨 Latest commit 344e9d8
🔍 Latest deploy log https://app.netlify.com/projects/kleros-v2-neo/deploys/6a2abf770b3b010008d370c9

@netlify

netlify Bot commented Jun 11, 2026

Copy link
Copy Markdown

Deploy Preview for kleros-v2-testnet ready!

Name Link
🔨 Latest commit 344e9d8
🔍 Latest deploy log https://app.netlify.com/projects/kleros-v2-testnet/deploys/6a2abf77a12a6c0007ebb398
😎 Deploy Preview https://deploy-preview-2392--kleros-v2-testnet.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

This PR introduces DisputeKitForking, a new Solidity contract implementing the IDisputeKit interface to support fork-based resolution within the Kleros arbitration system. The implementation provides linked-list-based bid management, fork state initialization, and a complete lifecycle for evidence and execution periods. Integration TODOs are added to existing files marking future wiring work.

Changes

Forking Dispute Kit Implementation

Layer / File(s) Summary
Contract foundation and storage structures
contracts/src/arbitration/dispute-kits/DisputeKitForking.sol
Defines DisputeKitForking contract with upgradeable pattern, Fork and ForkBid linked-list structures with sentinel constants, core reference, fork array and dispute-to-fork mapping, events for bid operations, and access control modifier. Custom error types support validation, access control, and fork lifecycle.
Dispute creation and fork bootstrapping
contracts/src/arbitration/dispute-kits/DisputeKitForking.sol
createDispute initializes new fork instance, maps core dispute ID to fork, sets initial ruling and pinakion reference, creates virtual head/tail sentinel bids, and initializes cutoff state.
Bid submission and linked-list ordering
contracts/src/arbitration/dispute-kits/DisputeKitForking.sol
submitBid validates fork existence and evidence period, enforces min-support ordering constraints by checking surrounding bids, updates linked-list pointers, locks tokens via pinakion transfer, and emits ForkBidSubmitted. searchAndBid wrapper and search helper locate insertion points by traversing the sorted bid list.
Withdrawal and finalization lifecycle
contracts/src/arbitration/dispute-kits/DisputeKitForking.sol
withdraw restricts to evidence period, verifies sender and non-withdrawn status, unlocks funds, and decrements remaining support. finalize runs in execution period with bounded iteration to prune bids failing minimum support threshold, refunds pruned bids, persists final cutoff bid ID and remaining support, and prevents double-finalization.
Fork state queries and cutoff computation
contracts/src/arbitration/dispute-kits/DisputeKitForking.sol
remainingSupportAndCutOff simulates backward pruning from current cutoff, decrementing remaining support for bids with unmet minimum support, and returns final state. currentRuling returns stored fork ruling or reverts for unknown disputes.
IDisputeKit interface stub implementations
contracts/src/arbitration/dispute-kits/DisputeKitForking.sol
Provides non-functional stubs for remaining IDisputeKit methods: draw, castCommit, castVote, fundAppeal, and withdrawFeesAndRewards revert with UnsupportedOperation; reward/penalty, coherent count, vote status, and next-round-settings methods return zero/false/empty defaults; getRoundInfo and getVoteInfo return zero-valued tuples.
Pending forking integration markers
contracts/src/arbitration/KlerosCore.sol, contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol
TODO comments added in KlerosCore.appeal() and appealCost() note missing Forking-court-specific logic and appeal forbiddance checks. TODO in DisputeKitClassic.withdrawFeesAndRewards() notes pending detection of forking final court and tie distribution enforcement.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Poem

A forking kit sprouts in the arbitration tree, 🌳
With bids and linked lists dancing in harmony,
Sentinels stand guard at each linked list end,
While pruning and withdrawals gracefully blend—
The foundation is set for future extension spree! 🐰✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(DK): forking kit' directly reflects the main change: adding a new DisputeKitForking contract with comprehensive forking functionality.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/forking-kit

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sonarqubecloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
contracts/src/arbitration/KlerosCore.sol (1)

874-875: ⚡ Quick win

Clarify TODOs and verify placement for forking integration.

The TODO comments are vague and their placement may need reconsideration:

  1. "forking kit logic" doesn't specify what behavior is needed (e.g., should it prevent court jumps, create fork state, redirect to DisputeKitForking?).
  2. "handle arbitration fees in case of Forking" doesn't clarify whether fees should be refunded, held in escrow, or handled differently.
  3. These TODOs are placed after emitting the CourtJump event but before updating dispute.courtID. If forking logic needs to intercept or modify court jumps, this placement could emit misleading events or leave state partially updated.

Consider:

  • Making TODOs more specific (e.g., "TODO: If newCourtID is FORKING_COURT, initialize fork state in DisputeKitForking and skip standard appeal flow")
  • Verifying whether the placement before dispute.courtID = newCourtID is intentional or whether forking checks should happen earlier in the function
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@contracts/src/arbitration/KlerosCore.sol` around lines 874 - 875, The two
TODOs near the CourtJump emission are ambiguous and possibly misplaced; make
them explicit and move or augment the checks so forking is handled before
emitting CourtJump and before updating dispute.courtID: add a clear TODO like
"TODO: if newCourtID == FORKING_COURT, initialize fork state via
DisputeKitForking (create fork, assign fork ID) and bypass/alter standard appeal
fee handling" and another like "TODO: define arbitration fee behavior on fork
(refund to payer, hold in escrow, or transfer to fork bounty) and implement in
the same pre-CourtJump branch"; ensure code paths that touch dispute.courtID and
emit CourtJump only run after fork-specific initialization or redirection is
resolved so events/state remain consistent.
contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol (1)

494-494: ⚡ Quick win

Provide implementation guidance for forking court check.

The TODO lacks actionable details for the developer implementing this feature:

  1. Missing check: The code doesn't retrieve or check dispute.courtID from core.disputes(_coreDisputeID) to determine if the final court is the Forking court.
  2. Unclear mechanism: "Force the tie distribution" could mean:
    • Overriding finalRuling to 0 before the loop (line 496)?
    • Modifying the conditional logic inside the loop to treat all funded choices equally?
    • Applying tie distribution only to the last round while keeping earlier rounds' logic intact?
📝 Suggested implementation approach
 Dispute storage dispute = disputes[coreDisputeIDToLocal[_coreDisputeID]];
 (uint256 finalRuling, , ) = core.currentRuling(_coreDisputeID);
-// TODO: check if the final court is forking and if it is force the tie distribution for the last round.
+
+// Check if final court is FORKING_COURT and force tie distribution for last round
+(uint96 finalCourtID, , , , ) = core.disputes(_coreDisputeID);
+bool isForkingFinalCourt = (finalCourtID == FORKING_COURT);

 for (uint256 i = 0; i < dispute.rounds.length; i++) {
     Round storage round = dispute.rounds[i];
+    
+    // Apply tie distribution in the last round if final court is Forking
+    bool applyTieDistribution = isForkingFinalCourt && (i == dispute.rounds.length - 1);
+    uint256 effectiveRuling = applyTieDistribution ? 0 : finalRuling;

-    if (!round.hasPaid[_choice]) {
+    if (!round.hasPaid[_choice]) {
         // Allow to reimburse if funding was unsuccessful for this ruling option.
         amount += round.contributions[_beneficiary][_choice];
     } else {
         // Funding was successful for this ruling option.
-        if (_choice == finalRuling) {
+        if (_choice == effectiveRuling) {
             // This ruling option is the ultimate winner.
             amount += round.paidFees[_choice] > 0
                 ? (round.contributions[_beneficiary][_choice] * round.feeRewards) / round.paidFees[_choice]
                 : 0;
-        } else if (!round.hasPaid[finalRuling]) {
+        } else if (applyTieDistribution || !round.hasPaid[effectiveRuling]) {
             // The ultimate winner was not funded in this round, or forking tie distribution applies
             amount +=
                 (round.contributions[_beneficiary][_choice] * round.feeRewards) /
                 (round.paidFees[round.fundedChoices[0]] + round.paidFees[round.fundedChoices[1]]);
         }
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol` at line 494,
Retrieve the dispute via core.disputes(_coreDisputeID) and read dispute.courtID,
then query the court record to detect forking (e.g.,
core.courts(courtID).forking or a helper like core.isForkingCourt(courtID)); if
the final court is a forking court, force tie handling for the last round by
setting finalRuling = 0 before the loop that computes distributions and, when
iterating the rounds (use rounds[rounds.length - 1] or the variable that denotes
the last round), treat all funded choices as tied (i.e., don't prefer the
current finalRuling, instead distribute tie shares equally among funded choices
or use the same tie-distribution logic you apply elsewhere) while leaving
earlier rounds’ logic unchanged; reference symbols: _coreDisputeID, dispute,
dispute.courtID, core.courts / core.isForkingCourt, finalRuling, rounds and the
last round index.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@contracts/src/arbitration/dispute-kits/DisputeKitForking.sol`:
- Around line 184-197: In finalize(), avoid refunding the virtual TAIL sentinel
by checking localCutOffBidID (or bid.account == address(0)) and skipping the
refund/zeroing logic for that sentinel: if localCutOffBidID == TAIL then set
localCutOffBidID = fork.forkBids[localCutOffBidID].prev (advance to previous)
without calling fork.pinakion.safeTransfer or modifying value; otherwise proceed
as before but also guard safeTransfer calls by only calling when refund>0 and
bid.account != address(0) to prevent zero-address transfers and no-op transfers.
This change touches finalize(), the loop that reads
fork.cutOffBidID/localCutOffBidID, and the fork.forkBids[...].value/refund
handling referenced in the diff.
- Around line 281-287: DisputeKitForking.sol implements IDisputeKit but several
interface methods lack the override specifier; update the function signatures
for createDispute, draw, currentRuling, getDegreeOfCoherenceReward,
getDegreeOfCoherencePenalty, getCoherentCount, getRewards, areCommitsAllCast,
areVotesAllCast, isAppealFunded, getNextRoundSettings, isVoteActive, and
getVoteInfo to include the override keyword (e.g., function createDispute(...)
external onlyByCore override) so they properly override the IDisputeKit
interface; keep other modifiers and parameter names unchanged.

---

Nitpick comments:
In `@contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol`:
- Line 494: Retrieve the dispute via core.disputes(_coreDisputeID) and read
dispute.courtID, then query the court record to detect forking (e.g.,
core.courts(courtID).forking or a helper like core.isForkingCourt(courtID)); if
the final court is a forking court, force tie handling for the last round by
setting finalRuling = 0 before the loop that computes distributions and, when
iterating the rounds (use rounds[rounds.length - 1] or the variable that denotes
the last round), treat all funded choices as tied (i.e., don't prefer the
current finalRuling, instead distribute tie shares equally among funded choices
or use the same tie-distribution logic you apply elsewhere) while leaving
earlier rounds’ logic unchanged; reference symbols: _coreDisputeID, dispute,
dispute.courtID, core.courts / core.isForkingCourt, finalRuling, rounds and the
last round index.

In `@contracts/src/arbitration/KlerosCore.sol`:
- Around line 874-875: The two TODOs near the CourtJump emission are ambiguous
and possibly misplaced; make them explicit and move or augment the checks so
forking is handled before emitting CourtJump and before updating
dispute.courtID: add a clear TODO like "TODO: if newCourtID == FORKING_COURT,
initialize fork state via DisputeKitForking (create fork, assign fork ID) and
bypass/alter standard appeal fee handling" and another like "TODO: define
arbitration fee behavior on fork (refund to payer, hold in escrow, or transfer
to fork bounty) and implement in the same pre-CourtJump branch"; ensure code
paths that touch dispute.courtID and emit CourtJump only run after fork-specific
initialization or redirection is resolved so events/state remain consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0465cc9b-2036-4b38-a3fd-a52aca93986c

📥 Commits

Reviewing files that changed from the base of the PR and between 0f19d23 and 344e9d8.

📒 Files selected for processing (3)
  • contracts/src/arbitration/KlerosCore.sol
  • contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol
  • contracts/src/arbitration/dispute-kits/DisputeKitForking.sol

Comment on lines +184 to +197
uint256 localCutOffBidID = fork.cutOffBidID;
uint256 localRemainingSupport = fork.remainingSupport;

// Search for the cut-off bid while removing bids whose minimum support is not met.
for (uint256 it = 0; it < _maxIt && !fork.finalized; it++) {
ForkBid storage bid = fork.forkBids[localCutOffBidID];
if (bid.minSupport > localRemainingSupport && localCutOffBidID != HEAD) {
uint256 refund = bid.value;
bid.value = 0;
// Bid's condition is not satisfied, remove it.
localRemainingSupport -= refund;
localCutOffBidID = bid.prev; // Go to the previous bid.
// Refund the bid because its minimum support condition was not met.
fork.pinakion.safeTransfer(bid.account, refund);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Skip the virtual TAIL bid before refunding in finalize().

createDispute() seeds cutOffBidID with TAIL, so the first finalize() pass always enters the prune branch on the sentinel node. That path zeroes/refunds forkBids[TAIL] and calls safeTransfer on address(0); if the token rejects zero-address transfers, finalization gets stuck, and this call site also ignores the transfer result for real refunds.

Suggested fix
-        uint256 localCutOffBidID = fork.cutOffBidID;
+        uint256 localCutOffBidID = fork.cutOffBidID == TAIL ? fork.forkBids[TAIL].prev : fork.cutOffBidID;
         uint256 localRemainingSupport = fork.remainingSupport;
...
-                fork.pinakion.safeTransfer(bid.account, refund);
+                require(fork.pinakion.safeTransfer(bid.account, refund), TransferFailed());

Also applies to: 309-309

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@contracts/src/arbitration/dispute-kits/DisputeKitForking.sol` around lines
184 - 197, In finalize(), avoid refunding the virtual TAIL sentinel by checking
localCutOffBidID (or bid.account == address(0)) and skipping the refund/zeroing
logic for that sentinel: if localCutOffBidID == TAIL then set localCutOffBidID =
fork.forkBids[localCutOffBidID].prev (advance to previous) without calling
fork.pinakion.safeTransfer or modifying value; otherwise proceed as before but
also guard safeTransfer calls by only calling when refund>0 and bid.account !=
address(0) to prevent zero-address transfers and no-op transfers. This change
touches finalize(), the loop that reads fork.cutOffBidID/localCutOffBidID, and
the fork.forkBids[...].value/refund handling referenced in the diff.

Comment on lines +281 to +287
function createDispute(
uint256 _coreDisputeID,
uint256 /*_coreRoundID*/,
uint256 _finalRuling,
bytes calldata /*_extraData*/,
uint256 /*_nbVotes*/
) external onlyByCore {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n 'function (createDispute|draw|castCommit|castVote|fundAppeal|withdrawFeesAndRewards|currentRuling|getDegreeOfCoherenceReward|getDegreeOfCoherencePenalty|getCoherentCount|getRewards|areCommitsAllCast|areVotesAllCast|isAppealFunded|getNextRoundSettings|isVoteActive|getRoundInfo|getVoteInfo)\b' \
  contracts/src/arbitration/interfaces/IDisputeKit.sol \
  contracts/src/arbitration/dispute-kits/DisputeKitForking.sol

Repository: kleros/kleros-v2

Length of output: 3813


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== IDisputeKit.sol =="
nl -ba contracts/src/arbitration/interfaces/IDisputeKit.sol | sed -n '1,260p'

echo
echo "== DisputeKitForking.sol (function signatures region) =="
nl -ba contracts/src/arbitration/dispute-kits/DisputeKitForking.sol | sed -n '250,570p'

Repository: kleros/kleros-v2

Length of output: 143


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== IDisputeKit.sol =="
nl -ba contracts/src/arbitration/interfaces/IDisputeKit.sol | sed -n '1,260p'

echo
echo "== DisputeKitForking.sol (function signatures region) =="
nl -ba contracts/src/arbitration/dispute-kits/DisputeKitForking.sol | sed -n '250,570p'

Repository: kleros/kleros-v2

Length of output: 143


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== IDisputeKit.sol (relevant functions) =="
cat -n contracts/src/arbitration/interfaces/IDisputeKit.sol | sed -n '1,260p'

echo
echo "== DisputeKitForking.sol (relevant functions) =="
cat -n contracts/src/arbitration/dispute-kits/DisputeKitForking.sol | sed -n '240,570p'

Repository: kleros/kleros-v2

Length of output: 31305


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== DisputeKitForking.sol: contract declaration =="
rg -n "contract DisputeKitForking" -n contracts/src/arbitration/dispute-kits/DisputeKitForking.sol
sed -n '1,120p' contracts/src/arbitration/dispute-kits/DisputeKitForking.sol

echo
echo "== IDisputeKit.sol: check presence of extra methods =="
for fn in createDispute draw castCommit castVote fundAppeal withdrawFeesAndRewards currentRuling getDegreeOfCoherenceReward getDegreeOfCoherencePenalty getCoherentCount getRewards areCommitsAllCast areVotesAllCast isAppealFunded getNextRoundSettings isVoteActive getRoundInfo getVoteInfo; do
  echo "--- $fn"
  rg -n "\\bfunction[[:space:]]+$fn\\b" contracts/src/arbitration/interfaces/IDisputeKit.sol || true
done

Repository: kleros/kleros-v2

Length of output: 6215


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n "is IDisputeKit" contracts/src/arbitration/dispute-kits -S --glob '*.sol'

echo
echo "== Search for 'function getRoundInfo' override patterns =="
rg -n "function (createDispute|draw|currentRuling|getDegreeOfCoherenceReward|getDegreeOfCoherencePenalty|getRewards|getCoherentCount|areCommitsAllCast|areVotesAllCast|isAppealFunded|getNextRoundSettings|isVoteActive|getVoteInfo)\\b[^{;]*\\boverride\\b" contracts/src/arbitration/dispute-kits --glob '*.sol'

Repository: kleros/kleros-v2

Length of output: 6168


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for f in \
  contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol \
  contracts/src/arbitration/dispute-kits/DisputeKitShutter.sol \
  contracts/src/arbitration/dispute-kits/DisputeKitSybilResistant.sol; do
  echo "== $f (override on key IDisputeKit fns) =="
  rg -n "function (createDispute|draw|castCommit|castVote|fundAppeal|withdrawFeesAndRewards|currentRuling|getDegreeOfCoherenceReward|getDegreeOfCoherencePenalty|getCoherentCount|getRewards|areCommitsAllCast|areVotesAllCast|isAppealFunded|getNextRoundSettings|isVoteActive|getRoundInfo|getVoteInfo)\\b" "$f"
  echo
done

echo "== DisputeKitForking.sol (override presence) =="
rg -n "function (createDispute|draw|castCommit|castVote|fundAppeal|withdrawFeesAndRewards|currentRuling|getDegreeOfCoherenceReward|getDegreeOfCoherencePenalty|getCoherentCount|getRewards|areCommitsAllCast|areVotesAllCast|isAppealFunded|getNextRoundSettings|isVoteActive|getRoundInfo|getVoteInfo)\\b" contracts/src/arbitration/dispute-kits/DisputeKitForking.sol

Repository: kleros/kleros-v2

Length of output: 4080


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== DisputeKitClassic.sol pragma and createDispute/draw/currentRuling signatures =="
sed -n '1,40p' contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol
sed -n '220,320p' contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol
sed -n '540,620p' contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol

echo
echo "== DisputeKitForking.sol pragma and createDispute/draw/currentRuling signatures =="
sed -n '1,50p' contracts/src/arbitration/dispute-kits/DisputeKitForking.sol
sed -n '260,420p' contracts/src/arbitration/dispute-kits/DisputeKitForking.sol

Repository: kleros/kleros-v2

Length of output: 20772


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n "override[[:space:]]+virtual|virtual[[:space:]]+override" contracts/src/arbitration/dispute-kits --glob '*.sol' | head -n 50

Repository: kleros/kleros-v2

Length of output: 391


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== DisputeKitClassic: getRewards/createDispute/draw/currentRuling signatures =="
sed -n '230,320p' contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol
sed -n '520,860p' contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol

echo
echo "== KlerosCore: call to DisputeKit.createDispute (search) =="
rg -n "createDispute\\(" contracts/src/arbitration/KlerosCore.sol contracts/src/arbitration -S --glob '*.sol' --glob '!**/test/**' --glob '!**/mocks/**'

Repository: kleros/kleros-v2

Length of output: 26385


Add missing override specifiers for IDisputeKit methods in DisputeKitForking.sol.

DisputeKitForking implements IDisputeKit, but only getRoundInfo is marked override. Add override to: createDispute, draw, currentRuling, getDegreeOfCoherenceReward, getDegreeOfCoherencePenalty, getCoherentCount, getRewards, areCommitsAllCast, areVotesAllCast, isAppealFunded, getNextRoundSettings, isVoteActive, getVoteInfo. (castCommit, castVote, fundAppeal, withdrawFeesAndRewards are not in IDisputeKit.)

Suggested fix
     function createDispute(
         uint256 _coreDisputeID,
         uint256 /*_coreRoundID*/,
         uint256 _finalRuling,
         bytes calldata /*_extraData*/,
         uint256 /*_nbVotes*/
-    ) external onlyByCore {
+    ) external override onlyByCore {
         require(coreDisputeIDToForkID[_coreDisputeID] == 0, ForkAlreadyInitiated());
         ...
     }

     function draw(
         uint256 /*_coreDisputeID*/,
         uint256 /*_nonce*/,
         uint256 /*_roundNbVotes*/
-    ) external pure returns (address, uint96) {
+    ) external pure override returns (address, uint96) {
         revert UnsupportedOperation();
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function createDispute(
uint256 _coreDisputeID,
uint256 /*_coreRoundID*/,
uint256 _finalRuling,
bytes calldata /*_extraData*/,
uint256 /*_nbVotes*/
) external onlyByCore {
function createDispute(
uint256 _coreDisputeID,
uint256 /*_coreRoundID*/,
uint256 _finalRuling,
bytes calldata /*_extraData*/,
uint256 /*_nbVotes*/
) external override onlyByCore {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@contracts/src/arbitration/dispute-kits/DisputeKitForking.sol` around lines
281 - 287, DisputeKitForking.sol implements IDisputeKit but several interface
methods lack the override specifier; update the function signatures for
createDispute, draw, currentRuling, getDegreeOfCoherenceReward,
getDegreeOfCoherencePenalty, getCoherentCount, getRewards, areCommitsAllCast,
areVotesAllCast, isAppealFunded, getNextRoundSettings, isVoteActive, and
getVoteInfo to include the override keyword (e.g., function createDispute(...)
external onlyByCore override) so they properly override the IDisputeKit
interface; keep other modifiers and parameter names unchanged.

@unknownunknown1 unknownunknown1 marked this pull request as draft June 16, 2026 08:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant