DAO Voting

On-chain governance with token-weighted proposals and vote delegation

Pending Anchor 0.32
Program ID 6wGk7DpNBYDgwW4JZoRjdLB6iNni2AzhyuhiFsgES9ax
Binary Size 318K
Cluster Devnet

Instructions

IX create_dao

Initializes a new DAO with a governance token, quorum threshold, and voting period.

ParameterTypeDescription
nameStringName of the DAO (max 32 characters)
quorumu64Minimum total votes required for a proposal to pass
voting_periodi64Duration of voting in seconds
IX create_proposal

Creates a new governance proposal for the DAO members to vote on.

ParameterTypeDescription
titleStringTitle of the proposal (max 64 characters)
description_hash[u8; 32]SHA-256 hash of the full proposal description (stored off-chain)
IX cast_vote

Casts a token-weighted vote on an active proposal.

ParameterTypeDescription
voteboolVote direction: true for yes, false for no
amountu64Number of governance tokens to vote with
IX execute_proposal

Executes a proposal that has passed quorum after the voting period ends.

ParameterTypeDescription
No parameters
IX withdraw_vote

Withdraws locked governance tokens after the voting period has ended.

ParameterTypeDescription
No parameters

Accounts

Dao

FieldTypeDescription
authorityPubkeyDAO creator and admin
mintPubkeyGovernance token mint
nameStringName of the DAO
quorumu64Minimum votes for proposal passage
voting_periodi64Duration of each voting window in seconds
proposal_countu64Total proposals created
bumpu8PDA bump seed

Proposal

FieldTypeDescription
daoPubkeyThe DAO this proposal belongs to
proposerPubkeyWallet that submitted the proposal
idu64Sequential proposal ID
titleStringProposal title
description_hash[u8; 32]Hash of the off-chain description
yes_votesu64Total tokens voted yes
no_votesu64Total tokens voted no
created_ati64Unix timestamp when the proposal was created
executedboolWhether the proposal has been executed
bumpu8PDA bump seed

VoteRecord

FieldTypeDescription
proposalPubkeyThe proposal this vote is for
voterPubkeyWallet that cast the vote
amountu64Number of tokens committed
voteboolVote direction (true = yes)
bumpu8PDA bump seed

PDA Derivation

dao
seeds = [b"dao", authority, mint]
proposal
seeds = [b"proposal", dao, proposal_id.to_le_bytes()]
vote
seeds = [b"vote", proposal, voter]

Error Codes

NameTooLong DAO name exceeds the maximum 32 character limit
TitleTooLong Proposal title exceeds the maximum 64 character limit
VotingEnded The voting period for this proposal has already ended
VotingNotEnded Cannot execute or withdraw before the voting period ends
QuorumNotReached The proposal did not receive enough votes to reach quorum
AlreadyExecuted This proposal has already been executed
Overflow Arithmetic overflow in vote tallying

Usage Example

import { Program, BN } from "@coral-xyz/anchor";
import { PublicKey } from "@solana/web3.js";

// Derive the DAO PDA
const [daoPda] = PublicKey.findProgramAddressSync(
  [Buffer.from("dao"), authority.publicKey.toBuffer(), mint.toBuffer()],
  program.programId
);

// Create a DAO with 1M token quorum and 3-day voting
await program.methods
  .createDao(
    "My Protocol DAO",
    new BN(1_000_000),      // quorum
    new BN(3 * 86400)       // voting_period (3 days)
  )
  .accounts({
    authority: authority.publicKey,
    mint,
    dao: daoPda,
  })
  .signers([authority])
  .rpc();

// Cast a vote on proposal #0
const proposalId = new BN(0);
const [proposalPda] = PublicKey.findProgramAddressSync(
  [Buffer.from("proposal"), daoPda.toBuffer(), proposalId.toArrayLike(Buffer, "le", 8)],
  program.programId
);

await program.methods
  .castVote(true, new BN(500_000))
  .accounts({
    proposal: proposalPda,
    voter: voter.publicKey,
  })
  .signers([voter])
  .rpc();