Pieces Protocol

First Flight #32
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: high
Invalid

[H-3] Silent Failure Risk in TokenDivider::claimNft

Summary

The claimNft function in the TokenDivider contract uses the burnFrom function to burn ERC20 tokens but does not check its return value or handle failures properly. If the burnFrom call fails silently (e.g., due to insufficient allowance or a non-compliant ERC20 token), the function will not revert, and the contract state will be updated incorrectly. This can result in users losing their ERC20 tokens without receiving the corresponding NFT.

Vulnerability Details

The claimNft function calls burnFrom to burn ERC20 tokens but does not verify if the operation was successful. If burnFrom fails silently (e.g., returns false instead of reverting), the function will proceed to update the contract state (e.g., setting the user's balance to 0) without actually burning the tokens. This inconsistency can lead to users losing their ERC20 tokens without receiving the NFT they intended to claim.

code:

function claimNft(address nftAddress) external {
// ... (checks omitted for brevity)
ERC20ToGenerateNftFraccion(tokenInfo.erc20Address).burnFrom(msg.sender, erc20ToMintedAmount[tokenInfo.erc20Address]);
balances[msg.sender][tokenInfo.erc20Address] = 0;
erc20ToMintedAmount[tokenInfo.erc20Address] = 0;
emit NftClaimed(nftAddress);
IERC721(nftAddress).safeTransferFrom(address(this), msg.sender, tokenInfo.tokenId);
}

Impact

  1. High Impact: Funds are directly at risk. Users could lose their ERC20 tokens without receiving the corresponding NFT.

  2. State Inconsistency: The contract state (e.g., balances and minted amounts) will be updated incorrectly, leading to potential financial losses for users.

  3. User Dissatisfaction: Users may lose trust in the protocol if they experience unexpected losses.

Tools Used

Slither, Foundry

Recommendations

Ensure burnFrom reverts on failure and handle the state changes accordingly. Use a require statement to enforce the success of the burnFrom call. For example:

function claimNft(address nftAddress) external {
// ... (checks omitted for brevity)
bool burnSuccess = ERC20ToGenerateNftFraccion(tokenInfo.erc20Address).burnFrom(
msg.sender,
erc20ToMintedAmount[tokenInfo.erc20Address]
);
require(burnSuccess, "TokenDivider: Burn failed");
balances[msg.sender][tokenInfo.erc20Address] = 0;
erc20ToMintedAmount[tokenInfo.erc20Address] = 0;
emit NftClaimed(nftAddress);
IERC721(nftAddress).safeTransferFrom(address(this), msg.sender, tokenInfo.tokenId);
}

Additional Considerations:

Use OpenZeppelin's SafeERC20 library to handle non-compliant ERC20 tokens and ensure safe operations.

Emit an event for failed burns to improve transparency and debugging.

Updates

Lead Judging Commences

fishy Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.