-
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
contributeFor, batchContributeFor - attacker can delegate someone else's vote freely #459
Comments
Intended design choice, only initial delegate (i.e. zero voting power account) could be set by others, doing this attack means giving free ETH to others, negative financial incentive. File: contracts\crowdfund\ETHCrowdfundBase.sol
201: address oldDelegate = delegationsByContributor[contributor];
202: if (msg.sender == contributor || oldDelegate == address(0)) {
203: // Update delegate.
204: delegationsByContributor[contributor] = delegate;
205: } else {
206: // Prevent changing another's delegate if already delegated.
207: delegate = oldDelegate;
208: }
|
ydspa marked the issue as insufficient quality report |
gzeon-c4 marked the issue as unsatisfactory: |
hello @gzeon-c4 @ydspa claimed function _contribute(
address payable contributor,
address delegate,
uint96 amount,
uint256 tokenId,
bytes memory gateData
) private returns (uint96 votingPower) {
// Require a non-null delegate.
if (delegate == address(0)) {
revert InvalidDelegateError();
}
...
@> votingPower = _processContribution(contributor, delegate, amount);
// OK to contribute with zero just to update delegate.
if (amount == 0) return 0;
if (tokenId == 0) {
// Mint contributor a new party card.
@> party.mint(contributor, votingPower, delegate);
} else if (disableContributingForExistingCard) {
revert ContributingForExistingCardDisabledError();
} else if (party.ownerOf(tokenId) == contributor) {
// Increase voting power of contributor's existing party card.
party.increaseVotingPower(tokenId, votingPower);
} else {
revert NotOwnerError(tokenId);
}
}
function _processContribution(
address payable contributor,
address delegate,
uint96 amount
) internal returns (uint96 votingPower) {
address oldDelegate = delegationsByContributor[contributor];
if (msg.sender == contributor || oldDelegate == address(0)) {
// Update delegate.
@> delegationsByContributor[contributor] = delegate;
} else {
// Prevent changing another's delegate if already delegated.
delegate = oldDelegate;
} So, the delegator can be reset by attacker. The PoC code is the variation of |
gzeon-c4 marked the issue as duplicate of #311 |
gzeon-c4 marked the issue as satisfactory |
gzeon-c4 changed the severity to 2 (Med Risk) |
gzeon-c4 marked the issue as duplicate of #418 |
Lines of code
https://github.com/code-423n4/2023-10-party/blob/b23c65d62a20921c709582b0b76b387f2bb9ebb5/contracts/crowdfund/InitialETHCrowdfund.sol#L235-L249
https://github.com/code-423n4/2023-10-party/blob/b23c65d62a20921c709582b0b76b387f2bb9ebb5/contracts/crowdfund/InitialETHCrowdfund.sol#L302
https://github.com/code-423n4/2023-10-party/blob/b23c65d62a20921c709582b0b76b387f2bb9ebb5/contracts/crowdfund/ETHCrowdfundBase.sol#L201-L208
https://github.com/code-423n4/2023-10-party/blob/b23c65d62a20921c709582b0b76b387f2bb9ebb5/contracts/crowdfund/InitialETHCrowdfund.sol#L255-L273
Vulnerability details
Impact
Attacker can freely delegate other people's votes. Attacker can delegate votes without the user's knowledge. In the worst case, attacker delegate all votes and execute proposal immediately by unanimous vote. Then the attacker can be the Authority, steal assets, or crash the party.
Proof of Concept
If the attacker calls
contributeFor
orbatchContributeFor
, attacker can delegate votes of any user.https://github.com/code-423n4/2023-10-party/blob/b23c65d62a20921c709582b0b76b387f2bb9ebb5/contracts/crowdfund/InitialETHCrowdfund.sol#L235
https://github.com/code-423n4/2023-10-party/blob/b23c65d62a20921c709582b0b76b387f2bb9ebb5/contracts/crowdfund/InitialETHCrowdfund.sol#L255
https://github.com/code-423n4/2023-10-party/blob/b23c65d62a20921c709582b0b76b387f2bb9ebb5/contracts/crowdfund/InitialETHCrowdfund.sol#L275
In the
_processContribution
function, ifmsg.sender
is not thecontributor
, it keepdelegationsByContributor
as old value. But since the InitialETHCrowndfund contract does not use thedelegationsByContributor
, vote delegation todelegate
is not prevented.https://github.com/code-423n4/2023-10-party/blob/b23c65d62a20921c709582b0b76b387f2bb9ebb5/contracts/crowdfund/ETHCrowdfundBase.sol#L201-L208
This is PoC code. Add it to InitialEThCrowdfund.t.sol and run it.
Tools Used
Manual Review
Recommended Mitigation Steps
Use
delegationsByContributor
at_contribute
Assessed type
Other
The text was updated successfully, but these errors were encountered: