Gas is Dead or Why Avalanche Can Get The Price of Anything For Almost Nothing
Hello there, long time no post. Been too busy prepping Prospero to have its day in the Barcelona sun (…er, rain) at the upcoming Avalanche summit.
What’s that? Why yes, we are raising our pre-seed and it’s filling up fast. You want to see our deck, sizzle video, and demo? Sure thing! Just email my co-founder firstname.lastname@example.org. Thanks for asking!
Now in case you need a quick refresher, Prospero is an upcoming dApp on Avalanche that empowers anybody with Web 3 access to launch an investment portfolio or join top performing investment portfolios.
With our handy dandy portfolio rebalancer interface, managers can select the tokens they want, then multiswap one or many tokens into their desired portfolio allocations (the interface below is just our in-house beta interface, our fresh new intuitive UI is coming soon).
So practically speaking, what does this mean? On Prospero, Sanjit the valedictorian from Mumbai can manage a portfolio, distinguish himself as an elite trader on our blockchain-accounted leaderboard, and attract investors from all around the world…
…including millions of folks like my mom in Glendale who “wants to invest in Bitcoinchain but wouldn’t know where to begin.”
Additionally, my mom (and all other investors) can join multiple portfolios, diversifying their positions across varying strategies. She only pays fees on her profits and never pays gas for trades (that’s the portfolio manager’s responsibility) and only she can make deposits or withdrawals from her own account.
I have to admit, coding all of this was hands down the hardest ultramarathon I’ve ever run (and I’ve logged some serious road miles). Especially because I didn’t code Solidity and have never worked on Avalanche until about a year ago (for a lil post about my developer’s journey into Avalanche, click here).
There were countless uphill battles I faced while building Prospero’s backend. How do I create portfolios where the manager can rebalance but only their investors can withdraw or deposit funds? Collective pools like Uniswap without the LP tokens.
How do I keep gas low when Prospero is calling 60 swaps at a time for a portfolio rebalance? Building a multi-AMM route optimizer on chain and staying up until 3 for weeks on end optimizing our contracts.
And then there’s the one my stubborn co-founder foisted on me: on Prospero, portfolio managers need as many tradeable tokens as possible in order to maximize that sweet undiscovered alpha,… which means in order to build our portfolio rebalancer tool we needed access to prices for all those tokens on chain in a gas efficient way.
This means I had to stay away from using the gas expensive SSTORE or SLOAD operations for any kind of price caching (but we do cache a lot of the prices in other code in memory arrays). Solving this riddle was a slog… so I wrote this Medium post to share my process AND my github to help the Avalanche DeFi community never go through it.
To demonstrate why we needed this, imagine a manager wants to rebalance a portfolio of Eth, Btc and Wavax into a mix of 11 tokens:
In order for our multiswap tool to allocate the assets into the manager’s desired portfolio percentage balance, our first step is to get the price of all these tokens in USD.
At first I thought this would be impossible on chain and told my co-founder as much. In particular, I had heard of Chainlink but I figured that to request the price would be cost prohibitive in gas for whole buckets of tokens all at once.
However, my co-founder implored me to keep building and asserted that market incentives would force the necessary innovations to drive price down. In his words: “Otherwise Web 3 was already DOA and there were too many gigabrains working in the field, specifically at Ava Labs, for that to be the case.”
He’s annoying when he’s right.
Apricot slashed fees on Avalanche, EIP-1559 went down on Ethereum, and Chainlink released their price feeds for basically free. My co-founder gloated a bit, but I explained to him that while this was progress, we still needed prices for almost any token on the C-chain not just the price feeds Chainlink published. He told me he had every confidence I’d figure it out.
Did I mention that he’s annoying when he’s right?
My starting point: I knew the price of many tokens would be inherent in the pools in Pangolin, especially the ones with high liquidity. Why? These tokens are constantly being arbitraged by bots against prices on other exchanges.
By combining pricing information from the Pangolin pools and multiplying them against Chainlink price feeds for common tokens, I built a solution (available on Github) to get and confirm the price for almost any token (except reflection tokens, they suck goat horn) on the C-Chain within ~1% accuracy with Coingecko prices (when their API is working).
This is how our contract works:
- First, check if the token has a liquidity pool with the most popular tokens on Pangolin such as WAVAX, Ethereum and USDC that have Chainlink feeds.
- If it does, make sure the liquidity in these pools is sufficient.
- Then you can use the pricing information inherent in the pool (aka this much of x = this much of y) to estimate the price by multiplying by the known Chainlink price of Wavax, Ethereum or USDC against the liquidity in these pools.
I named this function in the ProsperoPrices contract getPrice.
But now as I read back over what I just wrote, I realize that my description might have been more chaotically abstract than Kanye’s last album, so let’s take a gander at a specific example:
Early on, I chose to test with a lesser known token called Arable Protocol that has no Chainlink price feed but that does have a pool on Pangolin with WAVAX.
Because we know 1 WAVAX is worth 902 acre on Pangolin (at the time I started writing this piece) and we know the price of WAVAX to be $71.5589546157 (well it was then, but not anymore. Go Red Coin, Go!), we know Arable’s price to be $71.5589546157 divided by 902 = $0.07933365257. Fairly simple, right?
Now let’s use it again for a different example where liquidity is low to see what happens. This time we’ll be using the Mint token. Let’s watch getPrice at work–
In the code above we’re iteratively searching to see if a liquidity pool exists for Mint token paired to either AVAX, USDC or ETH. It just so happens that it does with WAVAX (wrapped AVAX, hence essentially the same price as AVAX):
The price of WAVAX is determined to be 7035747962 by the Chainlink price oracle. Chainlink uses 8 decimals worth of scale, 7035747962/10⁸=$70. (Side note: we have to do all of this gnarly math because Solidity is not so hot at representing decimals. Did I mention I was up until 3 for a month? And that I have children? My wife is a living saint). Prospero then gets the current liquidity in Pangolin calling getReserves which will return the amount of the two tokens in the pool, which right now is: 1355194027467537473967 Mint and 2877608273236697193 WAVAX.
For non-coders, no, this pool is not worth a quadrillion zillion dollars in AVAX. Remember, these tokens are both represented with 18 decimals so by dividing by 10¹⁸ you get 1335 Mint and 2.8 WAVAX. After considering these far more reasonable figures, it begs the question, do we really want to use this pool as a reference point for a price?
To be honest, probably not. The liquidity is too low — if we try to swap with a pool with low liquidity the swap will not go through if your swap is bigger than the pool. Also, low liquidity pools are often not being arbitraged enough to give accurate prices.
Because of this, I programmed Prospero with a function that blocks individual token trades that will trigger slippage disruptive enough to cascade through our multiswap tool into imbalancing portfolios different than what the manager wanted… but obviosuly that gets complicated and we’ll save that migraine-inducing post for another day.
But let’s say you’re an insatiably curious Avalanche dev (like me) and just want to take the ProsperoPrices contract for a spin and don’t care about the necessary liquidity. You can change the amount of liquidity you are comfortable with by changing the MINIMUM_LIQUIDITY_REQUIRED amount in the contract. Want access to even more prices? Just add more helper tokens to the getHelper function like DAI or BTC.
Now all of this is merely academic and not practically useful in the slightest if the prices we end up with aren’t accurate. So we checked our prices against Coingeecko’s API. The sample we used were the top 150 tokens by total USD volume which we fetched using The Graph which is a nifty tool that can query analytics about Pangolin like so:
Running these top 150 tokens against Coingecko’s API we were able to get decently accurate results which can be found here. Again, we didn’t use Chainlink directly to arrive at these numbers: all the figures presented are reflective of the ProsperoPrices method of Pangolin ratio of (desired token : AVAX/USDC/ETH) x Chainlink price for AVAX/USDC/ETH.
And for our final step, we also measured gas costs because, again, I’m not a professor proving theories, I’m a dev building a dApp I want the entire planet and future Muskian Martian colonists to use. Thanks to Apricot (and my countless hours of gas optimization) we discovered that the gas costs for our ProsperoPrices method are pretty close to what you would pay for using the Chainlink price feeds on chain.
So there you have it: the tip of the iceberg of the code we have under the hood at Prospero. After a year of pandemic keyboard clacking in my basement garage, I’m keen to emerge into the light and share plenty with the community in the weeks ahead.
If you’re attending the Avalanche Summit and want to learn more about Prospero’s Fair Open Access Market (FOAM) for Web 3-powered investing, find my co-founder Brendan and let him buy you a sangria.
If you’re an Avalanche dev and want to chat about literally anything code-related in the space, drop me a line at email@example.com. Need an opening line? Our pricing contract is live on the Avalanche mainnet and you can demo it on the web — tell me how you want to use it or could make it better.
And last but not least, if you’re a DeFi superstar please reach out — it’s time we BUIDL together.
Join Coinmonks Telegram Channel and Youtube Channel learn about crypto trading and investing