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.