Skip to content

feat(indexer): wire P3-staking events — ValidatorJailed/Reactivated, governable MIN_STAKE, JailEvent entity - #72

Open
robertocarlous wants to merge 43 commits into
InfiniteZeroFoundation:feat/din-indexerfrom
robertocarlous:feat/din-indexer-65
Open

robertocarlous wants to merge 43 commits into
InfiniteZeroFoundation:feat/din-indexerfrom
robertocarlous:feat/din-indexer-65

Conversation

@robertocarlous

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to PR #29 (feat/din-indexer) addressing the P3-staking gap identified in the cross-PR review (discussion #47). Branches off feat/din-indexer and merges feat/p3-staking (PR #65) locally so the subgraph stays in sync with the staking contract additions without blocking on #65's own merge timeline into develop.

Root cause: feat/din-indexer was written before PR #65 added six new events to DinValidatorStake and converted MIN_STAKE from a Solidity constant to a governable storage variable. The event-coverage-audit (§2.2) flagged this exact scenario: "when a jailing mechanism is added, it must emit a ValidatorJailed event with the jailedUntil timestamp for the indexer to reconstruct status correctly."

What changed

  • abis/DinValidatorStake.json — regenerated from the compiled P3 contracts; includes all new functions, events, and errors
  • subgraph.yaml — registers handlers for all six new events: ValidatorJailed, ValidatorReactivated, MinStakeUpdated, UnbondingPeriodUpdated, ModelStakeBoundsUpdated, MaxConcurrentRegistrationsPerStakeUnitUpdated
  • src/staking.ts — adds the six corresponding handler functions; introduces a StakeGovernance singleton entity for governance-parameter writes and ModelStakeBounds entity writes
  • src/utils.ts — syncValidatorStatus gains a Jailed branch (jailedUntil != null → status "Jailed"); reads the current floor from StakeGovernance via getMinStake() instead of a hardcoded constant — no silent auto-return from Jailed, mirroring _syncValidatorStatus() semantics
  • schema.graphql — adds jailedUntil field and jailEvents relation to Validator; new JailEvent entity; new StakeGovernance singleton type; new ModelStakeBounds type

Also included from the parent branch (feat/din-indexer-65 base commits):

Merge order

This PR should merge after PR #29 (feat/din-indexer) and after PR #65 (feat/p3-staking) both land. It is not a blocker for either.

umeradl and others added 30 commits July 8, 2026 21:05
Documentation/ now describes only what exists in code on develop
(not the live Sepolia deployment), split by audience:
- public/ — participant-facing: setup, cli-reference (was common.md),
  getting-started, manifest, services, roles/, workflows/, guides/
- technical/ — internal: contracts/ (per-contract refs), mechanisms/,
  services/, testing/, upgradable-contracts/, ARCHITECTURE.md
  (placeholder moved from Developer/, lands via P3-DOC1)

Developer/ holds forward-looking material:
- design/ (new) — MECHANISM_DESIGN.md, suggested-staking-mechanism.md
  (moved from Documentation/technical/mechanisms — it specifies planned
  behavior, not current), feasibility-report.md
- proposals/ (was tooling/) — proposals for tools not yet built
- issues/, tasks/, discussion/, rejected-ideas/ unchanged

Also:
- Rewrote both index READMEs with the placement rule and layout
- Added "where does a new doc go" + graduation rule (shipped designs get
  rewritten as current-state in Documentation/technical/, not moved)
- Fixed all repo-internal links to moved files (CLAUDE.md, README.md,
  Developer/*, dincli/docker/node/README.md) and repaired relative links
  inside moved files; fixed dead blob/main GitHub URLs to blob/develop
- Added DevNet 2.0 mechanism design doc (design/MECHANISM_DESIGN.md)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Audits all events emitted by DINModelRegistry, DinValidatorStake,
DinCoordinator, and DinToken against indexer reconstruction requirements.

Findings:
- ModelRegistrationRequested: missing isOpenSource and fee — cannot filter
  pending requests by type or surface fee amounts without a storage call
- ManifestUpdateRequested: missing requester address — cannot attribute
  pending updates to their submitter
- DinCoordinator.withdraw(): no event emitted — ETH treasury outflows are
  invisible to the indexer
- SlasherContractAdded/Removed: identical signatures on DinCoordinator and
  DinValidatorStake — resolved at schema level via sourceContract field,
  no contract change needed
- ValidatorJailed path is dead code (jailedUntil is never set); flagged
  for the P3-4.x slashing spec to ensure a jailing event lands when that
  mechanism is added

Proposed additions (confirmed with Umer, 2026-07-09 — land as one PR after
audit review):
  1. ModelRegistrationRequested: + bool isOpenSource, uint256 fee
  2. ManifestUpdateRequested: + address indexed requester
  3. DinCoordinator: new ETHTreasuryWithdrawn(address indexed to, uint256 amount)

Includes daemon event schema table (P4-7.1 feed) mapping platform events to
dind subscription requirements and coverage gaps.
…ph (P4-IDX1)

Defines all queryable entities for the DIN platform subgraph covering
DINModelRegistry, DinValidatorStake, DinCoordinator, and DinToken.

Entities:
  Registry:  ModelRegistrationRequest, Model, ManifestUpdateRequest,
             ModelKillSwitchEvent, FeeSnapshot, RegistryFeeWithdrawal,
             DAOAdminTransfer
  Staking:   Validator (aggregate), StakeEvent, SlashEvent, UnstakeRequest,
             WithdrawalClaim, SlasherRegistration
  Coordinator: DINMintEvent, TreasuryWithdrawal, ExchangeRateSnapshot
  Token:     TokenMintEvent, TokenTransferEvent

Design notes:
- SlasherRegistration carries sourceContract to keep DinCoordinator and
  DinValidatorStake event streams distinguishable (identical event signatures)
- ModelRegistrationRequest.isOpenSource / .feePaid and ManifestUpdateRequest
  .requester are marked pending the §6.1/6.2 event additions; mapping handlers
  will use storage calls as a bridge until those events land
- TreasuryWithdrawal entity is defined but will not be populated until the
  ETHTreasuryWithdrawn event addition (audit §6.3) lands
- Task-level contracts (DINTaskCoordinator/DINTaskAuditor) are out of scope;
  deferred to P5+ dynamic data sources
Defines the Graph Protocol subgraph manifest covering all four platform
contracts on the local development chain (chainId 1337, network: din-local).

Data sources:
  - DINModelRegistry  → src/registry.ts    (15 event handlers)
  - DinValidatorStake → src/staking.ts     (8 event handlers)
  - DinCoordinator    → src/coordinator.ts (5 event handlers + 1 commented-out
                                            pending ETHTreasuryWithdrawn addition)
  - DinToken          → src/token.ts       (2 event handlers)

ABIs copied from dincli/abis/ into subgraph/abis/ — single source of truth
until a build step syncs them automatically.

Contract addresses are placeholders (0x000...001–004); replace with actual
deployed addresses after running the platform contract deployment script.

SlasherContractAdded/Removed duplicate-signature handling: DinValidatorStake
handlers produce the canonical slasher-set records; DinCoordinator handlers
produce audit-trail records with sourceContract set to the coordinator address.
Defines which platform-contract events the dind daemon must subscribe to,
the reaction each event triggers in the daemon job queue, and all current
coverage gaps. Handoff document from P4-IDX1 design to Santiago's P4-7.1
on-chain event listening engine.

Contents:
  §1 Subscription priority — immediate (blacklist/kill-switch), high-priority
     (slash/approval/manifest), and informational buckets
  §2 Full event payload reference for all daemon-consumed events, including
     PENDING field annotations for the two confirmed additions (audit §6.1/6.2)
  §3 Coverage gaps:
     - Task-level GI events (T1AggregationStarted etc.) not in platform
       contracts — listed as P5+ task-level indexing requirement with the
       exact event schema needed for daemon filtering
     - ValidatorJailed dead code path — required event shape documented for
       when P3-4.x slashing spec adds the jailing mechanism
     - ETHTreasuryWithdrawn missing from DinCoordinator.withdraw()
  §4 Subscription mechanics recommendation for Santiago (WebSocket
     eth_subscribe, lastProcessedBlock per-contract, replay on restart)
  §5 Integration order — dincli → SDK extraction → dind, per Umer 2026-07-09
…nnect-wallet fixes + OWS spike

Squash of three commits from the PR InfiniteZeroFoundation#16 review branch (634ce1e, 5cd1a9b,
6905808):

- list-accounts source tag: [..] was parsed by Rich as a markup tag and
  dropped; use (..) so imported/created/legacy renders. Docker node README:
  .session is a file, not a directory (review bugs #1, InfiniteZeroFoundation#6).
- connect-wallet: confirm before overwriting an existing named keystore
  (--yes/-y to bypass, mirrors send-eth), never encrypt a new keystore with
  a stale in-memory cached password, and parse .env once per unlock instead
  of per _get_password call (review items #2, #3, #5). Adds 7 tests.
- OWS delegation feasibility spike (Developer/discussion/
  ows-delegation-feasibility.md): hands-on verification that OWS signs an
  EVM tx without exposing the key; scoped-policy delegation remains
  unproven/follow-up. Corrects wallet-setup.md's broken OWS
  export-keystore flow.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ontracts

Five source files covering all 30 event handlers declared in subgraph.yaml.

src/utils.ts
  - eventId(): stable txHash-logIndex entity IDs for event-based records
  - loadOrCreateValidator(): initialises Validator aggregate on first encounter
  - syncValidatorStatus(): mirrors DinValidatorStake._syncValidatorStatus()
    to keep the Validator.status field in sync after every mutation

src/registry.ts  (DINModelRegistry — 15 handlers)
  - Registration request lifecycle: Requested → Approved / Rejected
  - Bridge for missing event fields: modelRequests(id) storage call populates
    isOpenSource, feePaid, manifestCID, taskCoordinator, taskAuditor until the
    audit §6.1/6.2 event additions land
  - Manifest update lifecycle: Requested → Updated / Rejected; requester
    derived from Model.owner as bridge until §6.2 addition lands
  - Kill switch: ModelDisabled / ModelEnabled update Model.disabled and emit
    ModelKillSwitchEvent
  - Fee snapshots: individual setters read full fee schedule from storage so
    every FeeSnapshot carries all four values; FeesUpdated reads from event
    params directly (atomic — no storage call needed)
  - FeesWithdrawn → RegistryFeeWithdrawal
  - DAOAdminUpdated → DAOAdminTransfer

src/staking.ts  (DinValidatorStake — 8 handlers)
  - ValidatorStaked / Slashed / UnstakeRequested / WithdrawalClaimed update the
    Validator aggregate and create the corresponding history entities
  - Slash handler mirrors contract's active-stake-first, then pending-withdrawal
    deduction logic for accurate aggregate tracking
  - Blacklisted / Unblacklisted flip Validator.blacklisted and re-sync status
  - SlasherContractAdded/Removed: canonical slasher-set records with
    sourceContract = DinValidatorStake address

src/coordinator.ts  (DinCoordinator — 5 handlers)
  - EthDepositAndDINminted → DINMintEvent
  - DinPerEthUpdated → ExchangeRateSnapshot
  - ValidatorStakeContractUpdated: intentional no-op (one-time deploy wiring)
  - SlasherContractAdded/Removed: audit-trail SlasherRegistration records with
    sourceContract = DinCoordinator address (distinct from staking.ts records)
  - ETHTreasuryWithdrawn handler stubbed and commented pending audit §6.3

src/token.ts  (DinToken — 2 handlers)
  - TokensMinted → TokenMintEvent
  - Transfer → TokenTransferEvent (covers mints from 0x0 and normal transfers)
Runs graph-node, IPFS (kubo), and Postgres against the local anvil chain
(chainId 1153 1337, network: din-local) for subgraph development and testing.

Services:
  graph-node  graphprotocol/graph-node:v0.34.1
    - ports 8000 (HTTP), 8001 (WS), 8020 (deploy), 8030 (status), 8040 (metrics)
    - ethereum env var maps din-local → host.docker.internal:8545
    - GRAPH_ETHEREUM_TARGET_TRIGGERS_PER_BLOCK_RANGE=1 for on-demand anvil blocks
  ipfs        ipfs/kubo:v0.27.0
    - port 5001 (API); used by graph-node and graph deploy
  postgres    postgres:16-alpine
    - POSTGRES_INITDB_ARGS sets UTF8/C locale required by graph-node TOAST

Both ipfs and postgres have healthchecks; graph-node depends_on postgres
with condition: service_healthy so it waits for the DB to be ready before
attempting to connect.

.env.example documents the ETHEREUM_RPC and Postgres credential overrides.
Linux users must replace host.docker.internal with 172.17.0.1.

Startup sequence is documented in the docker-compose.yml header comment.
Replace the two for-idx-in-range enumeration loops in
list-pending-requests with GraphQL queries to the local subgraph,
with a silent fallback to the original RPC loops when the
graph-node endpoint is unavailable.

Add unit tests covering the GraphQL happy path and all three
fallback triggers (connection error, GraphQL error body, HTTP 5xx).
Documents the integration point, GraphQL queries used, fallback
behaviour, DIN_SUBGRAPH_URL config, and follow-up RPC loop
candidates in lms.py and aggregation.py.
Cherry-picked from PR InfiniteZeroFoundation#28, relocated from Documentation/public/guides/
to Developer/proposals/: this documents research into a storage
provider dincli does not yet integrate (no FOC/filecoin-pin adapter
exists in ipfs.py), so per Developer/README.md's placement rule it
belongs with forward-looking tooling material, not with docs of what
already exists on develop.

Replaces the Storacha guide (PR InfiniteZeroFoundation#26, closed) as the storage
recommendation for Discussion InfiniteZeroFoundation#18: Storacha's infrastructure (console,
API host, and both storacha.link/w3s.link retrieval gateways) is down
as of this research -- Cloudflare Error 1000 on the apex domain,
NXDOMAIN on console/API subdomains, gateways redirecting into the
broken root. Not a frontend-only issue.

Covers Filecoin Pin (the filecoin-pin CLI/library, built on FOC's
Synapse SDK) in the same three-part structure as the Storacha guide:
Web setup, CLI upload/retrieve, and authentication -- wallet keys and
the Session Key delegation model, which turns out to be a much closer
parallel to Storacha's UCAN delegation than raw-key-or-nothing.

Fact-checked against the filecoin-pin GitHub repo directly (README,
CLI source in src/commands/, documentation/retrieval.md and
content-routing-faq.md) rather than docs.filecoin.io, which 404'd on
the CLI walkthrough page during this research. Caught and corrected
one safety-critical error from an earlier research pass: the CLI
defaults to Mainnet (real funds), not Calibration testnet as
initially assumed.
Discussion InfiniteZeroFoundation#18 hands-on testing ruled out both providers this doc
recommended: Lighthouse retrieval is payment-gated (fails the
"readers pay nothing" requirement), and Storacha's infrastructure is
down/deprecated. Point at the new Filecoin Onchain Cloud proposal
(Developer/proposals/filecoin-onchain-cloud.md) instead of leaving a
stale recommendation for the next reader to walk into.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…n guide (relocated)

Manually merged PR InfiniteZeroFoundation#28 by Similoluwa
Abidoye. Content unchanged from the PR except relocation from
Documentation/public/guides/ to Developer/proposals/: FOC/filecoin-pin
is not integrated into dincli (no code changed here, ipfs.py still
only supports env/filebase/custom), so per Developer/README.md's
placement rule this is forward-looking research material, not
documentation of what exists on develop.

Also updates Developer/discussion/add-filecoin-support.md, which
previously recommended Lighthouse and Storacha as the best
Filecoin-backed providers -- both since ruled out by this same
research (Discussion InfiniteZeroFoundation#18) -- so it no longer contradicts the new
proposal doc.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…niteZeroFoundation#22)

Manually merges the Part 1 deliverable of task_060726_4 from
Similoluwa Abidoye (@Abidoyesimze, PR InfiniteZeroFoundation#22, branch security/foundry-src-review).

The 7 contracts in foundry/src/ are byte-identical between the audit's
pinned commit (d136ff3) and current develop, so the findings and line
references apply as-is to the live contracts.

- Documentation/technical/audits/foundry-src-security-review.md
  (relocated from the PR's Developer/audits/ path)
- foundry/test/SecurityFindings.t.sol — 9 PoC/verification tests, all
  passing (forge test --match-contract SecurityFindingsTest).

Findings: 0 Critical, 4 High, 4 Medium, 8 Low/Informational.
Open follow-ups tracked on PR InfiniteZeroFoundation#22: severity of H-1/H-2 (candidate for
Critical) and a measured spec-scale gas number for H-1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Target architecture for the full stack — DAO/platform/task contracts,
indexer, SDK, dincli/dind, IPFS layer, din-node/worker — with layered
Mermaid + ASCII diagrams, key flows, and P4 dependency order. Links the
live diagram on mermaidviewer.com and indexes the doc in Developer/README.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… DINTaskAuditor templates

taskCoordinator.ts — four handlers covering aggregator registration,
T1/T2 batch creation, and aggregator slashing. GlobalIteration is
lazily instantiated on the first event per GI.

taskAuditor.ts — eight handlers covering auditor registration, audit
batch creation, scoring, eligibility voting/finalization, pass score
governance, and auditor slashing. Introduces loadOrCreateLMS() which
pre-creates a stub LocalModelSubmission (zero client/modelCID) on first
reference so the required relationship field on AuditScoreSubmission,
EligibilityVote, and EligibilityResult is never null at query time;
stubs are upgraded in-place once the LocalModelSubmitted event lands.
…proxies (PR InfiniteZeroFoundation#13)

Land the platform-upgradeable work from PR InfiniteZeroFoundation#13:
- DinCoordinator, DinToken, DinValidatorStake, DINModelRegistry converted
  to initializer-based transparent-proxy implementations
- V2 stub implementations under hardhat/contracts/upgrade/ with upgrade
  test suites under hardhat/test/
- deploy-platform.ts / upgrade-platform.ts scripts plus shared
  deploy/{constants,helpers,types}.ts and test/helpers/platform.ts
- MockSlasher test mock, hardhat-upgrades tooling deps, updated
  DinCoordinator/DinToken ABIs
- .gitignore: stop ignoring hardhat/scripts and hardhat/test so the
  deploy/upgrade tooling is tracked on develop

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…) with dincli harness, docs, wallet split

Follow-up integration on top of the PR InfiniteZeroFoundation#13 contract work:
- dincli test harness (tests/dincli/) updated to deploy the platform via
  the interim deploy-platform.ts script + import-deployments flow;
  hardhat/deployments/localhost.json and din_info.json tracked for it
- dincli: register-wallet/connect-wallet split follow-ups in
  cli/{context,core,system,utils}.py and main.py; regenerated
  DINModelRegistry/DinValidatorStake ABIs
- Documentation/technical/contracts/hardhat/: per-file docs for the new
  deploy/upgrade tooling, V2 contracts, and test suites (with coverage
  gaps); refreshed platform contract docs for the proxy conversion
- Documentation/technical/testing/: new docs for dintoken, ipfs-config,
  cache-client-dp, connect-wallet test suites; testing-guide and
  containerization-guide updates
- Documentation/public/: wallet-setup, keystore-migration, setup,
  getting-started, cli-reference, model-workflow updated for the wallet
  split and upgradeable deployment
- Developer/issues/dincli-native-proxy-deployment.md: backlog Option C
  (native dincli proxy deployment); retire technical/ARCHITECTURE.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…/home/azureuser

constants.py now resolves everything from the repo checkout, home
directory, or environment: repo root via __file__, venvs via
~/my_venvs/<name>, npx via the newest ~/.nvm/versions/node/*/bin/npx,
scratch dir ~/tempdir/dincli. All resolutions are overridable via env
vars (PYDIN_PYTHON, TORCHENV_PYTHON, TORCHENV_SITE_PACKAGES, NPX_BIN,
IPFS_BIN, DIN_TEST_TMPDIR), read from the real environment first and
then the repo-root .env. conftest.py and test_04_gi.py consume the
shared constants instead of their own literals.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ences

Rewrite all 101 remaining /home/azureuser occurrences across 17 files
in Documentation/ and Developer/:

- markdown links to repo files become relative links (GitHub-navigable)
- shell/repo paths use the /path/to/devnet placeholder
- venv and scratch paths use ~/my_venvs/... and ~/tempdir/dincli/
- HR profile pointers in migrate_to_foundy.md use ~/projects/HR/...
- DIN_STATE_DIR example uses /home/<user>/.din-node; drop a stray
  duplicate mkdir line in containerization-guide.md

Also repoint references to the six per-model service files
(client/aggregator/auditor/model/scoring/modelowner.py) from
dincli/services/ to cache_model_0/services/ — they moved there when
services became per-model — and retarget the proposed contribution.py
module to cache_model_0/services/ for consistency.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Working summary of Abraham Nash's DIN white paper (Jun 2026) with a
gap/alignment checklist mapping paper mechanisms to DevNet status,
feeding the P3 mechanism-design push.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
umeradl and others added 13 commits July 19, 2026 05:51
…acking into docs

- design/p3-design-plan.md: coordination page for the P3 mechanism-design
  push — mechanism -> design sources -> GitHub issue map (issues 36-43),
  open-decision -> discussion map (discussions 44-46), white-paper gap
  routing, definition of done
- ROADMAP.md: P3 status note (delayed pending designs; P4 active in
  parallel; dates not binding)
- MECHANISM_DESIGN.md, README.md: cross-references

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… (PR InfiniteZeroFoundation#35)

Original work by Robert (@robertocarlous, PR InfiniteZeroFoundation#35, branch
feature/foundry-platform-deployments, head 45dcda1), implementing issue
InfiniteZeroFoundation#34: DeployPlatform.s.sol, UpgradePlatform.s.sol, four V2 upgrade stubs
(DinTokenV2, DinCoordinatorV2, DinValidatorStakeV2, DINModelRegistryV2),
the forge test suite (DeployPlatform.t.sol), dincli's
`system import-deployments --foundry` flag, and the
foundry.toml/package.json/.gitignore changes needed to run them.

Three blocking bugs found in local verification, fixed here:
- DeployPlatform.s.sol: vm.writeJson has no parent dir on a fresh clone
  (foundry/deployments/ is gitignored and not committed) — call
  vm.createDir before vm.writeJson.
- All four V2 stubs: a plain `//` comment sat between the two `///`
  NatSpec lines, splitting the doc block so `@custom:oz-upgrades-from`
  never reached solc — UpgradePlatform.s.sol failed upgrades-core
  validation for every contract. Moved the `//` explanation above the
  NatSpec block so the `///` lines stay contiguous.
- Both scripts' own documented "Usage (from repo root)" command didn't
  compile (foundry.toml/remappings.txt live in foundry/, not repo
  root) — changed the usage comments to `cd foundry && forge script ...`.

Verified end-to-end: forge test (40/40 passing), and both scripts run
against a local chain (deploy -> deployments JSON -> dincli system
import-deployments --foundry -> upgrade, version() == 2 through the
proxy for all four contracts).

Co-Authored-By: umeradl <umermajeed.cto@gmail.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… harness

tests/dincli/ can now deploy the platform contracts via either the new
forge script from PR InfiniteZeroFoundation#35 or the existing hardhat script, selected by
PLATFORM_DEPLOY_TOOLCHAIN (tests/dincli/constants.py; default "foundry",
matching `dincli system import-deployments`'s own default). Overridable
via env var / .env for anyone who wants to keep exercising the hardhat
path.

- constants.py: FOUNDRY_DIR, FORGE_BIN, PLATFORM_DEPLOY_TOOLCHAIN,
  HARDHAT_DEV_ACCOUNT_0; DEPLOYMENTS_FILE now resolves under whichever
  toolchain's deployments/ dir.
- test_01_platform.py: test_deploy_platform_via_script branches on the
  toolchain (forge script vs hardhat run); test_import_deployments_into_din_info
  keeps passing an explicit --file since import-deployments' own
  --foundry/--hardhat default-path resolution is relative to cwd, and
  the harness's cwd is the isolated DIN_TEMP scratch dir, not the repo
  root.
- conftest.py: managed_services now starts the matching chain backend
  (Anvil via foundry/anvil.sh for "foundry", the existing Hardhat node
  for "hardhat" — both on chain-id 1337) and runs `forge build` when
  the foundry toolchain is active; `npx hardhat compile` still always
  runs since task-level contract deploys and dump-abi tests need
  hardhat's ABIs/bytecode regardless of which toolchain deployed the
  platform.

Verified: full tests/dincli/test_01_platform.py (8/8) under both
toolchains, and test_01 through test_03 (35/35) end-to-end under the
new foundry default.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Two follow-up fixes to files landed in b40fe2e (PR InfiniteZeroFoundation#35 foundry
platform deploy/upgrade parity):

- foundry/test/DeployPlatform.t.sol: the DinCoordinatorV2/
  DinValidatorStakeV2/DINModelRegistryV2 imports sat mid-file, after
  the MockTaskContract definition — moved them up next to the
  DinTokenV2 import at the top, with the rest of the imports.
- foundry/script/DeployPlatform.s.sol: added a `forge clean` step to
  the documented "Usage (from repo root)" comment, right after
  starting anvil. Without it, deploying then testing back-to-back
  after a recompile can hit upgrades-core's stale build-info bug
  ("Found multiple contracts with name ...") — reproduced again while
  re-verifying this change; `forge clean` resolves it.

Also ran `forge fmt` over both files (line-wrapping only, no logic
changes).

Re-verified: forge clean && forge test — 40/40 passing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds staking-design.md and tokenomics-design.md, and updates the
mechanism design, staking mechanism, and P3 plan docs to reflect them.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ions

Records outcomes from Abraham's Slack sync (2026-07-21) against the open
decisions tracked in MECHANISM_DESIGN §9, staking-design.md §5, and
tokenomics-design.md §6: slashed-stake destination (50/50 burn/treasury),
depositAndMint cap/retirement, emission decay with MAX_SUPPLY left open,
dual-source burn policy, delegation/tombstoning scope, and the white-paper
InfiniteZeroFoundation#46 alignment items. Fee denomination is resolved as a DIN/ETH split
(protocol fees in DIN, validator network fees in ETH), not the DIN-only
recommendation these docs previously carried.

GitHub Discussions InfiniteZeroFoundation#44/InfiniteZeroFoundation#45/InfiniteZeroFoundation#46 themselves are not yet updated to reflect
this — noted in p3-design-plan.md so the "resolved" checkbox isn't marked
done prematurely.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…iteZeroFoundation#37/InfiniteZeroFoundation#42/InfiniteZeroFoundation#43)

Scopes a 5-day platform-contract task combining the now-resolved staking,
tokenomics, and fees/treasury designs: new DinTreasury and DinFeeRouter
contracts, DinToken.burn(), DinCoordinator mint-cap/faucet-retirement/
treasury-routing, DinValidatorStake governable params + real jailing, and
a DIN-denominated fee path alongside DINModelRegistry's existing ETH fees.
Includes the exact deployment/wiring order and test plan.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… storage (InfiniteZeroFoundation#37)

Convert MIN_STAKE and UNBONDING_PERIOD from constants to DAO-settable
storage with onlyOwner setters. Add unenforced per-model stake bounds
(modelMinStakeBounds) and concurrent-registration cap storage
(maxConcurrentRegistrationsPerStakeUnit) — stored at platform level,
enforcement in task contracts is follow-up work. Implement jailValidator
(slasher-callable, extends but never shortens) and reactivate (explicit
operator re-entry after jail expires and stake >= floor). Fix
_syncValidatorStatus to never auto-return from Jailed — only reactivate()
can clear that status. Shrink __gap from [50] to [46] for the 4 new slots.
…rt bounds (InfiniteZeroFoundation#37)

26 tests: setMinStake/setUnbondingPeriod (onlyOwner, zero-revert, storage
update, no retroactive effect on in-flight withdrawals); setModelStakeBounds
(round-trip, min>max revert, no effect on staking); setMaxConcurrent
(round-trip, no effect on staking); full jail lifecycle (stake → jail →
early reactivate fails → warp past jail → StakeBelowFloor → top-up →
reactivate succeeds → isValidatorActive true); extend-never-shorten jail;
jailValidator guards (onlySlasher, zero address, zero duration, blacklisted).
…finiteZeroFoundation#37)

Issue InfiniteZeroFoundation#37 explicitly asks this to be documented. Stake gates eligibility
only — selection above the floor is random. Weighting is rejected because
it concentrates work in whales, weakens the cross-validator median, and
creates a centralisation feedback loop inconsistent with DIN's federated
model.
…dation#65)

Merging feat/p3-staking (PR InfiniteZeroFoundation#65) into the indexer branch introduced six
new DinValidatorStake events and changed MIN_STAKE from a constant to a
governable storage variable. This commit brings the subgraph up to date:

- abis/DinValidatorStake.json: regenerated from compiled P3 contracts
- subgraph.yaml: register handlers for ValidatorJailed, ValidatorReactivated,
  MinStakeUpdated, UnbondingPeriodUpdated, ModelStakeBoundsUpdated,
  MaxConcurrentRegistrationsPerStakeUnitUpdated
- staking.ts: add handleValidatorJailed, handleValidatorReactivated,
  handleMinStakeUpdated, handleUnbondingPeriodUpdated,
  handleModelStakeBoundsUpdated, handleMaxConcurrentRegistrationsPerStakeUnitUpdated;
  introduce StakeGovernance singleton and ModelStakeBounds entity writes
- utils.ts: syncValidatorStatus gains a Jailed branch (jailedUntil != null),
  reads the current floor from StakeGovernance via getMinStake() instead of
  a hardcoded constant — no silent auto-return from Jailed, mirroring the
  contract's _syncValidatorStatus() semantics
- schema.graphql: add jailedUntil field and jailEvents relation to Validator,
  new JailEvent entity, StakeGovernance singleton type, ModelStakeBounds type
@robertocarlous

Copy link
Copy Markdown
Collaborator Author

Hi @umeradl

Pls can you look into this. thanks

@umermjd11

Copy link
Copy Markdown
Collaborator

Review — against 1a2a877 (PR head), merge-base 866521a (feat/din-indexer / PR #29 HEAD)

Scope confirmed: this PR's base is PR #29 (feat/din-indexer), not develop. git diff 866521a..1a2a877 — the actual work this PR itself contributes — touches subgraph/abis/DinValidatorStake.json, subgraph/schema.graphql, subgraph/scripts/update-subgraph-addresses.sh, subgraph/src/staking.ts, subgraph/src/utils.ts, subgraph/subgraph.yaml, and dincli/cli/dindao.py (comments only) — matches the PR body's own "What changed" list exactly. Everything else in the raw diff (foundry/hardhat P3-staking contracts, their tests, ~30 doc files) is inherited unchanged from this PR's local merge of already-merged PR #65 (feat/p3-staking) into the feat/din-indexer line, not new work from this PR's own commits.

Files changed (this PR's own contribution)

File Change What it does
subgraph/subgraph.yaml +15 Registers handlers for the 6 new DinValidatorStake events (ValidatorJailed, ValidatorReactivated, MinStakeUpdated, UnbondingPeriodUpdated, ModelStakeBoundsUpdated, MaxConcurrentRegistrationsPerStakeUnitUpdated) and 3 new schema entities.
subgraph/src/staking.ts +97 Adds the 6 handler functions; introduces loadOrCreateStakeGovernance() singleton pattern for governance-parameter writes.
subgraph/src/utils.ts +29/-modified syncValidatorStatus gains a Jailed branch; getMinStake() reads the governable floor from StakeGovernance instead of a hardcoded constant.
subgraph/schema.graphql +73 Adds jailedUntil/jailEvents to Validator; new JailEvent, StakeGovernance, ModelStakeBounds types.
subgraph/abis/DinValidatorStake.json regenerated Includes the new P3-staking functions/events/errors.
subgraph/scripts/update-subgraph-addresses.sh (new) +78 Patches placeholder addresses in subgraph.yaml from a deployments JSON.
dincli/cli/dindao.py +6 Comments documenting the known first: 1000 GraphQL result cap.

Independently re-verified

  • All 6 event handlers, read directly against the actual event signatures in subgraph.yaml/the regenerated ABI: correct field mappings, no signature mismatches.
  • syncValidatorStatus: correctly implements "Jailed status has no silent auto-return — stays Jailed until reactivate() explicitly clears it." I checked this against develop's actual, currently-merged DinValidatorStake._syncValidatorStatus() (not this branch's own embedded copy — see finding below) and it's a precise match: if (validator.status == ValidatorStatus.Jailed) { return; }, no time-based auto-clear. Good catch by whoever wrote this — it would have been an easy place to get subtly wrong.
  • handleValidatorSlashed: mirrors slash()'s active-stake-then-pending-withdrawal consumption order exactly, including the pendingWithdrawal zeroing edge case.
  • Governance singleton pattern (StakeGovernance, ModelStakeBounds): sensible design — seeds initialize() defaults on first load, updates in place on each governance event, matches the "inert storage, not yet enforced" framing from the contract's own NatSpec.
  • npx graph codegen: clean, generates types for all 6 data sources with no errors.

Real finding: this PR's embedded DinValidatorStake.sol has drifted from what's actually on develop, and the indexer is missing a governance event as a direct result

This PR locally merges feat/p3-staking (PR #65) rather than waiting for it to land on develop — reasonable, since #65 had already merged separately by the time this PR was opened. But the two copies have diverged. Diffing this branch's foundry/src/DinValidatorStake.sol against develop's real, currently-merged version: develop has a slashTreasury mechanism this PR's copy doesn't — IBurnableToken interface, slashTreasury state var, SlashTreasuryUpdated event, setSlashTreasury() setter, and a 50%-burn/50%-treasury split inside slash(). This isn't in the version #65 was merged in with when this branch was cut.

Concrete, checkable consequence: SlashTreasuryUpdated and slashTreasury appear nowhere in this PR — not in subgraph.yaml, not in staking.ts, not as a field on the StakeGovernance entity alongside minStake/unbondingPeriod/maxConcurrentRegistrationsPerStakeUnit (which is exactly the entity built to hold DAO-governable params like this one). Not a bug in the code this PR wrote — a real gap caused by the snapshot it was built from being stale, and invisible to GitHub's conflict detection since this PR targets feat/din-indexer, never touches develop directly, and the two versions don't textually conflict (they just silently diverged).

Real finding: npx graph build fails — but it's pre-existing in PR #29, not introduced here

subgraph/src/registry.ts doesn't compile: AssemblyScript doesn't support TypeScript union-type parameters, and two helper functions there take event: ModelDisabled | ModelEnabled / event: OpenSourceFeeUpdated | ProprietaryFeeUpdated | OpenSourceUpdateFeeUpdated | ProprietaryUpdateFeeUpdated. There's also a harmless-but-also-broken inline import("@graphprotocol/graph-ts").Address type reference in the same file (redundant — Address is already statically imported at the top).

Confirmed via direct diff that registry.ts is byte-identical between this PR and PR #29's actual current head — this is entirely inherited, not something this PR's own commits touch or introduce. But it does mean the subgraph can't currently be built or deployed end-to-end with the real graph-cli toolchain, which blocks verifying this PR's own staking.ts the same way. Reviewed staking.ts/utils.ts by careful static reading against the ABI and contract source instead — no issues found there, and graph codegen (which parses the ABIs/schema independent of the AssemblyScript compile step) succeeds cleanly, giving reasonable confidence the types line up.

Follow-ups

  • Add SlashTreasuryUpdated/slashTreasury tracking to StakeGovernance (event handler + schema field) before this indexer work is considered complete for the currently-deployed contract shape.
  • Fix registry.ts's union-typed parameters (split into per-event-type functions, or a shared base interface) — blocks graph build/graph deploy entirely today. Belongs in feat(indexer): implement DIN Protocol subgraph — platform + task-level contracts #29, but nothing here can be end-to-end verified until it's fixed either there or as a small unblocking commit riding along with this PR.
  • subgraph/docs/event-coverage-audit.md (§ "No ValidatorJailed event") predates both the jailing mechanism and slashTreasury — worth a refresh pass once the above lands, since this PR is precisely the kind of change that audit doc exists to track.

Recommendation

The code this PR itself wrote is correct and well-verified — event wiring, status-sync semantics, and the governance-singleton pattern all check out against the real, current contract behavior. Two things worth resolving before treating the indexer as complete: the slashTreasury gap (concrete, scoped, this PR's responsibility since it's the one claiming to sync staking events) and the registry.ts build blocker (not this PR's bug, but worth linking to #29 so it doesn't get lost). Neither blocks merging into feat/din-indexer today.

@umermjd11

Copy link
Copy Markdown
Collaborator

Files changed — as of 1a2a877 (PR head)

Diffed against merge-base 866521a, which is PR #29's (feat/din-indexer) actual current head — confirmed as a real ancestor of this branch (git merge-base --is-ancestor checks out clean). This PR's own diff against that base: 165 files, 12,899 insertions(+) / 1,780 deletions(-), but the large majority of that is inherited unchanged content from this branch's local merge of already-merged PR #65 (feat/p3-staking), not new work — see the table below for what this PR's own commits actually touch.

(Table is per-file, key/value.)

subgraph/subgraph.yaml

Field Value
Change Modified
Lines +15
Diff (what exactly is in this PR) Registers the 6 new DinValidatorStake event handlers and 3 new schema entities on the existing DinValidatorStake data source.
Diff vs PR #29 current HEAD This is the diff — #29 doesn't have these registrations.
Local merge conflict No
GitHub merge conflict No

subgraph/src/staking.ts

Field Value
Change Modified
Lines +97
Diff (what exactly is in this PR) 6 new handler functions + loadOrCreateStakeGovernance() singleton helper.
Diff vs PR #29 current HEAD This is the diff.
Local merge conflict No
GitHub merge conflict No

subgraph/src/utils.ts

Field Value
Change Modified
Lines +29 (net)
Diff (what exactly is in this PR) Jailed branch in syncValidatorStatus; getMinStake() reads from StakeGovernance instead of a constant.
Diff vs PR #29 current HEAD This is the diff.
Local merge conflict No
GitHub merge conflict No

subgraph/schema.graphql

Field Value
Change Modified
Lines +73
Diff (what exactly is in this PR) jailedUntil/jailEvents on Validator; new JailEvent, StakeGovernance, ModelStakeBounds types.
Diff vs PR #29 current HEAD This is the diff.
Local merge conflict No
GitHub merge conflict No

subgraph/abis/DinValidatorStake.json

Field Value
Change Modified (regenerated)
Lines large (full ABI regen)
Diff (what exactly is in this PR) Regenerated from the (locally-merged) P3-staking contract compile.
Diff vs PR #29 current HEAD This is the diff — but see the review comment above: this ABI reflects a stale snapshot of DinValidatorStake.sol that's missing the slashTreasury additions actually on develop.
Local merge conflict No
GitHub merge conflict No

subgraph/scripts/update-subgraph-addresses.sh (new)

Field Value
Change New
Lines +78
Diff (what exactly is in this PR) Patches placeholder contract addresses in subgraph.yaml from a deployments JSON, foundry- or hardhat-schema.
Diff vs PR #29 current HEAD Net-new file.
Local merge conflict No
GitHub merge conflict No

dincli/cli/dindao.py

Field Value
Change Modified
Lines +6
Diff (what exactly is in this PR) Comment-only: documents the existing first: 1000 GraphQL result cap on two queries.
Diff vs PR #29 current HEAD This is the diff.
Local merge conflict No
GitHub merge conflict No

Everything else in the raw diff is inherited, not new

The remaining ~155 files (foundry/src/DinValidatorStake.sol + its hardhat mirror, foundry/test/DinValidatorStake.t.sol, ~30 Developer/Documentation reorganization files, tests/dincli/*, etc.) come from this branch's local merge commit (ecdd87b) pulling in already-merged PR #65's work, so feat/din-indexer stays buildable against the current staking contract shape without waiting on #65's own merge timeline. None of it is this PR's own authorship — flagged here only because it's where the slashTreasury drift documented in the review comment above actually lives.

No conflicts against the stated base

gh pr view 72: mergeable: MERGEABLE, mergeStateStatus: CLEAN against feat/din-indexer (#29). Confirmed independently: merge-base 866521a is PR #29's real current head, so this PR is sitting directly on top of it with nothing to reconcile.

Downstream risk, not a blocker on merging into #29 today

When #29 (and by extension this PR) eventually merges into develop, foundry/src/DinValidatorStake.sol as carried in this branch will need to reconcile against develop's real version — which has diverged (the slashTreasury mechanism, see review comment). Depending on how that merge is done, this is either a real textual conflict (the safe outcome — forces someone to look at it) or, if resolved carelessly favoring this branch's version, a silent regression that drops slashTreasury from develop. Worth flagging explicitly to whoever handles the eventual #29→develop merge; not something to fix in this PR, which only needs to merge cleanly into #29.

@umermjd11

Copy link
Copy Markdown
Collaborator

Reviewed in an isolated worktree against the real commit graph, not just GitHub's file-change summary.

Scope correction first: GitHub reports 185 files changed / +20937/-1412 against base feat/din-indexer — that's misleading. This PR's head (1a2a877) is confirmed 25 commits ahead of PR #29's head (866521a) and 0 commits behind it, i.e. it fully contains PR #29 (still unmerged into feat/din-indexer). PR #29 is reviewed separately; re-reviewing its content here would be redundant. Of those 25 incremental commits, only 2 are this PR's own work (1a2a877 "wire P3-staking events into subgraph" and 2b015f5 "document 1000-result GraphQL cap; add update-subgraph-addresses.sh"); the rest arrived via ecdd87b merging origin/feat/p3-staking (PR #65, already merged to develop on 2026-08-10) — old history feat/din-indexer-65 absorbed at branch-cut time, not new content. Scoping the diff to subgraph/ (the only directory this PR's own commits actually touch) gives the true content: 6 files, +962/-380 — confirmed via git diff 866521a..1a2a877 --stat -- subgraph/. I also confirmed the other 110 non-subgraph files that differ from current develop are pre-existing drift from develop's 165 commits of forward progress since this branch's snapshot — not anything introduced by this PR.

Claimed: Six new events (ValidatorJailed, ValidatorReactivated, MinStakeUpdated, UnbondingPeriodUpdated, ModelStakeBoundsUpdated, MaxConcurrentRegistrationsPerStakeUnitUpdated) are wired end-to-end.

Verified — all six match exactly: grep'd the live event signatures out of foundry/src/DinValidatorStake.sol (lines 90-95) and diffed them against the event: entries registered in subgraph.yaml (lines 139-150) — indexed-parameter positions match exactly, e.g. ValidatorJailed(indexed address,uint64,indexed bytes32,indexed address) matches the Solidity signature parameter-for-parameter. Each has a corresponding handle* function present in src/staking.ts.

Claimed: abis/DinValidatorStake.json was regenerated from the compiled P3 contracts.

Verified: the checked-in ABI contains all six new events plus the new errors (InvalidJailDuration, JailPeriodNotExpired, NotJailed, InvalidMinStake, InvalidUnbondingPeriod, AmountLessThanMinStake) and functions (jailValidator, setMinStake, setUnbondingPeriod, setModelStakeBounds, setMaxConcurrentRegistrationsPerStakeUnit) — grepped directly out of the JSON, all present.

Claimed: syncValidatorStatus's new Jailed branch mirrors the contract's _syncValidatorStatus() — no silent auto-return once jailedUntil passes; only explicit reactivation clears it.

Verified — exact semantic match: read _syncValidatorStatus() in foundry/src/DinValidatorStake.sol (lines 402-421): once status == Jailed it returns immediately regardless of timestamp, with an explicit comment "No silent auto-return: the operator must prove the node is back online first" — reactivate() (line 358) is the only path that clears it, gated by block.timestamp < v.jailedUntil → revert. The AS mirror in utils.ts checks jailedUntil != null before any other branch and returns early; handleValidatorReactivated in staking.ts sets jailedUntil = null (the only place that does), and handleValidatorJailed is the only place that sets it. Same state machine, same invariant.

Claimed: StakeGovernance singleton seeds correct defaults before any governance event fires.

Verified: loadOrCreateStakeGovernance() seeds minStake = 10000000000000000000 (10 DIN) and unbondingPeriod = 604800 (7 days) — matches the contract's initialize() exactly (MIN_STAKE = 10 * 1e18, UNBONDING_PERIOD = 7 days, foundry/src/DinValidatorStake.sol lines 121-122).

Claimed: ModelStakeBoundsUpdated writes a ModelStakeBounds entity, and the governance updates (MinStakeUpdated/UnbondingPeriodUpdated/MaxConcurrentRegistrationsPerStakeUnitUpdated) all update the same StakeGovernance singleton.

Verified: read all four handlers in staking.ts — all three governance-param handlers call the shared loadOrCreateStakeGovernance() and write to "singleton"; handleModelStakeBoundsUpdated correctly keys a per-model ModelStakeBounds entity by modelId. schema.graphql has matching StakeGovernance/ModelStakeBounds/JailEvent types and the new jailedUntil/jailEvents fields on Validator.

Claimed: subgraph/scripts/update-subgraph-addresses.sh patches subgraph.yaml placeholder addresses from a deployments JSON.

Verified: script present, reads foundry/deployments/localhost.json with a fallback to the hardhat path, patches subgraph.yaml in place. Not executed end-to-end (needs a live local deploy artifact), but the logic reads correctly.

Claimed (PR body, "also included from the parent branch"): known-limit comments on the two first: 1000 GraphQL queries in dincli/cli/dindao.py.

Correction: this file does not appear in this PR's own subgraph/-scoped diff — it's inherited from PR #29's head, not new content in #72. Not this PR's claim to verify; flagging so the merge-proposal table below doesn't imply otherwise.

Verified — codegen/build: npm install && npx graph codegen succeeds cleanly (types generated for all data sources, templates, and schema). npx graph build fails, but the failure is in src/registry.ts (TS1005/TS1110/TS1109 parse errors around line 204/253) — a file this PR does not touch (confirmed absent from the subgraph/-scoped diff). That's a pre-existing AssemblyScript compile issue inherited from PR #29's own work, out of scope here and worth flagging separately on PR #29 rather than blocking this one.

Not independently re-verified: a full green graph build of this PR's own handlers in isolation (blocked by the unrelated registry.ts crash above) and a live local Graph Node index-and-query run (no anvil/graph-node stack running in this worktree).


Every checkable claim in this PR's actual content (the 6 subgraph/ files) held up under direct comparison against the live Solidity source, byte-for-byte ABI inspection, and successful codegen. The one build gap (registry.ts) is pre-existing and belongs to PR #29, not this PR. Mergeable as-is once PR #29 lands first — this PR's head already contains #29's commits, so merging #72 alone (without #29 first) would silently pull #29's unreviewed content into feat/din-indexer as a side effect. Recommended order: PR #29 → feat/din-indexer, then PR #72 → feat/din-indexer (fast-forward or trivial merge, since #72 already has #29 fully merged in locally). PR #65's dependency is already satisfied (merged to develop 2026-08-10). Note feat/din-indexer itself is currently 187 commits behind develop — that gap should be addressed when feat/din-indexer merges to develop, not before.

@umermjd11

Copy link
Copy Markdown
Collaborator

Files changed (6) — as of 1a2a877 (PR head)

Scope note: GitHub's own diff stat against base feat/din-indexer (185 files, +20937/-1412) is inflated because this PR's head already contains PR #29's unmerged commits (confirmed: 25 commits ahead of PR #29's head, 0 behind) plus old history absorbed via the feat/p3-staking (PR #65, already merged to develop) merge commit. The table below is scoped to git diff 866521a(PR #29 head)..1a2a877(PR #72 head) --stat -- subgraph/ — the only files this PR's own 2 commits actually touch. GitHub agrees: mergeable: MERGEABLE, mergeStateStatus: CLEAN (against the stale base feat/din-indexer). Local git merge-tree of #72's head against feat/din-indexer + #29 applied first is clean — no conflicts, since #72 already contains #29 verbatim.

(Table format per PR #63's review.)

subgraph/subgraph.yaml

Field Value
Change Modified
Lines +15
Diff (what exactly is in this PR) Registers 6 new event handlers on the DinValidatorStake data source: ValidatorJailed, ValidatorReactivated, MinStakeUpdated, UnbondingPeriodUpdated, ModelStakeBoundsUpdated, MaxConcurrentRegistrationsPerStakeUnitUpdated.
Functionality — how & why How: each event:/handler: pair maps a Solidity event signature to a named AS function in staking.ts; the Graph Node indexer calls the handler whenever a matching log is emitted. Why: these six events exist on DinValidatorStake.sol (added by PR #65) but had no subgraph coverage — the event-coverage audit flagged this as a gap since the indexer can't reconstruct jail/governance state without them.
Diff vs current develop HEAD New relative to feat/din-indexer's stale base; no equivalent subgraph exists on develop yet (this whole directory is still pre-merge).
Recommended merge proposal Merged as-is — signatures verified byte-for-byte against foundry/src/DinValidatorStake.sol.
Actual merge proposal Soon
Pending proposal None
Local merge conflict No
GitHub merge conflict No

subgraph/src/staking.ts

Field Value
Change Modified
Lines +97
Diff (what exactly is in this PR) Adds handleValidatorJailed, handleValidatorReactivated, handleMinStakeUpdated, handleUnbondingPeriodUpdated, handleMaxConcurrentRegistrationsPerStakeUnitUpdated, handleModelStakeBoundsUpdated, plus a loadOrCreateStakeGovernance() helper that seeds the StakeGovernance singleton.
Functionality — how & why How: jail/reactivate handlers write jailedUntil on Validator and call syncValidatorStatus; a JailEvent audit row is also written per jail. Governance handlers all mutate one StakeGovernance("singleton") entity; ModelStakeBoundsUpdated writes a per-model ModelStakeBounds entity keyed by modelId. Why: mirrors the contract's actual state machine so queries reflect on-chain jail/governance state instead of assuming a hardcoded MIN_STAKE. Verified the singleton's seeded defaults (10 DIN, 7-day unbonding) match initialize() in the Solidity source exactly.
Diff vs current develop HEAD New file content, no conflicting equivalent on develop.
Recommended merge proposal Merged as-is — reactivate-clears-jail / no-auto-expiry semantics verified to match _syncValidatorStatus() exactly.
Actual merge proposal Soon
Pending proposal None
Local merge conflict No
GitHub merge conflict No

subgraph/src/utils.ts

Field Value
Change Modified
Lines +29/-? (net +29 per diffstat)
Diff (what exactly is in this PR) syncValidatorStatus gains a Jailed branch (checked before Exiting/Active) and now reads the active-stake floor via getMinStake() (pulled from StakeGovernance) instead of a hardcoded constant.
Functionality — how & why How: getMinStake() loads the singleton and falls back to a seeded default if ungoverned yet; the Jailed check returns early with no further status computation, same as the contract's guard. Why: without this, a jailed validator's status could be silently recomputed to Active/Exiting on the next stake-changing event — the exact bug class the event-coverage audit called out.
Diff vs current develop HEAD No equivalent on develop.
Recommended merge proposal Merged as-is.
Actual merge proposal Soon
Pending proposal None
Local merge conflict No
GitHub merge conflict No

subgraph/schema.graphql

Field Value
Change Modified
Lines +73/-?
Diff (what exactly is in this PR) Adds jailedUntil: BigInt + jailEvents: [JailEvent!]! @derivedFrom(...) to Validator; new entities JailEvent, StakeGovernance, ModelStakeBounds.
Functionality — how & why How: @derivedFrom gives Validator.jailEvents a reverse lookup with no extra storage, backed by JailEvent.validator. Why: exposes jail history and governance state to GraphQL consumers (dincli, external dashboards) without requiring separate RPC calls.
Diff vs current develop HEAD No equivalent on develop.
Recommended merge proposal Merged as-is.
Actual merge proposal Soon
Pending proposal None
Local merge conflict No
GitHub merge conflict No

subgraph/abis/DinValidatorStake.json

Field Value
Change Modified (regenerated)
Lines +1050/-380 (largely reformatted/expanded ABI JSON)
Diff (what exactly is in this PR) Full ABI regeneration from the compiled P3 contract — adds the 6 new events, 6 new errors, and 5 new functions used above.
Functionality — how & why How: used by graph codegen to generate typed AS event/contract bindings (generated/DinValidatorStake/DinValidatorStake.ts). Why: the handlers in staking.ts can't type-check or compile without the matching ABI entries; confirmed npx graph codegen succeeds cleanly with this ABI.
Diff vs current develop HEAD No equivalent on develop.
Recommended merge proposal Merged as-is — spot-checked all new event/error/function names present.
Actual merge proposal Soon
Pending proposal None
Local merge conflict No
GitHub merge conflict No

subgraph/scripts/update-subgraph-addresses.sh

Field Value
Change New
Lines +78
Diff (what exactly is in this PR) Shell script patching subgraph.yaml's placeholder contract addresses from foundry/deployments/localhost.json (falls back to the hardhat deployments path).
Functionality — how & why How: reads the deployments JSON, rewrites the address: fields in subgraph.yaml in place. Why: was review item #3 from the cross-PR discussion — removes a manual address-editing step before local graph deploy.
Diff vs current develop HEAD No equivalent on develop.
Recommended merge proposal Merged as-is — not executed end-to-end (needs a live local deploy artifact) but logic reads correctly.
Actual merge proposal Soon
Pending proposal None
Local merge conflict No
GitHub merge conflict No

Verification

npm install && npx graph codegen — clean, all data sources + templates + schema typed successfully. npx graph build fails, but the only failure is in src/registry.ts (unrelated file, not touched by this PR — inherited from PR #29, confirmed absent from this PR's own subgraph/-scoped diff). Full detail in the deep-verification comment above.

Local vs. GitHub agree: yes — GitHub's CLEAN/MERGEABLE against feat/din-indexer matches the local analysis; the only nuance GitHub's stat doesn't surface is that this PR's head already carries PR #29's commits, so #29 must land in feat/din-indexer first or its content arrives unreviewed as a side effect of merging #72.

umeradl added a commit that referenced this pull request Sep 24, 2026
…indexer events for Robbert

Three parts, three PRs into develop: Part A (#151, BL-11) future-block
dispute-subgroup seed; Part B (#152) platform-resolved treasury
forwarding through one burn/forward helper; Part C (#153) six
task-level lifecycle events, with the subgraph half landing on PR #29
after PR #72 is folded into it (Discussion #162).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants