-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PartyGovernanceNFT.sol: burn function does not reduce totalVotingPower making it impossible to reach unanimous votes #10
Comments
This seems to be a specific example of the issue described in #9 more broadly. |
0xean marked the issue as duplicate of #9 |
@0xean #9 describes that the I agree that both reports deal with |
Yea, that is fair. even if the snapshot did exist, the value would still be wrong. Un-duping. |
0xean marked the issue as not a duplicate |
@HollaDieWaldfee100 I like the recommended mitigation. Had a question, if there were snapshots of |
@0xble |
@0xble |
0xble marked the issue as sponsor confirmed |
0xean marked the issue as satisfactory |
Lines of code
https://github.com/code-423n4/2023-04-party/blob/440aafacb0f15d037594cebc85fd471729bcb6d9/contracts/party/PartyGovernanceNFT.sol#L201-L224
Vulnerability details
Impact
With the new version of the Party protocol the
PartyGovernanceNFT.burn
function has been introduced.This function is used to burn party cards.
According to the sponsor the initial purpose of this function was to enable the
InitialETHCrowdfund
contract (theburn
function is needed for refunds).Later on they decided to allow any user to call this function and to burn their party cards.
The second use case when a regular user burns his party card is when the issue occurs.
The
PartyGovernanceNFT.burn
function does not decreasetotalVotingPower
which makes it impossible to reach an unanimous vote after a call to this function and it makes remaining votes of existing users less valuable than they should be.Proof of Concept
Let's look at the
PartyGovernanceNFT.burn
function:Link
It burns the party card specified by the
tokenId
parameter and makes the appropriate changes to the voting power of the owner (by calling_adjustVotingPower
) and tomintedVotingPower
.But it does not reduce
totalVotingPower
which remains untouched by this function.In case this function is called by
InitialETHCrowdfund
it is intended thattotalVotingPower
is not reduced. In this case theburn
function is only called when the initial crowdfund is lost andtotalVotingPower
hasn't even been increased so it is still0
(the initial value).But why is it an issue when a regular user calls this function?
Let's consider the following scenario:
Now Alice decides to burn half of her voting power:
Now it is easy to see why it is a problem that
totalVotingPower
is not reduced.It is impossible to reach an unanimous vote because even if all users vote there is only a
(250/300) = ~83%
agreement.One vote only represents
1/300 = ~ 0.33%
of all votes even though it should represent1/250 = 0.4%
of all votes. And thereby votes are less valuable than they should be.You can see in the following test that
totalVotingPower
stays unaffected even thoughvoter1
burns his party card which represents a third of all votes.(Add the test to the
PartyGovernanceNFTUnit.sol
test file and add this import:import "../../contracts/party/PartyGovernance.sol";
to access theGovernanceValues
struct ).The remaining two voters will not be able to reach unanimous vote since the
_isUnanimousVotes
function is called withtotalVotingPower
as the total votes with which to calculate the percentage.Link
Link
Tools Used
VSCode
Recommended Mitigation Steps
It is important to understand that when
InitialETHCrowdfund
calls theburn
function it is intended thattotalVotingPower
is not reduced.So we need to differentiate these two cases.
Fix:
Also note that the
|| !isAuthority[msg.sender]
part of the condition is important.It ensures that if we are not yet in the governance phase, i.e.
totalVotingPower == 0
and a user calls theburn
function he cannot burn his party card. This is because thetotalVotingPower - votingPower
subtraction results in an underflow.This ensures that in the pre-governance phase a user cannot accidentally burn his party card. He can only burn it via the
InitialETHCrowdfund
contract which ensures the user gets his ETH refund.The text was updated successfully, but these errors were encountered: