๐Ÿ–ฅ๏ธVoting Power

Calculating voting weight and voting power

The stake weighting function is based on a quadratic formula, using the amount and duration of FISH tokens staked.

Let mm be the maximum staking period (1092 days) , xx be the number of days passed since the beginning of the period, and VVbe the maximum voting weight (currently 9). The voting weight at a given time xx can be described as:

f(x)=Vโˆ—(m2โˆ’x2)/m2+1f(x)=Vโˆ—(m^2โˆ’x^2)/m^2+1

+1+1 is added in the end to shift the weights to lie in [1,V+1][1,V+1]instead of [0,V][0,V].

Users will usually not stake the maximum duration, so xx has to be computed based on the remaining days until unstaking:

x=mโˆ’RemainingDaysx=mโˆ’RemainingDays

The userโ€™s voting power VPVP at a given time xx is the product of their stake xx and their voting weight:

VP(x)=f(x)โˆ—sVP(x)=f(x)โˆ—s

The total voting power equals the sum of the voting power of all users. However, since we canโ€™t iterate over an array with unlimited size, we need to compute it differently. Instead of summing up the user voting powers, we introduce a mapping, which stores the total amount of FISH to be unstaked on a given day, and call it stakedUntil.

Whenever a user stakes FISH, not only is their staking balance updated, but also stakedUntil[unstakingDay]. Whenever a user increases their staking balance, the mapping also needs to be increased. Whenever a user increases their staking time, their stake is subtracted from stakedUntil[previousUnstakingDay] and added to stakedUntil[newUnstakingDay].

Now, we can compute the voting power of all FISH staked until a given point in time in a single operation. The daily voting power DVPDVP is given by:

DVP(x)=f(x)โˆ—โˆ‘usu(x)DVP(x)=f(x)โˆ—\textstyle\sum_{u}s_u(x)

where โˆ‘usu(x)\textstyle\sum_{u}s_u(x) is the content of stakedUntil[x].

The total voting power can then be computed by summing up the daily voting powers of the next mm days:

TVP=โˆ‘x=0mโˆ—DVP(x)TVP=\textstyle\sum_{x=0}^ mโˆ—DVP(x)

This process requires mm iterations. With a maximum staking duration of 3 years, this would cost approximately 1,000,000 gas. In order to save gas costs, we decided to stake in bi-weekly periods instead. As a consequence, voting weights are only adjusted every 2 weeks and we need a maximum of 78 iterations (instead of 1095).

The stakedUntil mapping needs to be checkpointed to allow the computation of the total voting power for a point of time in the past. The same is true for the user stakes.

Delegating Voting Power

Given the possibility of delegation, a user can have a potentially large number of addresses delegating voting power to their address, with each of these other addresses staking for different durations. The voting power of a delegatee is computed the same way the total voting power is computed: as a sum of the voting powers per unstaking day.

Last updated