PartyDAO contest - bin2chen's results

A protocol for buying, using, and selling NFTs as a group.

General Information

Platform: Code4rena

Start Date: 12/09/2022

Pot Size: $75,000 USDC

Total HM: 19

Participants: 110

Period: 7 days

Judge: HardlyDifficult

Total Solo HM: 9

Id: 160

League: ETH

PartyDAO

Findings Distribution

Researcher Performance

Rank: 7/110

Findings: 2

Award: $2,015.33

🌟 Selected for report: 1

🚀 Solo Findings: 1

Findings Information

🌟 Selected for report: bin2chen

Labels

bug
2 (Med Risk)
resolved
sponsor confirmed
edited-by-warden

Awards

1932.8529 USDC - $1,932.85

External Links

Lines of code

https://github.com/PartyDAO/party-contracts-c4/blob/3896577b8f0fa16cba129dc2867aba786b730c1b/contracts/crowdfund/BuyCrowdfundBase.sol#L122

Vulnerability details

Impact

BuyCrowdfundBase.sol _buy() When callValue = 0 is settledPrice to totalContributions ignoring whether totalContributions > maximumPrice resulting in the minimum proportion of participants expected to become smaller

Proof of Concept

function _buy( IERC721 token, uint256 tokenId, address payable callTarget, uint96 callValue, bytes calldata callData, FixedGovernanceOpts memory governanceOpts ) ... settledPrice_ = callValue == 0 ? totalContributions : callValue; //**** not check totalContributions>maximumPrice****// if (settledPrice_ == 0) { // Still zero, which means no contributions. revert NoContributionsError(); } settledPrice = settledPrice_;

(AuctionCrowdfund.sol finalize() similar)

add check

function _buy( IERC721 token, uint256 tokenId, address payable callTarget, uint96 callValue, bytes calldata callData, FixedGovernanceOpts memory governanceOpts ) ... settledPrice_ = callValue == 0 ? totalContributions : callValue; if (settledPrice_ == 0) { // Still zero, which means no contributions. revert NoContributionsError(); } +++ if (maximumPrice_ != 0 && settledPrice_ > maximumPrice_) { +++ settledPrice_ = maximumPrice_; +++ } settledPrice = settledPrice_;

#0 - merklejerk

2022-09-22T15:21:23Z

We will cap the callValue to maximumPrice.

#1 - 0xble

2022-10-02T16:13:25Z

#2 - HardlyDifficult

2022-10-04T10:02:22Z

This is a potential violation of user expectations - agree with Medium risk.

1: PartyGovernance.sol accept()

If the user participates in the crowdfunding but has not burn(), at this time votingPower==0, if go to vote, can succeed, but votingPower==0, lost the original should have votingPower Suggest adding votingPower==0 can not vote

function accept(uint256 proposalId, uint256 snapIndex) public onlyDelegateCall returns (uint256 totalVotes) { .. // Increase the total votes that have been cast on this proposal. uint96 votingPower = getVotingPowerAt(msg.sender, values.proposedTime, snapIndex); +++ require(votingPower!=0);

2: Crowdfund.sol _initialize() Suggest adding the judgment that opts.initialContributor is not address(0), to avoid losing the amount

function _initialize(CrowdfundOptions memory opts) internal { .. uint96 initialBalance = address(this).balance.safeCastUint256ToUint96(); if (initialBalance > 0) { +++ require(opts.initialContributor!=address(0)); // If this contract has ETH, either passed in during deployment or // pre-existing, credit it to the `initialContributor`. _contribute(opts.initialContributor, initialBalance, opts.initialDelegate, 0, ""); }
AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter