Voting
How a proposal is voted and resolved on the two OhShii governance families:
- ONS (OhShii Network System) —
ohshii_governance, the single OhShii ecosystem DAO. It governs the entire OhShii ecosystem — the launcher, the locker, and the OHSHII token itself (ledger and index) — plus any external dapp that adds it as a controller, which it can then upgrade (backend code and frontend assets) by proposal. - SONS —
sons_governance, one DAO per LGE campaign. It governs that campaign’s treasury, token ledger suite, asset canister, and pool — and, like ONS, any external dapp added as one of its controllers (same code + asset upgrade powers).
ONS does not govern SONS. While an LGE is in progress the launcher backend and ONS are temporary controllers of the new campaign’s canisters (so OhShii can monitor and finalize it). At completion (finalization) those controllers are removed and the campaign DAO becomes fully autonomous — from then on only its own SONS DAO can act on it; ONS has no power over a completed campaign. See Creating a Liquidity Generation Event for the controller lifecycle.
This page is the voting mechanics reference. For the full proposal catalog (every category and allowlisted method) see Governance: ONS vs SONS; for vote delegation see Liquid Democracy; for the identity layer see Google Verification, Telegram Verification, World ID Verification and DecideID Verification; for how these mechanics add up to capture resistance (threat model, honest limits, and the SNS comparison) see Governance & Capture Resistance.
ONS and SONS share the same two-axis voting engine and (by default) the same threshold constants; they differ mainly in where Voting Power comes from and how identity verification is gated. Those differences are summarised at the end.
The vote
Section titled “The vote”- A vote is a single boolean:
decision = true→ Adopt (yes),false→ Reject (no). There is no Abstain — abstaining means not voting, which counts against quorum. - Voting is free. It costs no tokens; you only need eligible lock-based Voting Power. (Only creating a proposal costs a fee — see Proposing.)
- The anonymous principal is always rejected (
guard = "reject_anonymous"), and each call passes through the OhShii Shield (PoW / rate-limit / Defcon) with the PoW solution as the trailing optional argument. - Rate limit: at most 3 vote attempts per hour per (caller, proposal). The veto-override round uses a separate counter, so spending your round-1 attempts never locks you out of an override vote.
- One recorded vote per principal per round; a second attempt is rejected (
Already voted on this proposal).
Wire signatures:
ONS : vote(proposal_id: nat64, decision: bool, voting_token: principal, pow_solution: opt blob) -> (variant { Ok; Err: text })SONS : vote(proposal_id: nat64, approve: bool, pow_solution: opt blob) -> (variant { Ok; Err: GovernanceError })ONS takes a voting_token (which token’s locks supply your VP — OHSHII for ecosystem proposals, or a completed campaign’s token). SONS always uses its own campaign token.
Voting Power
Section titled “Voting Power”Voting Power is quadratic and time-weighted:
weight(lock) = token_amount × lock_months²VP = min( sqrt( Σ weight(lock) ) , 36,000 )- Weights are summed first; the square root is applied once, to the principal. For a single lock this reduces to
sqrt(token_amount) × lock_months, the familiar form — which is why one lock’s number is unchanged by the aggregation. - Splitting a stake across several locks gains nothing, at any level.
klocks ofA/ktokens for the same duration produce exactly the same VP as one lock ofA. The cap (max_voting_power_per_user, default 36,000) then applies to that single aggregate number. - Where an interface shows a per-lock figure, it is a share of the aggregate, not a standalone amount: the shares sum to the total and cannot be added to anything else.
- A lock is eligible only if its duration ≥
min_lock_duration_days(default 45 days = 1.5 months) and its status is Active. A freshly-created Inactive vesting lock grants zero VP until the beneficiary activates it. - VP is read live at vote time (recomputed from your current locks on every vote). What is snapshotted at proposal creation is the set of decision thresholds (
ProposalVotingSnapshot), so a proposal is judged by the rules in force when it was created (grandfathering) — not your VP balance.
| ONS | SONS | |
|---|---|---|
| VP token | OHSHII | the campaign’s own token |
| How VP is read | inter-canister call to lock_storage (15s bounded wait; never silently defaults to 0 on failure) | computed canister-locally from the DAO’s own locks (get_locks_by_creator, zero ICC) |
| Quadratic detail | float sqrt over the summed weight | the same float sqrt over the summed weight — ONS and SONS produce identical numbers for the same locks |
A short duration grace (ten minutes) exists so that a lock created a few seconds under a round duration still counts as meeting the minimum. It affects eligibility only; it does not add to the month count, so a lock earns weight for exactly the time it commits.
The quadratic formula is hardcoded (changes only by a canister upgrade); the cap value, the 45-day minimum, and days_in_month are governance-votable.
The two-axis model: Normal vs Critical
Section titled “The two-axis model: Normal vs Critical”Every proposal is either Normal (standard) or Critical, which sets its voting window, quorum, and approval rule.
A proposal is Critical when its category is one of: UpgradeCanister, UpgradeGovernanceCanister, UpgradeAssetCanister, CriticalGovernanceOperation, UpgradeCanisterBatch, UpgradeDappBatch. Adding/replacing a guardian also clears Critical thresholds. In addition, a subset of ExecuteAdminMethod proposals run the Critical tier even though the category is Normal — the high-blast-radius AdminMethod calls: on ONS (admin_method_call_is_critical) treasury / balance withdrawals, liquidity removal, ICPSwap position transfers, the treasury-funded liquidity operations (create / add / retry / remove-to-treasury / forward-retry), OhShii Locker lock mutations (update-status / delete / transfer-recipient) and campaign deletion, plus token-metadata edits of the OHSHII ledger and LGE-info edits of the root campaign dao-0000000001; on SONS (is_critical_admin_method) the equivalent AdminMethods — TreasuryWithdraw, RemoveLiquidity, TransferLiquidityPosition, CreatePoolAndAddLiquidity, AddLiquidityToPool, ModifyLock, DeleteLock, TransferLockBeneficiary, TransferLockCreator, BatchSetFollow, UpgradeIndexCanister. Everything else (Motion, config/fee changes, most AdminMethods) is Normal. Only Critical proposals can be guardian-vetoed and can close early.
| Parameter | Default | Floor / bound | Votable? |
|---|---|---|---|
| Normal voting window | 3 days | guardian_min ≤ normal ≤ critical | yes |
| Critical voting window | 7 days | > 0 | yes |
| Guardian-created Normal min window | 1 day | > 0 | yes |
| Guardian-removal window | ≥ 7 days | hardcoded floor (never early-close; vetoable-but-overridable) | no |
| Standard quorum (VP) | 250,000 | ≠ 0 | yes |
| Standard min voters | 15 | ≠ 0 | yes |
| Standard approval | simple VP majority — adopt VP > reject VP (a tie rejects) | hardcoded rule | — |
| Critical quorum (VP) | 350,000 | ≠ 0 | yes |
| Critical min voters | 20 | ≠ 0 | yes |
| Critical approval | ≥ 65% | 1–99 | yes |
| Critical immediate-close VP | 450,000 | > 0 | yes |
| Critical immediate-close voters | 30 | ≠ 0 | yes |
| Critical immediate-close approval | ≥ 75% | 1–99 | yes |
| Veto-override approval | ≥ 80% | 1–99 | yes |
| Veto-override quorum (VP) | 700,000 | ≠ 0 | yes |
| Veto-override min voters | 50 | ≠ 0 | yes |
| Veto-override window | 24 h | ≥ 1 day hard floor | yes |
| VP cap per user | 36,000 | > 0 | yes |
| Min lock duration | 45 days | — | yes |
| Min VP to propose | 10,000 | ≥ 1 | yes |
| Proposal creation fee | 30,000 tokens | ±50% per change; ≥ rejection_cost + ~3× ledger_fee | yes |
| Rejection cost | 25,000 tokens | ±50% per change; ≤ proposal fee | yes |
| Vote rate limit | 3 / hour / proposal | hardcoded | — |
The “normal immediate-approval” constants (90% / 20 voters / 500,000 VP) are vestigial — early close is disabled for Normal proposals in the two-axis model. They are retained only for stable-storage / snapshot compatibility.
Tally rules
Section titled “Tally rules”- Normal, at the deadline: quorum met iff
voters ≥ min_quorum_votes (15)andtotal_VP ≥ standard_quorum_vp (250,000). If met → Adopt iffadopt_VP > reject_VP(strict; tie → Rejected). If quorum not met → Expired. Normal proposals never close early. - Critical, at the deadline: quorum met iff
total_VP ≥ critical_quorum_vp (350,000)andvoters ≥ critical_min_quorum_votes (20). If met and any votes cast → Adopt iffadopt% ≥ critical_approval_pct (65%), else Rejected. Quorum met but zero votes, or quorum not met → Expired. - Critical early close (inside
vote(), before the deadline):voters ≥ 30andtotal_VP ≥ 450,000andadopt% ≥ 75%→ Approved immediately. The symmetric early reject fires atadopt% ≤ 25%. Guardian gate: if the proposal is vetoable and a guardian is set, an early approval additionally requires the guardian to have voted yes (this preserves a real veto window; the early-reject side has no such gate). A guardian-removal proposal can never close early.
Proposal lifecycle
Section titled “Proposal lifecycle”The stored status enum is PendingUpload, Open, Approved, Executing, Executed, Rejected, Expired, ExecutionFailed, Vetoed, VetoOverrideExpired. Vetoed is non-terminal (the override round is open); VetoOverrideExpired is a display-only status — once an override window has lapsed the UI shows it, but the stored status stays Vetoed until the timer finalises it to Approved/Rejected. Resolution runs on a periodic timer (ONS ≈ every 5 minutes): expire/close → execute approved → process refunds.
Guardian veto and the override round
Section titled “Guardian veto and the override round”The guardian is a single trusted principal (set via SetGuardian) who can cast a blocking but overridable veto on any Critical/vetoable Open proposal. guardian_veto is deliberately the least-gated update — it is gated by the guardian check alone, so an emergency veto cannot be held back by rate limits or the Shield. It moves Open → Vetoed and opens a separate override round with its own tally and its own vote map (a round-1 voter may vote again; the override round is direct-only — no delegation cascade — and has no early close).
At the override deadline the timer finalises: the override succeeds (Vetoed → Approved) iff override_voters ≥ 50 and override_VP ≥ 700,000 and adopt% ≥ 80%; otherwise the veto is upheld (Vetoed → Rejected). A guardian-removal proposal is itself vetoable-but-overridable: the guardian may veto its own removal, but the community can still remove it by clearing that override supermajority (with a fresh personhood re-attestation per voter) — so removing a guardian that fights its removal takes the 80% / 700,000 VP / 50-voter override, not a bare majority. The guardian can never vote on its own removal in either round. (The 700,000 VP override quorum is intentionally kept reachable — an unreachable bar would turn every veto into a permanent kill.)
An upheld veto blocks the proposer for 30 days. When the override round closes against the proposer (Vetoed → Rejected), that principal cannot create another proposal on that DAO for 30 days; the refusal names the unban date, and the block is checked before the creation rate limit so a blocked proposer never spends their window — nor, on a SONS, their fee approval. An overridden veto (Vetoed → Approved) carries no block, and neither does an ordinary rejection: the penalty is attached to the veto being upheld, not to the proposal failing. Each DAO keeps its own register, so a block on OHSHII governance does not reach any campaign DAO and a block on one campaign does not reach another. It can be lifted early — on OHSHII governance by the guardian, on a campaign DAO by a passed proposal.
Proposing a proposal
Section titled “Proposing a proposal”Creating a proposal (unlike voting) costs tokens and needs stake:
- No block from an upheld veto: a proposer whose veto was upheld in the last 30 days is refused up front, before the VP check and before any fee moves (see above). Guardians are exempt.
- Min VP to propose: live VP ≥
min_vp_to_propose(default 10,000), checked before the fee is charged. SONS additionally requires a raw token balance ≥ 100 tokens (hardcoded floor). Guardians are exempt from the VP/fee checks at proposal creation (and, on SONS, from the 100-token balance floor). ONS proposal creation is currently paused for the transition phase. A fee a guardian has already paid to stage an upload (prepare_wasm_upload/prepare_asset_upload) is attached to its proposal and settled by outcome exactly as for any other proposer. - Creation fee: default 30,000 tokens (OHSHII for ONS, the campaign token for SONS), collected via ICRC-2 and frozen on the proposal. The deposit is held by the governance canister itself.
- Refund (single source of truth
refund_for(status)):
| Outcome | Refund |
|---|---|
| Approved / Executed / ExecutionFailed | Full (fee − ledger fee) |
| Rejected / Expired (no quorum) | Partial (fee − rejection_cost − ledger fee); the withheld rejection_cost (default 25,000) goes to the platform treasury (ONS) / stays on-canister (SONS) |
| Vetoed / still Open / Executing | None yet |
Abandoned paid PendingUpload | Forfeited |
Identity verification gate
Section titled “Identity verification gate”OhShii supports four independent verification methods on two strength levels; a principal is verified if any of them has verified them, and one verification works on every OhShii DAO (verification state lives on ohshii_governance).
- World ID — Strong, and legacy (closed to new proofs since 2026-09-05; existing verifications keep counting). Scan a World ID document (
@worldcoin/idkit); the canister signs the Relying-Party request with IC threshold ECDSA (no HTTPS outcall; the key never materializes). Anti-replay via spent nullifier. - DecideID — Strong, and legacy (closed to new proofs since 2026-09-05; existing verifications keep counting). An Internet-Identity-issued JWT Verifiable Presentation validated by pure on-canister crypto (no inter-canister calls, no HTTPS outcalls). Anti-replay via a presentation digest.
- Google — Standard, live. An attribute bundle signed by Internet Identity asserting a verified Google address; the canister never contacts Google. One Google account per wallet, anti-replay via a salted address digest. Available to Internet Identity sessions only.
- Telegram — Strong. Control of a phone-verified Telegram account, proved by the signed launch data of a Telegram Mini App session and checked as a signature against Telegram’s published key; the canister makes no outbound call. Anti-replay via a salted per-account fingerprint. Like every provider it ships closed and is opened by an ONS proposal — and, during the transition phase, also by the deploying principals; opened on mainnet on 2026-09-05.
What strength changes. Any method opens standard proposals, delegation, hotkeys, the creation flows and sponsor attribution. A Strong method is additionally required for critical proposals (voting and creating), for a delegated ballot that lands on one, for the LGE purchase-tier ladder, and for the veto-override attestation. Strong is a superset of Standard, so holding one Strong method satisfies everything.
Each provider carries two independent flags: enabled (does it make the gate mandatory?) and accepts_new_proofs (will it still register a new proof?). Closing a provider to new proofs retires it without revoking anyone.
A verification, once granted, persists even if the DAO later disables that method or closes it to new proofs (the check reads the verified-user sets, not the flags). There is no “set verified” backdoor — only the real proof flow adds; the verification state can only be cleared (never forged) by the authorized caller, ohshii_governance executing an approved proposal (and, during the transition phase, also by the deploying principals).
Is verification required to vote? It depends on the DAO family:
| Governance action | ONS (ecosystem) | SONS (per-campaign) |
|---|---|---|
| Cast a vote | Conditional — required only if at least one provider is enabled on ONS. All default OFF, so by default no verification is required. On a critical proposal the requirement rises to a Strong method whenever any Strong provider is enabled. | Conditional on requires_verification, which DEFAULTS TO TRUE. An LGE campaign DAO is always created with it ON; an imported DAO may be created with it OFF by the importer (then participation is gated by holding vesting-locked tokens instead). Once created, only a Critical vote can flip it. The Strong requirement on critical proposals applies here too. |
| Create a proposal | Same conditional gate (guardian exempt) | Same gate (guardian exempt; plus an emergency exemption — see below) |
| Delegate / follow | Same conditional gate (caller + delegate) | follow primitives carry the same gate; vote delegation is an ONS feature (see Liquid Democracy) |
| Guardian veto | Never gated | Never gated |
SONS holds no verification store of its own — it calls ohshii_governance.is_verified (10s bounded wait, behind a circuit breaker), then caches a success in a local “Forever Verified” set so the DAO keeps working even during an ONS outage (eviction is restricted to the authorized caller). To prevent a DAO soft-bricking itself (no verified holder left to flip the gate off), an emergency exemption lets any staked holder submit the one narrow rescue proposal — a CriticalGovernanceOperation whose only effect is turning requires_verification off — without being verified.
When the gate is off — either method disabled on ONS, or requires_verification = false on a SONS (e.g. an imported DAO created verification-free) — the system is not ungated:
- Direct voting / proposing still require VP > 0 (and, on SONS, stake ≥
min_vp_to_proposeplus the proposal fee). - Delegation substitutes an active-lock anti-Sybil check:
followrequires the followee to own at least one Active lock, andset_accepts_followers(true)requires the caller to own at least one Active lock. Because Voting Power derives only from Active, creator-owned locks, participation costs real locked tokens whether or not identity verification is on. - Cycle-drain / grinding-DoS defense is independent of the identity gate.
vote,create_proposal,follow, andset_accepts_followersare each wrapped by the OhShii Shield (layered rate limits + Argon2id proof-of-work under Defcon + a cycle-reserve floor) at verification level None — the Shield’s cost-of-attack defenses run identically whetherrequires_verificationistrueorfalse. Turning identity verification off does not weaken the canister’s protection against cycle-drain attacks; it only swaps the personhood check for the locked-token check above.
Separate, do not conflate: verification also gates LGE participation economics (purchase tier above Guest, the OHSHII guest fee — both of which need a Strong method, not merely any verification), and sponsor rewards require active-voter status — but those are LGE/economic gates, not governance-voting gates. “Active voter” (recent participation) is a different concept from “verified”, which is itself different from “strongly verified”. See Participating in an LGE.
ONS vs SONS — summary of differences
Section titled “ONS vs SONS — summary of differences”| Aspect | ONS (ohshii_governance) | SONS (sons_governance) |
|---|---|---|
| Instances | one (ecosystem) | one per LGE campaign |
| Scope / can control | launcher, locker, OHSHII ecosystem + any dapp that adds ONS as a controller | its campaign’s canisters + any dapp that adds that SONS as a controller; ONS can act on the campaign only before completion, autonomous after |
| VP token | OHSHII | the campaign token |
| VP source | ICC to lock_storage | canister-local |
| Verification gate | conditional on a method being enabled (default off) | per-DAO requires_verification (default on) |
| Verification store | source of truth | calls ONS + “Forever Verified” cache |
| Vote delegation | yes (Liquid Democracy) | follow primitives exist; delegation product is ONS |
| Param routing | all voting params via one CriticalGovernanceOperation (set_voting_parameters) | split: fees via ConfigChange (Normal); all thresholds/durations/VP-cap/min-lock/requires_verification via CriticalGovernanceOperation |
| Threshold constants | — | identical defaults to ONS |
Both families snapshot per-proposal thresholds at creation (grandfathering); both reject zero quorum; both forbid changing the formula/critical-category classification without a canister upgrade.
See also
Section titled “See also”- Governance: ONS vs SONS — the full proposal/method catalog and the votable-vs-hardcoded parameter reference.
- Liquid Democracy — ONS vote delegation (follow/unfollow, cascade, rate limits).
- Google Verification (Standard, live) and Telegram Verification (Strong).
- World ID Verification and DecideID Verification — both Strong and both legacy.
- Core Workflows — proposal creation, execution, and finalization flows end to end.