Elegant Arctic Stork
Medium
The fee calculation approach in buyNFT will cause precision loss for the auction owner and fee recipient, as currentPrice is divided by (10 ** differenceDecimals) too early in the process, leading to inaccurate fee and transfer amounts.
In Auction.sol:124 the fee calculation divides currentPrice by (10 ** differenceDecimals) before multiplying by the fee percentage, resulting in rounding errors when currentPrice has significant decimal values. https://github.com/sherlock-audit/2024-11-debita-finance-v3/blob/main/Debita-V3-Contracts/contracts/auctions/Auction.sol#L124
- The auction needs to be active (isActive set to true).
- The difference in decimals (differenceDecimals) must be greater than zero (i.e., the selling token has fewer than 18 decimals).
- The selling token's decimal precision must differ from 18, leading to adjustments in currentPrice.
- A user triggers the buyNFT function to buy the NFT.
- The contract calculates currentPrice in the native token decimal form, then divides by (10 ** differenceDecimals), causing a rounding error.
- This miscalculation results in a slight discrepancy in feeAmount and the amount transferred to the auction owner and the fee address, impacting the precision of the auction proceeds.
The auction owner and fee recipient may experience a slight precision loss, typically in the range of fractions of tokens per transaction. Over multiple transactions, this can result in accumulating discrepancies, particularly if the contract is frequently used.
For example, if currentPrice is 100.5 tokens with a differenceDecimals of 2, dividing by 100 before calculating the fee introduces a rounding error that causes the fee and transfer amounts to be off by 0.5 tokens.
// Adjust currentPrice
to base 18 decimals for accurate fee calculation
uint adjustedCurrentPrice = currentPrice * (10 ** s_CurrentAuction.differenceDecimals);
uint feeAmount = (adjustedCurrentPrice * fee) / 10000;
uint transferAmount = adjustedCurrentPrice - feeAmount;
// Normalize amounts for transfer back to token decimals
uint normalizedTransferAmount = transferAmount / (10 ** s_CurrentAuction.differenceDecimals);
uint normalizedFeeAmount = feeAmount / (10 ** s_CurrentAuction.differenceDecimals);
// Then use normalizedTransferAmount and normalizedFeeAmount for actual transfers
This approach ensures currentPrice is adjusted accurately before division, minimizing precision loss and improving the reliability of the auction process.