Spartan is a DeFi protcol for assets running on BSC/BNB. This is mostly the same as the UniswapV2 protocol with some small differences. This is an AMM.
When putting funds into a pool, a user is able to remove (liquidate) these funds. When a user removes these funds, the amount of the funds they are entitled to must be calculated. When taking funds out of the pool, the user must send back LP tokens, which are essentially receipts for putting funds into the pool.
The simple way to do this is returning LP tokens/total LP tokens. This allows them to obtain a total for the underlying assets proportional to what they put in. At this point, the tokens will be burned (destroyed). This math is where the vulnerability occurs at because of bad state handling.
The vulnerability occurs when syncing costs between the reserves and the pools contributions. Since these values are not being updated properly, they were able to exploit the slippage between the two prices. This desync between the amount of total funds and the assets put into the pool makes it possible to take out more funds than expected.
To perform this attack, the following steps have to be done:
- Add liquidity to the pool and get LP tokens back.
- Transfer assets into the pool. This amplifies the amount of assets in the LP token, which allows the attack be possible.
- Remove the liquidity. Since there are more assets (from step 2), we get more liquid returned than what we put in.
- Put the assets into the contract as liquidity then remove it.
- Perform this operation multiple times.
This took me a while to understand. The important nuance here is that asset and liquid are slightly different concepts. Adding assets to the pool would amplify the price of the liquidity in an unfair way. Eventually, when the liquidity was removed, we get some assets back than we put in. Neat!