May 29 Incident Report

Belt Finance
Belt Finance
Published in
11 min readMay 30, 2021

Introduction

We here at Belt.fi hold the trust of our users with utmost importance. Belt is a service with over $2 billion in TVL and tens of thousands of users, of which every single user is important to us. While we maintain our vigilance with periodic audits and safeguards, an attack took place today with pinpoint accuracy with a method that we failed to safeguard against. We apologize for the inconvenience and distress this may have caused amongst our users, and with a heavy heart, explain what happened.

On May 29, 2021, a flash loan attack was initiated on the BSC 4Belt (USDT/USDC/BUSD/DAI) pool. The attacker created a smart contract that used PancakeSwap for flash loans and exploited our beltBUSD pool and its underlying strategy protocols and then proceeded to execute the contract 8 times for a total profit of 6,234,753 BUSD. beltBUSD vault users suffered a 21.36% loss of funds, while 4Belt pool users suffered a 5.51% loss of funds. No other pools/vaults were affected.

We paused withdrawals and deposits as soon as we were aware of the attack to prevent further losses and protect our users and their assets. While we are aware that this may cause our users inconvenience, it was done to prevent the same exploit from attacking our other vaults/pools. All other pools/vaults and all funds remain unaffected and safe from this attack, and we have now patched the attack vector that allowed this exploit of 4Belt and beltBUSD.

As our contracts are time-locked, withdrawals & deposits of funds will resume within the next 24–48 hours. Rest assured that your funds are safe, and we are devising a compensation plan that will be released within the next 48 hours.

This is an in-depth analysis to notify our users of the nature of the attack, the methods used, and the measures that we have taken to prevent similar exploits.

Overview

This is a high level overview of the process of attack, our previous prevention measures, our new solution, and what will happen going forwards. A detailed breakdown of everything, including the exact transactions, is given after this overview.

The Exploit

Starting on May 29, 2021, at 19:23:28 UTC, the attacker used a smart contract to start executing flash loan attacks on the 4Belt BLP Pool.

The attacker acquired a flash loan of around 390 million BUSD from PancakeSwap for the exploit, which is close to the maximum amount of BUSD that could be garnered from all pools with BUSD on PancakeSwap. The attacker then deposited around 200 million BUSD of it into the beltBUSD vault (with Venus as the strategy protocol) so the ratio between strategies was shifted heavily towards Venus. Before the attack, the beltBUSD vault had a ratio split of around 60M BUSD in Venus, 60M BUSD in Alpaca, 60M BUSD in Ellipsis, and 20M BUSD in ForTube for a total of about 200M BUSD. The attacker’s deposit made it so that the Venus strategy had around 260M BUSD, so the total of beltBUSD was around 400M.

The attacker’s contract simultaneously moved 190M BUSD to the Ellipsis.fi 3pool to exchange 190M BUSD to around 169.5M USDT. This swap resulted in a significant increase of the value of Ellipsis 3pool LP. The 3pool LP supply change did not change but this $21.5M difference went to increase the value of the 3pool LP by around 3%. This in turn increased the value of the Ellipsis strategy of the 4Belt pool 3% from 60M BUSD to 61.8M BUSD, raising the whole beltBUSD vault from 400M BUSD to 401.8M BUSD (a 0.5% gain).

The attacker then withdrew from the beltBUSD vault for a gain of around 0.5% on their 200M BUSD deposit, or about 1M BUSD (201M BUSD withdrawn from a 200M BUSD deposit). The attacker then swapped back the USDT to BUSD on Ellipsis, returning the LP to its previous value, and thus left the beltBUSD vault with a 1M BUSD loss.

The attacker’s smart contract then repeated this cycle multiple times in this same transaction (as much the Tx gas limit maximum allowed), covering the flash loan fee and Ellipsis swap fees to eventually leave a profit. The attacker then took the BUSD profit to their address and swapped it to anyETH before using the Nerve Bridge to send their anyETH to the Ethereum Mainnet.

This exploit transaction, starting from the PancakeSwap flashloan and ending with sending anyETH to the Ethereum mainnet, was repeated 8 times.

Previous Prevention Measures and Where they were Overcome

We had a function as a prevention measure for flashloan exploits due to LP value changes with our Ellipsis strategy as it has an AMM feature allowing for gaps in token prices. Our function checked whether the pool was “healthy” before depositing or withdrawing. If there were abnormalities in the Ellipsis pool ratio, transactions to and from that pool would be reverted. This prevented the Ellipsis strategy itself from being exploited.

We did not respond to Ellipsis strategy changes affecting the deposit and withdrawals from other strategies in the multi-strategy vault, as this function is related to a direct read relationship with the Ellipsis pool, flash loan attacks based around its impact to deposits/withdrawals to other vaults were not expected. As the attack happened with two vectors, Ellipsis LP price manipulation and large deposits/withdrawals from other beltBUSD strategies, this gap was exploited.

The attack was intricately executed in having its contract include these two attack vectors working with each other to not have the attack transaction revert with consideration of the complexity of our multi-strategy vaults. The attack repeatedly moved around 200M BUSD to get off with around 1M BUSD with calculations of price impact and sizes of liquidity and withdrawals.

Our Solution

In the case of the StrategyEllipsis, the isPoolSafe() is used to limit withdrawal in case of price gaps. Now, for all strategies, we check the status of the Ellipsis swap to solve the problem by limiting users’ withdrawal and deposits when there is a discrepancy between USDC, BUSD, and USDT. This makes it so that there can be no more exploits through manipulating Ellipsis LP prices. More details are explained below.

What happens now

We are very much committed to keeping our service secure and profitable for our users. As such, we are currently in the process of patching the exploited points, as well as consulting the services we work with to ensure this will not happen again. We are also re-visiting every vault we offer to make sure they are not exposed to similar methods of exploitation.

We have requisitioned for additional audits for our contracts, in addition to reviewing them ourselves.

At the moment, withdrawals and deposits are disabled to ensure no more damage can occur. We apologize for the inconvenience caused by this, but we are making sure the vaults are secure and free from risks prior to opening them. We expect the withdrawals and deposits to resume within the next 48 hours.

Through this turbulent time, we thank those who stand by us for their continued support. Whether you are a BELT holder, or someone who uses our vaults, we wish to make sure that this incident will not affect you negatively. We are currently working to create a fair and comprehensive compensation plan for those affected with a snapshot of the accounts that were affected by this attack. We will release a compensation plan within the next 48 hours, a time frame necessary for us to get and go through all the logs to see exactly which users need to get compensated.

Our compensation plan, while in the works, will try to effectively address and right any wrongs made to our beloved users. We understand that trust is what makes or breaks a protocol, and will do everything in our power to restore and retain the trust users have put in us.

Detailed Breakdown and Analysis of Events

In the process of development, we added the following function as a safeguard against attacks when the value of the Ellipsis Pool was unsafe.

The isPoolSafe function works to check the health of the Ellipsis 3pool by measuring the ratio of its tokens (which it contains the most of, and least of). This function works to prevent StableSwap AMMs with unnatural ratios from affecting Belt.

isPoolSafe function acts prior to, and after _deposit(), _withdraw() functions to check pool health, and if the pool ratio is skewed, the transaction reverts to prevent any statement update. This was to act as a preventative measure against a flash loan attack on our Ellipsis strategy.

By using Ellipsis’ swap, it is possible to momentarily manipulate the ratio of BUSD, USDC, and USDT in the ellipsisSwap contract, and through this it is possible to manipulate the price of 3pool LP.

We did not respond when the epsToWant() that the MultiToken function that calculates Ellipsis strategy’s wantTotalLocked() Ellipsis 3Pool ratio was broken and affected other strategies’ deposits and withdrawal. As this function is an interface related to Read, we did not expect a direct relation to flash loans.

As a result, the flash loan caused the wantTotalLocked value in the Ellipsis strategy to increase and MultiVault ran a withdrawal with a higher value than the actual asset volume. This was the root of the exploit.

The attacker exploited this gap.

Here is the process of the 8 transactions.

Details of the exploit transaction on 19:23:28 UTC are as follows:

https://bscscan.com/tx/0xf598e092ab82ce08798f9dab7ea6ade64f152aa91db897f3449b23ab591baa1d

[ Transaction start ]

* The exploiter secured funds on PancakeSwap (PCS) to stage and carry out the flash loan attack (hereafter termed “flashed”, the whole sequence was done within one, single transaction)

- Flashed 107,956,994 BUSD from PCS BNB/BUSD

- Flashed 38,593,199 BUSD from PCS USDC/BUSD

- Flashed 155,203,983 BUSD from PCS USDT/BUSD

- Flashed 31,676,534 BUSD from PCS DAI/BUSD

- Flashed 17,698,988 BUSD from PCS UST/BUSD

- Flashed 17,481,089 BUSD from PCS VAI/BUSD

- Flashed 10,975,178 BUSD from PCS ALPACA/BUSD

- Flashed 10,793,357 BUSD from PCS CAKE/BUSD

* A total of 390,379,325.49927646 BUSD was flashed from PCS

* 200,379,325 BUSD moved to 235,391,847 beltBUSD mint. (selected strategy : bVenusStrategy)

* 190,000,000 BUSD moved to Ellipsis.fi 3pool to exchange 190,000,000 BUSD to 168,535,055 USDT

>> This swap resulted in an approximate 3% increase of LP value of 3pool on Ellipsis.fi

* Withdrew (burn) 235,391,847 beltBUSD and get 201,383,385 BUSD (selected strategy : bVenusStrategy, getting an extra 1,004,060 BUSD)

* Exchanged 168,535,055 USDT to 189,339,377 BUSD on the Ellipsis.fi 3pool

* 200,722,763 BUSD to 237,006,836 beltBUSD mint (selected strategy : bVenusStrategy)

* Exchanged 190,000,000 BUSD to 168,501,231 USDT on the Ellipsis.fi 3pool

* Withdrew (burn) 237,006,836 beltBUSD to 201,731,704 BUSD (selected strategy : bVenusStrategy, getting an extra 1,008,941 BUSD)

* Exchanged 168,501,231 USDT to 189,338,762 BUSD on the Ellipsis.fi 3pool

* 201,070,467 BUSD to 238,649,866 beltBUSD mint (selected strategy : bVenusStrategy)

* Exchanged 190,000,000 BUSD to 168,467,410 USDT on the Ellipsis.fi 3pool

* Withdrew (burn) 238,649,866 beltBUSD to 202,084,332 BUSD (selected strategy : bVenusStrategy, getting an extra 1,013,865 BUSD)

* Exchanged 168,467,410 USDT to 189,338,149 BUSD on the Ellipsis.fi 3pool

* 201,422,482 BUSD to 240,321,619 beltBUSD mint (selected strategy : bVenusStrategy)

* Exchanged 190,000,000 BUSD to 168,433,591 USDT on the Ellipsis.fi 3pool

* Withdrew (burn) 240,321,619 beltBUSD to 202,441,315 BUSD (selected strategy : bVenusStrategy, getting an extra 1,018,833 BUSD)

* Exchanged 168,433,591 USDT to 189,337,538 BUSD on the Ellipsis.fi 3pool

* 201,778,854 BUSD to 242,022,800 beltBUSD mint (selected strategy : bVenusStrategy)

* Exchanged 190,000,000 BUSD to 168,399,774 USDT on the Ellipsis.fi 3pool

* Withdrew (burn) 242,022,800 beltBUSD to 202,802,701 BUSD (selected strategy : bVenusStrategy, getting an extra 1,023,847 BUSD)

* Exchanged 168,399,774 USDT to 189,336,930 BUSD on the Ellipsis.fi 3pool

* 202,139,632 BUSD to 243,754,134 beltBUSD mint (selected strategy : bVenusStrategy)

* Exchanged 190,000,000 BUSD to 168,365,959 USDT on the Ellipsis.fi 3pool

* Withdrew (burn) 243,754,134 beltBUSD to 203,168,537 BUSD (selected strategy : bVenusStrategy, getting an 1,028,905 BUSD)

* Exchanged 168,365,959 USDT to 189,336,324 BUSD on the Ellipsis.fi 3pool

* 202,504,862 BUSD to 245,516,374 beltBUSD mint (selected strategy : bVenusStrategy)

* Exchanged 190,000,000 BUSD to 168,332,147 USDT on the Ellipsis.fi 3pool

* Withdrew (burn) 245,516,374 beltBUSD to 203,538,872 BUSD (selected strategy : bVenusStrategy, getting an extra 1,034,010 BUSD)

* Exchanged 168,332,147 USDT to 189,335,720 BUSD on the Ellipsis.fi 3pool

(* A total loss of 7,132,461 USD was incurred to the protocol through the 7 step trade listed above)

* Flash Loan Repayment

- Repaid 10,825,835 BUSD on PCS CAKE/BUSD

- Repaid 11,008,203 BUSD on PCS ALPACA/BUSD

- Repaid 17,533,690 BUSD on PCS VAI/BUSD

- Repaid 17,752,245 BUSD on PCS UST/BUSD

- Repaid 31,771,849 BUSD on PCS DAI/BUSD

- Repaid 155,670,996 BUSD on PCS USDT/BUSD

- Repaid 38,709,327 BUSD on PCS USDC/BUSD

- Repaid 108,281,840 BUSD on PCS BNB/BUSD

* Transfer 1,320,605 BUSD to exploiter’s address

[ Transaction end ]

A total of 8 transactions were performed in an identical manner as above.

https://bscscan.com/tx/0x50b0c05dd326022cae774623e5db17d8edbc41b4f064a3bcae105f69492ceadc

https://bscscan.com/tx/0xc4d4156aab1fca85c99e85352b836274d3c53bafe98a2c9867b68950e1eafde9

https://bscscan.com/tx/0xb57acfeab13d52664416aa2ada9b490e340292731fced049fc8c4a730b7af700

https://bscscan.com/tx/0xcca1ebf01e694bb4c447f6018eebb34a3b829cff9ea1ec5fce236eb3cc2ef99c

https://bscscan.com/tx/0x7719e1bae25dbe80539edea37c962e941ec4141145e6eabe63540b7178ffd0d0

https://bscscan.com/tx/0xd790026feda9a16646647e9df0779dc4a7b173053369847691b8f3f678da1f66

https://bscscan.com/tx/0xf598e092ab82ce08798f9dab7ea6ade64f152aa91db897f3449b23ab591baa1d

https://bscscan.com/tx/0x7b3b727a56d1649ee325c42416a1199f4a9b4f4eb024a60b5848a7b1485953b1

Through the above transactions, the attacker caused a total loss of 50,030,452 BUSD to the beltBUSD pool, and used 43,795,699 BUSD as fees for PCS, Venus and Ellipsis. The attacker ultimately withdrew 6,234,753 BUSD to their wallet.

As a result of this attack, the price of beltBUSD price declined from 1.018262 to 0.800687, a loss of 21.36% to the deposits in the beltBUSD vault.

4Belt LP price declined from 1.017904 to 0.961767, a 5.51% loss to the 4Belt LP holders.

To rectify this, instead of calling on isPoolSafe() function only on withdrawals and deposits, we made modifications to the code to call upon isPoolSafe() while measuring the value of the assets within the protocols.

Here are the commit hashes for our solution: https://github.com/BeltFi/belt-contract/commit/d08d73d160d07e10ac47acbaa624ab7844160907

Now for all of our strategies, we check the ratio of the Ellipsis 3pool LP and limit all withdrawals and deposits to the multitoken vaults when a price difference occurs. We amended the code to allow the usage of isPoolSafe with a read function, and added a require() statement to isPoolSafe so that read/write can be reverted with the call of isPoolSafe.

We made it so that when wantLockedTotal is calculated, the eps3ToWant function calls the isPoolSafe() function and so the read is reverted when there are abnormalities.

For a more conservative response, we have changed the standards for our health check of the maximum Ellipsis 3Pool ratio change to be 5x lower than it was before. To read a more accurate quantity we are directly interacting with the balances interface given by StableSwap.

[BEFORE]

safetyCoeffNumer 10

safetyCoeffDenom 1

[AFTER]

safetyCoeffNumber 10

safetyCoeffDenom 2

--

--

Belt Finance
Belt Finance

Belt.fi is an AMM protocol that incorporates multi-strategy yield optimizing on Binance Smart Chain (BSC)