The Lender.sol
contract allows users to supply assets which can then be borrowed by providing collateral by other users in a peer-to-peer fashion. As the lending market is open anyone can create a pool with any two assets - loanToken and collateralToken. Whenever a user decides to borrow the loanToken he needs to provide a sufficient amount of collateralToken so that the final ratio of the loan is below a pre-set maxLoanRatio. Essentially the idea is to allow users to borrow from other users with sufficient overcollateralization on their loan in a way that if the loan is defaulted the lender would receive the collateral and not lose funds.
However the protocol does not take into account tokens with 18 decimals and assumes that all tokens added on a pool creation i.e. both loanToken and collateralToken have 18 decimal spots. This is not the case for many major tokens which can be expected to be either added as collateral or as a loan tokens like WBTC (8 decimals), USDC (6 decimals) etc. This lack of accountability allows an attacker to drain the funds supplied by the user who set the pool with a minimum investment. The following PoC shows how this can be done by using USDC/WETH as a pool pair where USDC is the loanToken and WETH is the collateral - quite major and widely used combination:
A few notes:
The PoC uses a fork of Ethereum Mainnet
The maxLoan is set to 2*10**18 which is taken from the official Lender.t.sol
test in the repo
The test can be ran with the following command:
The test completes successfully showing how on a pool created by a regular user with 5000 USDC initial loanToken deposit and WETH as collateral, an attacker could borrow all the 5000 USDC with just 0.00000001 WETH (roughly 0.000018$ at todays prices).
Any pools which have a loan token with less than 18 decimals can be drained with almost insignificant collateral provided.
Note: This issue is bi-directional as a pair where the loanToken has 18 decimals and the collateralToken has less than 18 decimals also breaks the core logic of the protocol by producing an extremely high loanRatio
essentially blocking any transaction as the check if (loanRatio > pool.maxLoanRatio) revert RatioTooHigh();
would almost every time cause a revert.
Manual Review / Foundry
Make sure to scale debt and collateral based on the token decimals in order to calculate properly the loanRatio
. This can be easily done by changing the loanRatio calculation as follows:
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.