buyLoan()
does not enforce you use one of your own pools as an input parameter. Therefore you could have never created a pool, buyLoan() by inputting another address' pool and successfully buy loan to yourself. The attempts to alter the Pool struct's values do not work as the Struct has not been created yet. The lender is set to msg.sender
, who doesn't have a pool which breaks functionality of several functions which contain this code pattern:
The getPoolId
assumes that the lender has initiated a pool, which is untrue. In this case the function reverts.
This POC proves that you can buy a loan into an address with no pre-existing poolID. The contract address, address(this)
never creates a pool, but ends up as the owner the loan. The POC should be copy/pasted into the lender.t.sol in Beedle folder.
In the //insert transactions here part, you can substitute attempts to repay, giveLoan, refinance etc to verify they are broken. For example, repay reverts due to over/underflow and refinance reverts due to tokenMismatch. Basically every function is broken.
An attacker can purposely buy a loan without poolID so that the borrower can never repay or refinance until the attacker creates a pool. The attacker can wait a long time before creating a pool (creating a pool with accurate specifications can restart functionality), so they can can collect interest over a long period of time, or they can blackmail the borrower.
BuyLoan transfers to a address with a non-existent poolId, which can break multiple Refinance, BuyLoan and GiveLoan, causing to revert or update invalid values
Foundry
Manual Review
Ensure that buyLoan() can only transfer loans to the owner of the input pool. Ensure msg.sender == owner of pool
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.