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

Incorrect calculated multiplier and claim tokens amount in `FjordAuction` contract for auction token not with 18 decimals

Summary

The assumption that the auction token will have 18 decimals in the FjordAuction contract leads to incorrect calculations for the multiplier and claim token amount when the actual auction token used in the contract has fewer than 18 decimals. This discrepancy could result in a loss of protocol funds due to an incorrect amount of claim tokens being transferred to users or the claiming process will fail if the claim amount is larger than what the protocol holds.

https://github.com/Cyfrin/2024-08-fjord/blob/0312fa9dca29fa7ed9fc432fdcd05545b736575d/src/FjordAuction.sol#L84

https://github.com/Cyfrin/2024-08-fjord/blob/0312fa9dca29fa7ed9fc432fdcd05545b736575d/src/FjordAuction.sol#L197

https://github.com/Cyfrin/2024-08-fjord/blob/0312fa9dca29fa7ed9fc432fdcd05545b736575d/src/FjordAuction.sol#L217

Vulnerability Details

In the FjordAuction contract, the auction token is assumed to have 18 decimals, and a constant PRECISION_18 is used for calculating the multiplier and claim token amount. If the actual auction token has fewer than 18 decimals, this assumption causes the multiplier to be inflated, leading to incorrect calculations of the claim token amount in FjordAuction:claimTokens. Consequently, this results in a loss of protocol funds due to an incorrect amount of auction tokens being transferred to the user account or the claiming process will just fail due to the claim amount is larger than what the protocol holds.

Proof of Concept:
In test/unit/action.t.sol, add the following tests:

function test_audit_auctionTokenNotIn18decimals_wrongMultiplierCalculated() public {
address bidder_wbtc = address(0x3);
uint256 bidAmount_wbtc = 100e8; // wbtc has 8 decimals
deal(address(fjordPoints), bidder_wbtc, bidAmount_wbtc);
vm.startPrank(bidder_wbtc);
fjordPoints.approve(address(auction), bidAmount_wbtc);
auction.bid(bidAmount_wbtc);
vm.stopPrank();
skip(biddingTime);
auction.auctionEnd();
uint256 expectedMultiplier_wbtc = totalTokens.mul(1e8).div(bidAmount_wbtc);
console.log("calculated multiplier_wbtc: ", auction.multiplier());
console.log("expected multiplier_wbtc: ", expectedMultiplier_wbtc);
assertEq(auction.multiplier(), expectedMultiplier_wbtc);
}

The forge test run on the above will fail indicating the calculated multiplier is incorrect

Ran 1 test for test/unit/auction.t.sol:TestAuction
[FAIL. Reason: assertion failed: 100000000000000000000000000000 != 10000000000000000000] test_audit_auctionTokenNotIn18decimals_wrongMultiplierCalculated() (gas: 428693)
Logs:
calculated multiplier_wbtc: 100000000000000000000000000000
expected multiplier_wbtc: 10000000000000000000

Because of the inflated multiplier, the claim token amount calculated and transfered to the user is also larger than what it suppose to be :

function test_audit_auctionTokenNotIn18decimals_wrongClaimTokenAmount() public {
address bidder_wbtc = address(0x3);
uint256 bidAmount_wbtc = 100e8; // wbtc has 8 decimals
deal(address(fjordPoints), bidder_wbtc, bidAmount_wbtc);
vm.startPrank(bidder_wbtc);
fjordPoints.approve(address(auction), bidAmount_wbtc);
auction.bid(bidAmount_wbtc);
vm.stopPrank();
skip(biddingTime);
auction.auctionEnd();
vm.prank(bidder_wbtc);
auction.claimTokens();
uint256 auctionTokenReceivedByBidder_wbtc = auctionToken.balanceOf(bidder_wbtc);
console.log("claim_token_amount_bidder_wbtc: ", auctionTokenReceivedByBidder_wbtc);
console.log("original_bidAmount_wbtc: ", bidAmount_wbtc);
}

A test run of the above will pass with the console message

Logs:
claim_token_amount_bidder_wbtc: 1000000000000000000000
original_bidAmount_wbtc: 10000000000

it shows that the wrong calculated large claim token amount is successfully transfered to user, a huge loss of protocol fund.

Impact

Protocol fund loss due to inflated multiplier calculated based on a fix 18 decimals precision for auction token that is actually with fewer than 18 decimals.

Tools Used

Manual review complemented with forge test

Recommendations

Instead of using a fix precision constant, calculation of the multiplier and claim token amount shall factor in the actual decimals from the auction token

Updates

Lead Judging Commences

inallhonesty Lead Judge
about 1 year ago
inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Known issue
Assigned finding tags:

Low decimal tokens or super small bids can lead to 0 claims

Support

FAQs

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