TL;DR
- The only canonical deployment of Uniswap V2 is on Ethereum mainnet.
- There is demand for V2-style AMMs on non-Ethereum chains and many V2 forks have been deployed with varying degrees of modification.
- To the extent that these forks have been modified, they may prove unsafe for users.
- To the extent that these forks have liquidity, that liquidity could likely have accrued to Uniswap V2.
- The combination of Uniswap V2 and Uniswap V3 can often provide better execution for small-volume swappers via the Universal Router.
Introduction
When Uniswap V3’s Business Source License expired and the code’s license transitioned to GPL, the DAO created a process by which it would declare canonical deployments of the contracts. This process serves to identify instances of the V3 code that are a) not modified and b) owned and controlled by the Uniswap governance contracts. These assurances are meant to provide developers and users with comfort that the code they’re using is safe and any changes to it (to the extent that changes are even possible) will be telegraphed long in advance.
Uniswap V2 is governed by the same permissive GPL license but has not been subject to the same DAO-run multi-chain expansion as V3. Instead, it has been forked and deployed under different brand names and across many chains almost continuously since Sushi’s vampire attack in the summer of 2020. These forks may contain modifications to the code, and their ownership structure can range from DAO governance contracts to single-signature wallets. Nevertheless, forks of V2 can garner significant liquidity and volume relative to other AMMs.
Proposal
Deploy Uniswap V2 on all chains where there is a canonical instance of V3.
Rationale
There are at least three compelling arguments to move forward with this proposal.
First, V2 forks have been plagued by hacks that have caused the loss of user funds. The Uniswap V2 contracts have been deployed on mainnet since May 4, 2020 with no loss of user funds; they can be considered among the most battle-hardened contracts on Ethereum. Canonical versions of the Uniswap contracts can provide DEX users on new chains - swappers, liquidity providers, and developers - with the safety and security for which the protocol is known.
Second, there is demand for traditional, full-range AMMs on new chains. Uniswap should be in a place to service this demand and continue to grow our user base and brand equity across multiple ecosystems.
Third, integrating Uniswap V2 pools into the Universal Router will help incrementally improve execution quality for applications that already use the Router to allow their users to swap.
Process
This process will be very similar to the first vote to declare V3 canonical implementations. We will evaluate a batch of deployments, create a new ENS name, and populate the text record for each of those deployments. More specifically:
- Chains that have a V3 deployment have already gone through the community vetting process and should be eligible for a V2 deployment by default.
- V2 deployments should be owned by the same contract that owns the V3 deployment on its respective chain and subject to the same cross-chain governance mechanism
- V2 deployments should be cataloged in the text records of a new ENS subdomain v2deployments.uniswap.eth with the key equal to the network ID and the value equal to the bridge sender contract address and the destination chain’s UniswapV2Factory contract address
The relevant contract addresses can be found in this Google Sheet or on the Forum in this post.
Vote Transaction Details
If executed, this proposal will execute two function calls.
- Create the
v2deployments.uniswap.eth
subdomain by calling the setSubnodeRecord
function on the ENS Registry contract and passing it the hashed values of the main name (uniswap.eth) and the new subname (v2deployments) as well as the timelock's address and the resolver we're using (the ENS public resolver here).
- Add the text records to the newly-created
v2deployments.uniswap.eth
by calling the multicall
function on the ENS registry (since we have > 9 records to create and our governor contract can call max 10 functions per proposal). We pass multicall
an array of the encoded bytes data for each function we want to call. Concretely, multicall
receives an array of 14 items, each of which is the encoded bytes data for the function call that sets a text record in the format described above.
The code used to generate these function arguments (show below) can be found here.