Beyond the market risk: a logic bug identified in SushiSwap’s KashiPairMediumRiskV1 contract
By BlockSec
On Nov 08, 2022, we detected that some attacks successfully drained assets from pools that are built on top of Sushi’s official KashiPairMediumRiskV1 contract (or some contracts that fork from it). After investigation, we found that the root cause is due to a logic bug that causes the miscalculation of the token prices.
We immediately contacted Sushi’s security team, and they confirmed our findings. The good thing was that they were taking action to protect some valuable but vulnerable pools from being attacked. Besides, they also provided procedures to compensate those that lost funds from the exploit. As such, we now believe it is safe to disclose the details about the vulnerability and the attacks. In this report, we’d like to provide a detailed analysis.
Vulnerability Analysis
After analyzing the source code of the KashiPairMediumRiskV1 contract, we conclude that this bug lies in the borrow
function, which uses the outdated exchangeRate
to verify the borrowed share in the solvent
modifier. Specifically, the verification will be performed based on the current value of exchangeRate
in the _isSolvent
function.
While in the liquidate
function, the updateExchangeRate
function is invoked at the very beginning. Hence the verification and calculation will be performed based on the updated value.
Obviously, this bug could be exploited to lead to a (huge) price difference.
Attack Analysis
We observed two attacks:
- https://etherscan.io/tx/0xcf8f242ea83100b6d43e659f7f53a698d304fc6ac2ca6fe79e3e07ee05fefe58: the victim uses the KashiPairMediumRiskV1 contract, and the loss is around 9,466 USDC.
- https://etherscan.io/tx/0x3d163bfbec5686d428a6d43e45e2626a220cc4fcfac7620c620b82c1f2537c78: the victim is a strategy contract uses CauldronMediumRiskV1 (the fork of KashiPairMediumRiskV1), and the loss is around 110,911 MIM.
Note that, the first attack transaction was launched by a bot which front-runs the original attack transaction: https://etherscan.io/tx/0x7a845d8d2af7919f5b9e22dd5571305cb5347d17986a8402715c1463d515fc18, and the original attacker address is 0xb7ea0f0f8c6df7a61bf024db21bbe85ac5688005.
Here we take the first attack transaction as an example, which consists of the following steps:
- Borrowing a flashloan of 40,900 BADGER and 121,904 USDC from
Balancer
. - Depositing 40,900 BADGER and 113,599 USDC to
BentoBox
. - Invoking the
addCollateral
function of kmBADGER/USDC-LINK to deposit 40,900,000,000,000,000,000,000 shares of BADGER. - Invoking the
addAsset
function of kmBADGER/USDC-LINK to deposit 112,529,000,000 shares of USDC. - Invoking the
borrow
function to borrow 120,755,095,093 shares of USDC. - Invoking the
UpdateExchangeRate
function. - Invoking the
liquidate
function to liquidate itself. - Withdraw 40,899 BADGER and 123,006 USDC from
BentoBox
. - Repaying the flashloan and obtaining a profit of about 9466 USDC.
Note that step 6 is not necessary, because the
borrow
function will invoke theUpdateExchangeRate
function.
The key steps are as follows:
It is not difficult to figure that the value of exchangeRate
used in the borrow
function deviates from the value used in the liquidate
function:
- In the
borrow
function: 250,997,938,545,109,237,740,214,705,193 - In the
liquidate
function: 328,266,883,541,864,569,505,752,156,794
The Impact
There are dozens of pools (on both Ethereum and BSC) that might be affected by this bug. A temporary method to mitigate this issue is to reduce or eliminate the deviation by invoking the UpdateExchangeRate
function occasionally (or periodically). This method has already been adopted by many affected projects and the corresponding transactions can be observed in the wild.