On-chain implementation of the whitepaper v1.7 charity governance: token-weighted votes that direct the Charity Pool to a whitelisted charity operator. Not yet deployed.
Locked rules (v1.7)
- Votes happen at two gates only:
end_human_emission(gate 0, after season 32 closes) andend_chaos(gate 1, after season 33 closes). - Eligibility: voter must hold ≥ 1 whole $420POP.
- Token-weighted: vote weight = the voter's whole-token $420POP balance.
- Quorum: 10,000 total weighted votes.
- Duration: 99 days.
- Tie: re-vote (admin opens a new
round). - Failed quorum: funds remain in the Charity Pool.
- Operator must be a whitelisted verified charity.
Instructions
| Instruction | Who | What |
|---|---|---|
whitelist_charity(operator, name) |
admin | Adds a verified operator (["charity_op", operator] PDA). |
open_charity_vote(gate, round) |
admin | Opens a 99-day vote; requires the gate's season closed. Quorum = 10k. |
cast_charity_vote() |
any eligible holder | One token-weighted vote per wallet per proposal. |
finalize_charity_vote() |
permissionless | After close: routes Charity Pool to the winner, or marks failed-quorum / tie. |
Accounts / PDAs
CharityProposal—["proposal", gate, round]. Tracks window, quorum,total_votes, and the top-two tallies (leading_votes/second_votes) so an exact tie is detectable at finalize.OperatorTally—["tally", proposal, operator]. Accumulated weight per operator (init_if_needed).VoteReceipt—["vote", proposal, voter].init⇒ one vote per wallet per proposal.WhitelistedCharity—["charity_op", operator]. Operator + active flag + name.
Voting & finalize
cast_charity_vote reads the voter's $420POP token account (mint must equal config.mint, owner
must be the voter), computes weight = amount / 10⁹, requires weight ≥ 1, writes a VoteReceipt,
adds the weight to the operator's tally and the proposal total, and updates the top-two tracker.
finalize_charity_vote (after end_ts):
total_votes < quorum→failed_quorum = true, funds stay in the Charity Pool;leading_votes == second_votes→tie = true, admin mustopen_charity_votewith a newround;- otherwise the winner =
leading_operator(re-checked against the passed operator + whitelist) and the Charity Pool's distributable balance is transferred to the operator wallet.
Known limitations (documented, pre-audit)
- Snapshot-less weighting: weight is the current balance, so tokens moved between wallets can be re-used to vote from multiple wallets. A balance snapshot or vote-time token lock/escrow is the hardening step before mainnet.
- Quorum unit is whole-token weight (10,000), matching the token-weighted default; confirm against the whitepaper if a one-wallet-one-vote interpretation was intended instead.