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

Refinance function doubly deducts the borrowed amount from the new lender pool balance

Summary

Refinance function use is to be called by the borrower to refinance a loan under new lending condition. The function moves the loan partially or totally from one lender or pool to another. The balance of the old pool is increased by debt amount payed back while the balance of the new pool is decreased. There is an error on the accounting where the new pool balance is decreased two times.

Vulnerability Details

1st decrease

2nd decrease

A POC can be made by adding to the Lender test, test_refinance() :

diff --git a/test/Lender.t.sol b/test/Lender.t.sol

@@ -410,8 +410,25 @@ contract LenderTest is Test {
        Refinance[] memory rs = new Refinance[](1);
        rs[0] = r;

+        bytes32 lender2PoolId = keccak256(
+                abi.encode(
+                    address(lender2),
+                    address(loanToken),
+                    address(collateralToken)
+                )
+            );
+
+        (,,,,uint256 poolBalanceBefore,,,,) = lender.pools(lender2PoolId);
+
        lender.refinance(rs);

+        (,,,,uint256 poolBalanceAfter,,,,) = lender.pools(lender2PoolId);
+
+        assertEq(poolBalanceBefore, 1000*10**18);
+        // pool balance after a refinance of 100 tokens should be 900.
+        assertEq(poolBalanceAfter, 800*10**18);
+        // pool balance is being reduced twice
+

Impact

A borrower can keep refinancing on different pools and reducing the poolBalance to zero. This will break the contract internal accounting and will result in loss of funds stuck on the contract, impossible to withdraw by the lender.

Tools Used

Foundry

Recommendations

Remove one of the balance decrements.

diff --git a/src/Lender.sol b/src/Lender.sol

@@ -695,7 +695,6 @@ contract Lender is Ownable {
            // update loan lender
            loans[loanId].lender = pool.lender;
            // update pool balance
-            pools[poolId].poolBalance -= debt;
            emit Borrowed(
                msg.sender,
                pool.lender,

Support

FAQs

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