Skip to content

Latest commit

 

History

History
174 lines (132 loc) · 13.3 KB

task_061026_20.md

File metadata and controls

174 lines (132 loc) · 13.3 KB

Task: Contract Follow-ups: DINTaskAuditor Size (#201 A4), Dual-Role Guard (#180), Cross-Model S5 (#193)

ID: task_061026_20 Assigned to: Umer Majeed (@umermjd11) Created: 2026-10-06 Status: Open (assigned) Dates: Oct 6 – Oct 9, 2026 (about 3 working days; per-Part estimates below). Parts A and C can start right away. Part B goes with Part A (same contract and byte budget). If anything slips, say so early in the tracking discussion. Repo: https://github.com/InfiniteZeroFoundation/DevNet Base branch: develop. The spec was written against a1fcce2 (2026-10-05). The task contracts and DinValidatorStake are unchanged since 740a613, where the source plan was verified. Re-pull before starting. Roadmap ref: P3-6.3a (gas/size), P3-6.3b (audit preparation, open findings), P3-4.2 (penalty tiers, S5) Source plan: Developer/tasks-plan/umermjd11/task-plan-051026-1.md, reviewed in PR #219 (verification review, reviewer decisions, decisions applied) Companion task: task_061026_21 (full-GI alignment). See Coordination. Tracking:

  • Part A: #201 Part A, item 4 (the DINTaskAuditor review). #201 Part B stays open.
  • Part B: #180 (closes, pending review).
  • Part C: #193 (closes, pending review).
  • Discussion #230 (progress updates, questions, PR links)

Status check at a1fcce2

Item State
#201 A4 DINTaskAuditor is 22,718 B runtime (1,858 B margin, so the CI gate warns). It has 16 public mappings. Four of them either have no reader outside the contract or duplicate an existing view
#180 registerDINAuditor (DINTaskAuditor.sol:667-698) and registerDINaggregator (DINTaskCoordinator.sol:401-434) have no cross-role check. The PR #182 review ruled dual-role not intended (Developer/design/adversarial-threat-model.md, Judgment call 2; Row 6 = KNOWN GAP). Stale NatSpec remains at DinValidatorStake.sol:121, :451 and :462
#193 The S5 ring is _partialSlashGIs[validator][msg.sender] (DinValidatorStake.sol:146; slashPartial at :294-322), so it is counted per slasher contract. That splits S1 (auditor contract) and S2 (coordinator) even within one model. Developer/design/MECHANISM_DESIGN.md:81 defines S5 per validator, across both roles

Sequencing

Part PR Touches Conflicts with Rule
A PR 1, commit 1 DINTaskAuditor.sol (getter visibility, folds), dincli/abis/DINTaskAuditor.json, DINTaskAuditor.md §3 B (same contract and budget); task_061026_21 Part B (DINTaskAuditor bytes) Start right away
B PR 1, commit 2 DINTaskAuditor.registerDINAuditor, IDINTaskCoordinator + new error (DINShared.sol), DinValidatorStake.sol NatSpec, tests, threat model Row 6 A; task_061026_21 Part B (DINShared.sol enum) Same PR as A, so the gate proves both fit
C PR 2 DinValidatorStake.sol (S5 storage + slashPartial), S5 tests, deploy-script S5 keys, DinValidatorStake.md, MECHANISM_DESIGN.md, threat model Row 11 — In parallel with PR 1, since it's a different contract

PR #218 (P3Adversarial.t.sol, #154 Part 2) encodes Row 6 and Row 11 as test_knownGap_dualRoleRegistration / test_knownGap_perSlasherS5Evasion. If it merges first, PR 1 and PR 2 each flip their row's test to test_defended_…. Otherwise PR #218 rebases and flips them. No test may be left asserting a closed gap. Row 11's test calls slashPartial directly as each task contract, which makes it a good regression check for Part C.

Rebase each PR on develop after the previous one merges; no stacked branches.


Part A — #201 Part A item 4: DINTaskAuditor size review — PR 1, commit 1

Shrink the contract in place, with no library, split or deploy change. Only getter visibility changes: no state-changing function, event or storage slot changes. Prototyped in the plan and re-measured in the PR #219 review (via_ir, 200 runs):

Getter → internal Readers outside the contract Saving
auditBatches none (only a comment, RewardEngine.t.sol:895). getAuditorsBatch already returns the batch −100 B
dinAuditors none. getDINtaskAuditors already returns the list −83 B
Is_testdataCIDs_Assigned none. It is written at :1028 and read only by its own guard at :1026 −58 B
auditorGIWeight none −79 B
The four together (Decision 1) −320 B → 22,398 B (2,178 B margin)

Keep public: rewardClaimed, testDataDisputes and giRewardSnapshot. task_061026_21's claim and dispute commands read them.

Scope:

  • Make the four getters internal. No test reads them, so no test changes.
  • Fold review: required. #201 item 4 asks for "the same review" of per-phase duplication that the coordinator got. Measure folds of the near-duplicate dispute and reassignment paths. Commit a fold only if it shrinks the contract: in task_021026_19, via_ir made the coordinator's commit/reveal/finalize folds grow it (+177 B / +166 B). Report every measurement in the PR, including the ones not taken.
  • Regenerate dincli/abis/DINTaskAuditor.json (dincli system dump-abi --artifact foundry/out/DINTaskAuditor.sol/DINTaskAuditor.json --output dincli/abis --official) and update the DINTaskAuditor.md §3 tables.
  • Check PR #29's subgraph for reads of the four getters, and post an ABI note there. Don't push to that branch.

DINTaskAuditor budget across both tasks (Decision 1). Measured on a1fcce2:

Step Runtime Margin Band
develop 22,718 B 1,858 B warn
+ Part A 22,398 B 2,178 B ok
+ Part B (+102 B) 22,500 B 2,076 B ok (28 B above the warn line)
+ task_061026_21 Part B's every-batch commitment check (+75 B) 22,575 B 2,001 B warn (still far above the 1,024 B fail line)

There are two ways back out of the warn band: a fold that actually saves bytes, and removing Is_testdataCIDs_Assigned once task_061026_21's AuditTestDataAssigned coordinator state guards the double-set. Whichever of the two tasks lands second reports the combined size.

Deliverables (Part A)

  • The four getters are internal, with no change to state-changing functions, events or storage layout
  • A size table from one build of the implementation, plus every fold measured (kept or not)
  • Bundled ABI regenerated, DINTaskAuditor.md §3 updated, ABI note posted on PR #29
  • cd foundry && npm ci && forge build && python ../.github/scripts/contract_size_gate.py && forge test is green, including UpgradeValidation.t.sol. pytest -m "not integration" is green

Estimate: 1 day.


Part B — #180: one address can't hold both roles in a GI — PR 1, commit 2

Decision 2: a per-address guard in registerDINAuditor. A second address with its own stake gets around it (Sybil), but the attack then costs a second stake and is visible on-chain.

  • Where. Aggregator registration (states 6–7) always comes before auditor registration (8–9) (DINShared.sol:17-20), so the auditor side is the only place the guard can fire:
    if (dintaskcoordinatorContract.isDINAggregator(_GI, msg.sender)) revert TA_DualRoleNotAllowed();
    Add isDINAggregator(uint256,address) returns (bool) to IDINTaskCoordinator (DINShared.sol:110-121). The coordinator's public mapping isDINAggregator (DINTaskCoordinator.sol:34) already provides it. Add TA_DualRoleNotAllowed to DINShared.sol.
  • Cost: +102 B on DINTaskAuditor, measured. The coordinator doesn't change.
  • NatSpec:
    • DinValidatorStake.sol:451 and :462 say "(not yet enforced)". Both are enforced now, in the two registration functions.
    • :121 says "decremented at endGI time". The decrement now happens in releaseGIRegistrationSlots.
  • Tests (next to the StakingEnforcement.t.sol registration tests):
    • an aggregator registering as an auditor in the same GI reverts with TA_DualRoleNotAllowed
    • the same address registering as an auditor in a different GI succeeds
    • a different address with its own stake succeeds, which documents the Sybil limit
  • Docs:
    • threat model Row 6 changes from KNOWN GAP to DEFENDED (with the Sybil note), and its stale line refs are refreshed (:386 → :401, :660 → :667)
    • in DINTaskAuditor.md, update the registration checks and the §13 caveat
    • add a DINShared.md error row

Deliverables (Part B)

  • Guard, interface entry and error added, with the three tests
  • NatSpec fixed at DinValidatorStake.sol:121, :451, :462
  • Threat model Row 6 updated (and PR #218's Row 6 test flipped if it has merged)
  • The gate is green, and the PR shows the A + B size

Estimate: 0.5 day.


Part C — #193: S5 escalation across models — PR 2

Decision 3: a two-level check.

  • The per-slasher GI ring stays as it is, with the same per-model escalation and the same tests.
  • Add a per-validator ring of block.timestamp values, _partialSlashTimes[validator], with s5GlobalWindow (seconds) and s5GlobalThreshold.
    • Timestamps only increase, across every slasher, so the ascending-order trim that forced per-contract keying (DinValidatorStake.sol:136-146) stays safe.
    • slashPartial escalates (full MIN_STAKE slash + jail) when either level reaches its threshold, and then clears both rings.
  • This also closes the same-model split: one validator's S1 and S2 misses now add up.

Scope:

  • Storage. Append the new variables before __gap (:174, 50 slots) and shrink the gap by the slots used. (Amended at PR No. 236: __gap stays at 50. Nothing on develop is deployed yet, so per the "Core rules" in storage_layout.md new variables go above __gap without shrinking it, as 07fd597 did for DinEmission.) DinValidatorStakeV2 inherits them. UpgradeValidation.t.sol and the DeployPlatform.t.sol upgrade tests must stay green.
  • Setter. setS5GlobalParams(window, threshold), validated like setS5RecidivismParams (:583-594).
  • Defaults. s5GlobalWindow = 7 days and s5GlobalThreshold = 6 (2 × s5RecidivismThreshold). These are placeholders until #155.
    • Set them in initialize.
    • On an upgraded proxy, 0 means off; no reinitializer. Nothing on develop is deployed, and DevNet 2.0 is a fresh DeployPlatform.s.sol run.
    • Add optional deploy-script env keys S5_GLOBAL_WINDOW / S5_GLOBAL_THRESHOLD, matching the existing S5_* keys. Add them to DeployPlatform.md and its env-override tests.
  • Event. ValidatorEscalatedS5 gets a level flag, or a sibling event is added, so indexers can tell which level fired.
  • Tests:
    • two task contracts each slash one validator (threshold − 1) times within the window, and the global level escalates
    • when the window expires, the global count resets
    • the existing S5 tests (SlashingInvariants.t.sol:488, :518, :540) and test_crossModelGICollision_slashPartialDoesNotUnderflow (PR146SlashingRegression.t.sol:321) stay green
    • the default and override deploy tests cover the new keys
  • Docs:
    • DinValidatorStake.md
    • the Developer/design/MECHANISM_DESIGN.md S5 row
    • threat model Row 11 (KNOWN GAP → DEFENDED)
    • record, but don't change, the separate discrepancy: MECHANISM_DESIGN.md:87 says S5 is "entire slashable stake + blacklist", while the code does a MIN_STAKE slash + a s5JailDuration jail (7 days)

Deliverables (Part C)

  • Two-level S5 with setter, defaults, "0 means off", event and deploy-script keys
  • The new tests, with the existing S5 and upgrade-validation tests green
  • Docs updated (and PR #218's Row 11 test flipped if it has merged)

Estimate: 1.5 days.


Coordination with task_061026_21

  • DINShared.sol. Part B adds isDINAggregator to IDINTaskCoordinator. task_061026_21 Part B edits the GIstates enum. The sections differ, and whichever PR merges second rebases.
  • dincli/abis/DINTaskAuditor.json. Both tasks regenerate it. The second to merge regenerates on top.
  • The DINTaskAuditor budget is tracked in Part A's table. Whichever task lands second reports the combined size.
  • The #180 guard and the integration suite. The suite uses separate accounts for each role (aggregators 11–22, auditors 50–58), so it isn't affected. task_061026_21 adds a negative check once Part B lands.
  • #193 doesn't affect a single-model GI.

Out of scope

  • #201 Part B (slash reason for committed-but-unrevealed): a mechanism decision tied to #155 / #38.
  • #194, #78, #181, #178: each needs a design note or a decision first, or is mainnet-grade.
  • dincli, the integration suite and the GI docs: task_061026_21.
  • Don't split DINTaskAuditor to win bytes. If the budget can't be met with the levers above, stop and raise it in the tracking discussion.