Incorrect Handling of Tokens with Different Decimals Causes Miscalculations in Debt and Interest Calculations
Summary
The PredictDotLoan contract is designed to work with tokens like USDB (18 decimals) and USDC (6 decimals). However, the contract assumes that all tokens have 18 decimals in its calculations, particularly in the _calculateDebt. This assumption leads to incorrect calculations of debt, interest, and fees when tokens with fewer decimals (like USDC) are used. The disparity in decimal places causes significant scaling errors, potentially allowing borrowers to repay less than they owe or causing lenders to receive incorrect amounts, ultimately compromising the protocol's financial integrity.
Here, loanAmount is in the token's smallest unit (dependent on its decimals), and interestRatePerSecond is scaled by 1e18. When loanAmount has 18 decimals (like USDB), the calculation works correctly. However, for tokens like USDC with 6 decimals, the loanAmount is significantly smaller in magnitude, causing the multiplication with the scaled interestRatePerSecond to result in a value that is off by a factor of 1e12.
This is the scenario when USDC is used:
loanAmount = 100 USDC = 100 * 1e6
interestRatePerSecond = 1e18 + rate (scaled by 1e18)
Calculated debt will be off by a factor of 1e12 due to the mismatch in decimal scaling.
As a consequence, the borrower may end up owing significantly less than intended, or the lender may receive less interest, leading to financial discrepancies.
Impact
Financial Loss: Lenders may receive less interest than they are owed, and borrowers might underpay their debts, leading to potential financial losses for lenders and the protocol.
Protocol Integrity: Miscalculations can undermine trust in the platform, as users cannot rely on the accuracy of loan terms and repayments.
Mitigation
Normalize Token Decimals:
Implement a mechanism to normalize all token amounts to a standard number of decimals (e.g., 18 decimals) before performing calculations.
Use the decimals() function from the ERC20 token interface to adjust token amounts accordingly.
Modify functions like _calculateDebt to account for the token's decimals:
Massive Foggy Gorilla
High
Incorrect Handling of Tokens with Different Decimals Causes Miscalculations in Debt and Interest Calculations
Summary
The PredictDotLoan contract is designed to work with tokens like USDB (18 decimals) and USDC (6 decimals). However, the contract assumes that all tokens have 18 decimals in its calculations, particularly in the
_calculateDebt
. This assumption leads to incorrect calculations of debt, interest, and fees when tokens with fewer decimals (like USDC) are used. The disparity in decimal places causes significant scaling errors, potentially allowing borrowers to repay less than they owe or causing lenders to receive incorrect amounts, ultimately compromising the protocol's financial integrity.Root Cause
The contract uses InterestLib.ONE, which is defined as 1e18, to scale interest rates and perform calculations: https://github.com/sherlock-audit/2024-09-predict-fun/blob/main/predict-dot-loan/contracts/PredictDotLoan.sol#L42 In the _calculateDebt function, the debt is calculated as: https://github.com/sherlock-audit/2024-09-predict-fun/blob/main/predict-dot-loan/contracts/PredictDotLoan.sol#L1182-L1188
Here, loanAmount is in the token's smallest unit (dependent on its decimals), and
interestRatePerSecond
is scaled by 1e18. When loanAmount has 18 decimals (like USDB), the calculation works correctly. However, for tokens like USDC with 6 decimals, the loanAmount is significantly smaller in magnitude, causing the multiplication with the scaledinterestRatePerSecond
to result in a value that is off by a factor of 1e12. This is the scenario when USDC is used:Impact
Financial Loss: Lenders may receive less interest than they are owed, and borrowers might underpay their debts, leading to potential financial losses for lenders and the protocol. Protocol Integrity: Miscalculations can undermine trust in the platform, as users cannot rely on the accuracy of loan terms and repayments.
Mitigation
Normalize Token Decimals:
_calculateDebt
to account for the token's decimals: