-
Notifications
You must be signed in to change notification settings - Fork 4
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#mint - User can delegate another user funds to themselves and brick them from changing the delegation #418
Comments
Plz refer File: contracts\party\PartyGovernance.sol
451: function delegateVotingPower(address delegate) external {
452: _adjustVotingPower(msg.sender, 0, delegate);
453: } Invalid |
ydspa marked the issue as insufficient quality report |
The warden described a potential griefing vector where an attacker (Alice) can temporarily steal the delegation from another user (Bob) who contributed for a user (User). |
gzeon-c4 changed the severity to 2 (Med Risk) |
gzeon-c4 marked the issue as primary issue |
gzeon-c4 marked the issue as satisfactory |
gzeon-c4 marked the issue as selected for report |
Lines of code
https://github.com/code-423n4/2023-10-party/blob/b23c65d62a20921c709582b0b76b387f2bb9ebb5/contracts/party/PartyGovernanceNFT.sol#L194-L198
Vulnerability details
Impact
The natural flow of minting a new Card is through contributing to the Crowdfund. The protocol also allows users to
contributeFor
in the name of someone else.Let's follow the flow of the
contributeFor
:The function immediately calls
_contribute
Some checks are done, then we call
_processContribution
.Inside we see this if/else statement. It allows for anyone to set delegate for a user, but only if
oldDelegate == address(0)
, meaning it's never been set before. Ifmsg.sender == contributor
he can still set the delegate to whoever he wishes, anyone else callingcontributeFor
after the original contributor has delegated, can't change the delegate.The rest of then function finishes and we go back to
_contribute
after which we callparty.mint
.Inside
mint
we see the following.Here we check if
delegationsByVoter[owner] != address(0)
, meaning this is the first time a deleagte is being set, if a delegate already exists we set the newdelegate
to the olddelegationsByVoter[owner]
.This is where the problem lies, note that this function doesn't take into account if
msg.sender == contributor
, so oncedelegationsByVoter[owner]
is set, there is no changing it through themint
function again.So let's imagine the following scenario:
maxTotalContributions = 20 ether
.5 ether
to the crowdfund.15 ether
to finalize it early, and sets himself asinitialDelegate
.contributeFor{value: 1 }(0, payable(address(bob)), address(alice), "");
setting Bob's delegate to herself.At this point
delegationsByVoter[bob] = alice
mint
we hit this:Since Bob already has a delegate, he can't change it here, so Bob's
delegate
gets overwritten to Alice and he is unable to change the delegate.15 ether
get delegated to Alice inside_adjustVotingPower
propose/accept
with a huge amount of voting power that was never intended for her and she can influence proposals that she shouldn't be able to.delegateVotingPower
, but Alice will have enough time to influence the Party.Note that this way a 51% attack can easily be executed by a malicious user. A malicious user can steal multiple delegates this way and influence the Party greatly.
Proof of Concept
Tools Used
Manual review
Foundry
Recommended Mitigation Steps
We recommend removing the
contributeFor
function.Assessed type
Other
The text was updated successfully, but these errors were encountered: