The use of ERC20 tokens with decimals different from 18, such as GUSD with 2 decimals, as the auctionToken in the FjordAuction contract can result in a loss of funds. When the totalBids exceed totalTokens, the multiplier becomes less than 1e18, causing the users to receive zero tokens upon claiming. This issue can also occur with 18-decimal tokens when totalBids is greater than totalTokens.
The protocol specifies that ERC20 tokens with decimals different from 18 are in-scope for potential issues. The auction mechanism allows users to bid using FjordPoints token, which has 18 decimal. However, if the auction uses tokens with fewer decimals (like GUSD with 2 decimals) as the auctionToken, complications arise.
When such tokens are used, and the auction ends via the auctionEnd function, totalBids (the sum of all bids by participants) can exceed totalTokens either intentionally or unintentionally. When this occurs, the multiplier variable becomes less than 1e18 due to the following calculation:
Because the multiplier is less than 1e18, users attempting to claim their tokens through the claimTokens function will receive zero tokens:
If userBids multiplied by the multiplier results in a value less than 1e18, the user's claimable tokens amount to zero. Consequently, all tokens remain stuck in the FjordAuction contract, causing a loss of funds.
This issue can also occur with tokens having 18 decimals if totalBids exceeds totalTokens and the multiplier is less than 1e18. A malicious actor can manipulate this by contributing more to the auction to inflate totalBids beyond totalTokens, making it impossible for other users to claim their tokens.
Attack Scenario:
An auction is initiated with an ERC20 token having decimals other than 18 (e.g., GUSD with 2 decimals).
Users place bids using FjordPoints token, which has 18 decimal.
The totalBids surpass the totalTokens due to overbidding, or intentional manipulation.
The auction ends using the auctionEnd function, and the multiplier is calculated to be less than 1e18.
Users attempt to claim their tokens using the claimTokens function but receive zero tokens due to the userBids multiplied by the multiplier results in a value less than 1e18. This amount when divided by PRECISION_18 results in zero amount of token to be claimed by the user.
The users who participated in the auction suffer a loss of their bid amounts as they cannot retrieve their claimable tokens from the contract. The tokens remain locked in the FjordAuction contract, leading to a permanent loss of funds.
Auctions launched with smaller decimal tokens such as tokens with 10 or less decimals will leads to loss of funds for all the users participating in that auction.
Auctions launched with 18 decimal tokens can still result in loss of funds for some users who have smaller bids.
Manual Review
Prevent Excess Bidding: Add a condition in the FjordAuction::bid function that reverts if totalBids is greater than totalTokens.
Add this code in FjordAuction::bid function:
Adjust Decimal Precision: Instead of using a fixed PRECISION_18, replace it with a precision value that matches the auctionToken's decimals. This adjustment will allow the contract to handle tokens with any number of decimals correctly, avoiding calculation errors that lead to a loss of funds.
Import IERC20Metadata interface in the FjordAuction contract, create a new uint variable named decimalPrecision and add this code in FjordAuction's constructor:
Add this code in FjordAuction::auctionEnd function:
Add this code in FjordAuction::claimTokens function:
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.