I need to get some sort of token to send to people who actually do it, to reward them in some way, because nobody ever does.
Well folks, if you put on your video, you might get a token. Probably not. You have some socks there you go. A tenth of a sock. I'll send anyone a tenth of a sock who puts on video. There you go. That's like $20. Yeah, that's no joke.
There we go. We got one more. I got tempted by a tenth of a sock. Here we go. It'll be in the mail. Just keep an eye out for a very small package. You know, I meant a physical tenth of a sock, not a digital one.
Cool. I think we're good. Hayden, if you can multitask, you can retweet the live stream.
Yeah, I don't... okay, let me do that right now.
Cool. Other than that, I'll let Jacob do an intro and then we can get started.
Yeah, sure. So first of all, thanks so much for being a part of this, Hayden and Noah. We're excited to have Uniswap as part of Hack Money and excited to be doing this as our last final event of Hack Money before judging. So we've come to the end. It's been an exciting four weeks. Your team has been super helpful in the channels and everywhere helping people build on top of Uniswap. I'm excited to see what people built. I assume you guys are as well. But in the meantime, maybe we'll do a little bit of chatting about how we got to Uniswap V1, some updates about V2 which launched on mainnet very recently in the last week, which is amazing, just in time for people to deploy their Hack Money projects to mainnet too. So perfect timing there. And just get an idea of the story, what's up with V2, and of course an opportunity for you guys in the audience around the world to ask some questions to the team as well. So with that out of the way, may we start with a couple questions maybe for Hayden and then we'll jump into some V2 stuff. Noah, I would love to get your opinion on that. So Hayden, I'd love to know how you got into Ethereum in the first place and maybe what you were working on beforehand. I know it's an interesting story. I think it would be cool for everybody else to hear too.
Yeah, before working on Uniswap, I was a mechanical engineer. I graduated in May 2016 from engineering school and then I spent a year working as a mechanical engineer doing thermodynamics, basically tracking heat flow in car designs. I was working at Siemens. I got laid off after about a year. At the time, I was starting to get a little bit into crypto. I had a friend, Karl Floersch, who at the time was working at ConsenSys and then he moved to the Ethereum Foundation. He was delving really deep into Ethereum and would talk to me about it, trying to get me interested. I didn't really care that much until the price went from like $5 to like $100 in a few months, and then I was like, okay, maybe it's interesting. It timed out nicely where I got laid off and I had a call with Karl. He was basically like, congratulations, you're now an Ethereum developer. I was like, I don't really know how to develop that well, but I guess I'll try it out because I didn't know what else to do. So I spent a few months experimenting with Solidity, learning how to write token contracts. But I wasn't really sure what to do. It started to feel like I needed a bigger project to learn on. Karl actually pointed me towards this blog post from Vitalik which was talking about automated market making and a different way to make a trading platform or an exchange. That ended up being the earliest version of Uniswap. I spent a few months building out an initial proof of concept, which turned out pretty well. Once I had that, I started to go to a lot of Ethereum events and meet more people. I heard about other projects in the space like 0x, which was doing some similar things. I got some ideas from there, going from just a thing that could swap between two tokens to a thing that could hop between any tokens. I just continued working on it, still pretty much unemployed for this entire time, living at home for a good portion of it, occasionally doing a little contracting work. I just kept working on the smart contracts and an interface for it. I eventually built out a good enough proof of concept. I met some people at the Ethereum Foundation, I met Vitalik in basically spring 2018, and he recommended I apply for an Ethereum Foundation Grant. So I did that, got an Ethereum Foundation Grant, and I paid contractors to build out a front end and do design work. I finished up the smart contracts and paid smart contract auditors and formal verifiers to make sure they were secure to the extent that we could at the time. And then that turned into Uniswap, which was pretty cool.
Very cool. And obviously, I think most people on this call will be aware of the explosion that Uniswap had. It almost became like a mindworm, where there were all these other things and all of a sudden it was just Uniswap and everybody used Uniswap. It became very popular very fast. What do you think led to that? Was it specific design choices you made, or was it significantly better in every way or just in a specific way? What do you think led to it taking off like a rocket ship?
Yeah, I think it definitely wasn't something I was expecting or anticipating when I was working on Uniswap, the scale of what it was relative to all these projects that had done huge ICOs and were a lot more established. I wasn't expecting it to compete in the same way. The design choices behind it were very UX focused. The feeling where all you need to interact with is a smart contract, so it's just like I put in this token, I get out this other token, and it feels almost like a vending machine. That was a design improvement compared to EtherDelta, which was still the most popular trading platform at the time and was a lot more complicated to use. Some of the other design choices were about how to make a trading platform that mimics the underlying properties of Ethereum itself. I noticed about a lot of projects built on Ethereum that they made various sacrifices on some of the underlying properties that I cared about most. Ethereum is very censorship resistant, but a lot of projects built on top of it aren't. So the idea of Uniswap was, can we make something that's as decentralized as Ethereum itself, as unstoppable and as trustless? I think that resonated with a lot of people. It felt a little bit different from a lot of other projects, and that got a lot of initial excitement. Another thing is the fact that you can trade anything for anything on Ethereum, and you don't need professional market makers. For the order book model, you always need professional market makers to ensure liquidity for any token, but for the longer tail of tokens, it's hard to scale professional market making. Having automated liquidity provision where you can just lock up your tokens in the smart contract and there's liquidity for those tokens forever is a fairly powerful thing.
Yeah, very interesting. So you've got V1, V1 is doing very well, lots of growth, lots of people using it. When did you start to realize maybe you needed to have a V2?
Basically as soon as it was doing an absurd amount of volume and had an absurd amount of traction. The scale of resources that had been put into thinking about building Uniswap, I mean it was literally just me working on my own for most of the time for V1. You heard the story I told at the beginning, I wasn't that experienced as an engineer. It was the first version of it, and it's hard to get something perfect on the first time. I wouldn't say V2 is perfect either. We're already starting to think about a V3. But the point is that when this thing started doing a million dollars a day in trading, I was like, okay, we have to work on this. This thing clearly has proved itself as a concept, but I was very sure that it wasn't in its ideal engineered state. So I definitely thought it was worth continuing to iterate and improve.
Got it. Cool. So now you're thinking about improving it. What was the first thing you knew that in V1 you were either really worried about or something you wish you'd built in the first version? What was the initial feature that you thought would be a perfect candidate for V2?
I think the first one we decided on was probably the arbitrary pairs, allowing any ERC20 to be paired against any other. It was definitely the most requested thing. A lot of people wanted to denominate in stablecoins or have two highly correlated things, and they wanted to be a liquidity provider on that and not have as much price risk. They couldn't because everything was forced to be denominated in ETH. I think ETH is a great pair and will probably always be one of the most common ones, but adding in this broader options was probably the first thing. I was very resistant to the idea early on just because there's a more complicated routing thing that occurs.
Awesome. Sweet. So maybe we'll let Noah jump into these ones too. Feel free to get an answer from both you guys for these open questions, and ideally pick different features so you can talk about more V2 features. So maybe starting with Noah for this one. What is for you the most exciting feature of V2 that you think is going to have the biggest impact?
Interesting. That's a good question. I think something that I was actually very hesitant about adding is one particular feature: flash swaps. We were really close to the end of the contract lifecycles, getting them formally verified, they were frozen in our minds, stable for quite a while. Then Dan Robinson, who's one of our investors and a brainstormer for these kinds of things, had this idea, and Hayden had thought about it as well. It's basically this idea of flash swaps, which has been around for a bit. We had this really nice design to add it into V2. So that was a call we had to make on whether or not we were going to add it. I was playing the cautious side, and Hayden and Dan were pushing me in the other direction. We ended up adding it, and that tacked on some time to our formal verification. It initially added this additional complexity to the underlying mechanics of a swap on Uniswap, but the more we spent time with the code, we realized it was a really natural fit into the way we were already thinking about the invariant and preserving properties about the contracts. We ended up getting it in, and I think it's a bit complicated right now for people to use because it's so new, but it offers a lot of really interesting atomic abilities to atomically arbitrage and loop through other protocols, and do things upfront that you would otherwise have to do iteratively. On the flip side, it's also forcing projects that might be vulnerable to flash loan governance tokens to be aware of this. We don't want to encourage that kind of behavior, but if it's possible on some other venue, we might as well be accelerationist in that regard and force this higher standard of security for all these projects. We made sure to be appropriately cautious and talk to people who this might impact, but at the end of the day, we felt it was a reasonable feature to add, and there's a lot of benefits. So that's something I think is going to be pretty exciting to see where it goes.
On the security thing, if being able to flash swap some tokens from Uniswap impacts the security of your system, then you should be aware that you can already flash loan a ton of ETH from dYdX and then atomically buy any token on Uniswap and then attack those same systems. Any system that is broken by flash swaps is already broken by a combination of dYdX and Uniswap V1 essentially. That was one thing that helped us get comfortable with adding it despite some people's initial concern about the implications. I'll also add my personal answer to that question would probably be the oracles. I already mentioned ERC20 pairs, and I think those are super important. I do think that having on-chain price feeds that are very decentralized and also very easy to reason about is important. A lot of on-chain oracle systems depend on people voting on a price feed or various trusted parties coming together and averaging across them. This is very different from any of those. It's very much just based on what's the amount of money you would lose moving the price on Uniswap away from the real price, and what's the amount of money that would cost you in arbitrage if you did that every block for a thousand blocks if you're doing a 10,000 block average. So it's a lot easier to reason about for some use cases. I think it's going to be really cool and important.
Cool. Awesome. What about the feature that was maybe the most challenging to build? It would be great to dig into what kind of hurdles you guys hit when you were trying to build this thing. You want to take that one, Noah? What do you think was most challenging?
That's a good question. I'll talk about one really thorny one, and Hayden can maybe do a more broad one. Something that's very technical and specific, but potentially pretty bad, is this issue of minimum divisibility. In Uniswap V1, the way to determine how many pool tokens a given amount of ETH and a given amount of token would give you is basically it just gave you the amount of pool tokens corresponding to how much ETH you sent to the contract. That's pretty reasonable because ETH was this canonical base pair. It had this idea of intrinsic value and was a reasonable unit of account for V1 pool shares. But in V2, we don't have this property anymore. Not every pool has an ETH component. So we had this problem of how to denominate pool tokens. You might think you could pick the minimum or the maximum or maybe the average, or even in Uniswap style, the geometric mean, which is the square root of the product. But it turns out there are all these attackability issues with that. If you mint the minimum number of pool shares, like you send one wei of one token and one wei of another token, that'll give you root two rounded down, which is one wei of pool shares. But then you can actually send a bunch of value into the contract. Uniswap can't control the token balances of any other arbitrary contract. So someone could take a million wei of one token and two million of another token, send those to the contract, and suddenly one wei of pool tokens denominates this incredibly large amount of liquidity. It's this really arcane pattern, not something you typically do, and there's no real reason to do it. But if you do, it becomes a barrier to entry for new liquidity providers. You have to have above the threshold of tokens that were sent to the contract in order to get even one wei of pool shares and contribute to being an LP. You can get around this by wrapping or doing other things, but it's frustrating. We did find a way around this. We essentially enforced that there's this minimum threshold of liquidity tokens in the minting process. The first liquidity provider has to burn this small, tiny, minuscule fraction of pool shares, typically less than a cent for almost any reasonable pair. It ensures there's always going to be this very small unit of measurement of pool tokens that ensures this divisibility issue can't get that bad, because there's some multiplicative factor on how bad this divisibility can get. Very technical and specific, but these are the kinds of things you have to worry about. Even though it's not that realistic and there's no real incentive to do what I was describing, you do have to be aware of these kinds of things in a permissionless system.
Yeah, V1 has this griefing attack actually. If someone deploys a new pair, if you're the first liquidity provider, you can create any arbitrary minimum liquidity threshold to become the next liquidity provider for all future users. So if you're the first liquidity provider on a pair on Uniswap, you could set that to a million dollars and say anyone else who wants to join the pool has to put in at least a million dollars. We didn't really realize that until well into the V2 design process. It's not like you can steal people's money who've already put in pools, and it can't affect existing pools, but for any future pools, if someone is aware and sees this, they could deploy and do this griefing thing. My answer would be oracles. There was this idea of how do we store built-in moving averages, like one hour averages, one day averages, built into the contracts. We started to realize it was really hard to choose what periods of time to average across. So we ended up on this other oracle system where we're storing these price accumulators that let anyone else building on top of it choose their own periods they care about. That ended up solving the problem really nicely, but it took a while to get to the current oracle design.
Very cool. Maybe jumping forward a little bit to what could be a future feature. I remember at Devcon last year, a project called Unipig, or in general, Optimistic Uniswap. I think we're settling into the new normal that gas prices are quite high and they've been quite high for a while. First of all, how do you guys feel about gas prices being this high? Does that affect users or liquidity pools? And maybe just chat a little bit about could a layer 2 Uniswap V2 exist? What could that look like? Should it be something that somebody should have built this hackathon or maybe the next one?
That's a good question. First off, it obviously does impact everyone who uses Ethereum in that all users are paying more towards gas fees. It kind of sucks for them, and it sucks for the platforms themselves because it might disincentivize future usage if people have to pay a lot of fees. So it's not great. The way I think about layer 2 solutions is that a lot of past layer 2 solutions like plasma and other ideas all felt like a huge sacrifice on what it meant to be an application on Ethereum. When you're building on top of Ethereum, you have these really nice properties where you can interoperate between other applications on Ethereum without needing to deposit into an application and then withdraw. You can just use tokens on Uniswap and then use them in Compound and use them in Maker, and you don't need to worry about withdrawals and exits. Being able to seamlessly interoperate between applications is such a core property. Another core property is the development experience of Ethereum. Some people complain about it, and Ethereum killers say it's horrible, but actually building on top of Ethereum is pretty great. There's a ton of tools, and writing smart contracts isn't too hard. For a layer 2 to completely take off and fill the needs of Uniswap, it needs to have these underlying properties of Ethereum: general interoperability, the ability to write general smart contracts out of the gate, and not need the applications themselves to create really intense, complicated things that some past scaling solutions required. I think optimistic rollup is the right level of trade-off where you can actually create a general smart contract platform on optimistic rollup that interoperates out of the gate. So I'm a big fan of the team formerly known as Plasma Group, now called Optimism. They are the people we collaborated with on Unipig. They're working on a general smart contract optimistic rollup chain. I expect to see a version from them that's made ready at some point, and I'm very excited for it personally. I do think it would be worth putting Uniswap V2 on it. Something to note is that for it to be ready, for it to be the layer 2 that wins or gets DeFi on it, it needs to support Uniswap basically. It needs to be like Ethereum where we can just deploy Uniswap to it and not need to build a whole backend. So we're waiting on that to some extent, but we're expecting it to happen fairly quickly.
Got it. Cool. Days and weeks?
Neither days nor weeks. Some longer period of time than that. But I wouldn't be surprised if it was less than a year for us to have a fully general purpose optimistic rollup chain with native Solidity and all that stuff. But we'll see.
Cool. Awesome. And I think this will be the last question from my end. So anybody in the chat, if you have questions, start thinking about them, write them in the chat, and we'll call on you one by one. You can just ask it live. But maybe just to wrap up this section, as you think back from your development of V2 to V1, what are some of the things you noticed that were sort of beginner mistakes you had made or things that made things more difficult as you were thinking about designing further software? What are some things that maybe first-time developers or even seasoned developers should be thinking about when they're putting together a protocol?
I don't know if I'm fairly happy with V1, but I'll say that mistakes definitely obviously like informing people of risks. There have been people who kind of...
Like, are we sort of seeing things and being like, 'Well, no one would ever do that, that's really dumb,' and then all of a sudden hundreds of people start doing that. So I think that just being really, really careful with informing people of the risks of using things is one thing I would highlight. And I guess also the trade-off: I think the mistakes that a lot of other projects are making is just being aware — and probably we've made those mistakes as well — being aware of the trade-offs that you're making, super hyper-aware, because sometimes people make what feels like a very minor trade-off and it just very fundamentally changes the entire security properties of their system. Or suddenly this one small change that you made, now you're dependent entirely on some small trusted party for everything in your system to work. So yeah, I just think trade-offs are under-considered sometimes, the implications of them.
Yeah, I don't have too much to add. I think the one thing that, from a slightly more practical perspective, differs between V1 and V2 is that V2 has this kind of core helper separation where the core contracts are very minimalistic, very brutalist, and really only exist to verify the security and safety of Uniswap — make sure that x * y = k is preserved more or less, and that liquidity providers aren't going to be fleeced in any way. And then we have this whole constellation of external contracts which are responsible for maintaining oracles, performing flash swaps, and even just doing the very basics of routing between multiple pairs in order to support trading for users and front-end interfaces. So I think this is really nice because it's very extensible and flexible, and approvals can be given fairly freely to these helper contracts because they should be extremely simple, stateless, never doing anything suspect or complicated. So very easy to verify the properties of, and that's something we're pretty excited about because there's always new exciting ways to transfer ERC-20 tokens or perform different types of swaps. So that's something we want to keep doing going forward, and we'd like to see other projects do: separate out these core pieces of logic from helpers.
Yeah, I agree that was a good answer, much better than mine. Sounds good. Cool, awesome. Well, let's turn this over to the audience, ultimately why we're here. So I think Ven had a question. Ven, I don't know if you're able to unmute and ask it yourself; if not, I'm happy to repeat it.
What went into determining the 0.3% point? Yeah, exactly. So I'll read it for the stream too. So the question from Ven, who's not able to say it out loud right now, is: what went into determining the 0.3% fee? Are there ideas around making that variable? I guess basically trying to get a sense for how we arrived at that number.
Oh yeah, I'll say that in terms of what: the 0.3% fee in V2 is a continuation of the 0.3% fee in V1, which came from a discussion between me and Vitalik. It was a very short discussion. I had it at 0.25, and then I was worried it might be too low and liquidity providers wouldn't make enough, and he said, 'You could try 0.3,' and then I changed it and it never changed. But the general thought that went into it was that it should be somewhat competitive with other types of trading platforms, and we didn't want too much active governance in V1 or V2, just because it felt like — the funny thing is that whatever the fee is, whether it's 0.3, 0.25, or 0.35, there's probably a different amount of liquidity where the market might reach some sort of equilibrium. Definitely for certain types of pairs it would make sense to have much lower or much higher fees, and it's something we very much explore in V3. So we are working on a V3, and I'd say that dynamic fees fall in the scope of that. But one of the reasons it wasn't in V1 or V2 is just because you always have this trade-off when you introduce governance to systems, and we want to make sure that if we do implement a dynamic fee system, we do it in the right way where it doesn't create weird incentives between different users of the system.
Cool, got it. All right, Ven accepts the answer. Awesome. 0.3% works for a lot of use cases surprisingly, for a lot of pairs it actually works fairly well.