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

Reentrancy Attack on FjordAuction:: claimTokens()

Summary

https://github.com/Cyfrin/2024-08-fjord/blob/main/src/FjordAuction.sol

The claimTokens() function is vulnerable to reentrancy attacks. The function transfers auction tokens to the bidder before updating the internal state variable bids. An attacker can exploit this by re-entering the claimTokens() function multiple times, allowing them to claim more tokens than they are entitled to.

Vulnerability Details

The claimTokens() function allows users to claim their auction tokens after the auction ends. However, the function is vulnerable to reentrancy attacks because the external call to transfer tokens (auctionToken.transfer(msg.sender, claimable)) occurs before the internal state variable bids[msg.sender] is reset to zero.

An attacker could exploit this by re-entering the claimTokens() function through the external token contract's fallback or callback mechanism and claim more tokens than they are entitled to before the state is updated.

Impact

Financial Loss: An attacker could repeatedly call claimTokens() to drain the contract’s auction tokens.

Auction Integrity: This undermines the fairness of the auction, as honest participants may not receive their rightful tokens.

Tools Used

Manual Review

Recommendations

Implement a reentrancy guard using OpenZeppelin's ReentrancyGuard contract and apply the nonReentrant modifier to the claimTokens() function. This will prevent reentrancy attacks by disallowing recursive calls into the function

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract FjordAuction is ReentrancyGuard {
function claimTokens() external nonReentrant {
uint256 userBids = bids[msg.sender];
if (userBids == 0) {
revert NoTokensToClaim();
}
uint256 claimable = userBids.mul(multiplier).div(PRECISION_18);
bids[msg.sender] = 0; // Update state before external call
auctionToken.transfer(msg.sender, claimable); // External call
emit TokensClaimed(msg.sender, claimable);
}
}

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

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