Skip to content

Token Voting Plugin

The Token Voting Plugin is the "one token, one vote" governance plugin, the most common way an OSx DAO governs itself. Members' influence is proportional to the governance tokens they hold (or that others delegate to them), and a proposal passes when it meets a configurable majority-voting rule. It also puts the protocol's shared building blocks to work: it reuses the proposal, membership, and ratio primitives, adds token-based voting power, and is installed through the standard framework.

This folder covers it in four pages:

  • This page — what it is, the proposal lifecycle, and the permissions it sets up.
  • Voting power — where power comes from: the token, the snapshot, delegation, and who may propose.
  • Governance tokens — mint a new token, reuse an IVotes token, or wrap an existing ERC-20.
  • The shared voting model: majority voting (the thresholds) and voting modes (Standard / Early Execution / Vote Replacement).

Why it needs a special token

The problem any token vote must solve is double voting: hold tokens, vote, transfer them to a fresh address, vote again, the same tokens counted twice. The plugin sidesteps this by only accepting tokens that support historical, per-account snapshots (IVotes / ERC20Votes). Every proposal fixes a snapshot block at creation and weighs each vote by the holder's balance at that block, so moving tokens after a proposal opens changes nothing. This one requirement, and everything that follows from it (delegation, snapshots, wrapping a plain ERC-20), is the subject of Voting power.

The proposal lifecycle

Create. A proposal records its snapshot block, freezes the voting settings and its execution target (where its approved actions are sent, normally the DAO), stores the actions to run if it passes, and its start and end dates (the end must be at least minDuration after the start). The creator may cast their vote in the same transaction ("propose and vote yes"). Who may create is gated, see gating proposal creation.

Vote. Eligible holders call vote with Yes, No, or Abstain, weighted by their snapshot power. Whether a voter can later change their vote depends on the voting mode. A voter may also ask to execute in the same call (tryEarlyExecution) if the mode and thresholds allow and they hold execute permission.

Execute. Once the proposal has passed (all thresholds met, and the timing allowed by the mode), anyone with EXECUTE_PROPOSAL_PERMISSION_ID calls execute. The plugin hands the approved actions to the DAO (via execute, which is why it holds EXECUTE_PERMISSION_ID on the DAO) and marks the proposal executed. A passed proposal stays executable until someone runs it, there's no expiry.

Voting settings (supportThreshold, minParticipation, minDuration, minProposerVotingPower, the voting mode, and minApproval) are changed through updateVotingSettings / updateMinApprovals, gated by UPDATE_VOTING_SETTINGS_PERMISSION_ID (held by the DAO, so tuning governance is itself a governance decision). Changes only affect proposals created after them; each proposal keeps the settings frozen at its creation.

Permissions it sets up

TokenVotingSetup wires these on install (verified against the plugin's own docs):

PermissionOn (where)Granted to (who)ConditionGates
EXECUTE_PERMISSION_IDDAOpluginnonethe plugin calling dao.execute
CREATE_PROPOSAL_PERMISSION_IDpluginany addressVotingPowerConditioncreateProposal
EXECUTE_PROPOSAL_PERMISSION_IDpluginany addressnoneexecute
UPDATE_VOTING_SETTINGS_PERMISSION_IDpluginDAOnoneupdateVotingSettings, updateMinApprovals
SET_TARGET_CONFIG_PERMISSION_IDpluginDAOnonesetTargetConfig
SET_METADATA_PERMISSION_IDpluginDAOnonesetMetadata
MINT_PERMISSION_IDgovernance tokenDAOnonemint (only when a new token is minted)

The two any address grants are intentional: proposal creation is opened to everyone but narrowed by the VotingPowerCondition to holders above a minimum, and execution is opened to everyone because the threshold math already decides whether a proposal may execute, letting anyone trigger it just stops a passed proposal getting stuck.

Installing it

You never wire this by hand. TokenVotingSetup (a plugin setup) deploys the plugin proxy, arranges the governance token, deploys the VotingPowerCondition, and returns the permission set above for the PluginSetupProcessor to apply. Its helpers are the condition and the token, so an update or uninstall can find them again. The token decision is the substance of that step, see Governance tokens.

Keep in mind

  • Delegate, or you have no power. Holding the token isn't enough; voting power is zero until delegated. The most common "why can't I vote?" is an undelegated balance. See voting power.
  • Power is fixed at the snapshot. Acquiring or delegating more tokens after a proposal opens does nothing for that proposal.
  • Identical proposals collide. The proposal id hashes the actions and metadata, so a byte-identical resubmission reverts; vary the metadata to resubmit.

See also