Disputes & Bonds (Flags, Cases, Grace, Refunds, Community Notes)

Status: Concept for v0 / v0.1 Last updated: YYYY‑MM‑DD


1) Purpose & Scope

The Disputes & Bonds module handles:

  • Flags (paid requests for review),

  • Case lifecycle (open → resolve),

  • Time‑based grace for author publish bonds,

  • Refund/forfeit rules for flags and bonds,

  • Community Notes (DAO‑approved context labels).

ELI5: If readers think something is wrong, they pay a small deposit to raise a hand. If the DAO agrees and takes action, those readers get their money back and the author’s publish deposit can be taken (within ~10 days). If the DAO does nothing, the readers’ deposits are kept by the protocol, and the author gets their deposit back after ~10 days.

Out of scope: recording a wallet’s single action (that’s Actions) and article publication itself (that’s ArticlesRegistry).


2) Responsibilities & Non‑Goals

Responsibilities

  • Escrow flag deposits; open cases at threshold.

  • Resolve cases; process refunds/forfeits.

  • Enforce time‑based grace for publish bond refunds/slashing.

  • Store and expose Community Notes (IPFS CIDs).

Non‑Goals

  • Voting, downvotes, upvotes (Actions module).

  • Search, ranking, indexing (CIN node).

  • DAO voting mechanics (handled by the governance process off‑chain/on‑chain, but Disputes enforces the final decision via authorized roles).


3) External Dependencies

  • CRUMBS (ERC‑20) — currency for flags/bonds.

  • ArticlesRegistry — authoritative record of cid existence and publish timestamp (createdAt) and author address.

  • Actions — enforces single‑action rule and routes flag(...) into Disputes.

  • Vault — destination for unrefunded flag fees and slashed bonds.

  • Config (DAO‑timelocked) — parameters & percentages.


4) Parameters (DAO‑timelocked defaults)

  • FLAG_FEE F = 25 CRUMBS

  • FLAGS_TO_OPEN K = 3

  • GRACE_SECONDS ≈ 10 days (time‑based; not block‑based)

  • PUBLISH_BOND B = 100 CRUMBS

Economic rules (as finalized):

  • Downvotes (Dislike/DownVote): 100% to Vault.

  • Upvotes: 20% of counted part to Vault; 80% of counted + 100% of tips to Author.

  • Flags:

    • If DAO action taken → flaggers refunded F.

    • If no action → flags forfeit to Vault.

  • Publish bond:

    • If DAO action taken within grace → bond slashed to Vault.

    • If no upheld action during grace → bond refundable to Author after grace.

    • If action is taken after grace, flags still refunded, but bond cannot be slashed (already refundable/returned).


5) Data Model & State

Notes

  • One open case per CID at a time. Additional flags while a case is open are added to that case.

  • After resolution, a new case can open later if fresh flags reach threshold again (rare; allowed).


6) Flows

6.1 Publish (handled via ArticlesRegistry; bond recorded here)

  1. ArticlesRegistry.publish(cid, ...) requires B CRUMBS; Actions/Registry calls Disputes._onPublish(cid, author, createdAt) to record:

    • bondOf[cid] = { amount: B, publishTime: createdAt, refunded: false, slashed: false }.

6.2 Flag (called from Actions.flag)

  1. Verify cid is published and caller hasn’t acted (Actions enforces).

  2. Pull F CRUMBS from caller into Disputes escrow.

  3. If openCaseOf[cid] == 0:

    • Create new case with CaseStatus.Open, push FlagInfo, set openedAt = now.

    • If total flags in case ≥ K, emit DisputeOpened.

  4. Else:

    • Append flag to existing Open case.

    • If flags cross threshold and case was not announced, emit DisputeOpened.

  5. Emit Flagged(cid, flagger, noteCid?).

Single‑action: the wallet’s action ledger is in Actions; Flags here assume Actions already consumed that slot.

6.3 Resolve (DAO‑authorized)

resolveDispute(caseId, actionTaken, noteCids[])

  1. Preconditions: cases[caseId].status == Open.

  2. Set cases[caseId].status = Resolved, resolvedAt = now, resolution = actionTaken ? ActionTaken : NoAction.

  3. Store Community Notes (noteCids[]) in the case (append).

  4. If ActionTaken:

    • For each flag in case: mark refundable; do not pull from Vault; refunds go from escrow (see 6.4).

    • If now <= bondOf[cid].publishTime + GRACE_SECONDS and bond is not refunded/slashed:

      • Slash bond: transfer B to Vault; mark slashed = true.

    • Else (grace elapsed): bond remains refundable; no slashing.

  5. If NoAction:

    • Transfer all flag escrow for this case to Vault (flaggers will not be refunded).

  6. Emit DisputeResolved(caseId, actionTaken, noteCids).

6.4 Flag refunds (pull‑based)

claimFlagRefund(caseId) — callable by each flagger if and only if:

  • cases[caseId].status == Resolved && cases[caseId].resolution == ActionTaken, and

  • The caller appears in flags[] and refunded == false.

On success:

  • Transfer F to caller; set refunded = true; emit FlagRefunded(caseId, caller, F).

6.5 Author bond refund (pull‑or‑anyone‑trigger)

autoRefundBond(cid) — callable by anyone if and only if:

  • now >= bondOf[cid].publishTime + GRACE_SECONDS, and

  • No ActionTaken resolution exists within grace for this cid, and

  • Bond not already refunded or slashed.

On success:

  • Transfer B to the Author of the cid; mark refunded = true; emit BondRefunded(cid, author, B).

Edge: If ActionTaken happens after grace, the bond may already be refunded or eligible; Disputes must not attempt slashing after grace.


7) Interfaces & Events (Solidity Sketch)

Access control:

  • flag(...)only callable by Actions module (prevents bypassing single‑action rule).

  • resolveDispute(...)onlyDAO (e.g., governed timelocked executor / council multisig).

  • autoRefundBond and claimFlagRefund — public, with guards.


8) Community Notes

  • Notes are IPFS CIDs (immutable), approved on resolution.

  • UIs display notes prominently with the dispute label.

  • CIN nodes index note CIDs alongside article docs so clients can fetch summarized context.

Categories (recommendation for UI, not enforced on‑chain):

  • Misleading / Missing Context

  • Plagiarism / Copyright

  • Harmful / Illegal in Jurisdiction

  • Malware / Phishing

  • Other (free text in note file)


9) Security & Invariants

  • Escrow conservation: For each case, the sum of all flag deposits ends either in refunds (ActionTaken) or Vault (NoAction). No stranded CRUMBS.

  • Bond finality: A bond is exclusively refunded or slashed or still escrowed; never double‑spent.

  • Grace correctness: Slashing is only allowed if now ≤ publishTime + GRACE_SECONDS.

  • Reentrancy‑safe: nonReentrant on resolveDispute, refunds, and bond transfers; CEI pattern.

  • Auth boundaries: Only Actions can add flags; only DAO can resolve.

  • Time source: block.timestamp is the clock; avoid assumptions about block cadence.


10) Testing Checklist

Unit

  • Flag escrow: amounts recorded; thresholds open cases; events emitted.

  • Resolve(ActionTaken): flag refunds claimable; no Vault transfer of flags; bond slashing within grace; no slashing after grace.

  • Resolve(NoAction): flag escrow transferred to Vault; no refunds; bond auto‑refundable after grace.

  • autoRefundBond: succeeds after grace; fails before; idempotent via state flags.

  • Single‑action integration: bypass attempts rejected via onlyActions (mock Actions).

Property/Fuzz

  • Conservation: sum(flags) = sum(refunds) (ActionTaken) or = transferToVault (NoAction).

  • Bond state never double‑finalizes.

  • Random interleavings of flags/resolve/refund maintain invariants.

Integration

  • With Actions: flag() path, single‑action consumption.

  • With ArticlesRegistry: publish time and author address consistent.

  • With Vault: balances match expectations (flags/no action, bonds/slash).


11) Read‑Model for UIs & Indexers

  • Per CID: current open caseId (if any), case status, flag count, openedAt, notes.

  • Author view: bond status (escrowed | refunded | slashed), grace deadline timestamp.

  • Flagger view: list of cases where wallet flagged, and whether refund is claimable.

CIN nodes should mirror case metadata to power:

  • “Under Review” ribbons,

  • “Action Taken” labels + notes,

  • Countdown to grace expiry for authors.


12) Performance & Gas Notes

  • One open case per CID keeps state small.

  • Flags stored densely; consider cap or pagination for extremely popular disputes (UI can compress).

  • Refunds are pull‑based to avoid looping transfers on resolve (gas‑safe and reentrancy‑safe).


13) Acceptance Criteria

  • Flags open cases at K; DAO resolutions process funds as specified.

  • Bonds are slashed only within GRACE_SECONDS; otherwise refundable after grace.

  • UIs can query complete case status and notes.

  • No double refunds, no stuck funds, all events emitted.


14) Changelog

  • v1: Initial Disputes & Bonds spec with time‑based grace, escrowed flags, refunds/forfeits, slashing rules, and Community Notes.

Last updated