feat(indexer): wire P3-staking events — ValidatorJailed/Reactivated, governable MIN_STAKE, JailEvent entity - #72
Conversation
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.
…slash history (P4-IDX2)
…ions from P4-IDX (P4-IDX3)
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>
…nd DINTaskAuditor
…gistration entities
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>
…Update, GIStateTransition entities
… source templates
… 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>
…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
|
Hi @umeradl Pls can you look into this. thanks |
Review — against
|
| 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 untilreactivate()explicitly clears it." I checked this againstdevelop's actual, currently-mergedDinValidatorStake._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: mirrorsslash()'s active-stake-then-pending-withdrawal consumption order exactly, including thependingWithdrawalzeroing edge case.- Governance singleton pattern (
StakeGovernance,ModelStakeBounds): sensible design — seedsinitialize()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/slashTreasurytracking toStakeGovernance(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) — blocksgraph build/graph deployentirely 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(§ "NoValidatorJailedevent") predates both the jailing mechanism andslashTreasury— 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.
Files changed — as of
|
| 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.
|
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 Claimed: Six new events ( Verified — all six match exactly: Claimed: Verified: the checked-in ABI contains all six new events plus the new errors ( Claimed: Verified — exact semantic match: read Claimed: Verified: Claimed: Verified: read all four handlers in Claimed: Verified: script present, reads Claimed (PR body, "also included from the parent branch"): known-limit comments on the two Correction: this file does not appear in this PR's own Verified — codegen/build: Not independently re-verified: a full green Every checkable claim in this PR's actual content (the 6 |
Files changed (6) — as of
|
| 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.
…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>
Summary
Follow-up to PR #29 (
feat/din-indexer) addressing the P3-staking gap identified in the cross-PR review (discussion #47). Branches offfeat/din-indexerand mergesfeat/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-indexerwas written before PR #65 added six new events toDinValidatorStakeand convertedMIN_STAKEfrom a Solidityconstantto a governable storage variable. The event-coverage-audit (§2.2) flagged this exact scenario: "when a jailing mechanism is added, it must emit aValidatorJailedevent with thejailedUntiltimestamp for the indexer to reconstruct status correctly."What changed
abis/DinValidatorStake.json— regenerated from the compiled P3 contracts; includes all new functions, events, and errorssubgraph.yaml— registers handlers for all six new events:ValidatorJailed,ValidatorReactivated,MinStakeUpdated,UnbondingPeriodUpdated,ModelStakeBoundsUpdated,MaxConcurrentRegistrationsPerStakeUnitUpdatedsrc/staking.ts— adds the six corresponding handler functions; introduces aStakeGovernancesingleton entity for governance-parameter writes andModelStakeBoundsentity writessrc/utils.ts—syncValidatorStatusgains aJailedbranch (jailedUntil != null→ status"Jailed"); reads the current floor fromStakeGovernanceviagetMinStake()instead of a hardcoded constant — no silent auto-return fromJailed, mirroring_syncValidatorStatus()semanticsschema.graphql— addsjailedUntilfield andjailEventsrelation toValidator; newJailEvententity; newStakeGovernancesingleton type; newModelStakeBoundstypeAlso included from the parent branch (
feat/din-indexer-65base commits):subgraph/scripts/update-subgraph-addresses.sh— patchessubgraph.yamlplaceholder addresses from adeployments.json(item Bump web3 from 7.10.0 to 7.15.0 in /dincli in the pip group across 1 directory #3 from review)first: 1000GraphQL queries indincli/cli/dindao.py(item Bump cryptography from 46.0.4 to 46.0.7 in /dincli in the pip group across 1 directory #2 from review)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.