Community DAOs
Quorum & Thresholds

Quorum & Thresholds

Every number that governs a community DAO proposal, in one place, with the arithmetic that converts the time periods into key-blocks.

The numbers

RuleValueCheck
Cost to open a voteExactly 555 AE, paid to the DAO, non-refundableCall.value == 555 * (10 ^ 18), else ADD_VOTE_DAO_DONATION_MISSMATCH
Who can open a voteA holder at or above the community's minimum token threshold, measured at call timeOption.default(0, token.balance(Call.caller)) >= minimum_token_threshold
Default minimum token threshold1 token (10^18), until a vote changes itSet by the factory at creation
Voting period6,720 key-blocks, about 2 weeksclose_height = Chain.block_height + (60 / 3) * 24 * 7 * 2
Approval thresholdAt least 55% of the voted stake in favour(vote_state[true] * 100) / total_vote_stake >= 55
Participation (quorum)At least 10% of total supply at execution time(total_vote_stake * 100) / token_total_supply >= 10
Execution window960 key-blocks after the close, about 2 daysvote.close_height() + state.vote_timeout >= Chain.block_height
Who can executeAny account, via DAO.apply_vote_subject(vote_seq_id)No caller check
BallotBinary: in favour or againstvote_option = bool
Voting powerLinear in tokens staked; tokens are locked while the vote standsvote_state[option] + amount
Description lengthAt most 300 charactersString.length(metadata.description) =< 300
One vote per addressA second vote is rejected, not mergedVOTER_ALREADY_VOTED

The vote contract only tallies. Both the approval and participation checks are made by apply_vote_subject at execution time, so a vote can show a passing tally and still abort when applied.

The two periods, in key-blocks

æternity separates leader election from transaction production. Key-blocks are the proof-of-work blocks, targeted at one every three minutes; micro-blocks carry the transactions and appear about every three seconds between them. Contract heights, including DAOVote.close_height and DAO.vote_timeout, are key-block heights, so compute with the three-minute figure.

key-blocks per hour  = 60 / 3        =     20

DAOVote.close_height = create_height + (60 / 3) * 24 * 7 * 2   =  6,720 key-blocks
DAO.vote_timeout     =                (60 / 3) * 24 * 2        =    960 key-blocks

A proposal opened at key-block height H closes at roughly H + 6720, and must be applied before roughly H + 7680.

These are targets, not guarantees: proof-of-work block times vary, so the wall-clock length of a two-week vote drifts by hours in either direction. The app converts the remaining block count at exactly three minutes per block, so every date it shows is an estimate.

Fixed or per-community?

The voting period, execution window, 555 AE cost, 55% approval and 10% quorum are literals in the contracts. Every community deployed by the same factory gets the same constants. No entrypoint writes them and none of the seven vote subjects touches them, so a community cannot vote itself a shorter voting period or a cheaper proposal fee.

Two qualifications:

  • vote_timeout is readable per-DAO at runtime with DAO.vote_timeout(). Read it rather than assuming, especially on a DAO you did not deploy.
  • A ChangeDAO migration to a different DAO implementation replaces the code that holds these constants. A replacement DAO may use different numbers for votes opened after the migration. See Replaceable DAOs.

The one number that is per-community is the minimum token threshold. It lives in CommunityManagement.minimum_token_threshold, starts at 10^18 (one whole token) for every community the factory creates, and is changed by a ChangeMinimumTokenThreshold vote. A vote can set it to any value, including 0, which lets anyone with 555 AE open a proposal. See Moderators and Write Thresholds.

How the two thresholds interact

They test different denominators, and both must pass.

approval      = stake_in_favour / (stake_in_favour + stake_against)   >= 0.55
participation = (stake_in_favour + stake_against) / total_supply      >= 0.10

Both are integer comparisons ((x * 100) / y >= 55 and (x * 100) / y >= 10), so the percentages are floored before comparison. Exactly 55.0% and exactly 10.0% both pass; anything a fraction below either bar fails. Multiply before you divide if you check the outcome yourself.

The denominators are read at different times. total_vote_stake is fixed at the closing height; token_total_supply is read from the AEX-9 contract when apply_vote_subject runs, so buys between the close and the execution dilute participation and sells concentrate it. The short execution window limits that drift.

A worked case, for a token with 1,000,000 tokens in supply:

OutcomeIn favourAgainstApprovalParticipationResult
Passes80,00040,00066.7%12.0%Both cleared
Fails on approval60,00060,00050.0%12.0%Below 55%
Fails on quorum40,0000100%4.0%Below 10%
Fails on both20,00020,00050.0%4.0%Below both

Unanimous support from a small turnout is still a failed proposal, and the 555 AE is still spent.

Revoking a vote reduces both numerator and denominator. A proposal that is comfortably passing can drop below the participation quorum if enough voters on either side revoke before the closing height.

Why each number is what it is

NumberPurpose
555 AE to openSpam resistance. Proposals cost real money, so the queue cannot be flooded and every proposal carries economic commitment.
Two-week periodEnough time for a globally distributed holder base to notice a proposal and act on it.
55% approvalA supermajority rather than a bare majority, so a proposal that barely splits the community does not move the treasury.
10% participationPrevents low-turnout capture: a handful of tokens cannot decide a payout because nobody else was watching.
Two-day execution windowLimits how long a passed but unapplied proposal stays live, so a stale decision cannot be applied months later.
Token lockingPrevents the same balance being moved between addresses and voted more than once on the same proposal.

Related