Skip to content

Latest commit

 

History

History
74 lines (47 loc) · 4.18 KB

File metadata and controls

74 lines (47 loc) · 4.18 KB

Thankful Ivory Mantaray

Medium

Inappropriate Maximum Borrow Rate for Fast Block Times on Sonic Chain

Summary

The accrueInterest function in Mach Finance relies on a constant value borrowRateMaxMantissa to prevent excessively high borrow rates. This value, however, is not adaptable to different blockchains and can lead to potential protocol instability on faster chains like sonic.

Root Cause

In Mach Finance (and Compound v2), the accrueInterest() is the common function which calculates interest accrued from the last checkpointed block up to the current block and writes new checkpoint to storage.

There are lines which fetch the interest rate (borrowRateMantissa) as shown below:

      /* Calculate the current borrow interest rate */
      uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);
      require(borrowRateMantissa <= borrowRateMaxMantissa, "borrow rate is absurdly high");

This borrowRateMantissa is fetched from interestRateModel.getBorrowRate, but the issue here is the check of borrowRateMaxMantissa:

require(borrowRateMantissa <= borrowRateMaxMantissa, "borrow rate is absurdly high");

This check is to make sure the borrow rate fall under the configured borrowRateMaxMantissa

   // Maximum borrow rate that can ever be applied (.0005% / timestamp)
    uint256 internal constant borrowRateMaxMantissa = 0.0005e16;

Most of Mach Finance's configuration is mimicking Compound v2; for example, the above borrowRateMaxMantissa uses the same constant value as in Compound.

The purpose of borrowRateMaxMantissa is to put the protocol in failure mode when absurd utilization causes the borrow rate to become unreasonably high. It is defined as a constant but should really be changed according to the average block time of the chain the protocol is deployed on.

Assuming block time on L1 where Compound v2 is deployed is 12 seconds, we can safely assume, the current borrowRateMaxMantissa value should be 12 times lower.

However, on faster chains like Sonic, which have block times of around 0.3-0.5 seconds, the same rate will result in significantly higher annualized rates, potentially leading to an absurdly high borrow rate that could destabilize the protocol.

Another Compound fork on Optimism, Hundred Finance, uses the correct value 0.00004e16.

Impact

On faster blockchains like Sonic, the current borrowRateMaxMantissa can result in significantly higher annualized borrow rates. This can potentially trigger the "absurdly high" borrow rate check more frequently, causing the protocol to enter a failure state and destabilize.

PoC

Maximum borrow rate that can ever be applied (.0005% / timestamp)

uint256 internal constant borrowRateMaxMantissa = 0.0005e16;

Example for Ethereum Chain (Block Time = 12 Seconds)

For Ethereum, which has an average block time of 12 seconds, the maximum borrow rate per year can be calculated as follows:

Annualized Borrow Rate for Ethereum = 0.0005 * (365 * 24 * 3600) / 12

= 0.0005% × 31,536,000 seconds per year/12 seconds per block

= 1314% annualized borrow rate

Example for Sonic Chain (Block Time ~0.4 Seconds)

Let’s calculate the annualized borrow rate for Sonic chain with an average block time of 0.4 seconds:

Annualized Borrow Rate for Sonic Chain = 0.0005 * (365 * 24 * 3600) / 0.4

= 0.0005% × 31,536,000 seconds per year/0.4 seconds per block

= 39420% annualized borrow rate

This 39420% is obviously much too high. which potentially trigger the "absurdly high" borrow rate check more frequently, causing the protocol to enter a failure state.

Mitigation

Decide on a maximum borrow rate that the protocol is comfortable with and adjust the borrowRateMaxMantissa according to the block time of the chain(sonic).