Even non-coders in Curve community should check out the most recent Curve Brownie Tutorial. The video explores how the TriCrypto pool functions under extreme attempts to hack it. In the process, it makes it a bit easier to understand the mechanics of how the pool behaves.
It’s a good video, and that’s not just my biased opinion!
If you’re like me and hate watching videos, even videos with hosts so uncannily handsome they must be a deepfake, here’s a written redux:
The video searches for an attack vector against TriCrypto by brute force. This helps to show how the pool actually functions in real world circumstances, which is useful because it’s easier to understand experimentally than theoretically. You may not easily comprehend this:
Yet it’s not so tough in practice. The pool likes to be balanced. This may not be immediately obvious because the pool contains volatile assets:
But it’s really simple to multiply by the price of these assets and divide by decimals to see that the pool is usually in a state of balance at any given time.
We can see that USDT, WBTC, and WETH all contain nearly the exact same value of assets at the moment, about $146MM apiece.
The functioning of the pool depends on the capability of the pool to calculate the effective price of these assets. TriCrypto does not rely on an external oracle, instead the fancy math shown in the white paper to deduce the current price. The current balanced state of the pool is according to the internal “price oracle”, which is the pool’s expectation of the current price based on the pool activity.
Enter the distinction between the price_oracle and the price_scale. The price scale can be thought of the actual conditions of the pool. As activity happens in the pool, it pushes in the direction of the oracle price, but lags slightly (as an exponential moving average). We can see the same script as above, but computed using the price_scale instead of the price_oracle, shows a slight imbalance.
At the moment, the scale price of ETH and BTC is a bit higher than the oracle price, so these assets are slightly overweighted. We would expect these to push downwards towards the oracle price as long as profits permit. Within the code, the pool is basically capturing profit where it can. It will spend up to half of this profit moving liquidity around to realize the current price. Moving liquidity costs money, but the contract can calculate how much.
To illustrate this effect, we examine the effect of nuking the pool. Since we’re working with an exponential moving average, one transaction won’t move the price a lot. But we can manipulate the pool’s price by running several transactions in one direction. In the case of the video, we show the effect of depositing $1MM worth of Tether 200 times in a row.
How it started:
How it’s going:
We moved the price of Bitcoin from $46.4K to $52.9K, and all it took was $200 million dollars!
If you look at the before and after balances, you can see the effect in action. At the outset, each asset had about $95MM. Once the pool got flooded with Tether, TriCrypto assumed Bitcoin and Ethereum were the scarce asset, so their price shot up accordingly. We also observe the scale price lagging the oracle price as it pushes in this direction.
We also observe TriCrypto doesn’t take any action to capture profit at this point. The initial balance of BTC ($95,499,776 / $46,410.86 = 2,057.7 BTC) is the same as the balance after the nuke ($108,850,466 / $52,899.02 = 2,057.7 BTC) — the pool’s added to its balance of BTC and ETH only by increasing the oracle price.
At the reverse of the nuke, after $1MM is withdrawn 200 times in a row. The price of BTC and ETH are still drifting upwards ever so slightly, presumably the oracle prices still have upward pressure in adjusting to the prior shock before the downward pressure kicks in, so the final price ends up about level but slightly up. The final balance ($114,003,316 / $55,403.19 = 2057.7 BTC) shows the exact same balance at the end.
Knowing that we can manipulate the price with a lot of money, is it possible to drive up the price and get a quick arbitrage opportunity? We test this out by running both possible directions. The first direction is a lemon:
We drive up the price of the pool, convert a million Tether to 151 ETH, run it back through Sushi, and we lose $516K. Not a surprise, since we made ETH expensive. What about in reverse?
Well, unsurprisingly, the other direction works better. When we get $1MM Tether worth of ETH at Sushi it’s now cheaper, so we get 307 ETH to play with, and converting it to Tether in TriCrypto gets us $1MM.
Easy profit? Well, it cost us $200MM in the first place to nuke the pool to this state. Our bosses won’t be too happy if we spent $200MM to make a million. We try to get our money back out after the fact, but we can’t get it back so easily. When we un-nuke the pool by withdrawing $1MM at a time, we find that at the end of the day we’ve actually lost money.
Maybe this is just a function of the symmetry — we unnuked and nuked exactly 100 times apiece. Perhaps if we adjust the amounts and values of our nukes, we could find a scenario that captures this advantage for ourselves.
Here we create a script to test this possibility. We provide an integrative test, which will vary parameters until it finds a failing condition.
We assert that the pool cannot be arbitraged in this manner, then we vary the parameters and fail the test if we find a set of parameters that successfully make money on the trades. It’s notably slow to run this, of course since there’s hundreds of trials apiece.
Having varied these parameters in several ways, I’ve yet to stumble upon a successful strategy. If I had, you can be sure I’d be arb-ing my way to a rare-looking NFT of a rock, instead of posting my L’s here.
To be clear, there are arb strategies with TriCrypto that work, and other bots or lightning fast traders appear to have hopped right on it. Through the normal course of people interacting with the pool, there’s occasional imbalances that can appear, and opportunities to take profit are short-lived. The arb strategy that’s not working here is the attempt to manipulate the price, arb, and get your money back in one closed circuit loop.
We’d be interested in hearing your ideas for how to break TriCrypto! Now that you understand TriCrypto a bit better, see if you can brainstorm a way to crack it. If you figure a clever strategy and it doesn’t work, we can feature it in a future newsletter. Or run it yourself with the code here: https://github.com/curvefi/brownie-tutorial/tree/main/lesson-18-applications-ii
Or if you share a strategy and it works, we can both retire and enjoy looking at our rock collection!


For more info, check our live market data at https://curvemarketcap.com/ or our subscribe to our daily newsletter at https://curve.substack.com/. Nothing in our newsletter can be construed as financial advice. Author is a Curve maximalist and has a stake in TriCrypto2.