Governance
Liqua is governed at near-unanimity. Two powers — reverting the chain (rollback) and updating a parameter (change) — each require 98% agreement. To keep that from freezing the chain, the 98% is measured against attesting ve-weight in a rolling window, not all-time supply. This page explains the rule and how it runs.
The rule
A proposal passes only if, over a continuous trailing window of recent blocks:
approvingWeight / attestingWeight(window) ≥ 0.98
// in Governor98.sol, exactly:
forWeight * BPS >= QUORUM_BPS * attestingWeight // QUORUM_BPS = 9800, BPS = 10000
Two design choices make this work in practice:
- The denominator is attesting weight, not all supply. If 98% were measured against every token ever minted, any large dormant holder would permanently block changes. Instead the chain sums only the ve-weight that's online and attesting in the window — dead/idle stake is excluded from the denominator.
- Weight is ve-weight (§2), which decays with remaining lock. Your say is proportional to how much you've locked and for how long — and it melts as your lock approaches expiry. Conviction, not just balance.
Summing the online set on-chain every block would be unbounded gas, so the consensus layer
publishes the rolling-window attesting total to the contract each block via
setAttestingWeight() (onlyChain). Validators who co-sign the
head are what populate that window — co-signing is how your stake earns a governance voice.
Two powers
| Power | Kind | What it does · how it's enacted |
|---|---|---|
| Change | CHANGE | updates a parameter. On execute, the contract does target.call(data) — e.g. calling VeLock.setBoostMaxBps(). Enacted entirely on-chain. |
| Rollback | ROLLBACK | reverts the chain to a prior height (R9). On execute it emits Executed(ROLLBACK); the consensus layer watches for that and performs the revert. |
Proposal lifecycle
Four steps, all in Governor98.sol:
Propose
propose(kind, payload)—payloadis abi-encoded: a target height for ROLLBACK, or(target, calldata)for CHANGE. Returns the proposalidand emitsProposed.Vote
castVote(id)addsve.veWeight(you)to the proposal'sforWeight, once per address. Reverts if you have no weight or have already voted. EmitsVoted.Check quorum
quorumMet(id)is true onceforWeightreaches 98% of the currentattestingWeight.Execute
execute(id)revertsBELOW_98unless quorum is met; otherwise it performs the CHANGE call (or emits for a ROLLBACK) and marks the proposal executed. EmitsExecuted.
Worked example · retuning a parameter
The verified demo evm/gov-escrow-demo.mjs runs the whole path end to end: a CHANGE
proposal raises VeLock.boostMaxBps from 50% → 80%, reaching 98% of attesting ve-weight,
and executes the on-chain retune — then the now-higher boost is reflected in subsequent ve-weight reads. The same
demo shows a RewardEscrow claim reverting before its confirmation gate and
minting after.
node evm/gov-escrow-demo.mjs # 98% CHANGE retunes VeLock.boostMaxBps 50%→80% on-chain
Governance & genesis
The parameters a proposal can change are exactly the ones committed at genesis — ve-lock bounds, emission shape, the confirmation gate, even the quorum window. Changing any committed param is, in effect, moving to a new genesis, which is precisely why it takes 98%: the chain should be very hard to re-constitute.
- Conservative by design. Near-unanimity means a malicious change needs almost everyone — which essentially never happens by accident or attack. The flip side: a genuine holdout of just 2.1% of attesting weight can block a change. Excluding idle stake from the denominator softens this, but it's a real tradeoff the spec flags.
- No proposal UI yet.
Governor98runs and is verified on-chain, but there is no interactive surface to create a proposal and cast votes — today it's exercised via the demo and direct contract calls. A governance page (propose · vote · track quorum) is on the roadmap.