Skip to content

Conversation

jaybuidl
Copy link
Member

@jaybuidl jaybuidl commented Oct 13, 2025

Made the distinction more explicit between

  • round-specific jump checks and
  • dispute-specific unknown dispute checks.

Removed the parameter _coreRoundID from withdrawFeesAndRewards() which was responsible for several edge cases as seen in #2159 and in a tentative fix 1e7d185.

Renamed the errors for clarity:

  • DisputeJumpedToParentDK → DisputeJumpedToAnotherDisputeKit
  • NotActiveForCoreDisputeID → DisputeUnknownInThisDisputeKit

PR-Codex overview

This PR enhances the DisputeKitClassicBase contract and its derived contracts by improving the handling of dispute states and active rounds. It introduces a new Active struct for tracking dispute activity and modifies several functions to ensure correct dispute state management.

Detailed summary

  • Added Active struct to track dispute and current round status.
  • Replaced jumped boolean with Active struct in coreDisputeIDToActive mapping.
  • Updated modifiers from notJumped to isActive to check dispute status.
  • Modified event Withdrawal parameters for clarity.
  • Adjusted tests to reflect changes in dispute state handling and removed obsolete checks.

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

Summary by CodeRabbit

  • New Features

    • Enhanced dispute activity tracking with dual-status flags (dispute + current round).
    • Withdrawals now aggregate rewards across all rounds and auto-clear contributions.
  • Refactor

    • Stricter activity validation across voting, commits, and appeals; some commit functions no longer require the old precondition.
    • Dispute creation now requires specifying number of votes.
    • Simplified withdrawal API and streamlined event payload; query return shapes and error messages updated.
  • Documentation

    • Added guidance: a round must exist before creating a dispute.
  • Tests

    • Updated to reflect the new activity model, API changes, and event schema.

Copy link
Contributor

coderabbitai bot commented Oct 13, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Introduces an Active struct for dispute tracking (dispute + currentRound), replaces per-dispute jumped flag and notJumped modifier with isActive, updates createDispute signature (adds _nbVotes), aggregates withdrawal logic across rounds and simplifies Withdrawal event, and removes notJumped guards from Shutter castCommit functions; tests updated accordingly.

Changes

Cohort / File(s) Summary
Active-state refactor (Classic DK)
contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol
Introduces Active struct and changes coreDisputeIDToActive to Active; removes Dispute.jumped; replaces notJumped with isActive; updates createDispute (adds _nbVotes and reuse logic), fundAppeal, draw/cast flows, error names, and state updates.
Withdrawal API & events
contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol
Changes withdrawFeesAndRewards signature (removes one param), aggregates reimbursements across all rounds when withdrawing, clears per-round contributions after payout, and updates Withdrawal event to the new 4-field form.
Shutter DK modifier changes
contracts/src/arbitration/dispute-kits/DisputeKitShutter.sol, contracts/src/arbitration/dispute-kits/DisputeKitGatedShutter.sol
Removes notJumped(_coreDisputeID) modifier from castCommitShutter; inline comments adjusted to note _castCommit() validates activity/ownership.
Interface change
contracts/src/arbitration/interfaces/IDisputeKit.sol
createDispute gains an extra uint256 _nbVotes parameter and docs note that KlerosCore.Round must exist before calling.
Tests updated (Foundry)
contracts/test/foundry/KlerosCore_Appeals.t.sol, .../KlerosCore_Disputes.t.sol, .../KlerosCore_Execution.t.sol, .../KlerosCore_Voting.t.sol
Tests adjusted for new coreDisputeIDToActive return shape (tuple: dispute,currentRound), changed disputes(...) return shape (removed jumped), updated revert selectors (DisputeJumpedToAnotherDisputeKit, DisputeUnknownInThisDisputeKit), updated withdrawFeesAndRewards calls and expected Withdrawal emits, and other assertions aligned to new active/currentRound semantics.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Core as KlerosCore
  participant DK as DisputeKitClassicBase
  participant DKs as DisputeKitShutter*
  participant Juror
  participant Funder as Crowdfunder

  Note over Core,DK: Dispute creation (new API)
  Core->>DK: createDispute(coreDisputeID, choices, extraData, nbVotes)
  DK->>DK: set coreDisputeIDToActive[coreDisputeID] = Active{dispute=true, currentRound=true}
  DK-->>Core: local dispute initialized / reused

  Note over Core,DK: Voting / Commit / Draw
  Juror->>DKs: castCommitShutter(coreDisputeID, ...)
  DKs->>DK: _castCommit(...) -> DK.isActive(coreDisputeID)? (dispute && currentRound)
  DK-->>Juror: accept/reject commit

  Note over Core,DK: Appeal funding and jumping
  Funder->>Core: fundAppeal(coreDisputeID,...)
  Core->>DK: fundAppeal(...)
  DK->>DK: If jump -> coreDisputeIDToActive[coreDisputeID].currentRound = false
  DK-->>Core: appeal result / jump noted

  Note over DK,Funder: Withdrawal (aggregated)
  Funder->>DK: withdrawFeesAndRewards(disputeID, recipient, round)
  DK->>DK: iterate rounds, compute reimbursements, clear contributions
  DK-->>Funder: emit Withdrawal(disputeID, round, recipient, amount)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • unknownunknown1
  • kemuru
  • tractorss

Poem

Hop-hop, I tidy every burrow and mound,
Two flags now guard where disputes are found.
No more mystery jumps mid-night,
Shutters listen, commits feel right.
Rounds counted, carrots shared—logic sound. 🥕🐇

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title concisely summarizes the primary change—refactoring Dispute Kit state/jump checks to make active-vs-jumped semantics explicit—and matches the PR objectives and diffs. It is short, clear, and focused without listing files or unrelated details, so a reviewer can quickly understand the high-level intent. The wording could be slightly more precise about the introduced "Active"/"isActive" API but remains accurate.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 374b4f2 and f9fd944.

📒 Files selected for processing (2)
  • contracts/src/arbitration/dispute-kits/DisputeKitGatedShutter.sol (2 hunks)
  • contracts/src/arbitration/dispute-kits/DisputeKitShutter.sol (2 hunks)

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

@jaybuidl jaybuidl changed the title Refactor of the active DK and jump checks Refactor the Dispute Kit checks: active dispute and jump checks Oct 13, 2025
@jaybuidl jaybuidl changed the title Refactor the Dispute Kit checks: active dispute and jump checks Refactor the Dispute Kit checks: active dispute and jumps Oct 13, 2025
@jaybuidl jaybuidl changed the title Refactor the Dispute Kit checks: active dispute and jumps Refactor the Dispute Kit checks: active dispute and isJumped Oct 13, 2025
@jaybuidl jaybuidl force-pushed the feat/recurring-dk-test branch from 1e7d185 to 536e61c Compare October 13, 2025 22:53
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol (1)

56-75: Blocking: new Active layout corrupts existing state

Upgrading the proxy with coreDisputeIDToActive now storing Active (two bools) instead of a single bool is not storage-compatible. All legacy entries were 0x01 (meaning “true”). After the upgrade, that same slot decodes to dispute = true but currentRound = false. Because isActive now requires both flags, every dispute that was mid-round before the upgrade will immediately revert with DisputeJumpedToAnotherDisputeKit, preventing draws, commits, votes, and appeals. There is no way to backfill currentRound for those mappings on-chain.

Please preserve the old storage contract (e.g., keep the original bool, or derive currentRound lazily while distinguishing real jumps) or provide a safe migration path that sets currentRound for all active disputes before enforcing the new check. As written, this change bricks live disputes post-upgrade.

🧹 Nitpick comments (2)
contracts/test/foundry/KlerosCore_Appeals.t.sol (2)

586-589: Initial active/currentRound semantics — LGTM

Good use of (disputeActive, currentRound) to assert both dispute visibility and round ownership.

Consider extracting a tiny helper in the test base to assert (active,current) pairs to reduce repetition across tests.


716-719: Fix misleading comment: argument is a core dispute ID, not a local one

The function coreDisputeIDToActive expects a core dispute ID. The inline comment says “local dispute id”.

Apply:

- (disputeActive, currentRound) = disputeKit3.coreDisputeIDToActive(0); // local dispute id
+ (disputeActive, currentRound) = disputeKit3.coreDisputeIDToActive(0); // core dispute id
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1e7d185 and 374b4f2.

📒 Files selected for processing (8)
  • contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol (12 hunks)
  • contracts/src/arbitration/dispute-kits/DisputeKitGatedShutter.sol (1 hunks)
  • contracts/src/arbitration/dispute-kits/DisputeKitShutter.sol (1 hunks)
  • contracts/src/arbitration/interfaces/IDisputeKit.sol (1 hunks)
  • contracts/test/foundry/KlerosCore_Appeals.t.sol (15 hunks)
  • contracts/test/foundry/KlerosCore_Disputes.t.sol (1 hunks)
  • contracts/test/foundry/KlerosCore_Execution.t.sol (2 hunks)
  • contracts/test/foundry/KlerosCore_Voting.t.sol (2 hunks)
🔇 Additional comments (16)
contracts/test/foundry/KlerosCore_Appeals.t.sol (16)

301-302: Active-state check on jumped DK — LGTM

Correctly asserts currentRound is false on the DK the dispute jumped from.


315-316: Active DK currentRound assertion — LGTM

Correctly asserts the new DK has currentRound = true.


320-320: Renamed error selector usage — LGTM

Updated to DisputeJumpedToAnotherDisputeKit as per refactor.


439-440: Post-jump active-state on dk3 — LGTM

Asserting currentRound = false on the old DK is correct.


453-454: Active DK switched — LGTM

Correct currentRound = true on the destination DK.


458-458: Error rename on draw guard — LGTM

Expecting DisputeJumpedToAnotherDisputeKit is correct after the jump.


624-627: After first jump: dispute active but round jumped — LGTM

Asserting active=true, currentRound=false is correct for the source DK.


643-646: Destination DK active/current — LGTM

Asserting active=true, currentRound=true is correct on the new DK.


652-652: Draw from outdated DK reverts — LGTM

Correctly guarded by DisputeJumpedToAnotherDisputeKit.


665-665: castVote on outdated DK reverts — LGTM

Correct revert selector used.


674-675: fundAppeal on outdated DK reverts — LGTM

Matches the new unknown/jumped semantics.


692-695: After second jump: dk2 round jumped — LGTM

active=true, currentRound=false is correct.


730-730: Draw from outdated DK reverts — LGTM

Selector update is consistent.


743-743: castVote from outdated DK reverts — LGTM

Selector update is consistent.


757-775: Withdrawal flow: signature change and error rename — looks right

  • Updated withdrawFeesAndRewards(disputeID, recipient, choice) usage is correct.
  • Withdrawal amounts and DK targeting align with active/currentRound semantics.
  • Reverts with DisputeUnknownInThisDisputeKit on an unrelated DK are correct.

If handy, add quick asserts around DK balances post-withdrawals to ensure funds moved as expected and no dust remains due to rounding:

// e.g., after the two withdrawals:
assertEq(address(disputeKit3).balance, /* expected */);
assertEq(address(disputeKit2).balance, /* expected */);

Optionally, also assert no event is emitted for zero-withdrawal paths to lock event semantics.


826-826: Updated disputes() return shape — LGTM

Tuple destructuring matches the new getter.

@jaybuidl jaybuidl merged commit a0a3a67 into feat/recurring-dk-test Oct 14, 2025
3 of 4 checks passed
@jaybuidl jaybuidl deleted the refactor/active-dk branch October 14, 2025 14:39
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants