Unicode Kick-off | Keynote: The Price is Right
ETHGlobal·Sun, Oct 9, 2022, 12:00 AM
Join us for Noah Zinsmeister's Keynote talk titled, "The Price is Right," all part of the Kick-off of UniCode, a virtual hackathon focused on the UniSwap Protocol running from Friday, Oct 29th through Wednesday Nov 10th, hosted by Uniswap Grants in partnership with ETHGlobal. ---------------------------------------------------- Follow us: https://twitter.com/ETHGlobal Check us out: https://ethglobal.com Email us at: hello@ethglobal.com
Transcript
[Music] [Applause] [Music] i want to quickly invite noah from the uniswap labs team known as the head of engineering at union spot labs and he's going to be sharing a quick talk about uniswap oracles the talk is separately titled the price is right and without further ado i'd like to welcome noah to come on and tell us more about how you can get this working with v3 welcome thanks kartik um and thanks also for just the the great intro and lots of uh of great information we're super excited um to partner with all these great groups that you've already heard from um at uniswap um for you to you know create whatever um whatever your heart desires and we're here to help and um so yeah i thought i'd give a little presentation um about something specific rather than you know just a general overview because i thought that would be a bit more fun and just sort of inspire you um if not to work on oracle's directly to sort of understand the scope of the kind of things that you'll be able to build during these two weeks or so so let me quickly share my screen here and i'll confirm that everyone can see that everything is good to go great okay so um welcome the price is right um full disclosure i actually haven't seen any episodes of this show so i don't know uh the the the title is is about all i've got but um i figured i would talk a little bit about v3 oracles today and um i'm going to start off with this meme um you know i received your gas you received two ops so um ultimately um the unisop oracle is a you know a fully on-chain um system of you know creating and uh and distributing tu ops which is time weighted average prices um a little bit of inside terminology there okay so why why are vp oracle school why am i talking about this as opposed to any other feature on uniswap um frankly it's even a bit under the radar like most people when they think of unison they don't think oracle's they think about trading or liquidity provision or you know ticks or concentrated liquidity or what or what have you but i thought it would be fun to just chat a bit about um oracle's because i think it features some of the really interesting design patterns that we developed in v3 and it's just a great example of how v3 can serve you as a developer and and can be sort of a bedrock upon which you can build really interesting really complex you know other protocols build out your ideas things like that so i'm just gonna i'm just gonna hit each of these little bullet points here um and just briefly describe like what i meant when i when i wrote this and like why it might be interesting to you as a developer thinking about writing um an integration on top of uniform so accumulators so that's the first that's the first bullet point um this one's pretty interesting so um there's a lot of history here i won't go into the exhaustive details but um you know the way that we track prices in uniswap in both v2 and v3 both of which feature oracle um you know capabilities um we track prices via an accumulator so um what this basically means is that we don't just track the price and like store the price history um overall time because you know that's a prohibitively expensive thing to do but what it turns out you can do is if you if you actually know the price at some time t0 and you every second add the current price to that historical price and you just keep this ongoing running sum that's getting bigger and bigger and bigger all the time you can actually back out average prices within intervals um by taking the difference in accumulator values so if you take accumulator value at time two and time one and you subtract them it turns out that the average you know that value is the average price within that duration and this can extend to any number of arbitrary intervals and um and and it's very flexible and it's an interesting pattern right it's sort of somewhat non-intuitive um and there's lots of ways that we tried and failed to get this um you know this pattern to work and so anyway accumulators is this very interesting pattern that you'll you'll get exposed to if you've ever looked at the oracle code um so it's a good tool to have in your toolkit okay integer overflow what's this so um we're hyper optimized you know we're hyper focused on optimizing for gas usage at uniswap so this is something we've sort of become notorious for um sometimes in fact we actually sacrifice a bit of code quality or code sort of readability for gas efficiency and so um we're hyper focused on making sure that swappers are paying no more than they actually absolutely need to and so what we've done is we've actually taken a you know the time stamp which again as i mentioned the oracle is accumulating on a per second basis um and and what we've done is essentially allowed we've compressed the timestamp from 256 bits which is its native representation on in the evm down into 32 bits and that lets you express a smaller range of times and it's actually about 100 and something years so um you know two to the 32 seconds is something like a hundred years um and so actually what happens is every 100 years the unicef oracles will all um potentially overflow and so we've actually written all the logic in the oracle integration of v3 to be fully integer overflow resistant or or you know um basically everything just works no matter if the energy is overflow or not and so this is a pretty non-intuitive pretty interesting pattern so again if you're interested in overflow um or you know being robust to 100 plus year intervals of of tracking prices you know this this oracle is for you okay variable length circular queues this one's this one's wild um very interesting um and don't feel like you need to understand all this by the way i'm just trying to pique your interest here um so what this means is um in v3 um unlike v2 we offer you the ability to natively uh calculate the t-wap the timeout average price to you know about which i'm going to go into more detail later don't worry if you still don't really understand what that is but anyway in v3 we offer you the ability to calculate this um over basically any arbitrary time frame within the last about week or so in v2 this wasn't the case you had to do a lot more work actually in order to extract these average prices and if you didn't sort of track um a price at a particular time snapshot you were unable you know in the future to sort of retroactively go back and check what the price was at any point that that wasn't that specific time that you tracked we solved this problem in v3 by while implementing variable length circular queues and what this basically means is we rather than tracking a single accumulator value which just is overwritten on an ongoing basis we actually track an array with a variable length which stores each accumulator value um for each new block that touched the unisoft pair so rather than having one value and just consistently overriding it with a new accumulator value again and again and again we actually stack and we push these accumulator values onto an array and then when we reach the end of the array let's say length 5 or length 10 we actually just loop back to the beginning hence circular and then we just keep writing in perpetuity right and what happens is you can actually increase the length of that array and so by default we don't make you pay as a swapper or an lp we don't make you pay for um this ability to read t-wops in the far past but if you want that feature right you can actually extend the length of this queue um and uh and and get you know access to these historical prices and so very complicated um implementation you don't you can you know don't take my word for you can go look um but a very interesting feature that was that was basically core to this improvement in oracle's um from v2 to v3 okay binary search this is a cool one too so again now that we don't have just a singular observation we have actually an array of them um we have this problem where we need to get the observation or the accumulator value or the price right at a historical time and that time might be a long time ago it could be a day it could be an hour it could be two and a half hours it could be um you know a week and we we actually don't natively know where to look in this array for that value and so what we actually have to do is a binary search so we know that this circular queue is sorted with an offset right so like because it's circular you know you're never starting it's not guaranteed to be sorted from like index 0 to index max but it is sorted sort of starting from the the current index you know and going around in a loop and so we can actually abuse that feature by performing a binary search whenever we're looking for a historical observation at a particular time moment and so again don't take my word for it this is this implementation is like publicly available you can look at it in our github super interesting and again a great tool to have in your toolkit binary search extremely efficient um login complexity um a really great way to find data in a in a gas efficient way um given that you know your sort of your input data is sorted chronologically or you know by whatever in whatever by whatever sort of sorting criterion you care about okay linear interpolation we're almost done here and then i'm gonna actually explain what some of the oracle stuff does rather than just like titillating you with these fun little details okay linear interpolation this is a cool one so as i mentioned um the accumulators and the oracles in general work on a per second basis right so you can get the price at any given you know second which is what we sort of intuitively understand um you know as humans right but uh but what the evm understands isn't just seconds it's also like blocks and blocks are sort of the canonical unit of time in in blockchain land and so what we need to do actually is if there's a block at time 0 and then another block at time 13 let's say we want the price at time 10 or time 8 right like we we can sort of we know what it should be right it's just like it never the price never changed between blocks because that's impossible but we sort of need to like we can't say that it's the price is what it was at time 0 or 13 because that's not quite right you know what i mean like we need to sort of do some well interpolation between 0 and 13. and so linear interpolation just refers to the fact that the the core um the v3 core code which implements oracle's actually does this job of linearly interpolating between blocks um if you're looking for the price at a historical moment which actually didn't have a block but just happened to be between two blocks so um yes this is another interesting feature and then finally we get to use all three pythagorean means when we're using oracle so this is a pretty cool one um i i one thing i didn't mention actually is that we don't just track average prices in v3 we actually track average liquidity as well in the same fashion and i won't go into um much more detail than that but suffice it to say that we're tracking average prices via an accumulator and average liquidity via the same and what this lets us do is take so first of all we can get arithmetic means of uh ticks which are a representation of prices in unison e3 right so arithmetic mean great and that's exactly using that logic that i mentioned earlier about the accumulator right like if you have an accumulator value at time two and times zero you can just take the delta divide by the you know interval length and now there's your average over that interval right so that's an arithmetic mean and so that's what we can do for for ticks say um what what we do with liquidity is we actually track not just liquidity natively but seconds over liquidity uh for complicated reasons that again i'm not going to explain but because we're tracking s over l and we're we're trying to get the average l liquidity um if you accumulate s over l on a sort of rolling basis and then you divide out by seconds um which you can obviously get from um you know from just the duration of um uh you know of whatever period you're looking at it turns out that's the harmonic mean right so the harmonic mean is like one over um you know x you know summed up you know divided by like the x or some you know i don't know if exactly i said it right but you know you can look up a harmonic mean and basically that's what this is and there's different properties that the harmonic mean has relative to the arithmetic mean that make it actually pretty pretty well suited for tracking average liquidity it sort of down weights um it it weights downward for low values of liquidity which is good because you want to you want to sort of um you know not put a lot of weight on sort of uh low liquidity pools for example right so that's two and the third is a geometric mean so um it turns out that the arithmetic mean of a over b when you sum it up over time and b over a is actually different right and that's just because a property of the arithmetic means the arithmetic mean of ratios isn't equal to the arithmetic mean of the inverse of the ratios um a little bit unfortunate and so in unison v2 we actually tracked both a over b and b over a you know so for each die say we track the east die price and also the di-ease price which are basically again the same right but because of this quark the arithmetic mean um they aren't actually um equal and so we tracked both which was a bit wasteful and so in v3 what we've actually done is we track now the geometric mean price and so instead of b over a and a over b we actually track the root of the product of a bunch of observations of a over b and actually it doesn't matter if it's a over b or b over a they're the same if it turns out like if you have a 0 b 0 a 1 b 1 if you take the product of those and then take the root the second root in this case um it's the same value as if you had just flipped everything right and so that's actually quite a nice feature it gives you sort of a canonical price for two assets rather than two which you need to choose between and or ultimately sort of arbitrate right so um it turns out that by tracking arithmetic mean ticks um which actually represent exponential prices um you get um geometric mean prices so arithmetic mean ticks correspond to geometric mean prices meaning um we've used all three means so anyway cool don't feel like you have to understand all this um but hopefully again it's just interesting and like prompts you to dive a bit more into the code um again which i'm gonna explain how to do very soon so okay without further ado let's move on from this and um we we still have a bit of time left so let's actually talk about like what you know um your oracles are maybe now that i've um fully confused everyone so uh they are on chain permission list t-ops which again are time-weighted average prices um and so basically what they are is for for any given liquidity pool on unisoc let's say eat die as a great example right you know people are constantly trading with this pool they're providing liquidity um and more importantly or most importantly perhaps they're arbitraging this price to match what the sort of true price um of ethai is across the entire market and so the unison price natively tracks the price of um uh you know of of these assets um you know in an incentive compatible way right like in this permissionless environment there's always an you know you'll make money by trading the price on unisoft closer to the true price and so um you know you'll you'll just you'll just do that and then um as a benefit right we have access to this price now because of this oracle feature and so we can use the sort of true or arbitrage um price of ether say as an input to any number of systems that we want to build on top and so like the most obvious example right is if you want to offer people like leverage where you deposit ethan you want to let them withdraw some dollar denominated um you know asset in in return you know up to some collateralization ratio and then you want to maintain this sort of ratio and have a liquidation system and um you know things like that well you can actually do that natively if you have access to some kind of true price of you know east usd or ethio or what have you and so um that's just one example of how you know tracking the price on unisop um and and having access to that on a historical basis crucially um can actually be a really powerful way to have a permissionless system of prices that you can use as inputs to other economic you know uh systems say so um that is what t-ups are and this is a bit of an example so if you were not following what i was talking about earlier with like the array of observations and things like that so on the bottom here let's start with this last row so that's the v2 oracle right and so we have this price accumulator which at time uh like 1pm it looks like is uh has a value of 11 400 right and and then there's a bunch of blocks that go by and then if we want to check again at time you know 2 p.m this accumulator you see has increased so it's now it's 48 000. and so what you can do is you can take the difference 48 000 minus 11 000 divide by you know one hour and then you get the average price over that whole duration while the accumulator was sticking up but crucially what we didn't do in v2 is we didn't store this 11 000 value you had to actually proactively go ahead and store it yourself wait an hour and then check what it was against you know against that historical value and so if you didn't store it you know you would you're you're out of luck and you know it's it's actually hard and costly and sort of frustrating to have to do this so what we've done in v3 which is now the top row we actually store all of these checkpoint values um on a rolling basis again in a circular queue um and so now at time two you don't have to have stored anything at time you know time one you can actually just look back in the array using a binary search um find that historical value perform the delta get your arithmetic average tick and then derive the geometric average price over the whole interval so this is super cool and you can actually do this not just at one time but like at any variable time in the whole you know duration of the tracked sort of period um that the oracle is the oracle is tracking and again you can see here it says up to nine days later right the oracle is about a week or eight or nine days worth of data um when it's you know fully initialized and so this is this is a really powerful way to like um calculate any sort of arbitrarily any arbitrary curve or price um you know average over over this whole interval so hopefully that helps a little bit um okay so why like more importantly like i've described more or less what unicef workers are and how they work but why would you use them so the first is that they're economically robust and i touched on this earlier right like it's important to have full incentive alignment um for a system to sort of be um you know trustworthy and so economically robust refers to the fact that again if the price of uniswap of you know let's say the eath die pool diverges from the east side price on coinbase or binance or any other decks on ethereum or any other decks anywhere there's going to be money on the table for some arbitrage whoever to come in and and and and trade the price back to its you know fair true value and so economically robust refers to the incentive alignment that that exists to push the uniform price close to the true price which is again probably what you care about if you're building this second order abstracted economic system the second is explicit manipulation costs so um you know there are other ways to get prices on ethereum right like you can maybe just have a trusted party submit a price that you know they have claimed is is the price of each site on some you know in some um aggregate fashion you can maybe have an external exchange like coinbase for example sign uh cryptographically the price of you know you die on their system every so often submit that price to the chain and then use that as your source of truth um there's other projects out there that like offer you know pricing as a service and they'll sort of report on a periodic basis what the price is of various things and it's not clear in any of those cases really what the manipulation cost is um for a reporter to perform uh you know poorly or sub-optimally or even maliciously and so uh in unisof that's not the case right like because the implementation is no because we we have a very clear like data provenance pipeline like we know every step of the way what's happening there is a cost to manipulate really you can pay money to push the unisoft price away from its true value but it will like you the only way to do that is to incur economic losses right because again you're just feeding arbitrage money the more you push your price away and it gets arbitraged back and so explicit manipulation cost refers to the fact that the only way to manipulate the system is to pay money in a fully public transparent manner whereas with an off chain reporter it's not at all clear what the incentive structures are how you know we're maintaining um verifiability and trust things like that um and so i think that this is an important property to have when you're when you're designing an oracle system okay guaranteed up time this is obviously just a simple one like unisop is always on because ethereum is always on and there's no off chain infrastructure like there's no reporting that can't happen um of course you know you can have a scenario where blocks are being stuffed and maybe no one is able to arbitrage the price on unison but i think that would be sort of a more systemic issue on ethereum um and not something sort of that we have to worry about as a as a dap level um project but um but you know in the general case i think that guaranteed up time is a huge feature um and you don't need to have any liveness concerns uh about oracle's when you're using unison and finally zero counterparty risk so this is i actually alluded to this earlier in the manipulation costs but um you know there's no party that's responsible for for you know publishing prices or being timely or being fair or accurate um again it's fully algorithmic it's just code um you can audit it yourself and there's literally zero counterparty risk there is smart contract risk of course there are economic considerations that you have to make hence the first two points um but uh yeah there's no actual party that is able to um you know that is able to cheat or or misuse uh your system so hopefully that it you know motivates you and it sort of explains why we think that decentralized permissionless oracles like you know swap are um you know very powerful and of course maybe not as um sort of fully accurate like they're not is they're not always going to track the exact price off chain of any of these different assets because again there's a little bit of arbitrage flow there's um there's the fact that you're just taking an average as opposed to looking at spot which you can sort of trust off-chain um but i think that these benefits are really quite strong and they potentially outweigh those costs um okay so here's just an example of what can go wrong if you have a bad oracle right like so if you're a landing protocol and you're thinking oh the spot price should be fine well what can happen is uh something disastrous like uh this stack trace that you're seeing so you know there have been a couple examples historically of of lending protocols usually or some variant of that where they're using uh the price of an asset again as i mentioned before to sort of collateralize um the borrowing of another asset and they're using more or less what what can be referred to as a spot price which is the the immediate price at any given moment which is fully manipulable right and there's like very little cost to manipulate the spot as opposed to an average um because you you have you can do that synchronously as opposed to you having to being forced to do that over multiple blocks over you know a given time time span so you know these lending protocols historically like use the spot price and in fact not even an off chain spot which is which would be more like an off chain oracle reporter where it's accurate maybe but there's like you don't know who that reporter is and you can't you don't know if you can trust them but they actually use the spot price of an on-chain protocol like they used to spot on a dex um to figure out the collateralization um ratios and so this is really dangerous right because you can fully manipulate the spot sort of at quite low cost um you know exploit the lending protocol as you can see here in the stack trace this is bzx um and uh you you can make a lot of money you can wreck people so uh yeah so this is just a cautionary tale about the fact that using oracle's is important and if you're going to use oracles maybe you should think about using a decentralized oracle network like uniform as opposed to you know a system of reporters right okay finally how so this is where i'm just gonna give a couple links and sort of bail out here because um i don't want to take too much more of your time but there's there's a couple places to go to look so the first link here um is the v3 core code on unisoft's github so um what this is is the implementation of oracle's at the lowest possible level this is going to have all the juicy details that i mentioned in the beginning variable link circular queues binary search all this good stuff so if you really want to if you want the sauce that's where to get it so v3 periphery is a bit different um this is a repo where we write code that is at a bit of a higher level than core and it doesn't implement the core like it's not the implementation of e3 that's in core what it is though is it's a set of sort of helper contracts helper libraries things that abstract a lot of the like nitty gritty details um for you and um and basically offer a sort of smooth developer friendly hopefully api surface right and so um an example of this is like the router contract which is actually how you trade through uniswap that's a peripheral contract because it's never holding people's funds it's not implementing the amm functionality it's simply like managing approvals it's managing transfers um you know doing the core sort of stoppage logic doing swapping logic doing slippage checks things like that uh crucially additionally it also has a lot of oracle functionality so there's a library in there called oracle library and it again offers like a bit of a smoother interface to using the three oracles um in a way that is going to be easier to digest as again as a third-party protocol that wants prices in some um you know for some for some input to their system finally there is some there are some docs so if i missed anything in this description of oracle's as i'm sure i did um you can look at this doc page here um probably just the easiest way to search it is just go to the doc's site yourself.org site and like search for oracle's um rather than typing out this link but um there's a lot of information um you know there uh about about this system and why it might be interesting to you and finally of course the discord is always available as a place to ask questions about these things and so i'll be on there a bunch of team members and people who meet global and and ugp and things like that will be will be hopefully on the discord to answer those types of questions and so you know i want to wrap up you know thank you first of all um oracles um i just wanted to say that you know we're really appreciative that you guys are all here and taking time out of your i'm sure busy lives to you know to hack for hack for fun and and maybe a little bit of profit um um you know hopefully this was interesting just as a bit of a a deep dive into a specific feature of e3 that is you know near and dear to my heart i wrote most of this code um i think it's really interesting i'm excited to see people building on top of it um but you know i just want to say that there's so many areas like this um around swapping around the user experience around lping around all kinds of really interesting things um that uh you know that are possible to build on top of unisof so um hopefully this is helpful um and inspiring and you know i know there's lots more to come um uh you know i know that aztec i i talked to those folks and they're they're really excited about some some interesting ideas um you know building on like layer two and zero knowledge to trade on unislop um i know there's a lot of interest in optimism and arbitrary um so yeah i'm excited to see what you all build don't feel like you have to use oracle's but um again thank you for your time and i'm gonna i'm gonna wrap it there awesome thanks noah um this is uh super helpful i think uh just uh it's a really good way to point out that it's not just about plugging into the liquidity and trading uh there's a lot more you can do with v3 is a perfect example i was going to say all those memories of me prepping for engineering interviews or fun coming back and uh you can see them in practice and hopefully everybody gets to use this too so with that i want to thank you for giving us that great overview for everybody who has questions please uh you can ping noah or the broader ugp and swap labs team on the discord for any help or questions and hope that a lot of you build really cool ways to uh use an immigrant orcas [Music] [Applause]
Automatic transcript — names and jargon may be misspelled.