Skip to content

Latest commit

 

History

History
170 lines (113 loc) · 23.3 KB

task_100926_13.md

File metadata and controls

170 lines (113 loc) · 23.3 KB

Task: P3 Slashing Depth, Aggregator-Recomputation Disputes & Reward/Tokenomics Economics (#38 remainder, #41, #42)

ID: task_100926_13 Assigned to: Robbert Abimbola (@robertocarlous) Created: 2026-09-10 Status: Open (assigned) Repo: https://github.com/InfiniteZeroFoundation/DevNet Base branch: develop — spec written against commit ef41a0d (2026-09-10); re-pull before starting regardless of when you begin. Depends on task_100926_12 §1 for its shared-registration-counter infrastructure (see §2 below) — check whether that's merged before starting §2. Roadmap ref: P3-4.1/4.2/4.3 (slashing depth, disputes), P3-5.2 (reward-split simulation), P3-5.2 (emission contract) Tracking: #38 (closes, pending review — the remainder not covered by task_100926_12 §2), #41 (closes, pending review), #42 (closes, pending review) · Discussion #138 (progress updates, questions, PR links)


Context

This task and its sibling, task_100926_12.md, come out of a 2026-09-10 audit of ten open P3 issues (#36-43, #75, #78) — the full audit is appended at the bottom of both files, unchanged. task_100926_12 covers the parts of this pending work where the design decision is already made and only wiring is missing; this task covers what's left, which genuinely needs either a slashing-economics judgment call or a simulation-first sequencing (reward-split percentages before the emission contract that depends on them). Expect more back-and-forth on this task than a typical wiring task — several sections below ask you to propose a number or a mechanism, not just implement a spec'd one.

This is a larger, more design-adjacent task than usual. If any section below turns out to be bigger in practice than it reads here, say so early and propose splitting it into its own follow-up rather than absorbing scope creep — same instinct Similoluwa used splitting #121's original ask into #124-127.


Scope for this task

1. Partial-slash tiers for S1/S2, plus S5/S6 (#38)

Background (MECHANISM_DESIGN §4):

# Condition Role Current state
S1 Missed audit vote Auditor Flat minStake() slash, AUD_NO_VOTE — DINTaskAuditor.sol:1268
S2 Missed T1/T2 submission Aggregator Flat minStake() slash — DINTaskCoordinator.sol:829 (slashAggregators)
S3 Score deviation from median Auditor Already wired, gated behind s3SlashingEnabled (default false) — DINTaskAuditor.sol:151,1229-1279. Not in scope here; enabling it is an operational decision pending empirical threshold data, not a code change.
S5 Recidivism (≥r partial slashes within w GIs) Both Spec-only, no code
S6 Registration without capacity (registers, never participates, across models) Both Spec-only, no code

a) S1/S2 → DAO-settable partial fraction. Today's flat minStake() "fully unstakes a floor-staked validator for one missed vote," which MECHANISM_DESIGN §4 explicitly calls over-punishment for a liveness fault. Add a DAO-settable fraction (matching the s3DeviationThreshold/setS3DeviationThreshold pattern already in DINTaskAuditor.sol — a public settable var + setter + event), applied to both slashAggregators (DINTaskCoordinator.sol) and slashAuditors's AUD_NO_VOTE branch (DINTaskAuditor.sol). The exact fraction (MECHANISM_DESIGN suggests 25-50% as an example, not a final number) is your call to propose in the PR description — this is explicitly still an open decision (§9 item 2), not something to treat as settled.

b) S5 — recidivism counter. Needs a per-validator count of partial slashes within a rolling window of w GIs, escalating to a full slash + jail on the r-th occurrence. Open design questions to resolve and note in your PR description:

  • Where does the counter live? DinValidatorStake.slash() is the single choke point for every slash call today, but it doesn't currently distinguish partial from full severity — you'll likely need to extend slash()'s signature (or add a parallel bookkeeping call) so the counter only increments on partial slashes.
  • What "within w GIs" means concretely — a rolling GI-index window needs each slash call to carry a GI number, which DinValidatorStake.slash() doesn't take today (it's called from task contracts that know their own GI but don't currently pass it through).
  • Escalation: once the recidivism threshold is hit, does the next triggering call become a full slash automatically, or does it require a separate step? Prefer automatic if it fits cleanly, but call out the tradeoff.

c) S6 — registration-without-capacity counter. "Registers, never participates, across models" implies a cross-task-contract counter, same shape as task_100926_12 §1(b)'s concurrent-registration-cap counter. Check whether task_100926_12 has merged before starting this — if its activeRegistrationCount-style counter on DinValidatorStake exists, extend it (or add a sibling counter) to also track a "registered but didn't submit anything" flag per registration, rather than building a second independent tracking mechanism. If task_100926_12 hasn't merged yet, propose the shared shape now and note the eventual merge point in your PR description.

Tests: partial-slash-fraction round-trip + a fuzz test confirming the fraction is applied correctly at the boundary (matches SlashingInvariants.t.sol's existing style); S5 escalation test (r-th partial slash within the window triggers full slash + jail); S6 counter test (registers-without-participating across ≥2 GIs triggers escalating partial slash, per the "partial, escalating" tier in the taxonomy table).

2. General-dispute recomputation verification for S4 (folded in from #40)

Background: #40 closed 2026-09-10 with one line folded into this issue: "Aggregator auditing: T1/T2 outputs verifiable by recomputation; any validator may open an S4 dispute." DINTaskCoordinator.openDispute/resolveDispute already exist as a scaffold (from #66) — bond custody, dispute window, fresh-subgroup reassignment excluding the accused (_assignFreshSubgroup) — but adjudication is onlyOwner (centralized human judgment call), not an on-chain recomputation check. This is distinct from PR #110's dispute mechanism, which is test-data-integrity-specific (DINTaskAuditor.disputeTestData/resolveDispute) and doesn't touch aggregation outputs at all.

This needs a short design note before code — "verifiable by recomputation" for T1/T2 aggregation isn't specified anywhere beyond that one sentence, and aggregation itself is deliberately off-chain (per the existing gas-simulation design doc's baseline: "aggregation logic is off-chain — only the final CID goes on-chain"). Concretely, propose an answer to: what does a validator submit to prove a T1/T2 CID is invalid, and what does the contract check on-chain to adjudicate it without re-running the aggregation itself (which it structurally can't, since the inputs and computation are off-chain)? A plausible shape: the fresh subgroup reassigned by _assignFreshSubgroup re-runs aggregation off-chain and submits a new CID; if it matches the disputed one, the dispute is frivolous (existing forfeiture path from task_100926_12 §2a applies); if it doesn't, the original is invalid (upheld path applies). Confirm or refine this with Umer before implementing — this is the one item in either task where the design isn't already settled by a prior decision.

Tests: once the mechanism is agreed, a dispute-and-recompute-mismatch test and a dispute-and-recompute-match (frivolous) test, following EncryptedTestData.t.sol's three-stage structure as a model for how PR #110 organized a similar staged-reveal flow.

3. Reward-split percentage simulation (#41)

Background: The 60/20/15/5 client/auditor/aggregator/treasury split shipped in #64 was never validated against the P3-5.2 income-stability model this issue's own scope calls for: "simulate in P3-5.2 at 10-50 validators / 100-500 clients." Developer/issues/validator-reward-mechanism/simulation.md and client-reward-mechanism/simulation.md are simulation plans, not completed simulations.

  • Model steady-state validator income at target / 10× / 0.1× participation, across the 10-50 validator / 100-500 client spec-scale range, for the current 60/20/15/5 split.
  • Deliverable: a Developer/design/*.md writeup (same shape as gas-simulation-network-fee.md — self-contained, states its own scope, methodology, and a clear recommendation) confirming the current split or proposing an adjustment with numbers behind it.
  • If the simulation surfaces a split-percentage change, that's a DINTaskAuditor.RewardSplit DAO-settable-parameter update (already governable, no new contract code needed) — flag the recommended values, don't just leave them as a doc conclusion nobody applies.
  • Also sweep BL-14 (bps-split rounding dust not swept to treasury) into this work if it's a small addition on top of whatever settlement-path code you're already touching for the simulation's validation; otherwise leave it as a separate small follow-up and say so.

4. Emission contract (#42)

Background: MECHANISM_DESIGN §9 item 5 records geometric decay per epoch and a GI-lifecycle-tied inflation guard as a resolved design decision, but no corresponding contract exists in foundry/src/ — today's reward pool (depositRewards, #64) is entirely externally funded, there's no protocol-emitted subsidy top-up at all.

Sequence this after §3 — the emission contract's decay-rate/epoch-length numbers should be checked against §3's income-stability simulation rather than picked independently, since they're feeding the same validator-income model.

  • New contract (or extension of an existing platform contract — propose which, following the existing Transparent Proxy pattern used by DinTreasury/DinFairLaunchDistributor): per-GI reward subsidy on a geometric decay schedule, tied to GI lifecycle (decays per completed GI, not wall-clock time — confirm this matches the "GI-lifecycle-tied inflation guard" phrasing in §9 item 5).
  • Mints via DinToken/DinCoordinator's existing mint path (check mintCap/totalMinted/faucetRetired from #60 — the emission contract's minting should respect the same cap machinery, not bypass it).
  • Steady-state target: emission → 0 as protocol fees mature to fund the reward pool on their own (per this issue's own framing) — the decay schedule should make this explicit (a final epoch or an asymptotic tail, your call, state which and why).
  • DAO-settable decay rate/epoch length, matching every other governable parameter in this codebase.

Tests: decay-schedule unit tests (emission amount at epoch N matches the geometric formula); an integration test funding a GI's reward pool partly from emission and partly from external depositRewards, confirming no double-counting; a mint-cap-respecting test (emission can't push totalMinted past mintCap, and is a no-op post-retireFaucet).


Deliverables

  • S1/S2 slash a DAO-settable partial fraction of minStake(), not the flat amount, with the fraction proposed and justified in the PR description
  • S5 recidivism counter + escalation to full slash, with the counter-placement and windowing design resolved and noted
  • S6 registration-without-capacity counter, sharing infrastructure with task_100926_12 §1(b) where possible
  • A design note for S4's recomputation-verification mechanism, confirmed with Umer before implementation; then the mechanism itself wired into DINTaskCoordinator's existing dispute scaffold
  • Developer/design/*.md reward-split simulation writeup with a concrete recommendation (confirm current 60/20/15/5 or propose new values)
  • If the simulation recommends new split values, DINTaskAuditor.RewardSplit updated to match
  • New emission contract: per-GI decaying subsidy, GI-lifecycle-tied, respecting mintCap/faucetRetired, DAO-settable decay parameters
  • forge build && forge test green, full suite
  • PR description(s) reference #38, #41, #42 as appropriate and record every design decision made along the way (partial-slash fraction, S4 mechanism, split percentages, decay schedule)

Submission

Four fairly distinct pieces of work (slashing tiers, S4 dispute mechanism, reward simulation, emission contract) — submit as separate PRs rather than one large PR, in roughly the order listed (§1 and §2 can go in parallel; §4 should follow §3, not precede it). Given the S4 mechanism (§2) genuinely needs a design decision first, don't start writing that PR's contract code until it's confirmed — same instruction as task_100926_11's §0 blocking-dependency note, just for a design confirmation instead of a merge.

Notes

  • Flag any change to DINTaskCoordinator.sol/DINTaskAuditor.sol/DinValidatorStake.sol for Umer's review given cryptoeconomic sensitivity, same as prior tasks in this area (task_210726_5, task_210726_6, task_100926_11).
  • Re-pull develop and re-run forge test right before opening each PR — this area of the codebase has had five merges in the last 48 hours (#110, #117, #129, #131, #133, #134), and task_100926_12 will also be touching adjacent code concurrently.
  • §2 (S4 recomputation) is the one item in either task without a settled design — don't guess past what's written above; ask.

Audit (shared with task_100926_12)

Pre-task audit: P3 issues #36-43, #75, #78 (2026-09-10)

Scope of this audit: #36, #37, #38, #39, #40, #41, #42, #43, #75, #78 — all OPEN as of 2026-09-10 (before this task split #38 and closed #40). Method: Read each issue's full body + comment history, cross-checked against git log/merged PRs since the 2026-09-08 status-check round, current develop source (foundry/src/*.sol), and a live forge test run of SlashingInvariants.t.sol. Status-check comments posted 2026-09-10 (Sept 8 comment was stale on these four): #36, #38, #40, #41. #37/#39/#42/#43/#78's 2026-09-08 comments are still accurate — not re-posted. #75 already had a fresh 2026-09-10 comment (PR #77 merge) before this audit started.


What changed between the 2026-09-08 round and today

Five PRs merged in that window that matter to this issue set:

PR Merged Title Issues affected
#110 2026-09-09 Real encrypted test-data key distribution + staged dispute resolution (Closes #40) #40 (directly), #38 (adjacent — new test-data-specific dispute path, not the general one #38 tracks)
#116 2026-09-09 import-deployments drops dinTreasury/dinFeeRouter (BL-8) none of these 10 directly
#117 2026-09-10 Realign SlashingInvariants.t.sol with burn/treasury split #38 (clears its "3 failing tests" item — confirmed 13/13 passing via a fresh forge test run)
#129 2026-09-10 Nonce collision fix (BL-1) none of these 10
#133 2026-09-10 Dispute bond denomination → DIN (BL-12, docs-only) #38, #36 (§9 item 7 denomination half)
#134 2026-09-10 Claim-pull reward settlement, O(1) endGI (BL-10) #41, #36
#131 2026-09-10 Weighted aggregator reward settlement + docs/gas-benchmark (#126, #127) #41, #36 — fixes a real stranded-funds bug in #134's interim isRewardableAggregator flat-split

Confirmed by direct inspection (not just PR descriptions): foundry/src/DINTaskCoordinator.sol now has aggregatorWeight/totalAggregatorWeight mappings incremented per finalized batch, isRewardableAggregator is gone; DINTaskCoordinator.sol/DINTaskAuditor.sol still carry three TODO(task_210726_5): forward to DinTreasury stubs (PR #133 only touched a NatSpec comment, no functional change).


Per-issue audit

#36 — P3 umbrella (mechanism design tracking)

Verdict: stays open, umbrella issue. Not independently closable — closes when all seven children close. Real movement this round: #38 and #41 both cleared concrete items; #40 is one item away from closable. MECHANISM_DESIGN §9 open-decision count: 6 of 14 now open (was 7) — item 7 (dispute bond) split-resolved, denomination done, size/window still open.

#37 — P3 staking

Verdict: no change, stays open. No merged PR touched this since 2026-09-08. Outstanding, confirmed unchanged: per-model stake bounds (modelMinStakeBounds) and the concurrent-registration cap exist as storage on DinValidatorStake but are read nowhere in DINTaskCoordinator/DINTaskAuditor registration — zero enforcement; withdrawal queue still single-pending-only (accepted gap, not a blocker). Task candidate: wire the two existing-but-unenforced storage values into GI registration checks. Self-contained, contract-only, well-specified — good task_12/13 candidate. → task_100926_12, §1.

#38 — P3 slashing

Verdict: stays open, but two items closed this round (see comment posted today). Confirmed via direct forge test that SlashingInvariants.t.sol is 13/13 passing (was 3 failing). Dispute-bond denomination resolved. Scope also now explicitly includes #40's leftover line (aggregator auditing / S4 recomputation dispute — folded in 2026-09-10, #40 closed as a result). Still outstanding and unchanged: S1/S2 flat-minStake() slash (not a DAO-settable fraction), S3 is fully wired but gated behind s3SlashingEnabled (default false) pending empirical threshold validation — an enablement decision, not missing code, S5/S6 spec-only (no code, need a per-validator counter), general dispute path (DINTaskCoordinator.openDispute/resolveDispute) still onlyOwner, no recomputation-based verification (the freshly-folded S4 gap), and its bond-forfeiture/bounty payout still stubbed (confirmed: treasuryAccrued + 2 more TODO(task_210726_5) comments live in source today). BL-11 (grindable redo entropy), BL-15 (resolved disputes can't reopen) also still open. Split across both tasks: treasury-forwarding piece → task_100926_12 §2; partial-slash tiers, S5/S6, and the S4 recomputation-dispute item → task_100926_13 §1-2.

#39 — P3 scoring

Verdict: no change, stays open. No merged PR touched this since 2026-09-08. P3-SCR validation workstream is done (#62); scenario-driven redesign (separating eligibility from utility) hasn't started beyond a design doc (Developer/issues/scoring-mechanism.md) and a reference contribution_mode implementation that #62 explicitly scoped as not-production. Not a good near-term task candidate — this is a design-first item (redesign needs agreement before code), not a wiring/bugfix task like the others. Left out of both task_12 and task_13.

#40 — P3 auditing

CLOSED 2026-09-10. PR #110 (Closes #40) merged 2026-09-09 — real encrypted-key scheme now on develop, matching the issue's own scope item verbatim. The one remaining scope line ("aggregator auditing: T1/T2 outputs verifiable by recomputation, S4 dispute") was architecturally #38's territory (DINTaskCoordinator's dispute path), not something specific to auditor evaluation — PR #110 never touched that contract. Per Umer's direction, folded that line explicitly into #38's Scope section (edited 2026-09-10) and closed #40 with a closing comment pointing to #38 for the rest. No standalone task_12/13 work — its only open line is now task_100926_13 §2.

#41 — P3 rewards

Verdict: stays open, but the headline gap closed this round. BL-10 (unbounded settlement loop, this issue's own biggest flagged risk) is fully resolved via #134 + #131, including a real stranded-funds bug fix in the aggregator path found along the way (task_100926_11's scope). Remaining: BL-14 (rounding dust not swept to treasury — cosmetic) and the reward-split-percentage simulation (60/20/15/5 defaults were never validated against the P3-5.2 income-stability model this issue calls for). → task_100926_13, §3.

#42 — P3 tokenomics

Verdict: no change, stays open. No merged PR touched this since 2026-09-08. Supply/burn/treasury mechanics are done; no emission contract exists in foundry/src/ at all — the "geometric decay per epoch" design decision in MECHANISM_DESIGN §9 has no corresponding code. Task candidate — the largest single gap in this whole set: a new emission contract (per-GI reward subsidy on a decay schedule) is greenfield work, not a fix to existing code. → task_100926_13, §4 (sequenced after §3's simulation, since the emission contract shouldn't be built before the split percentages it feeds are at least sketched).

#43 — P3 fees & treasury

Verdict: no change, stays open. #133 touched a fee-table doc line (dispute bond → DIN, cosmetic given #38 already covers the substance) but didn't touch this issue's real outstanding item. Confirmed still live in source: DINTaskCoordinator.treasuryAccrued and its two TODO(task_210726_5): forward to DinTreasury stubs — dispute-bond forwarding to DinTreasury still isn't wired despite the contract existing since #51 (merged 2026-08-07, over a month ago). No dynamic-fee base rate/multiplier code exists anywhere. → task_100926_12, §2 (same code path as #38's treasury-forwarding item).

#75 — Fair-launch distribution (long-running)

Verdict: no change needed, already current. Comment from earlier today (2026-09-10, before this audit) already covers PR #77's merge. Long-running tracking issue by design — next slice (indexer-backed eligibility snapshot) is explicitly blocked on P4-IDX1/IDX2, out of scope for either task.

#78 — Gas simulation for network fee

Verdict: no change, stays open, low urgency. No merged PR touched this since 2026-09-08. The simulation itself is complete and documented as such; what's missing is (a) pricing commitAuditScore gas (added by #63 after the simulation's baseline) and (b) actually wiring the recommended floor into a contract constant. → task_100926_12, §3.


Closure recommendations

  • Closed 2026-09-10: #40 — one leftover line folded into #38's scope, then closed.
  • Not closable yet, real work remains: #37, #38, #41, #42, #43, #78 — see task_100926_12/13 for the plan.
  • Not closable, not a near-term task either: #39 (needs a design decision before code, not a wiring task) — left out of both tasks.
  • No action, tracking issue by design: #75.