Started at 06:03:11 PM +UTC, Jun-28–2020, the DeFi platform, Balancer, was attacked by exploiting its flawed handling of ERC20 deflationary tokens. Technically, the main logic behind the incident is the incompatibility between Balancer and deflationary tokens, which is then misused by the attacker to create skewed STA/STONK pools states and make profits from that.
This hack consists of four different steps:
- Flashloan Borrow: The bad actor borrowed a flash loan (104,331 WETH) from dYdX.
- STA Depletion: With the borrowed WETH, the bad actor performed a flurry of swaps to deplete almost all STA tokens owned by a Balancer pool. Note that STA is a deflationary token that will charge 1% on every token transfer. The result of STA depletion is that there is only 1e-18 STA left in the pool.
- Exploitation for Profit The bad actor exploited the flawed handling of STA in Balancer and stoled the pool assets approximately valued $523,616.52.
- Flashloan Repay Finally, the bad actor repaid the dYdX flash loan and walked away with the stolen assets.
In the following, we analyze this particular hack as demonstrated in the transaction. http://oko.palkeo.com/0x013be97768b702fe8eccef1a40544d5ecb3c1961ad5f87fee4d16fdc08c78106/).
This step basically takes advantage of the dYdX flashloan feature to borrow 104,331 ETH. This part is already known and we will not go into the details.
In this step, the bad actor performed multiple
swapExactAmountIn() calls within the same transaction to drain the STA balance in the attacked Balancer pool. We notice that
swapExactAmountIn() sets the limit on the swap amount, i.e.,
inRecord.balance * MAX_IN_RATIO. The hacker calculated the limit and swapped the maximum allowed amount of WETH for STA via a flurry of operations as follows:
The result of performing the above swaps is to intentinally left 1e-18 in the Balancer pool:
Consequently, we now have
STA._balance[BPool] as follows:
Due to the fact that the amount of STA in BPool is close to zero, its price relative to other assets is extremely high. Anyone can swap 1 STA for a huge amount of other assets at this moment.
After the previous two steps, this step essentially exploitsed the vulnerability to steal the pool assets.
Specifically, by sending in 1e-18 STA into BPool via
swapExactAmountIn(), the bad actor swapped out 30,347 WETH in the first run. In internal records for book-keeping,
_records[STA] is increased by
tokenAmountIn (i.e., 1) before the BPool contract actually collects the corresponding STA tokens form the
At the bottom of
_pullUnderlying() function collected the STA tokens. However, as mentioned earlier, STA is a deflationary token that charges shown 1% on every token transfer. Because of the transfer fee cut, the Balancer pool (or Pool) actually got zero STA tokens. Therefore, there’s a mismatch between the actual STA balance of BPool and its internal records (i.e.,
To remedy the mismatch, here comes the interesting part. The
gulp() is exploited to reset the
_records[STA], which helps the bad actor to maintain the state that BPool has only 1e-18 STA. Therefore, the bad actor can continue to swap all pool assets out with the extremely valuable 1e-18 STA.
The final step repaid the flashloan back to dYdX.
This incident emphasizes the challenges posed by DeFi composability that may create less obvious incompatibility from deflationary tokens. It also reminds earlier incidents that show the incompatibility from ERC777 tokens. We expect the incompatibility will likely continue to exist and there is no easy solutions.
For this particular incident, on one hand, deflationary tokens (such as STA/STONK) should revert or return
false when the
transferFrom() is less than the charged fee. On the other hand, Balancer may need to always check the balance of BPool after each
transferFrom() call. Nevertheless, there is always a need to find out all corner cases with better coding practices and improved test coverage without making any unnecessary assumption on the expected behaviors of ERC20s, ERC777s, and other DeFi components.
The Balancer hack will likely not be the last incident. In the following, we put together the amount loss of various assets in this incident:
PeckShield Inc. is an industry leading blockchain security company with the goal of elevating the security, privacy, and usability of current blockchain ecosystem. For any business or media inquiries (including the need for smart contract auditing), please contact us at telegram, twitter, or email.