DeFiFoundry
20,000 USDC
View results
Submission Details
Severity: medium
Invalid

Potential for stuck tokens and failed distributions in `FjordAuction` due to blacklisted tokens

Summary

FjordAuction lacks proper error handling for token transfers and doesn't account for potential transfer restrictions in the auctionToken. This may lead to stuck tokens and failed distributions most especially if the auctionToken implements transfer restrictions like blacklisting.

Vulnerability Details

The claimTokens function in the FjordAuction contract performs a token transfer without checking for its success:

function claimTokens() external {
if (!ended) {
revert AuctionNotYetEnded();
}
uint256 userBids = bids[msg.sender];
if (userBids == 0) {
revert NoTokensToClaim();
}
uint256 claimable = userBids.mul(multiplier).div(PRECISION_18);
bids[msg.sender] = 0;
auctionToken.transfer(msg.sender, claimable);
emit TokensClaimed(msg.sender, claimable);
}

If the auctionToken transfer fails (e.g., due to a blacklist or other transfer restrictions), the function will not revert. This results in the user's bid being set to 0 without receiving tokens, effectively losing their claim to the auction proceeds.

One may ask how this affects the protocol. Now, if a blacklisted user participates in the auction and the distribution of tokens fails due to the blacklist, the auction tokens could become stuck in the contract. This means the protocol loses control over these assets. Also the auctionEnd function might not be able to complete its execution if it can't distribute tokens to all participants. This could leave the auction in an incomplete state.

Bear it in mind that USDC & USDT implement blacklisting feature to block suspicious users. This can become an issue if one of the approved holders is blacklisted by these tokens. The token transfer to these users will fail and will also brick the distribution system because the blacklisted user is never cleared.

USDC implements a blacklist function and these accounts cannot receive USDC:

function blacklist(address _account) external onlyBlacklister {
_blacklist(_account);
emit Blacklisted(_account);
}
function transfer(address to, uint256 value)
external
override
whenNotPaused
notBlacklisted(msg.sender)
notBlacklisted(to)
returns (bool)
{
_transfer(msg.sender, to, value);
return true;
}

Impact

Users may lose their rightful claim to auction tokens if the transfer fails. Also tokens can become permanently stuck in the contract if transfers to certain addresses are restricted.

Tools Used

Manual review

Recommendations

Implement a pull payment pattern for token distribution. Also consider implementing a recovery mechanism for stuck tokens, allowing the contract owner to rescue tokens in case of failed transfers. Ans lastly, consider using SafeERC20 from OpenZeppelin for safer token transfers.

Updates

Lead Judging Commences

inallhonesty Lead Judge
about 1 year ago
inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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