You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The DIN subgraph (PR #29 / #72) has 31 event handlers across all platform contracts. Five of those handlers are currently commented out because the events they listen to do not exist in the Solidity contracts yet:
Missing event
Should be emitted from
Blocks subgraph handler
LocalModelSubmitted
DINTaskCoordinator.submitLocalModel()
LMS submission indexing
T1AggregationSubmitted
DINTaskCoordinator.submitT1Aggregation()
T1 aggregation indexing
T2AggregationSubmitted
DINTaskCoordinator.submitT2Aggregation()
T2 aggregation indexing
GIStateChanged
DINTaskCoordinator — on GI phase transitions
GI lifecycle indexing
Without these events, the indexer cannot track the full GI lifecycle on-chain. Any query that relies on LMS or aggregation submission history — including the pending-requests endpoint in dindao.py — will fall back to slow RPC polling instead of the indexed GraphQL path.
What needs to change
Add emit LocalModelSubmitted(...), emit T1AggregationSubmitted(...), emit T2AggregationSubmitted(...), and emit GIStateChanged(...) at the appropriate points in DINTaskCoordinator, with matching event declarations in DINShared.sol. Event parameters should at minimum include the GI index, batch/tier identifiers, and the actor address so the subgraph can index per-validator history.
Once emitted, the five commented-out handlers in subgraph/src/ can be enabled and subgraph/subgraph.yaml updated to include them.
Acceptance criteria
Events declared in DINShared.sol with parameter signatures agreed with the subgraph team
Events emitted at the correct points in DINTaskCoordinator
The five subgraph handlers re-enabled and mapping to the new events
Existing Forge tests still pass; new tests cover the event emissions
Review — go-ahead, but use PR #29's own event spec, fix the scope, and split contract vs. subgraph work
Checked against develop @ d321c2a and PR #29's head (feat/din-indexer @ 866521a, 2026-07-14).
The need is real. None of these events exist on develop. The subgraph can't index LMS submissions, T1/T2 submissions, finalization, or GI phase transitions without them. Go-ahead on adding them.
The issue text doesn't match the spec it's meant to unblock, though, and a few details would produce the wrong events.
1. The source of truth already exists: follow PR #29's audit §4
PR #29 ships Documentation/technical/audits/task-contract-event-audit.md. Its §4 proposes exact signatures, and they match the commented-out lines in subgraph/subgraph.yaml. Implement those signatures, not the issue's looser "at minimum GI, batch, actor" wording, so the handlers can be uncommented without an ABI mismatch.
There are six pending task-level handlers, not five. The issue's table lists only four events:
finalizeT2Aggregation(), after b.finalCID = winningCID (:859)
❌ missing
Without the two finalization events, the indexer sees votes but never the outcome: which CID won each batch, and the new global model per GI. That's arguably the most-queried fact in the whole lifecycle, so both belong in scope.
2. Corrections to the issue text
No. 1: submitLocalModel lives in DINTaskAuditor (:700), not DINTaskCoordinator.
No. 2: Declare events in the contracts that emit them, not in DINShared.sol.DINShared.sol holds the enum, errors, and interfaces, and has zero event declarations today. Every existing event is declared in its own contract. Keep that convention.
No. 3: The dindao.py pending-requests endpoint isn't affected. It lists model-registration requests (ModelRegistrationRequested on the registry), which are already indexed. What these events do unblock is lms.py/aggregation.py, which iterate submissions over RPC (audit §3.2).
3. Two correctness details for the implementer
GIStateChanged would carry the wrong GI on GIstarted. The audit's _setGIstate(newState) helper emits GIStateChanged(GI, …), and that's the right approach: one emit site, so no future transition can be missed. But _startGI sets GIstate = GIstates.GIstartedbeforeGI++ (DINTaskCoordinator.sol:310-311). A mechanical find-and-replace would emit GIstarted with the previous GI. Increment first, then call the helper. Add a test asserting GIStateChanged(N, GIstarted) for GI N.
The enum ordinals in PR feat(indexer): implement DIN Protocol subgraph — platform + task-level contracts #29's docs are stale. The audit's example says newState == 16 is T1AggregationStarted. On develop it's 17, because LMSevaluationRevealStarted was inserted at ordinal 14 on 2026-08-27. GIstates now has 24 members. The subgraph's uint8 → GraphQL enum mapping and daemon-event-schema.md both need regenerating from current DINShared.sol, not from the July snapshot.
4. Stale item in audit §5
§5 calls RewardDeposited dead code and proposes deleting it. That's no longer true: DINTaskAuditor.depositRewards emits it (:488), and its signature is now RewardDeposited(uint256 indexed gi, address indexed depositor, uint256 amount), not the (address, uint256) the audit shows. Don't delete it. Add a subgraph handler for it instead, since reward-pool funding per GI is useful to index.
5. Split the work: contracts on develop, handlers on feat/din-indexer
PR #29 is still open and targets feat/din-indexer, not develop. There's no subgraph/ directory on develop at all. So "re-enable the five handlers" can't be part of a develop PR.
PR A → develop:
the six events + emit sites + _setGIstate refactor
Forge tests using vm.expectEmit for each event, including the GIstarted-carries-new-GI case and one T1BatchFinalized per batch in a multi-batch GI
refreshed dincli/abis/
update audit §4/§5 if it lands on develop with the subgraph work, or note the corrections in the PR
check forge build --sizes: DINTaskCoordinator is large, and a 24-transition refactor plus five new events isn't free
PR B → feat/din-indexer (after PR A merges):
rebase/refresh the branch on develop
regenerate subgraph/abis/
uncomment the six handlers, fix the enum mapping, add the RewardDeposited handler
ETHTreasuryWithdrawn (DinCoordinator, platform-level) is also still commented out in subgraph.yaml and doesn't exist on develop. Either drop that handler stub, or repoint it at the events DinTreasury actually emits (EthWithdrawn/ERC20Withdrawn/EthReceived) with a DinTreasury data source. It shouldn't wait on a DinCoordinator event that isn't planned.
Revised acceptance criteria
Six events declared in their emitting contracts, with signatures exactly as in audit §4
_setGIstate helper used for every GIstate assignment; GIstarted emits the new GI
vm.expectEmit tests for all six, plus the GI-ordering case; full forge test green; contract size within limit
dincli/abis/ refreshed
Follow-up PR on feat/din-indexer: ABIs regenerated, six handlers enabled, enum mapping regenerated from current GIstates, RewardDeposited handler added, ETHTreasuryWithdrawn stub resolved
Six events declared in their emitting contracts, signatures as audit §4.DINTaskCoordinator: GIStateChanged, T1AggregationSubmitted, T2AggregationSubmitted, T1BatchFinalized, T2Finalized; DINTaskAuditor: LocalModelSubmitted (in submitLocalModel). DINShared.sol has no event declarations. Checked against the six commented-out handler lines in PR No. 29's subgraph/subgraph.yaml — canonical types, indexed flags and parameter order match exactly, so the handlers can be uncommented without an ABI mismatch.
_setGIstate for every GIstate assignment; GIstarted emits the new GI. 24 call sites; the only bare GIstate = is inside the helper. startGI does GI++ before _setGIstate(GIstates.GIstarted).
vm.expectEmit tests for all six + GI ordering; full suite green; size within limit.foundry/test/LifecycleEvents.t.sol (9 tests), including GIStateChanged(N, GIstarted) for GI 1 and 2, one T1BatchFinalized per batch in a two-batch GI, and a full GIstarted → GIended walk — each mutation-checked (the tests fail with the ordering fix reverted / emission limited to batch 0). forge test 392/392; DINTaskCoordinator runtime 20,629 → 21,335 B, 3,241 B under EIP-170.
dincli/abis/ refreshed. Both regenerated via dincli system dump-abi --official: coordinator +5 events, auditor +1, nothing removed.
Follow-up on feat/din-indexer (ABIs regenerated, six handlers enabled, enum mapping regenerated from current GIstates, RewardDeposited handler, ETHTreasuryWithdrawn stub resolved) — not done yet; it's now unblocked. Tracked as task_240926_16 C0/C5 on PR No. 29 (still at 866521a) and in Discussion No. 163, per the planned split (this issue closes with the develop half).
The issue body's original four-event / DINShared.sol / DINTaskCoordinator.submitLocalModel wording is superseded by the review comment linked above; what landed follows the review.
Activity
umeradl commentedon Sep 24, 2026
Review — go-ahead, but use PR #29's own event spec, fix the scope, and split contract vs. subgraph work
Checked against
develop@d321c2aand PR #29's head (feat/din-indexer@866521a, 2026-07-14).The need is real. None of these events exist on
develop. The subgraph can't index LMS submissions, T1/T2 submissions, finalization, or GI phase transitions without them. Go-ahead on adding them.The issue text doesn't match the spec it's meant to unblock, though, and a few details would produce the wrong events.
1. The source of truth already exists: follow PR #29's audit §4
PR #29 ships
Documentation/technical/audits/task-contract-event-audit.md. Its §4 proposes exact signatures, and they match the commented-out lines insubgraph/subgraph.yaml. Implement those signatures, not the issue's looser "at minimum GI, batch, actor" wording, so the handlers can be uncommented without an ABI mismatch.There are six pending task-level handlers, not five. The issue's table lists only four events:
GIStateChanged(uint indexed GI, uint8 indexed newState)DINTaskCoordinator, every transitionLocalModelSubmitted(uint indexed GI, uint indexed modelIndex, address indexed client, bytes32 modelCID)DINTaskAuditor.submitLocalModel()T1AggregationSubmitted(uint indexed GI, uint indexed batchId, address indexed aggregator, bytes32 cid)DINTaskCoordinator.submitT1Aggregation()T2AggregationSubmitted(uint indexed GI, uint indexed batchId, address indexed aggregator, bytes32 cid)DINTaskCoordinator.submitT2Aggregation()T1BatchFinalized(uint indexed GI, uint indexed batchId, bytes32 winningCID)finalizeT1Aggregation(), per batch, afterb.finalCID = winningCID(:767)T2Finalized(uint indexed GI, bytes32 globalModelCID)finalizeT2Aggregation(), afterb.finalCID = winningCID(:859)Without the two finalization events, the indexer sees votes but never the outcome: which CID won each batch, and the new global model per GI. That's arguably the most-queried fact in the whole lifecycle, so both belong in scope.
2. Corrections to the issue text
submitLocalModellives inDINTaskAuditor(:700), notDINTaskCoordinator.DINShared.sol.DINShared.solholds the enum, errors, and interfaces, and has zero event declarations today. Every existing event is declared in its own contract. Keep that convention.dindao.pypending-requests endpoint isn't affected. It lists model-registration requests (ModelRegistrationRequestedon the registry), which are already indexed. What these events do unblock islms.py/aggregation.py, which iterate submissions over RPC (audit §3.2).3. Two correctness details for the implementer
GIStateChangedwould carry the wrong GI onGIstarted. The audit's_setGIstate(newState)helper emitsGIStateChanged(GI, …), and that's the right approach: one emit site, so no future transition can be missed. But_startGIsetsGIstate = GIstates.GIstartedbeforeGI++(DINTaskCoordinator.sol:310-311). A mechanical find-and-replace would emitGIstartedwith the previous GI. Increment first, then call the helper. Add a test assertingGIStateChanged(N, GIstarted)for GI N.newState == 16isT1AggregationStarted. Ondevelopit's 17, becauseLMSevaluationRevealStartedwas inserted at ordinal 14 on 2026-08-27.GIstatesnow has 24 members. The subgraph'suint8→ GraphQL enum mapping anddaemon-event-schema.mdboth need regenerating from currentDINShared.sol, not from the July snapshot.4. Stale item in audit §5
§5 calls
RewardDepositeddead code and proposes deleting it. That's no longer true:DINTaskAuditor.depositRewardsemits it (:488), and its signature is nowRewardDeposited(uint256 indexed gi, address indexed depositor, uint256 amount), not the(address, uint256)the audit shows. Don't delete it. Add a subgraph handler for it instead, since reward-pool funding per GI is useful to index.5. Split the work: contracts on
develop, handlers onfeat/din-indexerPR #29 is still open and targets
feat/din-indexer, notdevelop. There's nosubgraph/directory ondevelopat all. So "re-enable the five handlers" can't be part of adevelopPR.develop:_setGIstaterefactorvm.expectEmitfor each event, including theGIstarted-carries-new-GI case and oneT1BatchFinalizedper batch in a multi-batch GIdincli/abis/developwith the subgraph work, or note the corrections in the PRforge build --sizes:DINTaskCoordinatoris large, and a 24-transition refactor plus five new events isn't freefeat/din-indexer(after PR A merges):developsubgraph/abis/RewardDepositedhandlerETHTreasuryWithdrawn(DinCoordinator, platform-level) is also still commented out insubgraph.yamland doesn't exist ondevelop. Either drop that handler stub, or repoint it at the eventsDinTreasuryactually emits (EthWithdrawn/ERC20Withdrawn/EthReceived) with aDinTreasurydata source. It shouldn't wait on aDinCoordinatorevent that isn't planned.Revised acceptance criteria
_setGIstatehelper used for everyGIstateassignment;GIstartedemits the new GIvm.expectEmittests for all six, plus the GI-ordering case; fullforge testgreen; contract size within limitdincli/abis/refreshedfeat/din-indexer: ABIs regenerated, six handlers enabled, enum mapping regenerated from currentGIstates,RewardDepositedhandler added,ETHTreasuryWithdrawnstub resolvedGo-ahead with this scope.
docs(tasks): add task_240926_16 — dispute seed, treasury forwarding, …
umeradl commentedon Sep 27, 2026
Closing —
develophalf landed via PR No. 173; subgraph half continues on PR No. 29Landed on
developine9dc3f0(merge of PR No. 173) +04aa58d(review follow-ups); push CI green (run). Verified againstorigin/develop@04aa58d, per the revised acceptance criteria:DINTaskCoordinator:GIStateChanged,T1AggregationSubmitted,T2AggregationSubmitted,T1BatchFinalized,T2Finalized;DINTaskAuditor:LocalModelSubmitted(insubmitLocalModel).DINShared.solhas no event declarations. Checked against the six commented-out handler lines in PR No. 29'ssubgraph/subgraph.yaml— canonical types,indexedflags and parameter order match exactly, so the handlers can be uncommented without an ABI mismatch._setGIstatefor everyGIstateassignment;GIstartedemits the new GI. 24 call sites; the only bareGIstate =is inside the helper.startGIdoesGI++before_setGIstate(GIstates.GIstarted).vm.expectEmittests for all six + GI ordering; full suite green; size within limit.foundry/test/LifecycleEvents.t.sol(9 tests), includingGIStateChanged(N, GIstarted)for GI 1 and 2, oneT1BatchFinalizedper batch in a two-batch GI, and a fullGIstarted→GIendedwalk — each mutation-checked (the tests fail with the ordering fix reverted / emission limited to batch 0).forge test392/392;DINTaskCoordinatorruntime 20,629 → 21,335 B, 3,241 B under EIP-170.dincli/abis/refreshed. Both regenerated viadincli system dump-abi --official: coordinator +5 events, auditor +1, nothing removed.feat/din-indexer(ABIs regenerated, six handlers enabled, enum mapping regenerated from currentGIstates,RewardDepositedhandler,ETHTreasuryWithdrawnstub resolved) — not done yet; it's now unblocked. Tracked as task_240926_16 C0/C5 on PR No. 29 (still at866521a) and in Discussion No. 163, per the planned split (this issue closes with thedevelophalf).The issue body's original four-event /
DINShared.sol/DINTaskCoordinator.submitLocalModelwording is superseded by the review comment linked above; what landed follows the review.