Notes
- Writing a spec for Silo Chad
Problem
Snapshot is useful as a tool to determine:
- If an address has voted on a proposal;
- The timestamp of the start of the Voting Period; and
- The timestamp of the end of the Voting Period.
However, calculating quorum and voting power in Beanstalk governance proposals is more involved.
The Beanstalk UI currently calculates quorum and voting power purely based on the Stalk supply at the start of the Voting Period, which is incorrect.
Solution
A given Stalkholder’s voting power for a given proposal is their Stalk balance at the start of the Voting Period, minus any of their Stalk that is burned due to Withdrawals during the Voting Period.
Quorum is the sum of all Stalkholders’ voting power times some factor depending on the type of proposal (for BIPs, quorum would be the sum of all Stalkholders’ voting power * 0.5
).
Voting power and quorum should be displayed on the UI as such. The following is example pseudocode.
# Calculating quorum for a given governance proposal after the Voting Period is over
total_voting_power = 0
start_block_number = x # needs to be calculated based on timestamps in Snapshot
end_block_number = y # ditto
for stalkholder in stalkholders:
voting_power = get_stalk_balance(stalkholder, start_block_number)
stalkholder_withdrawals_in_voting_period = get_stalkholder_withdrawals_in_voting_period(
stalkholder,
start_block_number,
end_block_number)
for withdrawal in stalkholder_withdrawals_in_voting_period:
voting_power -= get_stalk_burned(withdrawal)
total_voting_power += voting_power
quorum = total_voting_power * X # where X depends on the type of proposal, i.e. X = 0.5 for BIPs
It’s important to note that in the case of BIPs/BOPs, only votes For count towards quorum. In the case of BFCPs and BSPs, votes Against count towards quorum as well.
Implementation
Snapshot only gives the timestamps of the start and end of the Voting Period, rather than the block numbers. Thus, any code used to calculate quorum from Snapshot needs to calculate the block numbers for the start and end of the Voting Period based on these timestamps .
In order to determine the block number of the start of the Voting Period, the block immediately preceding the start timestamp should be used. Similarly, in order to determine the block number of the end of the Voting Period, the block immediately preceding the end timestamp should be used.
The spec up to this point covers calculating quorum once the Voting Period is over. In order to estimate quorum during the Voting Period, regular code execution would be required either on a server somewhere or potentially in the Beanstalk subgraph. When estimating quorum during the Voting Period, code should replace end_block_number
with current_block_number
.
It is unclear how often that code should execute, and thus how often the estimated quorum on the Beanstalk UI is updated. It could potentially make sense to execute this code every 5 minutes for most of the Voting Period, and then every minute in the final 4 hours of the Voting Period.
Future Work
- Grown Stalk at the beginning of the Voting Period (if Mown during the subsequent Voting Period) should contribute to voting power and quorum.