Boost _ Folks Finance 33533 - [Smart Contract - Critical] depositDatainterestRate is not correct

Submitted on Mon Jul 22 2024 16:32:36 GMT-0400 (Atlantic Standard Time) by @ethprotector for Boost | Folks Finance

Report ID: #33533

Report type: Smart Contract

Report severity: Critical

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

Impacts:

  • Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield

Description

Brief/Intro

In HubPoolLogic.updateInterestRates function depositData.interestRate is not calculated correctly.

Vulnerability Details

function updateInterestRates(HubPoolState.PoolData storage poolData) internal {
        HubPoolState.PoolAmountDataCache memory poolAmountDataCache = getPoolAmountDataCache(poolData);
        uint256 totalDebt = poolAmountDataCache.variableBorrowTotalAmount + poolAmountDataCache.stableBorrowTotalAmount;
        uint256 utilisationRatio = MathUtils.calcUtilisationRatio(totalDebt, poolData.depositData.totalAmount);
        uint32 vr1 = poolData.variableBorrowData.vr1;

        // calculate new interest rates
        uint256 variableBorrowInterestRate = MathUtils.calcVariableBorrowInterestRate(
            poolData.variableBorrowData.vr0,
            vr1,
            poolData.variableBorrowData.vr2,
            utilisationRatio,
            poolData.depositData.optimalUtilisationRatio
        );
        uint256 stableBorrowInterestRate = MathUtils.calcStableBorrowInterestRate(
            vr1,
            poolData.stableBorrowData.sr0,
            poolData.stableBorrowData.sr1,
            poolData.stableBorrowData.sr2,
            poolData.stableBorrowData.sr3,
            utilisationRatio,
            poolData.depositData.optimalUtilisationRatio,
            MathUtils.calcStableDebtToTotalDebtRatio(poolAmountDataCache.stableBorrowTotalAmount, totalDebt),
            poolData.stableBorrowData.optimalStableToTotalDebtRatio
        );
        uint256 depositInterestRate = MathUtils.calcDepositInterestRate(
            utilisationRatio,
            MathUtils.calcOverallBorrowInterestRate(
                poolAmountDataCache.variableBorrowTotalAmount,
                poolAmountDataCache.stableBorrowTotalAmount,
                poolData.variableBorrowData.interestRate,
                poolData.stableBorrowData.averageInterestRate
            ),
            poolData.feeData.retentionRate
        );

        // update interest rates
        poolData.variableBorrowData.interestRate = variableBorrowInterestRate;
        poolData.stableBorrowData.interestRate = stableBorrowInterestRate;
        poolData.depositData.interestRate = depositInterestRate;

        emit InterestRatesUpdated(variableBorrowInterestRate, stableBorrowInterestRate, depositInterestRate);
    }

poolData.variableBorrowData.interestRate is not current value. That is for last updates. So if the attacker uses flashloan, when the tx is complated, depositData.interestRate is changed.

Impact Details

  • Attacker can make the depositData.interestRate more than actual value. So when users (and the attacker) can get more collateral tokens than expected and others loss the money.

  • Attacker can make the depositData.interestRate smaller than actual value and liquidate some loans.

To fix it

use variableBorrowInterestRate instead of poolData.variableBorrowData.interestRate,

Proof of concept

Proof of Concept

In this PoC, I am going to show the first case (make the value more).

Create oracleManager.sol

After a year, the contract is break in the testnet. So I used fixed price oracleManager for this test.

Create FlashloanContract.sol

Test contract

Output

Last updated

Was this helpful?