Voting Challenges
Voting challenges require a weighted quorum threshold to be met through votes from specified voters. This enables multi-signature-like approval where multiple parties must vote to approve transfers, with each voter having a configurable weight. Votes are stored separately and can be updated.
The system requires a minimum percentage of total voter weight to vote "yes" before a transfer can be approved. Each voter has a weight, and each vote allocates a percentage (0-100%) to "yes" with the remainder going to "no".
Structure
Challenge Fields
proposalId
string
Unique identifier for tracking votes
quorumThreshold
string
Percentage (0-100) of total possible weight that must vote "yes"
voters
Voter[]
List of voters with addresses and weights
uri
string
Optional metadata URI
customData
string
Optional custom data
Vote Fields
proposalId
string
Proposal ID this vote is for
voter
string
Address of the voter casting the vote
yesWeight
string
Percentage (0-100) allocated to "yes"; remainder goes to "no"
Voting Process
Cast Vote: Voters use
MsgCastVotewithyesWeight(0-100%)Store Vote: Votes stored with key:
collectionId-approverAddress-approvalLevel-approvalId-proposalId-voterAddressUpdate Vote: Casting a new vote with same parameters overwrites the previous vote
Calculate Threshold: On transfer attempt:
Retrieve all votes for the proposal
Calculate each voter's yes contribution:
(voterWeight Γ yesWeight) / 100Sum all yes contributions
Calculate percentage:
(totalYesWeight Γ 100) / totalPossibleWeightCompare to
quorumThreshold
Weighted Voting
Each voter has a configurable weight:
Example:
Total possible weight: 350
Quorum threshold: 50% of 350 = 175 weight must vote "yes"
Partial Votes
Voters can allocate a percentage to "yes" with the remainder going to "no":
yesWeight
Yes %
No %
100
100%
0%
70
70%
30%
50
50%
50%
0
0%
100%
Threshold Calculation
Important: The threshold is calculated as a percentage of total possible weight (all voters), not just voters who have cast votes. Non-voting voters count as 0% yes.
Example:
Voter A: weight 100, votes 100% yes β contributes 100 yes weight
Voter B: weight 200, votes 50% yes β contributes 100 yes weight
Voter C: weight 50, doesn't vote β contributes 0 yes weight
Total possible weight: 350
Quorum threshold: 50%
Calculation:
Total yes weight: 100 + 100 + 0 = 200
Percentage: (200 Γ 100) / 350 = 57.14%
Result: 57.14% β₯ 50% β Challenge satisfied
Implementation Details
Vote Key Format
Votes are stored with key: collectionId-approverAddress-approvalLevel-approvalId-proposalId-voterAddress
This scopes votes to specific collection, approver, approval level, approval ID, proposal ID, and voter.
Vote Verification
When checking if a challenge is satisfied:
Retrieve all votes for voters in the challenge
For each voter:
If vote exists: calculate yes contribution
(voterWeight Γ yesWeight) / 100If no vote: contribution is 0
Sum all yes contributions
Calculate percentage:
(totalYesWeight Γ 100) / totalPossibleWeightCompare to
quorumThreshold
Type Definitions
Cast votes using MsgCastVote.
Use Cases
Multi-Signature Approval
Require unanimous approval from multiple parties:
Requires all three voters to vote 100% yes.
Weighted Governance
Different stakeholders have different voting power:
Requires 66% of total weight (1056 out of 1600) to vote yes.
Flexible Approval
Lower threshold for partial approval:
Allows approval with 30% of total weight voting yes.
Error Conditions
The system fails if:
Voter is not in the challenge's voters list
yesWeightis greater than 100Percentage of yes votes is less than the quorum threshold
proposalIddoesn't match any voting challenge in the approvalChallenge has no voters or all voters have zero weight
Security Considerations
Proposal ID Management
Changing the proposalId resets the vote tracker. Use unique proposal IDs for each challenge to prevent vote overlap. Useful for rotating challenge configurations or creating new voting periods, but ensure old votes cannot be maliciously reused.
Vote Tampering Prevention
Votes are stored on-chain and cannot be tampered with. Votes can be updated by the voter, are scoped to specific contexts (preventing cross-context reuse), and the system validates voters are in the challenge's voters list.
Abstention Handling
Non-voting voters are treated as 0% yes (100% no). Set realistic thresholds that account for expected participation. High thresholds with many voters may be difficult to meet if voters abstain.
Weight Distribution
Weight distribution affects security. If one voter has most of the weight, they can control approvals. Distribute weights appropriately to prevent single points of failure. Use equal weights for multi-signature scenarios.
Use the uri and customData fields to provide context about what voters are approving. Monitor vote tallies to understand approval status.
Last updated