Strips Finance’s Price Manipulation Vulnerability Explained
Not long ago, the blockchain security team at Amber Group discovered a critical vulnerability in Strips Finance’s perpetual interest rate swap AMM (Automated Market Maker). The vulnerability would allow an attacker to manipulate the fixed market rate and drain funds from the insurance pool and all of the AMMs. At the time of discovery, around $3.5M USDC were at risk. As the vulnerabilities have already been patched and 90 days  have passed since an initial report was handed over to the Strips Finance team, we have elaborated on the details of the vulnerability in this blog post.
To begin, we will cover some background concepts relevant to Strips exchange.
Perpetual Interest Rate Swap Mechanics
Similarly to how typical perpetual futures work, Strips’s perpetual interest rate swap (IRS) allows users to speculate with up to 10x leverage on the future movements of interest rates, like AAVE’s USDC lending yield. However, unlike in a centralized exchange, where your counterparties are other users, your counterparty here is the Strips exchange AMM.
In the Strips exchange, the floating market rate is based on the reference yield, and the fixed rate is based on market supply/demand, with an AMM model used for price discovery. When you have a long position open, you receive a floating rate from the AMM, and pay the entry fixed rate of your position to the AMM. Likewise, for a short position, you pay out a floating rate and receive an entry fixed rate. The more longs there are open in the market, the higher the fixed rate becomes and vice versa.
When a position’s margin falls below the maintenance margin requirement of 5%, anyone can trigger the liquidation engine to force close the position, in exchange for part of the collateral which serves as an incentive to trigger the liquidation.
Profit and Loss
Perpetual IRS profit/loss is calculated as followed:
Funding PnL is the sum of the difference between the floating rate and the fixed rate in each block, and trading PnL is calculated as shown below:
(For longs, opposite for shorts)
If we look closely at the formula of trading PnL, we notice an intuitive pattern:
When the entry rate is constant, a smaller exit rate leads to greater profit or losses. The following graph shows the profit/loss at different exit rates when the entry rate is fixed at 2%.
We can observe that the lower the exit rate, the higher the multiple of profit or losses.
According to this function, we formulated a bold hypothesis: if the fixed rate can be manipulated into a diminutive rate, the profit of a short position becomes substantial. As long as the cost of manipulating the price is lower than the profit, there is room for arbitrage.
To verify the likelihood of success of this attack, we carefully read the source code that was accidentally made public on Github and found that one of the risk control mechanisms limits the net exposure of the AMM:
Each time a user opens a position, the smart contract checks if the notional size of the trade is less than the max notional to ensure that the AMM does not endure too much risk. According to the code snippet above, one can only have positions with at most a total notional size equal to the liquidity plus the unrealized profit of the AMM. At the time, this number was far from enough to feasibly realize this attack, because the size of a short position required to turn the fixed rate into a tiny number would be massive.
Things changed in early April. The Binance BTC funding rate market on the Strips exchange suffered from a premeditated liquidation cascade that resulted in ~$300,000 of bad debt. The team set the fixed rate movement caused by the liquidation to zero to avoid the event from repeating itself. This means that even if a position got liquidated, the fixed rate would NOT change, irrespective of its notional size.
With this update to the liquidation engine, we came up with a new way to bypass the fixed rate range restrictions caused by the risk control mechanism. It can be divided into three steps:
- Open a significant short position with 10x leverage. It needs to be big enough so that the margin ratio will be very close to 5% after opening. (The reason why the margin ratio will not be 10% is that the slippage will cause additional losses)
- Open a small long position that makes the previously opened short position’s margin ratio fall below 5%.
- Liquidate the short position.
The graph on the top shows the rate movement before the change, and on the bottom is after the change.
When calculating max notional, these steps only add a minimal short exposure (Counterparty of step 2) to the AMM’s net exposure. This change is so tiny that it can almost be ignored, but causes the fixed rate to drop due to the short position in step 1. As a trade-off to executing this strategy, we must liquidate our position and sacrifice some collateral.
Through this method, we can decrease the fixed rate while keeping the net exposure of the AMM nearly unchanged. The fixed rate can be made to be even lower by repeating these steps multiple times. To generate profit, we need to have some short positions open before lowering the fixed rate and then close them after lowering it.
We are then faced with another problem, not having enough short positions open to cover the costs incurred in price manipulation. If we simply open a lot of short positions, the net exposure of the AMM will increase, limiting the room for us to manipulate the fixed rates. Here we use a similar trick; after opening a short position, we open a long position of the same notional size, letting the long position offset the short position exposure.
Thanks to bchen from Perpetual Protocol for providing insights on the design of perpetual contracts.
Note that the smart contract of the AMM limits an address to a maximum of one open or close operation per block, so combining the above, we can construct an attack flow with three transactions:
1. Deploy multiple contracts for trade execution and pre-approve USDC for collateral
Deploy ‘subAccountAmount’ amount of trader contracts.
Note: Using EIP1167 (Minimal proxy standard) can save gas consumption when deploying multiple contracts with the same execution logic.
Let trader contracts approve the Strips contract for transferring their USDC to use as collateral.
2. Accumulate a lot of short positions
Here we use consecutive sub-accounts, i.e., trader contracts, to open positions, ‘_pump’ and ‘_dump’ send trade instructions to a sub-account:
Also, because short positions and long positions hedge against the risk of rate fluctuations, the risk exposure of an attacker is minimal even if it is not possible for the attacker to close these positions in the same block.
3. Lower the fixed rate and close the accumulated short positions for profit
We utilize some trader accounts that have not been used yet. First off, ‘_dump’ opens a sizable short position that can be liquidated right after some slight upward rate movement. Then, ‘_pump’ makes the short position’s margin fall below the requirement, so we liquidate the short by running ‘_liquidate’.
Note that due to the design of the Strips AMM, the notional size of each short has to be gradually increased to keep the margin ratio close to 5% after opening them.
Finally, we close the previously accumulated short positions to realize the profit.
Less than 200K USDC would be adequate for accumulating short positions to generate profit, and with the help of flash loans, an attacker doesn’t require a large amount of USDC upfront in order to manipulate the rate. Our PoC simulation results show a profit of $1.6M+ (i.e., 1,872k — 200k) from a single market and the insurance pool:
Timeline and Mitigation
April 23rd — Amber Group contacted the Strips Finance team
April 23rd — The team quickly confirmed the issue and paused the markets for trading
April 27th — The team sent us a $30K bug bounty for helping them find the bug
May 10th — The markets were resumed trading with a short-term mitigation patch applied to Strips v1
Jul 18th — The team announced the end of Strips v1 
At the time of writing, the team is working on upgrading their smart contracts to v2 and have recommended users not to actively interact with the protocol until v2 is released.
The information contained in this post (the “Information”) has been prepared solely for informational purposes, is in summary form, and does not purport to be complete. The Information is not, and is not intended to be, an offer to sell, or a solicitation of an offer to purchase, any securities. The Information does not provide and should not be treated as giving investment advice. The Information does not take into account specific investment objectives, financial situation or the particular needs of any prospective investor. No representation or warranty is made, expressed or implied, with respect to the fairness, correctness, accuracy, reasonableness or completeness of the Information. We do not undertake to update the Information. It should not be regarded by prospective investors as a substitute for the exercise of their own judgment or research. Prospective investors should consult with their own legal, regulatory, tax, business, investment, financial and accounting advisers to the extent that they deem it necessary, and make any investment decisions based upon their own judgment and advice from such advisers as they deem necessary and not upon any view expressed herein.