Deploy Uniswap
Overview
Uniswap is a decentralized exchange (DEX) protocol built on the Ethereum blockchain. Uniswap allows users to trade Ethereum-based tokens without the need for an intermediary or a centralized exchange. It uses a unique automated market maker (AMM) system to facilitate trades and provide liquidity to the platform.
Uniswap operates on a set of smart contracts that are open-source and decentralized, meaning they are not controlled by any centralized authority or entity. Instead, users interact directly with the smart contracts using their Ethereum wallets, and participate in the platform's liquidity provision and trading features.
A key feature of Uniswap is its unique AMM system, which uses a constant product formula to determine the price of tokens on the platform. This means that the price of a token is determined by the ratio of the token's supply to the supply of another token in a trading pair. This system allows users to trade tokens without relying on order books or centralized matching engines.
Another important feature of Uniswap is its liquidity provision system, which allows users to provide liquidity to the platform in exchange for a share of trading fees. This allows users to earn a passive income by contributing to the platform's liquidity and helping to facilitate trades between different tokens.
Uniswap has become one of the most popular decentralized exchanges on the Ethereum network, with a wide range of tokens and trading pairs available for users to trade. Its decentralized and open-source nature makes Uniswap a popular choice among cryptocurrency enthusiasts who value the principles of decentralization, transparency, and community governance.
Installation
- Refer to the above link to install NodeJS
- Create project dir and go there
mkdir uniswap cd uniswap
Deploy Contracts
v3-core
- Clone repo from github
git clone -n https://github.com/Uniswap/v3-core.git
- Go to
v3-core
directorycd v3-core
- Checkout version
git checkout -b wf d8b1c635c275d2a9450bd6a78f3fa2484fef73eb
- Install packages
yarn install
- Go to Networks - RPC Endpoints page and check params
- Add Waterfall Network to
hardhat.config.js
filenetworks: { ... waterfall: { url: "https://rpc.testnet9.waterfall.network", chainId: 1501869, accounts: ['07201008f00b31de405a0af22ff04871044e027878929b7b47569ca76555ff09'], // Private key from your account from: '0xa7062A2Bd7270740f1d15ab70B3Dee189A87b6DE' // Your Deployer Account } }
- Create
scripts
directorymkdir scripts
- Create
deploy.js
file inscripts
directory and past next code:async function main() { const UniswapV3Factory = await ethers.getContractFactory('UniswapV3Factory') // Start deployment, returning a promise that resolves to a contract object const uniswapV3Factory = await UniswapV3Factory.deploy() console.log('Contract deployed to address:', uniswapV3Factory.address);//0x61F5cC6C2792d7409FEC7ED4E798135e8fc26fD2 } main() .then(() => process.exit(0)) .catch((error) => { console.error(error) process.exit(1) })
- Deploy contract
npx hardhat run --network waterfall scripts/deploy.js Compilation finished successfully Creating Typechain artifacts in directory typechain for target ethers-v5 Successfully generated Typechain artifacts! Contract deployed to address: 0x48A6024B11F67eaBD632d6C98d62B1eEa7D05c1E
-
Save the contract address you received, you will need it later; eg:
0x48A6024B11F67eaBD632d6C98d62B1eEa7D05c1E
-
Exit to project directory
cd ../
v3-periphery
- Clone repo from GitHub
git clone -n https://github.com/Uniswap/v3-periphery.git
- Go to
v3-periphery
directorycd v3-periphery
- checkout version
git checkout -b wf 6cce88e63e176af1ddb6cc56e029110289622317
- Install packages
yarn install
- Go to Networks - RPC Endpoints page and check params
- Add Waterfall Network to
hardhat.config.js
filenetworks: { ... waterfall: { url: "https://rpc.testnet9.waterfall.network", chainId: 1501869, accounts: ['07201008f00b31de405a0af22ff04871044e027878929b7b47569ca76555ff09'], // Private key from your account from: '0xa7062A2Bd7270740f1d15ab70B3Dee189A87b6DE' // Your Deployer Account } }
- Create
scripts
directorymkdir scripts
- Create
deploy.js
file inscripts
directory and past next code:const web3 = require('web3') async function main() { const factoryAdr = '0x48A6024B11F67eaBD632d6C98d62B1eEa7D05c1E' // Use contract adress in previous step. const WWATER = await ethers.getContractFactory('WWATER') const _WWATER = await WWATER.deploy() wwaterAdr = _WWATER.address console.log('WWATER deployed at:', wwaterAdr) const UniswapInterfaceMulticall = await ethers.getContractFactory('UniswapInterfaceMulticall') const _UniswapInterfaceMulticall = await UniswapInterfaceMulticall.deploy() console.log('UniswapInterfaceMulticall address:', _UniswapInterfaceMulticall.address) const Quoter = await ethers.getContractFactory('Quoter') const _Quoter = await Quoter.deploy(factoryAdr, wwaterAdr) console.log('Quoter address:', _Quoter.address) const nativeCurrencyLabelBytes = web3.utils.asciiToHex("WATER\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); const NFTDescriptor = await ethers.getContractFactory('NFTDescriptor') const _NFTDescriptor = await NFTDescriptor.deploy() console.log('NFTDescriptor address:', _NFTDescriptor.address) const NonfungibleTokenPositionDescriptor = await ethers.getContractFactory('NonfungibleTokenPositionDescriptor', { libraries: { NFTDescriptor: _NFTDescriptor.address } }) const _NonfungibleTokenPositionDescriptor = await NonfungibleTokenPositionDescriptor.deploy(wwaterAdr, nativeCurrencyLabelBytes) console.log('NonfungibleTokenPositionDescriptor address:', _NonfungibleTokenPositionDescriptor.address) const NonfungibleTokenPositionDescriptorAddr = _NonfungibleTokenPositionDescriptor.address const NonfungiblePositionManager = await ethers.getContractFactory('NonfungiblePositionManager') const _NonfungiblePositionManager = await NonfungiblePositionManager.deploy(factoryAdr, wwaterAdr, NonfungibleTokenPositionDescriptorAddr) console.log('NonfungiblePositionManager address:', _NonfungiblePositionManager.address) const NonfungiblePositionManagerAddr = _NonfungiblePositionManager.address const SwapRouter = await ethers.getContractFactory('SwapRouter') const _SwapRouter = await SwapRouter.deploy(factoryAdr, wwaterAdr) console.log('SwapRouter address:', _SwapRouter.address) const V3Migrator = await ethers.getContractFactory('V3Migrator') const _V3Migrator = await V3Migrator.deploy(factoryAdr, wwaterAdr, NonfungiblePositionManagerAddr) console.log('V3Migrator address:', _V3Migrator.address) } main() .then(() => process.exit(0)) .catch((error) => { console.error(error) process.exit(1) })
- Update
factoryAdr
const which you got when deploying v3-core contracts - Create
contracts/lens/WWATER.sol
file and past next code:pragma solidity =0.7.6; contract WWATER { string public name = "Wrapped Water"; string public symbol = "WWATER"; uint8 public decimals = 18; event Approval(address indexed src, address indexed guy, uint wad); event Transfer(address indexed src, address indexed dst, uint wad); event Deposit(address indexed dst, uint wad); event Withdrawal(address indexed src, uint wad); mapping (address => uint) public balanceOf; mapping (address => mapping (address => uint)) public allowance; receive() external payable { deposit(); } function deposit() public payable { balanceOf[msg.sender] += msg.value; emit Deposit(msg.sender, msg.value); } function withdraw(uint wad) public { require(balanceOf[msg.sender] >= wad); balanceOf[msg.sender] -= wad; msg.sender.transfer(wad); emit Withdrawal(msg.sender, wad); } function totalSupply() public view returns (uint) { return address(this).balance; } function approve(address guy, uint wad) public returns (bool) { allowance[msg.sender][guy] = wad; Approval(msg.sender, guy, wad); return true; } function transfer(address dst, uint wad) public returns (bool) { return transferFrom(msg.sender, dst, wad); } function transferFrom(address src, address dst, uint wad) public returns (bool) { require(balanceOf[src] >= wad); if (src != msg.sender && allowance[src][msg.sender] != uint(-1)) { require(allowance[src][msg.sender] >= wad); allowance[src][msg.sender] -= wad; } balanceOf[src] -= wad; balanceOf[dst] += wad; emit Transfer(src, dst, wad); return true; } }
- Deploy contracts
npx hardhat run --network waterfall scripts/deploy.js Compilation finished successfully Creating Typechain artifacts in directory typechain for target ethers-v5 Successfully generated Typechain artifacts! WWATER deployed at: 0xe05FeCA8B752051B207f071D876B442cACC9bd2c UniswapInterfaceMulticall address: 0x0Ba145B472B04df34B20c249165bf1Ea726e888F Quoter address: 0xFed014fdb55180094093765276764FE21B67ed38 NFTDescriptor address: 0x4c05686A968EF683Ea47eF67585ADC32563d00F8 NonfungibleTokenPositionDescriptor address: 0x8864c400FA2CBB97e2fb41fb032007a790C24C35 NonfungiblePositionManager address: 0x94e00D88e5C0087F0Dd3E42b5FcEA398259b52d7 SwapRouter address: 0x33C432A9De272FcF70c8924F43793E250AffE886 V3Migrator address: 0xA0246FD3af3Ea069bD3742Fe89eFf3e773CA09E4
- Save the retrieved contract addresses, you will need them later
- Exit to project directory
cd ../
permit2
-
Install Foundry
Attention
Please use this specific version for the download, as other versions may not function correctly.
foundryup --version nightly-5b7e4cb3c882b28f3c32ba580de27ce7381f415a
-
Clone repo from github
git clone -n https://github.com/Uniswap/permit2.git
- Go to
permit2
directorycd permit2
- Checkout version
git checkout -b wf db96e06278b78123970183d28f502217bef156f4
- Prepare contract
forge install
- Deploy contract
forge create --rpc-url https://rpc.testnet9.waterfall.network --private-key [Your private key] src/Permit2.sol:Permit2 Deployer: 0xa7e558Cc6efA1c41270eF4Aa227b3dd6B4a3951E Deployed to: 0x720D15aB16B1443016Fd267d00cCF87b9Becf1aC Transaction hash: 0x5556c3a23fc79477991e16cb087a7528a1642861da1fce947bf5232f4a1d9bf0
- Save the retrieved contract address, you will need it later
eg:0x720D15aB16B1443016Fd267d00cCF87b9Becf1aC
- Exit to project directory
cd ../
Universal-Router
-
Install Foundry
Attention
Please use this specific version for the download, as other versions may not function correctly.
foundryup --version nightly-5b7e4cb3c882b28f3c32ba580de27ce7381f415a
-
Clone repo from Github
git clone -n https://github.com/Uniswap/universal-router.git
- Go to
universal-router
directorycd universal-router
- Сheckout version
git checkout -b wf 4104efca7dc786cec631a51030ffb28bd46e1e5e
- Install packages
yarn install
- Prepare contract
forge install
- Create
DeployWaterfall.s.sol
inscript/deployParameters
directory and paste next code:
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.15; import {DeployUniversalRouter} from '../DeployUniversalRouter.s.sol'; import {RouterParameters} from 'contracts/base/RouterImmutables.sol'; contract DeployWaterfall is DeployUniversalRouter { function setUp() public override { params = RouterParameters({ permit2: 0x720D15aB16B1443016Fd267d00cCF87b9Becf1aC, weth9: 0xe05FeCA8B752051B207f071D876B442cACC9bd2c, seaport: UNSUPPORTED_PROTOCOL, seaportV1_4: UNSUPPORTED_PROTOCOL, openseaConduit: UNSUPPORTED_PROTOCOL, nftxZap: UNSUPPORTED_PROTOCOL, x2y2: UNSUPPORTED_PROTOCOL, foundation: UNSUPPORTED_PROTOCOL, sudoswap: UNSUPPORTED_PROTOCOL, elementMarket: UNSUPPORTED_PROTOCOL, nft20Zap: UNSUPPORTED_PROTOCOL, cryptopunks: UNSUPPORTED_PROTOCOL, looksRareV2: UNSUPPORTED_PROTOCOL, routerRewardsDistributor: UNSUPPORTED_PROTOCOL, looksRareRewardsDistributor: UNSUPPORTED_PROTOCOL, looksRareToken: UNSUPPORTED_PROTOCOL, v2Factory: UNSUPPORTED_PROTOCOL, v3Factory: 0x48A6024B11F67eaBD632d6C98d62B1eEa7D05c1E, pairInitCodeHash: 0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f, poolInitCodeHash: 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54 }); } }
- Change permit2, weth9(WWATER) and v3Factory(v3-core) addresses, which you got in previous steps
- Compile contracts
forge build
- Deploy contract
forge script --broadcast --rpc-url https://rpc.testnet9.waterfall.network --private-key [Your private key] --sig 'run()' script/deployParameters/DeployWaterfall.s.sol:DeployWaterfall == Return == Universal Router Deployed: 0x37256428625e4ed086aaffd66805c86b9288f39a
- Save the gotten contract addresses, you will need the later
- Exit to project directory
cd ../
UI
- Clone repo from Github
git clone -n https://github.com/Uniswap/interface.git
- Go to
interface
directorycd interface
- Checkout version
git checkout -b wf bc48b4fb0e1abb2c5961ecee3e8cc134dee6ac87
- Upload new file schema.graphql in
interface/src/graphql/thegraph/schema.graphql
. - Upload new file schema.graphql in
interface/src/graphql/data/schema.graphql
. - Remove polyfill
yarn remove polyfill-object.fromentries
- Install packages
yarn install
- Add polyfill
yarn add polyfill-object.fromentries@^1.0.1
- Add support Waterfall network to
src/constants/chains.ts
fileexport enum SupportedChainId { ... WATERFALL = 1501869, } ... export const CHAIN_IDS_TO_NAMES = { ... [SupportedChainId.WATERFALL]: 'waterfall', } ... export const SUPPORTED_GAS_ESTIMATE_CHAIN_IDS = [ ... SupportedChainId.WATERFALL, ] ... export const L1_CHAIN_IDS = [ ... SupportedChainId.WATERFALL, ]
- Add Waterfall Network info to
src/constants/chainInfo.ts
fileconst CHAIN_INFO: ChainInfoMap = { ... [SupportedChainId.WATERFALL]: { networkType: NetworkType.L1, blockWaitMsBeforeWarning: ms`10m`, docs: 'https://docs.waterfall.network/', explorer: 'https://explorer.testnet9.waterfall.network/', infoLink: 'https://waterfall.network/', label: 'Waterfall', logoUrl: 'https://explorer.testnet9.waterfall.network/favicon-152-precomposed.png', nativeCurrency: { name: 'Water', symbol: 'Water', decimals: 18 }, }, }
- Create tokens list like here:
https://storage.waterfall.network/daps/uniswap/token-list-testnet9.json
You should deploy WRC20 tokens. - Add your tokens list to
src/constants/lists.ts
file... const WATERFALL_LIST = 'https://storage.waterfall.network/daps/uniswap/token-list-testnet9.json' ... export const DEFAULT_ACTIVE_LIST_URLS: string[] = [UNI_LIST, WATERFALL_LIST]
- Add rpc url to
src/constants/networks.ts
fileexport const FALLBACK_URLS = { ... [SupportedChainId.WATERFALL]: [ 'https://rpc.testnet9.waterfall.network' ], } ... export const RPC_URLS = { ... [SupportedChainId.WATERFALL]: [...FALLBACK_URLS[SupportedChainId.WATERFALL]], }
- Add rpc provider to
src/constants/providers.ts
fileexport const RPC_PROVIDERS: { [key in SupportedChainId]: StaticJsonRpcProvider } = { ... [SupportedChainId.WATERFALL]: new AppJsonRpcProvider(SupportedChainId.WATERFALL), }
-
Add explorer
src/utils/anonymizeLink.ts
const EXPLORER_HOSTNAMES: { [hostname: string]: true } = { ... 'explorer.testnet9.waterfall.network': true, }
src/utils/getExplorerLink.ts
const BLOCK_EXPLORER_PREFIXES: { [chainId: number]: string } = { ... [SupportedChainId.WATERFALL]: 'https://explorer.testnet9.waterfall.network', }
-
Add Waterfall Network selection in file
src/components/NavBar/ChainSelector.tsx
const NETWORK_SELECTOR_CHAINS = [ ... SupportedChainId.WATERFALL, ]
- Change factory address
node_modules/@uniswap/v3-sdk/dist/constants.d.ts
export declare const FACTORY_ADDRESS = "0x48A6024B11F67eaBD632d6C98d62B1eEa7D05c1E";
node_modules/@uniswap/v3-sdk/dist/v3-sdk.cjs.development.js
var FACTORY_ADDRESS = '0x48A6024B11F67eaBD632d6C98d62B1eEa7D05c1E';
node_modules/@uniswap/v3-sdk/dist/v3-sdk.esm.js
var FACTORY_ADDRESS = '0x48A6024B11F67eaBD632d6C98d62B1eEa7D05c1E';
- Update permit2-sdk module to add contract address which was deployed in previous step:
node_modules/@uniswap/permit2-sdk/dist/constants.d.ts
export declare const PERMIT2_ADDRESS = "0x720D15aB16B1443016Fd267d00cCF87b9Becf1aC";
node_modules/@uniswap/permit2-sdk/dist/permit2-sdk.cjs.development.js
var PERMIT2_ADDRESS = '0x720D15aB16B1443016Fd267d00cCF87b9Becf1aC';
node_modules/@uniswap/permit2-sdk/dist/permit2-sdk.esm.js
var PERMIT2_ADDRESS = '0x720D15aB16B1443016Fd267d00cCF87b9Becf1aC';
- Add universal router and permit addresses in
node_modules/@uniswap/universal-router-sdk/dist/universal-router-sdk.cjs.development.js
andnode_modules/@uniswap/universal-router-sdk/dist/universal-router-sdk.esm.js
in... var UNIVERSAL_ROUTER_ADDRESS = function UNIVERSAL_ROUTER_ADDRESS(chainId) { switch (chainId) { ... case 1501869: // waterfall return '0x37256428625e4ed086aaffd66805c86b9288f39a'; default: throw new Error("Universal Router not deployed on chain " + chainId); } }; var WETH_ADDRESS = function WETH_ADDRESS(chainId) { switch (chainId) { ... case 1501869: //waterfall return '0xe05FeCA8B752051B207f071D876B442cACC9bd2c'; default: throw new Error("WETH9 or UniversalRouter not deployed on chain " + chainId); } }; var PERMIT2_ADDRESS = '0x720D15aB16B1443016Fd267d00cCF87b9Becf1aC';
node_modules/@uniswap/universal-router-sdk/dist/utils/constants.d.ts
export declare const PERMIT2_ADDRESS = "0x720D15aB16B1443016Fd267d00cCF87b9Becf1aC";
- Update contracts addresses in
src/constants/addresses.ts
file... // Waterfall const WATERFALL_V3_CORE_FACTORY_ADDRESSES = '0x48A6024B11F67eaBD632d6C98d62B1eEa7D05c1E' const WATERFALL_V3_MIGRATOR_ADDRESSES = '0xA0246FD3af3Ea069bD3742Fe89eFf3e773CA09E4' const WATERFALL_MULTICALL_ADDRESS = '0x0Ba145B472B04df34B20c249165bf1Ea726e888F' const WATERFALL_QUOTER_ADDRESSES = '0xFed014fdb55180094093765276764FE21B67ed38' const WATERFALL_NONFUNGIBLE_POSITION_MANAGER_ADDRESSES = '0x94e00D88e5C0087F0Dd3E42b5FcEA398259b52d7' const WATERFALL_SWAP_ROUTER_ADDRESSES = '0x33C432A9De272FcF70c8924F43793E250AffE886' ... export const V3_CORE_FACTORY_ADDRESSES: AddressMap = { ... [SupportedChainId.WATERFALL]: WATERFALL_V3_CORE_FACTORY_ADDRESSES, } ... export const V3_MIGRATOR_ADDRESSES: AddressMap = { ... [SupportedChainId.WATERFALL]: WATERFALL_V3_MIGRATOR_ADDRESSES, } ... export const MULTICALL_ADDRESS: AddressMap = { ... [SupportedChainId.WATERFALL]: WATERFALL_MULTICALL_ADDRESS, } ... export const QUOTER_ADDRESSES: AddressMap = { ... [SupportedChainId.WATERFALL]: WATERFALL_QUOTER_ADDRESSES, } ... export const NONFUNGIBLE_POSITION_MANAGER_ADDRESSES: AddressMap = { ... [SupportedChainId.WATERFALL]: WATERFALL_NONFUNGIBLE_POSITION_MANAGER_ADDRESSES, }
- Go to
src/constants/tokens.ts
and add WRAPPED_NATIVE_CURRENCYexport const WRAPPED_NATIVE_CURRENCY: { [chainId: number]: Token | undefined } = { ... [SupportedChainId.WATERFALL]: new Token( SupportedChainId.WATERFALL, '0xe05FeCA8B752051B207f071D876B442cACC9bd2c', 18, 'WWATER', 'Wraped Water' ), }
- Start
yarn run prepare yarn start