Skip to content

chore: sync-changes-from-governor-in-kleros-v2#16

Open
tractorss wants to merge 11 commits intomasterfrom
chore/contracts-sync-with-kleros-v2
Open

chore: sync-changes-from-governor-in-kleros-v2#16
tractorss wants to merge 11 commits intomasterfrom
chore/contracts-sync-with-kleros-v2

Conversation

@tractorss
Copy link
Copy Markdown
Contributor

@tractorss tractorss commented Oct 6, 2025

WIP

Summary by CodeRabbit

  • New Features

    • Wrapped-native fallback for failed ETH transfers (wNative/WETH) and safer send behavior
    • URL-driven list examination modal with card-driven open handler
  • Improvements

    • Governance controls moved to owner-managed flows and clearer error reporting
    • Mapping to correlate external disputes with internal sessions (improved dispute tracking)
  • Updates

    • Dependency/version adjustments and removal of one verification dev-dependency
    • Deployment artifacts, env examples, docs, and helper scripts added/updated

✏️ Tip: You can customize this high-level summary in your review settings.

@netlify
Copy link
Copy Markdown

netlify bot commented Oct 6, 2025

Deploy Preview for kleros-governor-v2 ready!

Name Link
🔨 Latest commit 0dc929f
🔍 Latest deploy log https://app.netlify.com/projects/kleros-governor-v2/deploys/6944078a1a783a0008d2b4e6
😎 Deploy Preview https://deploy-preview-16--kleros-governor-v2.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

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

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Oct 6, 2025

Walkthrough

Adds SafeSend (WETH fallback) and wNative support, refactors KlerosGovernor access/errors and dispute mapping, updates deployment artifacts/scripts (WETH, chainId, factory args), consolidates Etherscan API usage, and adjusts frontend list modal flow and governor addresses.

Changes

Cohort / File(s) Summary
Dependency Updates
contracts/package.json
Removed @nomicfoundation/hardhat-verify; bumped hardhat-deploy to ^1.0.4; upgraded @kleros/kleros-v2-contracts to ^2.0.0-rc.1.
SafeSend Library
contracts/src/libraries/SafeSend.sol
Added WethLike interface and SafeSend library with safeSend(address payable,uint256,address) that attempts native transfer and falls back to WETH deposit+transfer.
Core Contract Refactor
contracts/src/KlerosGovernor.sol
Replaced many governor-only checks with owner semantics, introduced custom errors, added address public wNative and mapping(uint256 => uint256) public arbitratorDisputeIDToSessionIndex, integrated SafeSend.safeSend for transfers, updated constructor to accept _wNative, and changed DisputeRequest event signature.
Governor Factory
contracts/src/GovernorFactory.sol
deploy(...) now accepts address _wNative and forwards it to KlerosGovernor; import style for IDisputeTemplateRegistry adjusted.
Deployment Script Changes
contracts/deploy/00-governor-v2.ts
Retrieve WETH contract, include wNative.target in governor factory arguments, centralize argument arrays (gfArgs/kgArgs).
Deployment Artifacts
contracts/deployments/arbitrum/.chainId, contracts/deployments/arbitrum/WETH.json, contracts/deployments/arbitrumSepoliaDevnet/WETH.json
Added Arbitrum chainId file and WETH deployment artifacts (addresses, ABIs, metadata) for Arbitrum mainnet and Arbitrum Sepolia Devnet.
Dispute Template & Mappings
contracts/deploy/utils/disputeTemplate.ts
Template description now references sessionIndex; added ABI mapping call arbitratorDisputeIDToSessionIndex(uint256) to populate sessionIndex; adjusted mapping order to use sessionIndex.
Get Contracts Mapping
contracts/deploy/utils/getContracts.ts
NETWORK_TO_DEPLOYMENT["arbitrum"] changed from "mainnetNeo" to "mainnet".
Hardhat / Verification
contracts/hardhat.config.ts, contracts/scripts/verifyProxies.sh
Consolidated etherscan API key usage to ETHERSCAN_API_KEY, removed per-network apiUrl fields, verifyProxies.sh now accepts chainId, uses etherscan v2 endpoint, and requires an API key.
Env & Scripts
contracts/.env.example, contracts/scripts/dotenv.sh, contracts/.gitignore
Added env placeholders; added dotenv.sh helper to print env vars; .gitignore adjusted to allow .env.example.
Docs & Templates
contracts/README.md, contracts/README.md.template
Added deployment README; updated template references from GovernorV2 to KlerosGovernor; replaced some API key env names with ETHERSCAN_API_KEY_FIX in examples.
Frontend — List Modal Flow
web/src/app/(main)/governor/[governorAddress]/ActiveLists/ListCard.tsx, web/src/app/(main)/governor/[governorAddress]/ActiveLists/index.tsx
ListCard no longer manages modal state; accepts setIsOpen: (list) => void. Parent index component adds URL-driven open (listId), openList state, handlers, and renders ExamineModal.
Frontend — Governors Consts
web/src/consts/governors.ts
Updated three governor addresses to 0x6Bf62e6bBCE8c09d916189680F411E5DD0DAd004.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant User as User (EOA)
    participant Governor as KlerosGovernor
    participant Recipient as Recipient (payable)
    participant WETH as WETH (wNative)
    participant Arbitrator as Arbitrator

    Note over User,Governor: submitList / payout / dispute flow (high-level)
    User->>Governor: submitList(...){payable ETH}
    Governor->>Recipient: try native ETH transfer
    alt native transfer succeeds
        Recipient-->>Governor: receive ETH
    else native transfer fails
        Governor->>WETH: deposit() payable (wrap ETH)
        Governor->>WETH: transfer(Recipient, amount)
    end
    opt dispute requested
        Governor->>Arbitrator: createDispute(...)
        Arbitrator-->>Governor: disputeID
        Governor->>Governor: arbitratorDisputeIDToSessionIndex[disputeID] = sessionIndex
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Focus review on:
    • contracts/src/KlerosGovernor.sol (access control changes, custom errors, SafeSend/wNative handling, event signature).
    • GovernorFactory and deployment script argument propagation (00-governor-v2.ts).
    • verifyProxies.sh and hardhat.config.ts (Etherscan API changes and chainId handling).
    • Frontend modal prop change (ListCard) and parent wiring (index.tsx).

Possibly related PRs

  • Feat/homepage #8 — touches the same frontend ListCard/modal flow; likely overlaps with the ListCard prop/signature change.
  • feat: governor-functionality #10 — modifies KlerosGovernor and deployment tooling; likely overlaps with contract refactor and deployment updates.

Suggested reviewers

  • alcercu

Poem

🐰
I hopped through code with nimble paws,
Wrapped ETH in WETH when gas withdraws,
Owner-guarded gates and errors clear,
Deployments set and modals near —
I left a carrot where bugs once was. 🥕

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 PR title accurately describes the main objective: syncing changes from the governor in kleros-v2, which aligns with the substantial contract updates, dependency migrations, and integration changes across the codebase.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/contracts-sync-with-kleros-v2

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

Copy link
Copy Markdown

@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: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ebe7aa6 and 16b1997.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (3)
  • contracts/package.json (1 hunks)
  • contracts/src/KlerosGovernor.sol (16 hunks)
  • contracts/src/libraries/SafeSend.sol (1 hunks)
⏰ 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). (3)
  • GitHub Check: Redirect rules - kleros-governor-v2
  • GitHub Check: Header rules - kleros-governor-v2
  • GitHub Check: Pages changed - kleros-governor-v2

Comment thread contracts/src/KlerosGovernor.sol
Comment thread contracts/src/KlerosGovernor.sol
Comment thread contracts/src/KlerosGovernor.sol Outdated
@tractorss tractorss marked this pull request as ready for review November 19, 2025 06:30
Copy link
Copy Markdown

@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: 1

Caution

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

⚠️ Outside diff range comments (1)
web/src/consts/governors.ts (1)

21-43: Three governors sharing the same address breaks chain-specific resolution

Verification confirms the issue. All three governor entries (lines 22, 30, 38) use the identical address 0x52e6766e6C4fB05Caec92e5318668b3E366D649a:

export const getGovernor = (address: string) => governors.find((governor) => governor.address === address);

Since getGovernor searches by address alone and .find() returns the first match, any lookup for that address will always return the Arbitrum Sepolia entry. Additionally, generateStaticParams() will only create a single route for that shared address, making the Gnosis and mainnet entries unreachable.

Smart contracts typically deploy to different addresses on different networks. Either:

  • Update each governor entry with its correct network-specific address, or
  • Modify getGovernor to also accept and filter by chain if there is legitimate address reuse.

Without this fix, the Gnosis and mainnet governors cannot be accessed, and any route to that address will serve incorrect chain metadata.

♻️ Duplicate comments (2)
contracts/src/KlerosGovernor.sol (2)

55-60: Add a zero‑address guard for _wNative to avoid bricking SafeSend refunds

wNative is stored directly from the constructor argument with no validation:

address public wNative; // line 58
...
constructor(..., uint256 _withdrawTimeout, address _wNative) {
    ...
    wNative = _wNative;
}

If _wNative is ever passed as address(0), every SafeSend fallback path will revert when trying to interact with the WETH‑like contract, breaking refunds to contracts (e.g. Safes) whenever a plain ETH send fails.

Add a dedicated error and guard in the constructor:

@@
-    address public wNative; // The wrapped native token for safeSend().
+    address public wNative; // The wrapped native token for safeSend().
@@
-        uint256 _withdrawTimeout,
-        address _wNative
+        uint256 _withdrawTimeout,
+        address _wNative
     ) {
@@
-        arbitratorExtraData = _arbitratorExtraData;
-        wNative = _wNative;
+        arbitratorExtraData = _arbitratorExtraData;
+        if (_wNative == address(0)) revert InvalidWNativeAddress();
+        wNative = _wNative;
@@
-    error SubmissionTimeHasEnded();
+    error SubmissionTimeHasEnded();
@@
-    error AlreadyExecuted();
+    error AlreadyExecuted();
+    error InvalidWNativeAddress();

This is a one‑time check but prevents subtle failures in all paths relying on SafeSend.

Also applies to: 127-142, 460-478


90-93: onlyByOwner currently blocks all external governance calls

The onlyByOwner modifier still checks against address(this):

modifier onlyByOwner() {
    if (address(this) != msg.sender) revert OwnerOnly();
    _;
}

All governance setters (e.g., changeSubmissionDeposit, changeSubmissionTimeout, changeExecutionTimeout, changeWithdrawTimeout, changeArbitrator, changeDisputeTemplate) are now effectively callable only by the contract itself, making them unusable after deployment.

Introduce an explicit owner variable and set it in the constructor, then check msg.sender against that:

 contract KlerosGovernor is IArbitrableV2 {
+    address public owner;
@@
-    modifier onlyByOwner() {
-        if (address(this) != msg.sender) revert OwnerOnly();
-        _;
-    }
+    modifier onlyByOwner() {
+        if (msg.sender != owner) revert OwnerOnly();
+        _;
+    }
@@ constructor
-    ) {
-        arbitrator = _arbitrator;
+    ) {
+        owner = msg.sender;
+        arbitrator = _arbitrator;

Without this fix, all the governance configuration endpoints are effectively dead.

Also applies to: 163-208

🧹 Nitpick comments (8)
contracts/scripts/verifyProxies.sh (1)

5-5: Etherscan v2 wiring looks good; consider tightening the proxy file loop

The switch to the unified https://api.etherscan.io/v2/api endpoint with an explicit chainid and ETHERSCAN_API_KEY plus the added key check all look sane.

The only thing I’d tweak is the for f in $(ls …) pattern, which ShellCheck flagged (SC2045) and can misbehave with spaces / no matches. You can avoid ls and rely on globs directly:

 function verify() { #deploymentDir #explorerApiUrl #apiKey #chainId
@@
-    echo "verifying proxies on $(basename $deploymentDir)"
-    for f in $(ls -1 $deploymentDir/*_Proxy.json 2>/dev/null); do
+    echo "verifying proxies on $(basename "$deploymentDir")"
+    shopt -s nullglob
+    for f in "$deploymentDir"/*_Proxy.json; do
         contractName=$(basename $f .json)
@@
-        echo
-    done
+        echo
+    done
+    shopt -u nullglob
 }

This keeps behavior the same while being more robust.

Also applies to: 7-22, 24-28, 30-34

contracts/.env.example (1)

1-5: Align .env format with dotenv expectations and README, avoid export syntax

Using export VAR = "" is unconventional for .env files and may not be parsed as expected by dotenv, and it also conflicts with the linter output. Since contracts/scripts/dotenv.sh loads this via dotenv.config, I’d strongly suggest switching to plain KEY= lines and adding the optional keys mentioned in the README:

-export PRIVATE_KEY = ""
-export MAINNET_PRIVATE_KEY = ""
-export INFURA_API_KEY = ""
-export ETHERSCAN_API_KEY_FIX=""
-export ETHERSCAN_API_KEY=""
+PRIVATE_KEY=
+MAINNET_PRIVATE_KEY=
+INFURA_API_KEY=
+ETHERSCAN_API_KEY_FIX=
+ETHERSCAN_API_KEY=
+ARBISCAN_API_KEY=
+GNOSISSCAN_API_KEY=

This matches typical .env conventions, fixes the linter warnings, and keeps the example in sync with the docs.

contracts/scripts/dotenv.sh (1)

3-15: Simplify quoting around the Node dotenv call to avoid SC2027-style pitfalls

Functionally this works, but the current nested quoting ("$SCRIPT_DIR"/../.env inside a double-quoted node -e string) is fragile and triggered ShellCheck (SC2027). You can make it more robust by passing the path and key as arguments and keeping the Node snippet single‑quoted:

-node -e "
-  require('dotenv').config({ path: '"$SCRIPT_DIR"/../.env' })
-  console.log(process.env.$varKey)
-"
+node -e '
+  const [path, key] = process.argv.slice(2);
+  require("dotenv").config({ path });
+  console.log(process.env[key] ?? "");
+' "$SCRIPT_DIR/../.env" "$varKey"

This removes shell interpolation inside the JS, makes the script easier to maintain, and keeps behavior (load .env, print the requested key).

contracts/README.md (1)

69-80: Keep env var docs and .env.example in sync (ARBISCAN / GNOSISSCAN keys)

The README lists ARBISCAN_API_KEY and GNOSISSCAN_API_KEY as optional verification keys, but contracts/.env.example currently only defines PRIVATE_KEY, MAINNET_PRIVATE_KEY, INFURA_API_KEY, ETHERSCAN_API_KEY_FIX, and ETHERSCAN_API_KEY.

To avoid confusion for integrators, consider adding placeholders for ARBISCAN_API_KEY and GNOSISSCAN_API_KEY in .env.example (and/or updating this section if those keys are no longer used in the current Hardhat/verify setup).

web/src/app/(main)/governor/[governorAddress]/ActiveLists/index.tsx (1)

35-42: Modal open/close wiring looks good; minor optional cleanups

The handleOpen callback and closePopup with router.replace(window.location.pathname, { scroll: false }) correctly centralize modal state and clear the listId param on close.

Two optional polish points (no need to block on them):

  • ExamineModal is only rendered when openList is truthy, so isOpen={!isUndefined(openList)} is always true in that branch; you can hardcode isOpen or derive it once to reduce redundancy.
  • If you want list opens from ListCard to be shareable via URL (like those coming from the dispute template), you could also push ?listId=… in handleOpen for consistency.
web/src/app/(main)/governor/[governorAddress]/ActiveLists/ListCard.tsx (1)

19-25: Externalizing open behavior via setIsOpen looks solid (with one minor prop nit)

The switch to a parent‑supplied setIsOpen(list) on hover click cleanly removes modal state from ListCard and keeps the component focused on display concerns.

Minor optional tweak: IListCard still requires governorAddress, but ListCard no longer uses it. If nothing else depends on that prop, you can drop it from the interface and call sites to avoid unused‑parameter noise:

-interface IListCard {
-  list: Submission;
-  governorAddress: Address;
-  setIsOpen: (list: Submission) => void;
-}
-const ListCard: React.FC<IListCard> = ({ list, setIsOpen }) => {
+interface IListCard {
+  list: Submission;
+  setIsOpen: (list: Submission) => void;
+}
+const ListCard: React.FC<IListCard> = ({ list, setIsOpen }) => {

Also applies to: 60-69

contracts/deploy/00-governor-v2.ts (1)

21-45: wNative deployment wiring is consistent; gfArgs can be simplified

The script correctly:

  • Pulls WETH via ethers.getContract("WETH").
  • Passes wNative.target into both GovernorFactory.deploy(...) and the KlerosGovernor constructor (kgArgs).
  • Uses kgArgs again for constructor args during Etherscan verification, which should keep deploy/verify in sync as you evolve constructor parameters.

One small cleanup opportunity: gfArgs is only used to initialize kgArgs and never for GovernorFactory itself. You can inline or rename it to avoid confusion about its purpose, e.g.:

-  const gfArgs = [
+  const kgArgs = [
     klerosCore.target,
     extraData,
     disputeTemplateRegistry.target,
     disputeTemplate,
     dataMappings,
     0,
     600,
     600,
-    600, // feeTimeout: 10 minutes
+    600, // feeTimeout: 10 minutes
     wNative.target,
   ];
-
-  await governorFactory.deploy(
+  await governorFactory.deploy(
     klerosCore.target,
     extraData,
     disputeTemplateRegistry.target,
     disputeTemplate,
     dataMappings,
     0,
     600,
     600,
     600, // feeTimeout: 10 minutes,
     wNative.target
   );
-
-  const kgArgs = gfArgs;

Purely cosmetic, but it makes the intent of kgArgs clearer.

Also applies to: 59-67, 68-92

contracts/src/KlerosGovernor.sol (1)

273-291: Consider using safeSend for withdrawal refunds for consistency

withdrawTransactionList still refunds the deposit with a raw .transfer:

reservedETH -= submission.deposit;
payable(msg.sender).transfer(submission.deposit);

Every other ETH outbound path in this contract now goes through SafeSend to avoid bricking calls when the recipient is a contract without a payable receive/fallback. For consistency and resilience, you could align this path as well:

-        reservedETH -= submission.deposit;
-        payable(msg.sender).transfer(submission.deposit);
+        reservedETH -= submission.deposit;
+        payable(msg.sender).safeSend(submission.deposit, wNative);

Not strictly a regression, but it makes refunds behave the same way as the rest of the payout logic.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 74efbcd and 6cefd0c.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (14)
  • contracts/.env.example (1 hunks)
  • contracts/.gitignore (1 hunks)
  • contracts/README.md (1 hunks)
  • contracts/deploy/00-governor-v2.ts (2 hunks)
  • contracts/deploy/utils/disputeTemplate.ts (2 hunks)
  • contracts/deploy/utils/getContracts.ts (1 hunks)
  • contracts/hardhat.config.ts (6 hunks)
  • contracts/package.json (2 hunks)
  • contracts/scripts/dotenv.sh (1 hunks)
  • contracts/scripts/verifyProxies.sh (1 hunks)
  • contracts/src/KlerosGovernor.sol (16 hunks)
  • web/src/app/(main)/governor/[governorAddress]/ActiveLists/ListCard.tsx (3 hunks)
  • web/src/app/(main)/governor/[governorAddress]/ActiveLists/index.tsx (3 hunks)
  • web/src/consts/governors.ts (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • contracts/.gitignore
  • contracts/hardhat.config.ts
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-06-15T18:23:26.791Z
Learnt from: tractorss
Repo: kleros/governor-v2 PR: 10
File: contracts/deploy/utils/disputeTemplate.ts:42-44
Timestamp: 2025-06-15T18:23:26.791Z
Learning: In Kleros Governor dispute template data mappings, the "seek" array values should be strings (e.g., "2") rather than numbers because they represent path strings that the SDK splits on, not direct array indices for indexing.

Applied to files:

  • contracts/deploy/utils/disputeTemplate.ts
📚 Learning: 2025-06-15T17:21:38.772Z
Learnt from: tractorss
Repo: kleros/governor-v2 PR: 10
File: web/src/utils/txnBuilder/constructSubmissionData.ts:5-11
Timestamp: 2025-06-15T17:21:38.772Z
Learning: In the Kleros Governor v2 web application, input validation is handled at the form level rather than in utility functions like constructSubmissionData. The team prefers to centralize validation at entry points and fix any validation leaks at the form level when discovered.

Applied to files:

  • contracts/src/KlerosGovernor.sol
🧬 Code graph analysis (3)
web/src/app/(main)/governor/[governorAddress]/ActiveLists/ListCard.tsx (1)
web/src/hooks/useFetchSubmittedLists.ts (1)
  • Submission (23-33)
web/src/app/(main)/governor/[governorAddress]/ActiveLists/index.tsx (2)
web/src/hooks/useFetchSubmittedLists.ts (2)
  • Submission (23-33)
  • useFetchSubmittedLists (36-88)
web/src/utils/index.ts (1)
  • isUndefined (39-40)
contracts/deploy/00-governor-v2.ts (2)
contracts/deploy/utils/getContracts.ts (1)
  • getArbitratorContracts (11-20)
contracts/deploy/utils/disputeTemplate.ts (2)
  • templateFn (2-30)
  • dataMappings (32-65)
🪛 dotenv-linter (4.0.0)
contracts/.env.example

[warning] 1-1: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)


[warning] 2-2: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)


[warning] 2-2: [UnorderedKey] The MAINNET_PRIVATE_KEY key should go before the PRIVATE_KEY key

(UnorderedKey)


[warning] 3-3: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)


[warning] 3-3: [UnorderedKey] The INFURA_API_KEY key should go before the MAINNET_PRIVATE_KEY key

(UnorderedKey)


[warning] 4-4: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)


[warning] 4-4: [UnorderedKey] The ETHERSCAN_API_KEY_FIX key should go before the INFURA_API_KEY key

(UnorderedKey)


[warning] 5-5: [EndingBlankLine] No blank line at the end of the file

(EndingBlankLine)


[warning] 5-5: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)


[warning] 5-5: [UnorderedKey] The ETHERSCAN_API_KEY key should go before the ETHERSCAN_API_KEY_FIX key

(UnorderedKey)

🪛 markdownlint-cli2 (0.18.1)
contracts/README.md

85-85: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


91-91: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


99-99: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


107-107: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


129-129: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


135-135: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

🪛 Shellcheck (0.11.0)
contracts/scripts/verifyProxies.sh

[warning] 13-13: Iterating over ls output is fragile. Use globs.

(SC2045)

contracts/scripts/dotenv.sh

[warning] 13-13: The surrounding quotes actually unquote this. Remove or escape them.

(SC2027)

🔇 Additional comments (9)
contracts/package.json (1)

60-60: Version bumps look consistent with the rest of the PR

Updating @nomicfoundation/hardhat-verify and @kleros/kleros-v2-contracts aligns with the new deployment/verification and arbitration flows; I don’t see issues in this file itself. Please just confirm that the new deployment names / APIs in @kleros/kleros-v2-contracts@^2.0.0-rc.1 (e.g. mainnet vs mainnetNeo) match how you’re using them in getContracts.ts and deploy scripts.

Also applies to: 93-93

contracts/deploy/utils/getContracts.ts (1)

5-9: arbitrummainnet deployment mapping: confirm it matches kleros-v2 contract artifacts

Switching the NETWORK_TO_DEPLOYMENT entry for arbitrum to "mainnet" makes sense with the new @kleros/kleros-v2-contracts version, but it does tightly couple this file to the deployment naming in that package. If mainnetNeo artifacts still exist or naming changes again, getArbitratorContracts will start throwing.

Please double‑check that:

  • DeploymentName for Arbitrum mainnet is indeed "mainnet" in @kleros/kleros-v2-contracts@^2.0.0-rc.1, and
  • The deployments/arbitrum folder here lines up with that expectation.

Otherwise this file looks good.

contracts/deploy/utils/disputeTemplate.ts (1)

5-6: New sessionIndex mapping is consistent with governor changes; confirm "value" seek path

The template update to reference sessionIndex in the description and the new dataMappings entry that:

  • calls arbitratorDisputeIDToSessionIndex(arbitratorDisputeID),
  • populates "sessionIndex", and
  • then feeds {{{sessionIndex}}} into the existing getSession call

is conceptually sound and lines up with the new arbitratorDisputeIDToSessionIndex mapping on the contract.

Also, using string values in seek (["value"] for the first call and ["2"] for getSession) follows the earlier guidance that these are path strings, not numeric indices. Just make sure "value" matches the actual response shape expected by the dispute-template SDK for abi/call results.

Overall, this looks correct.

Based on learnings

Also applies to: 34-56

web/src/app/(main)/governor/[governorAddress]/ActiveLists/index.tsx (2)

59-60: ListCard integration aligns with externalized open handler

Passing setIsOpen={handleOpen} into ListCard for both last‑session and active lists matches the new pattern of delegating modal control to the parent. The props spread { governorAddress, list } remains type‑safe and backward compatible.

Also applies to: 75-76


77-84: ExamineModal props wiring is coherent with new state

Conditionally rendering ExamineModal when openList is set and passing the current list plus toggleIsOpen={closePopup} cleanly reflects the view state. This should work well with the deep‑link auto‑open behavior from the effect above once listId parsing is hardened.

contracts/src/KlerosGovernor.sol (4)

215-271: submitList checks and duplicate detection look correct now

The revamped submitList logic reads clean and defensive:

  • Length mismatches _target.length != _value.length / _target.length != _dataSize.length correctly revert with specific errors.
  • The deposit is computed as submissionBaseDeposit + arbitrator.arbitrationCost(arbitratorExtraData) and enforced via InsufficientDeposit.
  • The hash chain listHash and the duplicate guard:
if (alreadySubmitted[sessions.length - 1][listHash]) revert ListAlreadySubmitted();
alreadySubmitted[sessions.length - 1][listHash] = true;

correctly prevent resubmitting the same list in a session.

  • Remainder refunds use safeSend(remainder, wNative) to avoid .transfer pitfalls for contracts.

This section now matches the intended behavior and integrates wNative/SafeSend safely.


293-327: Dispute flow updates (mapping + SafeSend) are coherent

The dispute/approval flow changes appear consistent:

  • executeSubmissions now:

    • Uses AlreadyDisputed when session.status != Status.NoDispute.
    • Pays the single‑list submitter with submission.submitter.safeSend(sumDeposit, wNative);.
    • Records arbitratorDisputeIDToSessionIndex[session.disputeID] = sessions.length - 1; when creating a dispute, matching the new view mapping consumed by dataMappings.
  • rule:

    • Restricts entry to msg.sender == address(arbitrator) with OnlyArbitratorAllowed.
    • Enforces _ruling <= session.submittedLists.length and session.status == Status.DisputeCreated.
    • Uses safeSend(session.sumDeposit, wNative) to pay the winning submitter, then correctly zeroes session.sumDeposit and decreases reservedETH.

The flow remains single‑dispute‑at‑a‑time (via session status), and the introduced mapping is a useful read‑path hook without affecting core logic.

Also applies to: 329-356


362-378: Execution and expendable‑funds helpers look correct under stated invariants

  • executeTransactionList now:

    • Checks SubmissionNotApproved and TimeToExecuteHasPassed via custom errors.
    • Uses getExpendableFunds() per iteration, and guards against re‑entrancy by reverting with AlreadyExecuted if transaction.executed is set during the external call.
  • getExpendableFunds returns address(this).balance - reservedETH, which is correct assuming reservedETH is always kept ≤ balance as you already do when adjusting it in submission/withdraw/dispute flows.

Given those invariants, the new logic is sound and doesn’t introduce obvious re‑entrancy or accounting issues.

Also applies to: 380-387


389-455: View helpers and custom errors are a solid API improvement

The added view functions (getTransactionInfo, getSubmittedLists, getSubmission, getNumberOfTransactions, getNumberOfCreatedLists, getCurrentSessionNumber, getSession, getTotalSubmissionDeposit) give off‑chain code a clean, gas‑efficient way to inspect state without reconstructing it manually.

Grouping all the new custom errors at the bottom also improves readability and gas behavior versus string reverts.

No issues from a correctness perspective here.

Also applies to: 456-478

Comment thread web/src/app/(main)/governor/[governorAddress]/ActiveLists/index.tsx
Copy link
Copy Markdown

@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

🧹 Nitpick comments (10)
web/src/app/(main)/governor/[governorAddress]/ActiveLists/index.tsx (4)

19-23: URL-driven auto-open logic is now safe; consider making URL the single source of truth

The guarded BigInt(listId) with try/catch and !isUndefined checks looks solid and avoids crashes from malformed or missing listId. However, openList is only ever set (never cleared) in this effect, so the modal can stay open even if the user navigates to a URL without listId or with an invalid one (e.g., via browser back or manual URL edits).

If you want the URL to fully control which list is open, consider extending the effect to also clear openList whenever listId is null/invalid or no matching list is found, and, conversely, have handleOpen/closePopup update listId in the URL so state and URL can’t drift apart.

Also applies to: 27-36


38-41: Optionally sync handleOpen with the listId query param

handleOpen correctly centralizes modal control via openList, but it doesn’t update the URL, while the effect reads from listId to auto-open. This asymmetry means deep-links work, but clicking a card doesn’t produce a shareable URL.

If that’s desirable UX, consider having handleOpen also set listId in the query string (e.g., via router.replace/push), using list.listId.toString(). That would keep the URL and UI in sync and make list openings reproducible via navigation.


42-45: Avoid blowing away unrelated query params when closing the modal

closePopup currently calls router.replace(window.location.pathname, { scroll: false }), which clears all query parameters, not just listId. That can be surprising if other filters/search params are added later.

Consider deriving the current pathname/search from Next helpers and only removing listId, e.g. using usePathname + useSearchParams to rebuild a URL without listId, then router.replace(newUrl, { scroll: false }). This keeps modal state decoupled from any future query parameters.


80-87: Simplify isOpen handling for ExamineModal

Given the surrounding conditional {openList ? ( ... ) : null}, openList is guaranteed to be truthy when ExamineModal renders, so isOpen={!isUndefined(openList)} will always be true in practice.

You can either:

  • Derive a boolean once (e.g. const isModalOpen = !isUndefined(openList);) and use it both for the conditional and isOpen, or
  • Rely solely on the conditional render and hardcode isOpen={true} (if ExamineModal doesn’t need a separate closed-but-mounted state).

Either approach reduces duplicated state and makes the intent clearer.

contracts/.env.example (1)

1-5: Env example matches config; linter warnings are purely stylistic

The variable names line up with hardhat.config.ts, so this is functionally fine. If dotenv-linter warnings are enforced in CI, consider reordering keys alphabetically and adding a trailing newline to silence the UnorderedKey/EndingBlankLine notices; otherwise you can safely ignore them.

contracts/README.md (1)

69-79: Clarify the roles of ETHERSCAN_API_KEY vs ETHERSCAN_API_KEY_FIX

Both keys are documented with the same description, which makes it unclear when each is actually used (e.g., verify-all vs proxy verification or other flows). Consider briefly explaining which tooling reads each variable, or consolidating if only one is needed, so users don’t have to guess which key to set.

contracts/README.md.template (1)

63-65: Keep template aligned with README and clarify ETHERSCAN env vars

The updated template correctly mirrors the KlerosGovernor tag and new ETHERSCAN variables, but it carries the same ambiguity as the main README about how ETHERSCAN_API_KEY vs ETHERSCAN_API_KEY_FIX are used. Since this file is the source for generated docs, it’s a good place to add a short note explaining which tooling reads each variable so downstream READMEs stay clear.

Also applies to: 80-81, 104-105, 118-119

contracts/package.json (1)

41-41: Verify-all wiring and RC dependency bump

The etherscan-verify script now cleanly targets the new verify-all task, which matches the README examples. The bump to @nomicfoundation/hardhat-verify and @kleros/kleros-v2-contracts@^2.0.0-rc.1 looks intentional, but please double-check compatibility (especially with Hardhat 2.22.x) and that you’re comfortable depending on an RC before tagging a stable release.

Also applies to: 60-60, 93-93

contracts/tasks/verify-all.ts (1)

1-42: verify-all task looks solid; consider skipping imported deployments and hardening error match

The task correctly walks Hardhat-Deploy deployments, supports an optional --contract filter, and skips proxies by naming convention, which is a reasonable default. Two optional refinements you might consider:

  • If Hardhat-Deploy exposes a way to distinguish imported/external deployments (e.g. coming from @kleros/kleros-v2-contracts via external.deployments), you may want to skip those to avoid noisy failures or redundant verification attempts.
  • The "Already Verified" check is brittle against small message changes; a case-insensitive match or checking for a shorter, stable substring (like "already verified") would make the script more resilient across plugin versions.
contracts/hardhat.config.ts (1)

5-5: Etherscan config and verify-all wiring look correct; watch the dual API key envs

Importing @nomicfoundation/hardhat-verify and ./tasks/verify-all correctly wires up the new verification flow, and the top-level etherscan.apiKey using ETHERSCAN_API_KEY_FIX matches the new env/example setup. Network verify.etherscan.apiKey blocks still use ETHERSCAN_API_KEY, which is fine but means you now rely on two different env vars for verification depending on the path (verify-all vs other verify usages/proxy script).

It’s worth confirming that:

  • Both env vars are set appropriately in local and CI environments, and
  • This split is intentional (e.g., one key via a new gateway vs legacy per-network keys).

If the distinction is purely historical, you might eventually simplify to a single env var to reduce configuration drift.

Also applies to: 16-16, 69-71, 83-85, 95-97, 133-135, 148-155

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6cefd0c and e280f78.

📒 Files selected for processing (8)
  • contracts/.env.example (1 hunks)
  • contracts/README.md (1 hunks)
  • contracts/README.md.template (4 hunks)
  • contracts/deploy/00-governor-v2.ts (3 hunks)
  • contracts/hardhat.config.ts (7 hunks)
  • contracts/package.json (3 hunks)
  • contracts/tasks/verify-all.ts (1 hunks)
  • web/src/app/(main)/governor/[governorAddress]/ActiveLists/index.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • contracts/deploy/00-governor-v2.ts
🧰 Additional context used
🧬 Code graph analysis (1)
web/src/app/(main)/governor/[governorAddress]/ActiveLists/index.tsx (2)
web/src/hooks/useFetchSubmittedLists.ts (2)
  • Submission (23-33)
  • useFetchSubmittedLists (36-88)
web/src/utils/index.ts (1)
  • isUndefined (39-40)
🪛 dotenv-linter (4.0.0)
contracts/.env.example

[warning] 1-1: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)


[warning] 2-2: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)


[warning] 2-2: [UnorderedKey] The MAINNET_PRIVATE_KEY key should go before the PRIVATE_KEY key

(UnorderedKey)


[warning] 3-3: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)


[warning] 3-3: [UnorderedKey] The INFURA_API_KEY key should go before the MAINNET_PRIVATE_KEY key

(UnorderedKey)


[warning] 4-4: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)


[warning] 4-4: [UnorderedKey] The ETHERSCAN_API_KEY_FIX key should go before the INFURA_API_KEY key

(UnorderedKey)


[warning] 5-5: [EndingBlankLine] No blank line at the end of the file

(EndingBlankLine)


[warning] 5-5: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)


[warning] 5-5: [UnorderedKey] The ETHERSCAN_API_KEY key should go before the ETHERSCAN_API_KEY_FIX key

(UnorderedKey)

🪛 markdownlint-cli2 (0.18.1)
contracts/README.md

84-84: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


90-90: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


98-98: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


106-106: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


128-128: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


134-134: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

🔇 Additional comments (1)
web/src/app/(main)/governor/[governorAddress]/ActiveLists/index.tsx (1)

61-63: Centralizing modal open via setIsOpen={handleOpen} looks good

Passing setIsOpen={handleOpen} to ListCard for both last session and active lists is a nice consolidation of modal behavior. It keeps list cards dumb and moves the open/close logic into a single place (ActiveLists), which will make future changes around opening behavior much easier.

Also applies to: 75-79

coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 19, 2025
Copy link
Copy Markdown

@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/deploy/00-governor-v2.ts (1)

33-57: Eliminate code duplication by using gfArgs in the factory deploy call.

The gfArgs array is defined (lines 33-44) but then the identical arguments are duplicated in the governorFactory.deploy call (lines 46-57). This violates DRY and creates maintenance risk—if parameters change, both locations must be updated.

Apply this diff to use the spread operator:

-  await governorFactory.deploy(
-    klerosCore.target,
-    extraData,
-    disputeTemplateRegistry.target,
-    disputeTemplate,
-    dataMappings,
-    0,
-    600,
-    600,
-    600, // feeTimeout: 10 minutes,
-    wNative.target
-  );
+  await governorFactory.deploy(...gfArgs);
♻️ Duplicate comments (3)
contracts/hardhat.config.ts (3)

72-84: Arbitrum Sepolia Devnet config is consistent with the new key strategy

This mirrors the arbitrumSepolia change and keeps the devnet using the same ETHERSCAN_API_KEY, which is good for consistency. Just ensure the devnet/deployer environment also has ETHERSCAN_API_KEY set and no longer expects a dedicated Arbiscan key.


85-97: Main Arbitrum network now also using ETHERSCAN_API_KEY

Same pattern here: using ETHERSCAN_API_KEY for Arbitrum mainnet simplifies configuration and matches the Sepolia networks. As above, this relies on the API key being valid on Arbiscan via Etherscan’s multi-chain API system; worth confirming this with your currently issued key before merge.


123-135: GnosisChain verification also unified under ETHERSCAN_API_KEY

GnosisChain now uses the shared ETHERSCAN_API_KEY as well. This keeps all Etherscan-family explorers under one env var, which is nice, but increases coupling: rotating or changing keys now impacts multiple networks at once.

Make sure:

  • The new key is recognized by Gnosisscan.
  • Any previous GNOSISSCAN_API_KEY usage has been removed from scripts/docs so there’s no confusion.
🧹 Nitpick comments (1)
contracts/deploy/00-governor-v2.ts (1)

59-62: Consider using gfArgs directly instead of aliasing.

The alias kgArgs = gfArgs adds an extra variable without clear benefit. Unless there's a future need to differentiate these arguments, you could use gfArgs directly in the deployment.

-  const kgArgs = gfArgs;
   await deploy("KlerosGovernor", {
     from: deployer,
-    args: kgArgs,
+    args: gfArgs,
     log: true,
   });
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e280f78 and f676865.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (3)
  • contracts/deploy/00-governor-v2.ts (3 hunks)
  • contracts/hardhat.config.ts (4 hunks)
  • contracts/package.json (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • contracts/package.json
🧰 Additional context used
🧬 Code graph analysis (1)
contracts/deploy/00-governor-v2.ts (1)
contracts/deploy/utils/disputeTemplate.ts (1)
  • dataMappings (32-65)
🔇 Additional comments (3)
contracts/deploy/00-governor-v2.ts (2)

31-31: Good improvement: typed contract reference.

Adding the generic type parameter improves type safety and developer experience.


21-21: > Likely an incorrect or invalid review comment.

contracts/hardhat.config.ts (1)

58-71: Consolidating Arbitrum Sepolia onto ETHERSCAN_API_KEY looks correct; confirm multi‑chain key + env wiring

Using process.env.ETHERSCAN_API_KEY here aligns this network with the new single Etherscan-style API key strategy and should work fine with Etherscan’s multi-chain keys, assuming that key is enabled for Arbitrum’s explorer.

Please double-check:

  • The configured ETHERSCAN_API_KEY is a multi-chain key that covers Arbitrum Sepolia.
  • All relevant .env templates, CI secrets, and deployment environments now provide ETHERSCAN_API_KEY (and no longer rely on legacy ARBISCAN_API_KEY).

coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 9, 2025
Copy link
Copy Markdown

@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

Caution

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

⚠️ Outside diff range comments (1)
contracts/deploy/00-governor-v2.ts (1)

33-57: Remove duplicated arguments by using gfArgs for governorFactory.deploy().

The gfArgs array is constructed at lines 33-44 but then the same arguments are passed inline to governorFactory.deploy() at lines 46-57. This duplication creates a maintenance risk where updates to one location may not be reflected in the other.

🔎 Apply this diff to use gfArgs consistently:
  const gfArgs = [
    klerosCore.target,
    extraData,
    disputeTemplateRegistry.target,
    disputeTemplate,
    dataMappings,
    0,
    600,
    600,
    600, // feeTimeout: 10 minutes
    wNative.target,
-  ];
+  ] as const;

-  await governorFactory.deploy(
-    klerosCore.target,
-    extraData,
-    disputeTemplateRegistry.target,
-    disputeTemplate,
-    dataMappings,
-    0,
-    600,
-    600,
-    600, // feeTimeout: 10 minutes,
-    wNative.target
-  );
+  await governorFactory.deploy(...gfArgs);
🧹 Nitpick comments (2)
contracts/README.md (1)

9-24: Empty deployment sections should be populated or removed.

The Official Testnet sections (Arbitrum Sepolia at line 11, Sepolia at line 13) and Devnet Sepolia (line 23) are empty placeholders. Consider either populating them with actual deployment addresses or removing them until deployments are available to avoid confusion.

contracts/deploy/00-governor-v2.ts (1)

59-64: Consider adding inline comments for timeout values.

The gfArgs array contains multiple timeout values (600) with only the last one commented. For better maintainability, document all timeout parameters.

🔎 Suggested improvement:
  const gfArgs = [
    klerosCore.target,
    extraData,
    disputeTemplateRegistry.target,
    disputeTemplate,
    dataMappings,
-   0,
-   600,
-   600,
-   600, // feeTimeout: 10 minutes
+   0,   // submissionDeposit
+   600, // submissionTimeout: 10 minutes
+   600, // executionTimeout: 10 minutes
+   600, // feeTimeout: 10 minutes
    wNative.target,
  ] as const;
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f676865 and e2ae333.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (3)
  • contracts/README.md (1 hunks)
  • contracts/deploy/00-governor-v2.ts (4 hunks)
  • web/src/consts/governors.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/src/consts/governors.ts
🧰 Additional context used
🧬 Code graph analysis (1)
contracts/deploy/00-governor-v2.ts (1)
contracts/deploy/utils/disputeTemplate.ts (1)
  • dataMappings (32-65)
🪛 markdownlint-cli2 (0.18.1)
contracts/README.md

84-84: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


90-90: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


98-98: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


106-106: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


128-128: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


134-134: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

⏰ 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). (3)
  • GitHub Check: Redirect rules - kleros-governor-v2
  • GitHub Check: Header rules - kleros-governor-v2
  • GitHub Check: Pages changed - kleros-governor-v2
🔇 Additional comments (1)
contracts/deploy/00-governor-v2.ts (1)

21-22: LGTM!

The WETH contract retrieval pattern is correct and aligns with the SafeSend integration for native token handling.

Comment thread contracts/README.md
Comment thread contracts/README.md Outdated
Copy link
Copy Markdown

@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

♻️ Duplicate comments (2)
contracts/README.md.template (1)

64-65: Clarify the purpose of ETHERSCAN_API_KEY_FIX.

Both ETHERSCAN_API_KEY and ETHERSCAN_API_KEY_FIX are listed with identical descriptions. This creates confusion about which variable to use and when.

contracts/README.md (1)

77-78: Clarify the purpose of ETHERSCAN_API_KEY_FIX.

Both environment variables have identical descriptions, creating confusion about their distinct purposes.

🧹 Nitpick comments (2)
contracts/README.md (2)

84-84: Consider using proper headings for Shell labels.

Static analysis flags the bold text format for "Shell 1:" and "Shell 2:" labels. While this doesn't affect readability, using proper markdown headings (e.g., ##### Shell 1: the node) would align with markdown best practices and silence linter warnings.

Also applies to: 90-90, 98-98, 106-106, 128-128, 134-134


126-126: Consider numbering the "Running Test Fixtures" section.

The section numbering jumps from 4 to 5 with "Running Test Fixtures" unnumbered in between. While this may be intentional, sequential numbering (making this section 5 and renumbering verification to 6) would improve navigation consistency.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e2ae333 and 0dc929f.

📒 Files selected for processing (2)
  • contracts/README.md (1 hunks)
  • contracts/README.md.template (5 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.18.1)
contracts/README.md

84-84: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


90-90: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


98-98: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


106-106: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


128-128: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


134-134: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

⏰ 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). (3)
  • GitHub Check: Redirect rules - kleros-governor-v2
  • GitHub Check: Header rules - kleros-governor-v2
  • GitHub Check: Pages changed - kleros-governor-v2
🔇 Additional comments (5)
contracts/README.md.template (4)

80-80: LGTM: GovernorV2 → KlerosGovernor update.

The deployment tag reference has been correctly updated to KlerosGovernor, consistent with the contract refactoring described in this PR.


104-104: LGTM: Deploy command updated.

The deployment command correctly references KlerosGovernor tag.


118-118: LGTM: Test fixture tag updated.

The node command correctly references KlerosGovernor tag for test fixtures.


127-127: Section numbering corrected.

The verification section has been correctly renumbered to 5, addressing the sequential numbering of deployment instructions.

contracts/README.md (1)

19-21: Deployment addresses documented.

The devnet deployment addresses for GovernorFactory, KlerosGovernor, and WETH on Arbitrum Sepolia are properly formatted with block explorer links.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants