Boost _ Folks Finance 33694 - [Smart Contract - Medium] stableBorrowRates are manipulatable through

Submitted on Fri Jul 26 2024 15:07:59 GMT-0400 (Atlantic Standard Time) by @A2Security for Boost | Folks Finance

Report ID: #33694

Report type: Smart Contract

Report severity: Medium

Target: https://testnet.snowtrace.io/address/0xa9491a1f4f058832e5742b76eE3f1F1fD7bb6837

Impacts:

  • Protocol insolvency

Description

Title

Description

We are going to focus on the simplest path. When a user wants to create a stable loan, he automatically recieves the stableInterestRate of the pool

    function initLoanBorrowInterests(
        LoanManagerState.UserLoanBorrow storage loanBorrow,
        DataTypes.UpdateUserLoanBorrowParams memory params,
        bool isStable
    ) private {
        if (isStable) {
            loanBorrow.lastInterestIndex = MathUtils.ONE_18_DP;
@>            loanBorrow.stableInterestRate = params.poolStableInterestRate;
            loanBorrow.lastStableUpdateTimestamp = block.timestamp;
        } else {
            loanBorrow.lastInterestIndex = params.poolVariableInterestIndex;
            loanBorrow.stableInterestRate = 0;
            loanBorrow.lastStableUpdateTimestamp = 0;
        }
    }

The stableInterestRate is set to the pool stable interest rate. see prepareForBorrow()

This value is only updated when the function HubPoolLogic.updateInterestRates() is called generally at the end of each transaction that changes the state of a pool. For the example that is interesting for us it is called at the end of updateWithDeposi()

The stable rate is calculated using the curent utilization rate, which could be lowered simply through depositing large amounts of collateral or inflated by increasing debt (this could be used to force stable borrower to pay more rates by calling rebalanceUp() after attack to gain more yield as depositors)

As we can see the new calculation relays heavily on the current utilization ratio that relies on current total deposited amounts. This opens up the attack vectors for users to manipulating the utilization through large deposits right before locking themselves into a stable position

please also note, the attackers could also simply manipulate the borrowrate to near the rebalanceUpThreshold or rebalanceDownThreshold so no one could call it and even if position get's rebalanced. Attackers could repeat same attack to get the desired lower borrow rate.

Impact

We have found two major impacts, that caused by either manipulating rates up or down:

  • Attackers could manipulate the stable borrow rate, to pay less interest rates which leads to a loss of yield for the protocol and the liquidity providers (lenders) and allow lenders to borrow at a disavantageous rate then the current market conditions

  • Attackers could flashloan assets then borrow a large percentage, use the inflated stableRate to call rebalanceUp() on stableborrows, to force borrowers into inflated rates. This could be abused if the attacker has enough liquidity there to benefit from increase yield

Recomendation

To mitigate this issue, similar protocols that offer both variable and stable rates rely on time averaged total deposits + total debts in order to calculate the stable rates. Another possible fix is to block same block deposits and withdrawals, this however wouldn't protect against the case when the liquidity used for the manipulation is bootstrapped by a whale account

Proof of concept

Proof Of Concept

We have provide a coded proof of concept for the first scenario, the second scenario is also the same because it has same root cause (stable rate calculation relies on spot data, which is manipulatable through flash actions) The attacker wants to borrow USDC at a lowered intersest rate:

• Attacker prepares a large amount of collateral tokens for his intended borrow

• Attacker takes out a flash loan for USDC (or simply an amount he have if he is a whale) and deposit it to the usdc hubpool (in the hub chain so it can be in same transaction)

• This deposit into the lending pool, artificially lowers the utilization ratio, and as a consequence lowers the stable borrow rate

• Immediately after depositing, attacker takes out a stable rate loan, locking in the artificially low interest rate

• Attacker repays the flash loan

• Attacker now has a stable rate loan at a much lower interest rate than should be available based on true utilization

• Attacker can repeat this process to continually refinance at artificially low rates (if after some time he gets rebalanced)

For the coded Poc, please follow the following steps: first create the first file: test/pocs/base_test.sol

then please add the file that includes the poc to test/pocs/manipulateStableRatePoC.sol

to execute the poc, please run forge test --mt test_ManipulateStableBorrowRateThrough -vvv This is the expected result, after running the poc, in a terminal

Last updated

Was this helpful?