The protocol ignores the possibility of using an atypical decimals ERC20 token even though the developer stated that the goal here is to just allow any token combo. The Contract Overview section specifies that maxLoanRatio - the highest LTV they are willing to take on the loan (this is multiplied by 10^18). The decimals discrepancy between the loanToken and the collateralToken can be exploited to steal the borrowed amount.
Inside the body of the borrow function from Lender.sol the loanRatio is computed and checked as follows:
The lack of decimals control leads to the following situation:
(1) Alice decides to lend out 100,000 USDC with WETH as collateral.
(2) Vladimir listens for PoolCreated(poolId, p) events to check if there are any cases of low decimals loanTokens. He finds Alice's pool.
(3) Vladimir puts up a small collateral, as low as 0.0001 WETH (around 0.19$) and borrows the whole amount of 100,000 USDC (99,500 after fee). Obviously he will never repay this amount.
The same vulnerability is present in the other place where the loanRatio > pool.maxLoanRatio check is performed, in the refinance function.
Alice suffers a complete loss of funds + gas because Vladimir exploited the lack of decimals control. Vladimir "borrowed" 99,500 USDC for close to 0 $ collateral.
Foundry testing + Manual review
This can be remedied in two ways:
Insert a check that allows only the usage of typical decimals ERC20 tokens; (In my opinion this is the least favorable solution)
Ensure that the decimal discrepancy is taken into account when calculating the loanRatio;
This can be done by adding a function to retrieve decimals in IERC20.sol:
and the following lines in Lender.sol:
This way of computing the loanRatio is decimals agnostic.
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.