The Spartan Incident: Root Cause Analysis

Started at 04:38:39 PM +UTC, May 1, 2021, the Spartan protocol contract was exploited to result in more than $30M loss. The incident was due to a flawed liquidity share calculation in the protocol, which is exploited to drain assets from the pool. In this blog post, we elaborate the technical details of the issue.

Summary

This incident was due to a flawed logic in calculating the liquidity share when the pool token is burned to withdraw the underlying assets. In particular, the specific hack inflates the asset balance of the pool before burning the same amount of pool tokens to claim an unnecessarily large amount of underlying assets. The consequence of this attack results in more than $30M loss from the affected pool.

Details

In the following, we analyze this specific attack as demonstrated in the transaction of 0xb64a…3af8. The attack involves a number of operations to prepare the vulnerable pool, and then manipulate it to drain funds. In the following, we show below essential steps:

  1. It borrows a flashloan from PancakeSwap with 100K WBNB, which will be returned at the last step with 260 WBNB as the flashloan fee;
  2. It swaps WBNB to SPARTAN five times through the exploited Spartan pool, with each time swapping in 1,913.172376149853767216 WBNB to get 621,865.037751148871481851 SPARTA, 555,430.671213257613862228 SPARTA, 499,085.759047974016386321 SPARTA, 450,888.746328171070956525 SPARTA, and 409,342.991760515634291439 SPARTA respectively. The resulting total 2,536,613.206101067206978364 SPARTA, plus 11,853.332738790033677468 WBNB, are then added into the pool, minting 933,350.959891510782264802 pool token (SPT1-WBNB);
  3. Similarly, it swaps WBNB to SPARTAN ten times through the same pool, with each time swapping in 1,674.025829131122046314 WBNB to get 336,553.226646584413691711 SPARTA, 316,580.407937459884368081 SPARTA, 298,333.47575083824346321 SPARTA, 281,619.23694472865873995 SPARTA, 266,270.782888292437349121 SPARTA, 252,143.313661963544185874 SPARTA, 239,110.715943602161587616 SPARTA, 227,062.743086833745362627 SPARTA, 215,902.679301559370989883 SPARTA, and 205,545.395265586231012643 SPARTA respectively, resulting in total 2,639,121.977427448690750716 SPARTA.
  4. It inflates the asset balance in the pool by transferring into the pool 21,632.147355962694186481 WBNB and all SPARTA from the above step 3, i.e., 2,639,121.977427448690750716 SPARTA.
  5. It burns the 933,350.959891510782264802 pool tokens obtained from step 2 to withdraw the liquidity. Since the pool’s asset balance is inflated, the burn operation leads to 2,538,199.153113548855179986 SPARTA and 20,694.059368262615067224 WBNB. Note that step 2 only deposits 11,853.332738790033677468 WBNB, leading to the profit of about 9K WBNB.
  6. It adds the liquidity into the pool with the added assets in step 4 with 1,414,010.159908048805295494 pool token, which is immediately burned to obtain 2,643,882.074112804607308497 SPARTA and 21,555.69728926154636986 WBNB.
  7. It repeats the above steps to continue draining funds from the pool.
  8. It returns the flashloan with 100,260 WBNB.

The vulnerability stems from the fact that the liquidity share calculation calcLiquidityShare() is querying the current balance which can then be inflated for manipulation. A correct calculation needs to make use of cached balance in baseAmountPooled/tokenAmountPooled.

This attack leads to more than $30M loss from the pool. And most of the attacker’s funds from the above exploitations are currently held in this wallet: 0x3b6e. We are actively monitoring this wallet for any movement.

About Us

PeckShield Inc. is an industry leading blockchain security company with the goal of elevating the security, privacy, and usability of the current blockchain ecosystem. For any business or media inquiries (including the need for smart contract auditing), please contact us at telegram, twitter, or email.