governance - XibalbaTechSol/integrity-core GitHub Wiki
title: On-Chain Governance acronyms: [ITK] created: 2026-07-25 updated: 2026-09-15 type: concept tags: [tokenomics, layer-2] confidence: high source_files:
- contracts/src/oracle/IntegrityGovernance.sol
- contracts/test/IntegrityGovernance.t.sol
- contracts/script/Deploy.s.sol
- integrity-oracle/backend/src/chain.rs
- integrity-oracle/backend/src/handlers.rs
IntegrityGovernance (contracts/src/oracle/IntegrityGovernance.sol) is the
protocol's token-weighted, timelocked governance over on-chain parameters. It
implements the exact lifecycle the dashboard's GovernancePanel had long
documented as roadmap: propose โ vote โ queue โ execute, with voter funds
reclaimable once a proposal is terminal.
Table of contents
- Lock-to-vote (not ERC20Votes)
- Lifecycle & states
- The execute leg (the dangerous surface, constrained hard)
- Read surface (designed for the oracle)
- Genesis params & deploy status
- Deferred by design
Lock-to-vote (not ERC20Votes)
Vote weight is locked ITK, not checkpoint-counted balance. This is the correct model for this token, for two concrete reasons:
$ITK(IntegrityToken) is a plain ERC20 with noERC20Votes/getPastVotessurface โ there are no historical checkpoints to weight a vote against.- It deliberately removed fee-on-transfer, so
transferFrom(voter, contract, amount)credits exactlyamount(a documented property the Slasher and SmartBAA also depend on). Locking real ITK for the voting window is therefore both exact and flash-loan/sybil resistant: a flash-borrowed balance can't vote, because it can't stay locked across the window.
Proposing locks proposalThreshold ITK, recorded as the proposer's initial FOR
vote โ so proposing is itself flash-loan resistant and the proposer has skin in
the game. Voters reclaim locked ITK via withdraw once the proposal is terminal
(Defeated/Executed/Expired/Canceled); while Active/Succeeded/Queued
the stake stays locked.
Lifecycle & states
state(id) is derived purely from stored data + block.timestamp:
Active (voting open) โ after the window closes, Defeated (quorum unmet or
againstVotes >= forVotes) or Succeeded โ queue() sets a timelock ETA โ
Queued โ execute() after the ETA and within GRACE_PERIOD โ Executed. A
queued proposal not executed within the grace window becomes Expired (its locked
ITK reclaimable โ a stuck proposal can never permanently trap funds). cancel()
(proposer or guardian/owner, before execution) โ Canceled.
The execute leg (the dangerous surface, constrained hard)
The single highest-risk part of any governance contract is delayed execution of arbitrary calls. Here it is hand-rolled but bound tightly:
- The
(target, value, callData)action is fixed at propose time and executed verbatim โ there is no accept-actions-at-execute path, so a proposal's actions cannot be mutated between vote and execution (a classic governance bug). executeisnonReentrantand gated on both the timelock ETA and the boundedGRACE_PERIOD.- A failing action reverts the whole call (rolls back
executed), leaving the proposalQueuedand re-executable rather than consumed.
Read surface (designed for the oracle)
proposalCount() + getProposal(id) + state(id) view getters let the
oracle enumerate with a simple 1-based index
loop (ChainClient::read_proposals) โ deliberately not log-scanning. Exposed as
GET /v1/governance/proposals; the dashboard's GovernancePanel/GuardianPilot
render live proposals + FOR/AGAINST tallies from it.
Genesis params & deploy status
Wired into genesis Deploy.s.sol with testnet defaults (voting period 3 days,
timelock 2 days, proposalThreshold 1,000 ITK, quorum 10,000 ITK; guardian = the
governance protocol role). Not yet broadcast to Base Sepolia ("build now,
defer deploy") โ a gas-costing operator action. Where the singleton is absent the
oracle returns MissingSingleton (HTTP 400) and the panels stay in their honest
"Not Yet Live" state, never a live-but-empty list. deployments.local.json is also
deliberately not regenerated for it, since a fresh local deploy would remint every
address and break the seeded audit DB. See PRODUCTION_GAPS.md ยง4.
Deferred by design
The dashboard wiring is read-only: the write half (propose / castVote / queue /
execute โ all wallet-signed txs) is deliberately not in the UI yet (done via CLI/SDK),
noted inline in GovernancePanel and in PRODUCTION_GAPS.md โ an explicit deferral,
not a silent gap.
Related: contracts, integrity-oracle, Interface Contract.