Summary
After the Borrower calls the borrow
function the Lender can gamify some very important parameters seconds after what was agreed upon.
Vulnerability Details
This test I wrote shows that after the borrower enters the position the lender can gamefy the parameters as he wishes like increasing fees.
as long as the params respect these two requirements:
if (
p.lender != msg.sender ||
p.minLoanSize == 0 ||
p.maxLoanRatio == 0 ||
p.auctionLength == 0 ||
p.auctionLength > MAX_AUCTION_LENGTH ||
p.interestRate > MAX_INTEREST_RATE
) revert PoolConfig();
if (p.outstandingLoans != pools[poolId].outstandingLoans) revert PoolConfig();
Foundry test proving it.
function test_createPoolAndBorrow() public {
vm.startPrank(lender1);
Pool memory p = Pool({
lender: lender1,
loanToken: address(loanToken),
collateralToken: address(collateralToken),
minLoanSize: 100*10**18,
poolBalance: 1000*10**18,
maxLoanRatio: 2*10**18,
auctionLength: 1 days,
interestRate: 1000,
outstandingLoans: 0
});
bytes32 poolId = lender.setPool(p);
vm.prank(borrower);
Borrow memory b = Borrow({
poolId: poolId,
debt: 100*10**18,
collateral: 100*10**18
});
Borrow[] memory borrows = new Borrow[](1);
borrows[0] = b;
lender.borrow(borrows);
(,,,,,,,,uint256 updatedOutstandingLoans) = lender.pools(poolId);
Pool memory p2 = Pool({
lender: lender1,
loanToken: address(loanToken),
collateralToken: address(collateralToken),
minLoanSize: 100*10**18,
poolBalance: 1000*10**18,
maxLoanRatio: 2*10**18,
auctionLength: 1 days,
interestRate: 1000,
outstandingLoans: updatedOutstandingLoans
});
vm.prank(lender1);
lender.setPool(p2);
}
Impact
Lender can change loan terms right away, leading to unexpected costs for the borrower.
Tools Used
Foundry
Recommendations
Implement additional checks and constraints on parameter changes to prevent the lender from changing things like the fees right after the borrower gets in, the borrower might not even realize the interest is 10X what he thought.