we build smart contracts for Nouns. we're on twitter @davidbrai and @eladmallel.
A Nouns token delegation vulnerability
A Nouns token delegation vulnerabilityWe were recently approached by 0xkasper from hexens, a white hat security team, who found a new attack vector based on a vulnerability we were aware of in the Nouns token contract. Nouns tech grants pod has initiated a bounty payment of 30K USDC to the team.TLDRWho’s at risk? Noun owners delegating to EOA accounts (not smart contract accounts).What’s the damage? Noun NFTs can become non-transferrable with no voting power.How likely is it to happen? The pr...
Introducing Nouns Fork: A Last-Resort Minority Protection Mechanism
Forking is the crypto-native way for groups of token holders to exit together into a new instance of their protocol, resulting in maximal conservation of momentum in the ecosystem; famous examples include the Ethereum Classic fork and the Bitcoin Cash fork. We believe it's time to enable DAO forks as well, starting here at Nouns. To date, there has been no DAO version of forking, but it is needed. How can we protect a minority against a tyrannical majority? Or, in less extreme cases, how...
Nouns Governor: Design Alternatives
Welcome to the second post in the Nouns Governor series; Please check out the first post for more context. This time we’d like to share three different design directions we have in mind, with some high level details on how each direction might work. Our hope is the same as last time: to receive feedback from the community; do you have a preferred design direction? Do you think none of them are good enough? The current focus is on how delegation information is encoded and presented. The curren...
A Nouns token delegation vulnerability
A Nouns token delegation vulnerabilityWe were recently approached by 0xkasper from hexens, a white hat security team, who found a new attack vector based on a vulnerability we were aware of in the Nouns token contract. Nouns tech grants pod has initiated a bounty payment of 30K USDC to the team.TLDRWho’s at risk? Noun owners delegating to EOA accounts (not smart contract accounts).What’s the damage? Noun NFTs can become non-transferrable with no voting power.How likely is it to happen? The pr...
Introducing Nouns Fork: A Last-Resort Minority Protection Mechanism
Forking is the crypto-native way for groups of token holders to exit together into a new instance of their protocol, resulting in maximal conservation of momentum in the ecosystem; famous examples include the Ethereum Classic fork and the Bitcoin Cash fork. We believe it's time to enable DAO forks as well, starting here at Nouns. To date, there has been no DAO version of forking, but it is needed. How can we protect a minority against a tyrannical majority? Or, in less extreme cases, how...
Nouns Governor: Design Alternatives
Welcome to the second post in the Nouns Governor series; Please check out the first post for more context. This time we’d like to share three different design directions we have in mind, with some high level details on how each direction might work. Our hope is the same as last time: to receive feedback from the community; do you have a preferred design direction? Do you think none of them are good enough? The current focus is on how delegation information is encoded and presented. The curren...
we build smart contracts for Nouns. we're on twitter @davidbrai and @eladmallel.

Subscribe to verbs

Subscribe to verbs
Share Dialog
Share Dialog
>400 subscribers
>400 subscribers
Since our last update on Nouns Governor we’ve been working on speccing and implementing the design described as “Approach 1: Delegation NFTs”. While working on the proposed design for $nouns and soliciting feedback from Nouners (thanks 9999!) we discovered a flaw in the Nouns Gov design we were working towards.
The flaw enables an attacker to use the voting power of swappable Nouns sitting idle in a contract. We describe it in detail below.
All the solutions we could come up with to mitigate this attack require the Nouner to deposit their Noun(s) in a new contract, which is a requirement we were hoping to avoid.
If we choose to accept this requirement, then we think there’s a simpler design which enables granular delegation, without switching to an NFT based voting approach. We will describe it in a followup post.
When switching to NFT based voting we decided to not use the voting power checkpointing system used today. Voting by NFT eliminates the ability to double vote with the same token because we record each time an NFT is used to vote.
Unfortunately, removing the checkpoints also opens up a new attack vector.
Setting up the stage:
A contract (pool) holds 20 Nouns and enables permissionless swapping.
This could be the case with the proposed $nouns contract for example.
A Nouns proposal is up for voting.
Attack steps:
The attacker has one Noun; they vote with their Noun.
They swap their Noun with a Noun from the pool; they use the pool Noun to vote as well.
Repeat for all the Nouns available for swapping in the pool.
This enables the attacker to use the voting power of the Nouns in the pool as their own. This attack is not possible today because the Nouns contract keeps checkpoints of the voting power of each account at each block. Unless the attacker buys more Nouns, their swapping with the pool can only give them a single vote, because they can only hold a single Noun per block.
Unfortunately, the Nouns contract does not keep track of which account controlled which Noun in its checkpointing system, and the contract is not upgradeable, so the most straightforward solution - having said tracking native to Nouns token - is not possible. We detail below the alternatives we’ve come up with so far.
One of the ideas we were exploring as a mitigation to this attack was to have checkpoints for Noun Delegation Tokens (NDTs). NDTs are one-to-one NFTs which a Nouner can mint to delegate their voting power of that Noun to someone else. Any time an NDT changes ownership, we would record the block. This would allows us to answer the following question in the contract: was this user the owner of this NDT when this proposal’s voting started?
Unfortunately this does not solve the problem. One could perform a similar sequence to the one above, just before a proposal’s voting starts:
Swap their Noun with a Noun from the pool.
Mint themselves an NDT.
Repeat for all the Nouns in the pool.
This ensures that they will be the owner of all the NDTs at the proposal’s snapshot block. The only scenario in which this wouldn’t be the case is if another attacker backruns them and does the same thing. In any case, the problem remains.
The root of the problem is that we can’t hook into Nouns transfers. And since the Nouns token contract is not upgradeable, we can’t add those hooks either.
We could use storage proofs to prove that a Noun was owned by a specific account at a specific block; federation.wtf does something similar. Besides the additional complexity of requiring users to generate these proofs, it would probably also require relying on a third party to have access to historic block hashes. This level of complexity is not a good fit for the core governance contracts.
We could keep track of Nouns transfers if we require users to deposit their Nouns into a custody contract. This would allow us to keep ownership info checkpoints at the Noun level, and not just the NDT. For example, we could create a “WrappedNoun” contract (similar to wrapped punks). In this WrappedNoun contract, we could keep track of the owner per block.
The main drawback here is that Nouners would have to deposit their Nouns into a new contract, which is something we were hoping to avoid.
In the solution space of depositing Nouns in custody there’s another possible solution we’re currently exploring. We could have a delegator contract which keeps each of your Nouns in a separate custody wallet. This would allow you to delegate each Noun to a different address. One advantage of this solution is that it doesn’t require any changes in the current governor contracts. We’ll publish another post describing this solution in detail soon.
We aren’t happy with any of the solutions we came up with so far. We think this issue is risky enough to be a showstopper for the Nouns Governor design. We will soon publish a design for granular delegation that works with the current governor contract. If you think differently, or if you have other solutions in mind, we’d love to hear from you.
We will start a conversation about this in the new nouns-protocol channel on farcaster. We are experimenting with using rounds.wtf to incentivize and reward good ideas & feedback.
Since our last update on Nouns Governor we’ve been working on speccing and implementing the design described as “Approach 1: Delegation NFTs”. While working on the proposed design for $nouns and soliciting feedback from Nouners (thanks 9999!) we discovered a flaw in the Nouns Gov design we were working towards.
The flaw enables an attacker to use the voting power of swappable Nouns sitting idle in a contract. We describe it in detail below.
All the solutions we could come up with to mitigate this attack require the Nouner to deposit their Noun(s) in a new contract, which is a requirement we were hoping to avoid.
If we choose to accept this requirement, then we think there’s a simpler design which enables granular delegation, without switching to an NFT based voting approach. We will describe it in a followup post.
When switching to NFT based voting we decided to not use the voting power checkpointing system used today. Voting by NFT eliminates the ability to double vote with the same token because we record each time an NFT is used to vote.
Unfortunately, removing the checkpoints also opens up a new attack vector.
Setting up the stage:
A contract (pool) holds 20 Nouns and enables permissionless swapping.
This could be the case with the proposed $nouns contract for example.
A Nouns proposal is up for voting.
Attack steps:
The attacker has one Noun; they vote with their Noun.
They swap their Noun with a Noun from the pool; they use the pool Noun to vote as well.
Repeat for all the Nouns available for swapping in the pool.
This enables the attacker to use the voting power of the Nouns in the pool as their own. This attack is not possible today because the Nouns contract keeps checkpoints of the voting power of each account at each block. Unless the attacker buys more Nouns, their swapping with the pool can only give them a single vote, because they can only hold a single Noun per block.
Unfortunately, the Nouns contract does not keep track of which account controlled which Noun in its checkpointing system, and the contract is not upgradeable, so the most straightforward solution - having said tracking native to Nouns token - is not possible. We detail below the alternatives we’ve come up with so far.
One of the ideas we were exploring as a mitigation to this attack was to have checkpoints for Noun Delegation Tokens (NDTs). NDTs are one-to-one NFTs which a Nouner can mint to delegate their voting power of that Noun to someone else. Any time an NDT changes ownership, we would record the block. This would allows us to answer the following question in the contract: was this user the owner of this NDT when this proposal’s voting started?
Unfortunately this does not solve the problem. One could perform a similar sequence to the one above, just before a proposal’s voting starts:
Swap their Noun with a Noun from the pool.
Mint themselves an NDT.
Repeat for all the Nouns in the pool.
This ensures that they will be the owner of all the NDTs at the proposal’s snapshot block. The only scenario in which this wouldn’t be the case is if another attacker backruns them and does the same thing. In any case, the problem remains.
The root of the problem is that we can’t hook into Nouns transfers. And since the Nouns token contract is not upgradeable, we can’t add those hooks either.
We could use storage proofs to prove that a Noun was owned by a specific account at a specific block; federation.wtf does something similar. Besides the additional complexity of requiring users to generate these proofs, it would probably also require relying on a third party to have access to historic block hashes. This level of complexity is not a good fit for the core governance contracts.
We could keep track of Nouns transfers if we require users to deposit their Nouns into a custody contract. This would allow us to keep ownership info checkpoints at the Noun level, and not just the NDT. For example, we could create a “WrappedNoun” contract (similar to wrapped punks). In this WrappedNoun contract, we could keep track of the owner per block.
The main drawback here is that Nouners would have to deposit their Nouns into a new contract, which is something we were hoping to avoid.
In the solution space of depositing Nouns in custody there’s another possible solution we’re currently exploring. We could have a delegator contract which keeps each of your Nouns in a separate custody wallet. This would allow you to delegate each Noun to a different address. One advantage of this solution is that it doesn’t require any changes in the current governor contracts. We’ll publish another post describing this solution in detail soon.
We aren’t happy with any of the solutions we came up with so far. We think this issue is risky enough to be a showstopper for the Nouns Governor design. We will soon publish a design for granular delegation that works with the current governor contract. If you think differently, or if you have other solutions in mind, we’d love to hear from you.
We will start a conversation about this in the new nouns-protocol channel on farcaster. We are experimenting with using rounds.wtf to incentivize and reward good ideas & feedback.
No activity yet