Foundation Drop contest - ladboy233's results

Foundation is a web3 destination.

General Information

Platform: Code4rena

Start Date: 11/08/2022

Pot Size: $40,000 USDC

Total HM: 8

Participants: 108

Period: 4 days

Judge: hickuphh3

Total Solo HM: 2

Id: 152

League: ETH

Foundation

Findings Distribution

Researcher Performance

Rank: 21/108

Findings: 3

Award: $104.69

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

42.8343 USDC - $42.83

Labels

bug
duplicate
2 (Med Risk)

External Links

Lines of code

https://github.com/code-423n4/2022-08-foundation/blob/792e00df429b0df9ee5d909a0a5a6e72bd07cf79/contracts/mixins/nftDropMarket/NFTDropMarketFixedPriceSale.sol#L183

Vulnerability details

Impact

Detailed description of the impact of this finding.

if (IERC721(nftContract).balanceOf(msg.sender) + count > saleConfig.limitPerAccount) { if (saleConfig.limitPerAccount == 0) { // Provide a more targeted error if the collection has not been listed. revert NFTDropMarketFixedPriceSale_Must_Have_Sale_In_Progress(); } revert NFTDropMarketFixedPriceSale_Cannot_Buy_More_Than_Limit(saleConfig.limitPerAccount); }

we use IERC721(nftContract).balanceOf(msg.sender) to check if the user bypass the limitPerAccount restriction,

https://stackoverflow.com/questions/72604383/how-to-create-a-limit-in-minting-using-balanceof-over-contract but user can buy nft, transfer nft out to another account, and buy more nft to bypass the restriction.

If you use the wallet balance you may not be able to correctly check the amount of mints made by a wallet, as the balance only tells you how many tokens the wallet currently has.

Proof of Concept

Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.

For example, we set saleConfig.limitPerAccount to 2,

first, user buy two nft, second, user transfer two nft to his another wallet. third, user can buy two more nft.

Tools Used

I think you should create a mapping to store the amount of mints of each wallet. In your smart contract create a public mapping of mint amount of each wallet:

mapping(address => uint) public walletMints;

And then when the user mints you need add this amount to the address:

walletMints[msg.sender] = walletMints[msg.sender] + quantity_

When you create a public mapping the smart contract automatically creates a getter of this mapping that you can use in your javascript code and check the amount of mints made by a wallet.

#0 - 0xlgtm

2022-08-17T03:01:28Z

My issue here https://github.com/code-423n4/2022-08-foundation-findings/issues/59 with a proof of concept test in foundry but I disagree with severity as there are no loss of funds.

There are also too many dups for this issue so I won't list all of them down. Please check the de-dupe tool shared by kartoonjoy.

#1 - HardlyDifficult

2022-08-17T20:56:10Z

Lines of code

https://github.com/code-423n4/2022-08-foundation/blob/792e00df429b0df9ee5d909a0a5a6e72bd07cf79/contracts/mixins/nftDropMarket/NFTDropMarketFixedPriceSale.sol#L170 https://github.com/code-423n4/2022-08-foundation/blob/792e00df429b0df9ee5d909a0a5a6e72bd07cf79/contracts/mixins/shared/MarketFees.sol#L522

Vulnerability details

Impact

Detailed description of the impact of this finding.

When minting,

we go through

function mintFromFixedPriceSale( address nftContract, uint16 count, address payable buyReferrer ) external payable returns (uint256 firstTokenId) {

buyRefererer can be set to arbitrary address to the referral fee because when the referral fee is calcuulated.

if (buyReferrer != address(0) && buyReferrer != msg.sender && buyReferrer != seller && buyReferrer != creator) { unchecked { buyReferrerFee = totalFees / BUY_REFERRER_PROTOCOL_FEE_DENOMINATOR; // buyReferrerFee is always <= totalFees totalFees -= buyReferrerFee; } }

Proof of Concept

Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.

A user Bob wants to mint nft, he set Alice to receive the referral fee, but alice is bob's wallet address.

Tools Used

We can use another map to keep track of the referral.

mapping(address => address) referralMap;

and the function

function refer(address referTo) { referralMap[referTo] = msg.sender; }

and when a user is minting,

we can check if the referral address is correct.

function mintFromFixedPriceSale( address nftContract, uint16 count, address payable buyReferrer ) external payable returns (uint256 firstTokenId) { require(referralMap[msg.sender] == buyReferral, 'invalid referral') // other logic }

#0 - 0xlgtm

2022-08-17T02:36:18Z

Mitigation step does not actually mitigate sybil attack via referral fee since Bob can still set Alice address as a referral and he owns Alice's private key.

#1 - HardlyDifficult

2022-08-17T07:06:40Z

#2 - HickupHH3

2022-08-26T08:48:29Z

primary warden's QA report

#0 - HardlyDifficult

2022-08-19T15:23:12Z

Function can be marked as external

Invalid, this is used internally.

Cache Array Length Outside of Loop

May be theoretically valid, but won't fix. I tested this: gas-reporter and our gas-stories suite is reporting a small regression using this technique. It also hurts readability a bit so we wouldn't want to include it unless it was a clear win.

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