Skip to content

Release #2012

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 181 commits into
base: master
Choose a base branch
from
Draft

Release #2012

wants to merge 181 commits into from

Conversation

jaybuidl
Copy link
Member

@jaybuidl jaybuidl commented May 28, 2025

Contract changes


PR-Codex overview

This PR focuses on enhancing the dispute resolution system by introducing new components and updating existing ones, particularly around the Shutter dispute kit, along with various improvements in the codebase for better functionality and maintainability.

Detailed summary

  • Deleted AllCasesButton component.
  • Introduced SeeAllCasesButton and SeeAllJurorsButton components.
  • Updated JustificationArea import paths.
  • Enhanced dispute-related components with new props and functionality.
  • Added disputeKit to the StakingResult enum.
  • Updated environment variables to include REACT_APP_SHUTTER_API.
  • Improved error handling in hooks and queries.
  • Adjusted various components to use the new disputeKit structure.
  • Updated package versions in package.json files.
  • Refactored function signatures to include new parameters for dispute handling.
  • Enhanced UI components for better responsiveness and user experience.
  • Added new contracts for DisputeKitGatedShutterProxy and DisputeKitShutterProxy.
  • Cleaned up unused code and comments across multiple files.

The following files were skipped due to too many changes: web/src/pages/Profile/index.tsx, subgraph/core/abi-migrations/KlerosCore.json, web/src/assets/svgs/icons/gavel-executed.svg, contracts/test/arbitration/draw.ts, web/src/pages/Cases/CaseDetails/Voting/index.tsx, subgraph/core/subgraph.yaml, web/src/pages/Cases/CaseDetails/Voting/Shutter/Reveal.tsx, subgraph/scripts/update.sh, web/src/components/DisputePreview/DisputeContext.tsx, web/src/components/EvidenceCard.tsx, subgraph/core/tests/sortition-module-utils.ts, web/src/components/Verdict/FinalDecision.tsx, contracts/test/arbitration/index.ts, subgraph/core-neo/abi-migrations/SortitionModuleNeo.json, contracts/src/arbitration/dispute-kits/DisputeKitShutter.sol, web/src/pages/Cases/CaseDetails/Voting/Shutter/Commit.tsx, contracts/src/arbitration/dispute-kits/DisputeKitGated.sol, web/src/pages/Cases/CaseDetails/Appeal/Shutter/Fund.tsx, subgraph/core/abi-migrations/SortitionModule.json, subgraph/core-university/subgraph.template.yaml, web/src/utils/shutter.ts, subgraph/core/src/DisputeKitClassic.ts, yarn.lock, subgraph/core-neo/subgraph.template.yaml, web/src/components/Verdict/DisputeTimeline.tsx, subgraph/core/subgraph.template.yaml, contracts/src/arbitration/dispute-kits/DisputeKitGatedShutter.sol, contracts/src/arbitration/KlerosCoreBase.sol, contracts/scripts/shutter.ts, contracts/scripts/keeperBotShutter.ts, contracts/src/arbitration/university/KlerosCoreUniversity.sol, contracts/test/arbitration/dispute-kit-gated.ts, contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol, contracts/src/arbitration/university/SortitionModuleUniversity.sol, contracts/scripts/keeperBot.ts, contracts/deployments/arbitrumSepoliaDevnet/DisputeKitShutter_Proxy.json, contracts/test/arbitration/staking.ts, contracts/test/arbitration/staking-neo.ts, contracts/src/arbitration/SortitionModuleBase.sol, contracts/test/foundry/KlerosCore.t.sol, contracts/deployments/arbitrumSepoliaDevnet/DisputeKitShutter.json, contracts/deployments/arbitrumSepoliaDevnet/DisputeKitShutter_Implementation.json

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

Summary by CodeRabbit

  • New Features

    • Added "See All" buttons for cases and jurors for easier navigation.
    • Introduced new contract functions exposing detailed dispute and court info.
    • Enabled jurors to withdraw leftover PNK tokens after fully unstaking.
    • Added Shutter dispute kit supporting encrypted vote commit and reveal.
    • Launched appeal crowdfunding UI and logic for Shutter dispute kit.
    • Added Shutter vote commit and reveal components with encryption integration.
    • Added new dispute kits with token gating and shielded voting capabilities.
    • Added ERC1155 test token contract and deployment support.
    • Added scripts for Shutter vote auto-reveal and encryption/decryption utilities.
    • Added new proxy contracts for DisputeKitGatedShutter and DisputeKitShutter.
    • Added new Bash script to analyze initializer versions across multiple networks.
    • Added new subgraph manifests for Core Neo and University versions.
    • Added dynamic dispute kit ID handling in subgraph for multi-kit support.
    • Added support for multiple dispute kits in keeper bot and subgraph.
    • Added new React components and hooks for Shutter voting commit and reveal phases.
  • Improvements

    • Enhanced layout and alignment in "Latest Cases" and "Top Jurors" sections.
    • Improved appeal countdown wording for clarity.
    • Added color styling for loading states in document viewer.
    • Added pre-check to avoid unnecessary juror draw attempts.
    • Context-sensitive navigation in attachment headers.
    • URLs for policy and evidence links now include dispute IDs.
    • Enhanced dispute context and labeling components.
    • Streamlined timeline and verdict components.
    • Added thousands separators in numeric displays.
    • Centralized user case statistics calculation.
    • Introduced filter sanitization utility for queries.
    • Improved accuracy in dispute event identification.
    • Separated stake validation and state updates in staking contracts.
    • Simplified delayed stake handling and unified related events.
    • Improved penalty accounting and juror inactivity handling.
    • Strengthened access control on stake-related functions.
    • Enhanced dispute lifecycle state management on appeal decisions.
    • Improved shutdown handling and logging in keeper bot.
    • Integrated Shutter API for vote encryption and decryption.
    • Added Vite plugin to copy Shutter SDK static files.
    • Added environment variables for Shutter API endpoint across environments.
    • Improved popup components to support automatic vote reveal messaging.
    • Refined staking and delayed stake event handling in tests.
    • Updated contract initialization routines and versioning.
    • Simplified and unified event handlers in subgraph and test utilities.
    • Enhanced dispute kit event handling with dynamic dispute kit IDs.
    • Improved contract deployment scripts with new dispute kits.
    • Improved staking logic with explicit leftover PNK withdrawal functions.
    • Added support for DisputeKitShutter in contract utilities.
    • Added new environment variable declarations for Shutter API in multiple environments.
    • Upgraded Node.js and devDependencies versions in contracts package.
    • Updated Yarn version in package configuration.
  • Bug Fixes

    • Added active-state checks to prevent operations on inactive disputes.
    • Corrected court ID boundary checks and error handling in staking logic.
    • Fixed staking and delayed stake event emissions and token balance assertions in tests.
    • Fixed event signature and parameter mismatches in subgraph and contracts.
    • Corrected vote casting logic for multiple dispute kits.
  • Chores

    • Updated documentation and package versions.
    • Removed unused components and redundant code.
    • Consolidated event handlers and test utilities for simpler maintenance.
    • Added deployment and upgrade scripts for new dispute kits.

jaybuidl and others added 30 commits April 24, 2025 18:06
…ata sources not deployed

e.g. DisputeKitShutter on testnet
…ple-dispute-kit-above-id-1

feat: subgraph support for shutter disputekit in devnet
jaybuidl and others added 27 commits July 21, 2025 20:01
fix(subgraph): total-leaderboard-jurors-count
…bgraph

chore: dispute-kit-gated-subgraph-support
Support for Gated Dispute Kits and other improvements
chore: testnet upgrade and new Dispute Kits deployment
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: 2

🧹 Nitpick comments (1)
contracts/deployments/arbitrumSepolia/DisputeKitClassic.json (1)

757-785: Minor naming / UX nit – consider pluralising the function name

getLocalDisputeRoundID() returns two IDs (localDisputeID, localRoundID) yet its name is singular.
Renaming to getLocalDisputeAndRoundIDs (plural) would better communicate the tuple return and avoid future mis-reads.

Purely cosmetic, feel free to ignore if you want to preserve backwards compatibility.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e2e6412 and 041f3d9.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (10)
  • contracts/README.md (4 hunks)
  • contracts/deployments/arbitrumSepolia/DisputeKitClassic.json (5 hunks)
  • contracts/deployments/arbitrumSepolia/DisputeKitGated.json (1 hunks)
  • contracts/deployments/arbitrumSepolia/DisputeKitGatedShutter.json (1 hunks)
  • contracts/deployments/arbitrumSepolia/DisputeKitGatedShutter_Proxy.json (1 hunks)
  • contracts/deployments/arbitrumSepolia/DisputeKitGated_Proxy.json (1 hunks)
  • contracts/deployments/arbitrumSepolia/DisputeKitShutter.json (1 hunks)
  • contracts/deployments/arbitrumSepolia/DisputeKitShutter_Proxy.json (1 hunks)
  • contracts/deployments/arbitrumSepolia/KlerosCore.json (4 hunks)
  • contracts/deployments/arbitrumSepolia/SortitionModule.json (11 hunks)
✅ Files skipped from review due to trivial changes (6)
  • contracts/deployments/arbitrumSepolia/DisputeKitShutter_Proxy.json
  • contracts/deployments/arbitrumSepolia/DisputeKitGated_Proxy.json
  • contracts/deployments/arbitrumSepolia/DisputeKitGatedShutter.json
  • contracts/deployments/arbitrumSepolia/DisputeKitGated.json
  • contracts/deployments/arbitrumSepolia/DisputeKitGatedShutter_Proxy.json
  • contracts/deployments/arbitrumSepolia/DisputeKitShutter.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • contracts/README.md
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: jaybuidl
PR: kleros/kleros-v2#1746
File: contracts/config/courts.v2.mainnet-neo.json:3-5
Timestamp: 2024-11-19T17:18:39.007Z
Learning: In `contracts/config/courts.v2.mainnet-neo.json`, the General Court (id: 1) intentionally references itself as its parent (`"parent": 1`). This self-reference is acceptable and should not be flagged as an issue in future reviews.
Learnt from: kemuru
PR: kleros/kleros-v2#1702
File: web/src/pages/Home/TopJurors/JurorCard/index.tsx:10-11
Timestamp: 2024-10-07T06:18:23.427Z
Learning: In the `kleros-v2` codebase, the property `totalResolvedDisputes` should remain and should not be renamed to `totalResolvedVotes`.
Learnt from: kemuru
PR: kleros/kleros-v2#1702
File: web/src/pages/Home/TopJurors/JurorCard/index.tsx:10-11
Timestamp: 2024-10-08T16:23:56.291Z
Learning: In the `kleros-v2` codebase, the property `totalResolvedDisputes` should remain and should not be renamed to `totalResolvedVotes`.
contracts/deployments/arbitrumSepolia/DisputeKitClassic.json (4)

Learnt from: Harman-singh-waraich
PR: #1703
File: kleros-sdk/src/utils/getDispute.ts:38-40
Timestamp: 2024-10-21T10:32:16.970Z
Learning: The variables 'arbitrableChainID' and 'externalDisputeID' are required by the context to have uppercase 'ID', so they should remain unchanged even if the corresponding source properties use 'Id'.

Learnt from: kemuru
PR: #1702
File: web/src/pages/Home/TopJurors/JurorCard/index.tsx:10-11
Timestamp: 2024-10-07T06:18:23.427Z
Learning: In the kleros-v2 codebase, the property totalResolvedDisputes should remain and should not be renamed to totalResolvedVotes.

Learnt from: kemuru
PR: #1702
File: web/src/pages/Home/TopJurors/JurorCard/index.tsx:10-11
Timestamp: 2024-10-08T16:23:56.291Z
Learning: In the kleros-v2 codebase, the property totalResolvedDisputes should remain and should not be renamed to totalResolvedVotes.

Learnt from: Harman-singh-waraich
PR: #1703
File: web/src/hooks/queries/usePopulatedDisputeData.ts:58-61
Timestamp: 2024-10-14T13:58:25.708Z
Learning: In web/src/hooks/queries/usePopulatedDisputeData.ts, the query and subsequent logic only execute when disputeData.dispute?.arbitrableChainId and disputeData.dispute?.externalDisputeId are defined, so initialContext properties based on these values are safe to use without additional null checks.

contracts/deployments/arbitrumSepolia/KlerosCore.json (1)

Learnt from: jaybuidl
PR: #1746
File: contracts/config/courts.v2.mainnet-neo.json:167-170
Timestamp: 2024-11-19T16:31:08.965Z
Learning: In contracts/config/courts.v2.mainnet-neo.json, the minStake parameter is denominated in PNK, not ETH.

contracts/deployments/arbitrumSepolia/SortitionModule.json (3)

Learnt from: jaybuidl
PR: #1746
File: contracts/config/courts.v2.mainnet-neo.json:167-170
Timestamp: 2024-11-19T16:31:08.965Z
Learning: In contracts/config/courts.v2.mainnet-neo.json, the minStake parameter is denominated in PNK, not ETH.

Learnt from: jaybuidl
PR: #1746
File: contracts/config/courts.v2.mainnet-neo.json:3-17
Timestamp: 2024-11-19T16:09:41.467Z
Learning: In contracts/config/courts.v2.mainnet-neo.json, the General Court (ID: 1) can have its parent ID set to itself ("parent": 1), as there is no parent court with ID 0 currently.

Learnt from: jaybuidl
PR: #1746
File: contracts/config/courts.v2.mainnet-neo.json:3-5
Timestamp: 2024-11-19T17:18:39.007Z
Learning: In contracts/config/courts.v2.mainnet-neo.json, the General Court (id: 1) intentionally references itself as its parent ("parent": 1). This self-reference is acceptable and should not be flagged as an issue in future reviews.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (18)
  • GitHub Check: Redirect rules - kleros-v2-university
  • GitHub Check: Header rules - kleros-v2-university
  • GitHub Check: Pages changed - kleros-v2-university
  • GitHub Check: contracts-testing
  • GitHub Check: SonarCloud
  • GitHub Check: Analyze (javascript)
  • GitHub Check: Redirect rules - kleros-v2-neo
  • GitHub Check: Header rules - kleros-v2-neo
  • GitHub Check: Redirect rules - kleros-v2-testnet
  • GitHub Check: Pages changed - kleros-v2-neo
  • GitHub Check: Redirect rules - kleros-v2-testnet
  • GitHub Check: Header rules - kleros-v2-testnet
  • GitHub Check: Header rules - kleros-v2-testnet
  • GitHub Check: Pages changed - kleros-v2-testnet
  • GitHub Check: Pages changed - kleros-v2-testnet
  • GitHub Check: SonarCloud
  • GitHub Check: Analyze (javascript)
  • GitHub Check: contracts-testing
🔇 Additional comments (13)
contracts/deployments/arbitrumSepolia/DisputeKitClassic.json (4)

486-504: Confirm active-flag lifecycle is handled correctly

coreDisputeIDToActive() surfaces the liveness of a dispute at the DK level.
Because this is now part of the public interface, it is critical that the flag is:

  1. Set to true exactly once at dispute creation, and
  2. Reset to false immediately after the final ruling (including jumps / forks).

Otherwise the mapping becomes an ever-growing list of true values that can never be GC’d, inflating storage costs indefinitely.

Please double-check the implementation in DisputeKitClassic.sol and the core hooks that flip this bit.


787-804: LGTM – cheap accessor

getNumberOfRounds(uint256) is a view that will be heavily used by indexers; exposing it directly is welcome.
Assuming the implementation is an O(1) array length read, no concerns.


916-944: Ensure off-chain commit hash helpers include justification too

hashVote(uint256 _choice, uint256 _salt, string _justification) now factors the justification into the commitment.
This prevents jurors from editing justifications post-reveal, but it is a breaking change for any client code that previously used keccak256(abi.encodePacked(choice, salt)).

Please verify that:
• Front-end helpers (e.g. utils/hashVote.ts) have been updated,
• Keeper / bot scripts use the same formula, and
• Historical disputes created with the old hash are not affected (i.e. the DK version check gates the new logic).

If any external integrations rely on the old 2-field hash, consider keeping both helpers or bumping a major version.


965-969: Initializer v7 – double-check that storage gaps remain forward-compatible

The proxy now executes initialize7() with no arguments.
Given previous initializers took governor & core addresses, the new version presumably only migrates storage/layout.

Action items:

  1. Confirm initialize7() is reinitializer(7) (or equivalent) to guard against replay.
  2. Make sure the upgrade script does not accidentally re-run earlier initializers on fresh deployments.
  3. Verify that storage gaps (if any) were not repurposed, to avoid clashing with future upgrades.

Everything else looks consistent with the UUPS flow.

Also applies to: 1165-1167

contracts/deployments/arbitrumSepolia/KlerosCore.json (3)

1682-1686: initialize5() – verify upgrade flow & single-execution guarantee

The proxy is executed with initialize5() (no params).
Make sure:

  1. Older deployment scripts are updated to call only this new version to avoid the AlreadyInitialized revert.
  2. Any new storage introduced in re-initializer 5 is actually set via the call (empty args here suggest purely internal changes).

1329-1336: Audit all draw() invocations to consume its new return value

The draw method now returns nbDrawnJurors. Any script, test or front-end code that simply calls

await core.draw(disputeID, iterations)

will only get a TransactionResponse and silently discard the juror count. Please review and update all callers, for example:

  • contracts/test/integration/index.ts
  • contracts/test/arbitration/staking.ts
  • contracts/test/arbitration/draw.ts
  • contracts/scripts/console-init.ts
  • specifications/dispute-kit-classic.md

Ensure consumers needing the juror count use a static call or unpack the return, e.g.:

const nbDrawnJurors = await core.callStatic.draw(disputeID, 10);

Or, if you intentionally ignore it, make that explicit in code or comments.


1857-1874: transferBySortitionModule is already access‐controlled

The transferBySortitionModule implementation in KlerosCoreBase checks that only the sortition module can call it:

function transferBySortitionModule(address _account, uint256 _amount) external {
    if (msg.sender != address(sortitionModule)) revert SortitionModuleOnly();
    pinakion.safeTransfer(_account, _amount);
}

No further changes needed.

contracts/deployments/arbitrumSepolia/SortitionModule.json (6)

68-84: Event rename looks good – confirm downstream updates.

LeftoverPNK cleanly replaces the old delayed–stake leftover-PNK events and indexes the _account address, which is what sub-graph consumers usually filter on.
Please double-check that:

  1. Subgraph mappings (and any off-chain listeners) have been migrated to this new event name.
  2. No code still relies on the legacy StakeDelayedAlreadyTransferredDeposited/…Withdrawn events.

491-509: Handy view helper – LGTM.

getJurorLeftoverPNK(address) is a welcome addition and is view, avoiding gas for simple queries.
No concerns here.


562-566: initialize4() – ensure proper re-initializer guards.

Having both initialize and a parameter-less initialize4 is fine under the OZ reinitializer(4) pattern, but please verify that:
• The implementation contract uses @openzeppelin/contracts-upgradeable’s reinitializer(4) modifier, not a custom boolean, and
• Front-end/deployment scripts call the correct initializer only once.


1019-1031: Confirm Access Control on withdrawLeftoverPNK(address)

I wasn’t able to locate the Solidity source for the SortitionModule implementation, only its ABI in contracts/deployments/arbitrumSepolia/SortitionModule.json. Please verify in your SortitionModule.sol that:

withdrawLeftoverPNK(address _account) enforces that only _account can withdraw its own leftovers (for example, require(msg.sender == _account)).
• If there is no such check, either add an appropriate access modifier (onlyAccount, onlyOwner, etc.) or refactor the function to withdrawLeftoverPNK() (no args) and use msg.sender directly.

Without confirming these protections, callers could drain or grief arbitrary accounts.


858-880: Incorrect: setStake ABI matches contract signature

The deployed ABI’s setStake inputs—(_account, _courtID, _pnkDeposit, _pnkWithdrawal, _newStake)—exactly mirror the Solidity declaration in SortitionModuleBase.sol. There is no _alreadyTransferred parameter in the function signature to drop, nor any reordering beyond the intended parameter order.

You can safely ignore this review comment.

Likely an incorrect or invalid review comment.


128-141: Indexed uint96 is supported by The Graph via BigInt — no change needed

The Graph’s AssemblyScript API only offers i32 (for 32-bit values) and BigInt (for anything larger). A uint96 event parameter will automatically be decoded as a BigInt in your mappings, so you don’t need to switch it to uint256 or remove the indexed flag. Just be sure your handler uses:

let courtID = event.params._courtID.toBigInt();

Likely an incorrect or invalid review comment.

Comment on lines 725 to +737
"name": "penalizeStake",
"outputs": [],
"outputs": [
{
"internalType": "uint256",
"name": "pnkBalance",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "availablePenalty",
"type": "uint256"
}
],
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

penalizeStake return tuple changes are breaking.

The function now returns (pnkBalance, availablePenalty).
All callers (Core, DKs, bots, tests, subgraph handlers) must adjust to:

(uint256 balanceAfter, uint256 penaltyApplied) = sortition.penalizeStake(...);

Failing to update will silently ignore the new return data and may break business logic.

🤖 Prompt for AI Agents
In contracts/deployments/arbitrumSepolia/SortitionModule.json around lines 725
to 737, the penalizeStake function's return type has changed to a tuple
(pnkBalance, availablePenalty). Update all callers of penalizeStake in the Core,
DKs, bots, tests, and subgraph handlers to destructure the returned tuple into
two variables, for example (uint256 balanceAfter, uint256 penaltyApplied), to
properly handle both returned values and avoid ignoring important data that
could break business logic.

Comment on lines +967 to +1005
{
"inputs": [
{
"internalType": "address",
"name": "_account",
"type": "address"
},
{
"internalType": "uint96",
"name": "_courtID",
"type": "uint96"
},
{
"internalType": "uint256",
"name": "_newStake",
"type": "uint256"
}
],
"name": "validateStake",
"outputs": [
{
"internalType": "uint256",
"name": "pnkDeposit",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "pnkWithdrawal",
"type": "uint256"
},
{
"internalType": "enum StakingResult",
"name": "stakingResult",
"type": "uint8"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

validateStake should be view – no state mutation observed.

validateStake only returns computed values and an enum – it shouldn’t modify storage. Marking it nonpayable instead of view prevents Solidity from enforcing read-only guarantees and incurs higher gas if mis-used.

-function validateStake(address _account, uint96 _courtID, uint256 _newStake) external nonpayable
+function validateStake(address _account, uint96 _courtID, uint256 _newStake) external view

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In contracts/deployments/arbitrumSepolia/SortitionModule.json between lines 967
and 1005, the function validateStake is marked as nonpayable but does not modify
any state and only returns computed values. Change its stateMutability from
"nonpayable" to "view" to correctly indicate it is a read-only function,
enabling Solidity to enforce this and optimize gas usage.

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.

5 participants