Skip to content

Instantly share code, notes, and snippets.

@0xekez
Created February 15, 2023 19:46
Show Gist options
  • Save 0xekez/1986e6156479441da59d338548d83806 to your computer and use it in GitHub Desktop.
Save 0xekez/1986e6156479441da59d338548d83806 to your computer and use it in GitHub Desktop.

Vote delegation is DOSable without voting power update hooks

Say you want to implement vote delegation on top of the current DAO DAO voting module interface.

Let $E_t$ be the last time your voting module had a message executed on it. Let $state(t)$ be the complete state of the blockchain your voting module is running on at time $t$.

When queried at time $E_t + \Delta$ , for $\Delta \ne 0$, the maximum amount of state known to the contract without an additional query is $state(E_t)$. 1

This means that if any delegator's voting power has changed in $\Delta$, the contract will have to make an external query.

Assuming that future delegations can not be predicted, $state(E_t)$ does not contain information about the set of delegators that have updated their voting power between $E_t$ and $E_t + \Delta$. Thus, to determine the voting power of an address during a query, the contract needs to learn the new voting power changes of each delegator to that address.

As we are attempting this without modifying the voting module interface, there are two external queries available, VotingPowerAtHeight and TotalPowerAtHeight. Total power is not granular enough for updating delegated voting powers, so we must use VotingPowerAtHeight to learn of voting power changes of delegators. This requires $O(|delegators|)$ queries.

The gas cost of determining voting power growing with the number of delegators means that an attacker can sybil and split their delegation over many addresses to DOS queries for an addresses' voting power.

Footnotes

  1. Contracts can only update their state when a message is executed on them. The maximum possible amount of state a contract can know is the entire state of the chain. Thus, when queried the maximum amount of state known to the contract without performing a query is the entire state of the chain when it last had a message executed on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment