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

`refinance` reduces the pool's balance by the debt twice

Summary

refinance accidentally reduces the new pool balance 2 times instead of one, charging it 2x the debt balance.

Vulnerability Details

refinance as the name suggest refinances a loan, this means it can change a few of it's parameters, like reducing or increasing debt or changing the pool it uses and so on.

The current issue with this function is that it accidentally reduces the balances of the new pool twice once here and twice here. This means that it charges the pool of the lender twice instead of once thus lowering his potential profits, messing up the accounting and lowering the amount he can withdraw from the system.

This can be exploited accidentally when a normal user tries to refinance his loan or maliciously when someone want to cause harm on a given user.

Example:
This is Alice's pool

Preconditions values
Loan : Debt tokens USDC : DAI
Max borrow percentage 60%
Pool balance 1000 USDC
  1. Bob sees this pool, but he does not like Alice (for some reason), so he makes his own pool with the same parameter.

  2. Then Bob takes a loan of 300 USDC and provides 500 DAI.

  3. Bob calls refinance on his loan to move it from his pool to Alice's one.

  4. Now because of how refinance works Bob's pool is 100% sloven so he can withdraw everything.

Lets see how the refinance TX went:
Firstly everything is extracted and then checked, as expected the checks pass (because Bob created the exact same pool as Alice's one). Afterwards Bob pays small fees for his action and his pool becomes solvent again. Now Alice's pool gets charged the new debt

_updatePoolBalance(poolId, pools[poolId].poolBalance - debt);
pools[poolId].outstandingLoans += debt;

After some transfers to make sure everything is up and right the loan is moved to the new pool where the new pool balances are reduced again.

pools[poolId].poolBalance -= debt;
  1. Now because of the double debt removal, Alice's pool recorded balance (pools[poolId].poolBalance) is 400 USDC (600 less), and her collateral is only 500 DAI

Tools Used

Manual review

Recommendations

Deduct the debt from the pool balance only once, and remove the second reduction.

loans[loanId].collateral = collateral;
loans[loanId].interestRate = pool.interestRate;
loans[loanId].startTimestamp = block.timestamp;
loans[loanId].auctionStartTimestamp = type(uint256).max;
loans[loanId].auctionLength = pool.auctionLength;
loans[loanId].lender = pool.lender;
- pools[poolId].poolBalance -= debt; //@audit this is not needed

Support

FAQs

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