On Sunday, July 31st, the Integral team was alerted to a potential vulnerability within the protocol. We released an update on this last week. There remains no reports of fund loss or harm to liquidity providers. While the team works on implementing a solution, we offer a more detailed description of the vulnerability and a simple way to conceptualize it.
We present several protocol design facts and an illustrative example, to further illustrate a low-level description of the vulnerability, and how it poses potential risk.
- Fact 1 | Liquidity Imbalance & No Zero Case: Given the dynamic ratio, two-asset design of SIZE and FIVE pools, it is possible for nearly all the liquidity in the pool to be swapped to one side, while leaving very little on the other, but it is impossible for there to be zero liquidity on either side.
- Fact 2 | Reversion: On trades, if at settlement time, the amount to be swapped out of the pool totals greater than or equal to the given amount of liquidity for that side of the pool, the protocol will revert the order and the trader’s input funds will return to the trader. This upholds Fact 1.
- Fact 3 | Delayed Execution: The time delay (5, 30 min) of our system serves to protect LPs from arbitrage, as traders cannot predict/guarantee profit that far in the future at settlement time.
As described in our previous blog, a malicious trader, Alice, could take advantage by setting her order submission to purposefully cancel, unless the TWAP settlement price is in her favor. With this information, we can describe what a cancellation would look like.
For this example, consider the ETH<>USDC pool on SIZE. For simplicity, imagine the pair has 1 ETH and 0.1 USDC of liquidity available. Alice wants to swap her USDC into the pool for 1 ETH. The starting spot price of ETH is $1,000 USDC. Alice then submits the trade, and after 29 minutes the external oracle’s TWAP price turns out to be $995, with the market spot price at $990. In this case Alice knows that imminent SIZE settlement price will likely be around $995, compared to $990 for market spot. In this case, it’s in Alice’s interest to intentionally let this order cancel, as she would rather buy 1 ETH at $990 outside SIZE, rather than at $995 inside SIZE settlement.
This happens due to Fact #2 on Reversion (see Protocol Facts). At settlement time, Alice’s trade by default does not pass the pair liquidity check (since there would be exactly 0 ETH left if the trade were processed). Hence her funds will be returned to her.
Alice can repeat this process, allowing her order to “cancel” and revert funds at settlement, until she sees an imminent favorable TWAP price, which she would want to accept. For example if ETH starts at $1,000 (as in the case above), but rather ETH-USDC external oracle TWAP rises to $1,005 after 29 minutes, and market spot price rises to $1,010; then it’s in Alice’s interest to now accept the settlement to buy 1 ETH at $1,005 inside SIZE, rather than let the SIZE swap fall into reversion and buy at $1,010 on the open spot market.
Acceptance: Alice sends a trivial amount of ETH to the underlying SIZE trading pair contract, so that the pool is now a trivial amount larger than the size of her 1 ETH order. If Alice is able to submit this action in time to the Ethereum network, Alice allows her original swap to settle successfully (rather than fade into reversion) as the liquidity check between the swap and the pair is now valid. Hence, in this case, the swap executes with a price in Alice’s favor.
Taking advantage of the pair liquidity requirement and letting the order cancel at last minute gives the trader a systemic arbitrage advantage, because they can with high certainty guarantee themselves profit because they pick only the trade settlements that favor them.
Until the dev team can come up with a solution for this loophole, currently SIZE and FIVE are in withdraw-only mode, as trading and deposits have been paused. We have also paused farming rewards until this issue is fixed. We appreciate the patience of the community through all of this.
Another way to think of this: the trader is playing a coinflip betting game of heads or tails, that costs $1 million worth of crypto to play.
The outcomes are naturally dependent on how market prices naturally move.
The sketch of the game outcomes are as follows for the trader’s POV:
Heads: I get between [$1 million, $1 million + Y] crypto (In my favor)
Tails: I get between [$1 million – maximum slippage, $1 million – Y] crypto (In the LPs’ favor)
Y here is a random variable: representing the distribution of difference between (a) the traders TWAP settlement cost and (b) open market spot settlement cost. (In our example walkthrough above Y would be 5 USDC).
The $1 million cost to play is similar to how a trader would commit their capital upfront on SIZE or FIVE.
Bob, the honest trader, playing this game, in the long run should make $0 profit from this game – parallel to the design of our system. In expectation he should buy/sell at a TWAP price that is reached fairly. The coinflips in this game correspond to the bull/bear — the market’s up/down, for which they happens at some unknowable probability p and (1-p) respectively.
Alice, however, by manipulating the amountOut for the order to fail the liquidity check (Protocol Fact #2) can now be dishonest about her commitments, as it gives her ability to cancel and redo all Tails conflips, so that she eventually is guaranteed to reach the profitable Heads scenario if she plays enough flips, losing minimal transaction costs to back-out and “cancel” each Tail outcome.
If Alice is able to repeat this, it forces the LPs to take the opposite side of advantaged trades and exposes them to potential IL over sustained time. Alice would have to continue to play this game by rotating thru swap directions after each success case (ETH → USDC → ETH → …).
There are a few factors that affect Alice’s ability to accomplish this in-the-wild:
First, the amount that Alice can earn in Y each time is heavily dependent on the market. For example in order for Alice to be profitable there needs to be enough volatility in the market swinging in her favor during settlement TWAP windows.
Second, the cheaper it is to transact on the network (a combination of Ethereum gas prices, Integral Fees, etc), the less costly it would be for Alice and the less volatility she would need.
Lastly, this exploit also requires a malicious trader to commit a significant amount of capital upfront. For example, if there is $1mm worth of USDC and $2mm worth of ETH in the pool, the required funds for this exploit would be $1mm worth of WETH and $2mm worth of USDC. It is also important to note that these funds cannot be sourced from a flash loan due to Integral’s asynchronous design.
In the abundance of caution, as mentioned above, both FIVE and SIZE remain in withdraw-only function to ensure all users funds remain safe while the team works to resolve this issue.
We believe in building products that provide value for traders and uphold fairness to LPs. The team has always taken bug bounty submission seriously and we are working very hard to come up with a correct solution to this vulnerability and improve the product with usability in mind. At the moment, all the developers are working towards a fix, and we will update you soon on the progress.