Repository navigation
Description
Three separate findings, batched because they share the same shape: each is a mechanism that exists in some form (an admin function, a fee flow, a slashing path) but nobody has made — or at least documented — the decision on whether/how it's actually meant to be used. None are exploitable bugs; all three just need someone with product/mechanism-design authority to decide, so the code (or the docs) can be made to match.
M-2: DINModelRegistry.disableModel() doesn't reach the live task contracts
modelDisabled[modelId] (DINModelRegistry.sol:119) only gates requestModelRegistration/requestManifestUpdate inside the registry itself (L151, L330). Confirmed by inspection against develop @ 740a613: DINTaskCoordinator.sol has zero references to DINModelRegistry, and DINTaskAuditor.sol's only two references are doc comments, not functional checks. A model the DIN-Representative has disabled — e.g., because its task contracts have a bug wrongfully slashing honest validators — keeps running full GIs completely unaffected. The task contracts' own doc table calls this a "kill-switch," which it currently isn't.
Decision needed: wire the task contracts to check DINModelRegistry.modelDisabled(modelId) before state-changing calls (real fix, requires threading the model ID + registry address into contracts that don't currently know about the registry at all), or explicitly document disableModel as registry-metadata-only so operators stop treating it as a circuit breaker.
L-4: rejectModel() never refunds the registration fee
Checked the full flow: feePaid is recorded at requestModelRegistration() (DINModelRegistry.sol:197) and is never refunded on either outcome — not on rejectModel() (L261-271) and not on approveModel() either (L217-258 doesn't touch feePaid at all). This consistency suggests the fee is intentionally a pay-to-apply cost regardless of outcome (anti-spam), not an oversight specific to rejection — but this was never written down anywhere as a deliberate choice.
Decision needed: confirm non-refundable-regardless-of-outcome is the intended design and document it (in DINModelRegistry.md and/or the dinrep role docs), so a future reader doesn't "fix" it into an inconsistent partial-refund state.
BL-31: S6 no-participation slashing is implemented, tested, but never called
DinValidatorStake.recordNoParticipation() (S6: escalating 10%-per-breach slash past a threshold, L333-354) is fully implemented and has its own tests. Every call site in both task contracts is a comment explaining why it's deliberately not called (DINTaskAuditor.sol:1391, DINTaskCoordinator.sol:1185) — slashPartial (S1/S2) already penalizes the same missed-work behavior, and calling both would double-penalize past MIN_STAKE. Confirmed: zero functional call sites anywhere in foundry/src/.
Decision needed: either S6 is meant to cover a gap S1/S2 don't (e.g., a validator registered but never assigned to any batch, so S1/S2 never trigger on them at all) and needs wiring to that specific case, or it's superseded dead code that should be removed along with its threshold parameter and event, per the slashing taxonomy (#38).
References
Developer/BACK_LOG.mdBL-31Documentation/technical/audits/foundry-src-security-review.mdM-2, L-4 (confirmed still accurate againstdevelop@740a613; several of that doc's other findings — M-3, M-4, L-1, L-5, L-7 — are already fixed but the doc was never updated to say so, a separate minor doc-hygiene item not covered by this issue)- PR fix(cli): remove broken non-proxy
dinrep deploy, fix add-slasher crash; refresh contract docs (#203) #204 review (BL-31's source) - P3 slashing: conditions taxonomy, penalty tiers, slashed-stake destination, dispute resolution (P3-4.1/4.2/4.3) #38 (slashing taxonomy, relevant to the S6 decision)
Activity
umeradl commentedon Oct 6, 2026
Status update: confirmed; decisions pending
Checked against
develop@a1fcce2. All three hold as described. These are maintainer decisions; options and a recommendation for each are below. Nothing here is in task_061026_22.M-2:
disableModel()doesn't reach the task contractsmodelDisabled(foundry/src/DINModelRegistry.sol:119) gates onlyrequestModelRegistration(:151) andrequestManifestUpdate(:330). Neither task contract reads the registry.disableModelas registry-only (it blocks manifest changes), and stop calling it a kill switchmodelDisabled(modelId)before state-changing callsRecommended: A now. Revisit B with the GI-abort design (issue No. 222), since "stop a misbehaving model" needs the same "what happens to the in-flight GI" answer.
L-4:
rejectModel()keeps the registration feefeePaidis set at request time (:197,:307) and refunded on neither outcome (rejectModelat:261).DINModelRegistry.mdandroles/dinrep.mdRecommended: A.
BL-31: S6 is implemented but never called
DinValidatorStake.recordNoParticipation(:333) has no caller. Both task contracts skip it on purpose whereslashPartial(S1/S2) already penalises the miss (DINTaskAuditor.sol:1391,DINTaskCoordinator.sol:1185).DinValidatorStakeis upgradeable, so the storage has to stay or be gappedRecommended: decide with the slashing taxonomy (issue No. 38). Until then, C.
docs(backlog,audit): link BL-27..31 to new issues, mark stale finding…
abrahamnash commentedon Oct 26, 2026
Decisions (Abraham):
modelDisabled; the task contracts don't). GivenDINTaskCoordinator's size headroom (see Contract size headroom for all contracts (DINTaskCoordinator −9 B over EIP-170 with PR No. 197) + slash reason for committed-but-unrevealed across commit-reveal flows #201), consider putting the check inDINTaskAuditoror a small external guard rather than the coordinator.DINModelRegistry.mdand the dinrep role docs.Suggest splitting (1) into its own implementation issue; (2) is docs-only; (3) needs either a removal PR or a "parked" note in the docs.
Santiagocetran commentedon Oct 30, 2026
Based on this conversation, I’ve implemented the agreed changes in PR #305: preventing disabled models from starting new GIs, documenting the non-refundable registration fee, and marking S6 as parked for testnet.
The PR includes tests and deployment compatibility notes. It overlaps with #261, which should land first; I’ll reconcile the branch and rerun the relevant checks afterward.
Ready for review—feedback is welcome!
umeradl commentedon Nov 7, 2026
@robertocarlous, could you run the closing check on this issue (
din-close-issue 224)? The peer check refuses me: I authored PR No. 229, a task-plan doc that references this issue. Santiago is the implementer, so he can't run it either.PR No. 305 merged into
developas3def72fand covers M-2 (disableModelas a real kill-switch, BL-34). Two things to check againstorigin/develop:rejectModelfee is non-refundable) and BL-31 (wire in or remove S6 no-participation slashing): is a decision recorded for each, in code, in docs or in a comment? If either is still open, this gets a status update, not a close.get_codeordering indeploy task-auditor, CID pinning). Please note them in the result so they're tracked.