├── .gitignore ├── images ├── toggle.png └── uniswap.png ├── important_accounts_and_addresses_to_control.md ├── utils ├── housekeeping.sh └── find_init_code_hash.py ├── uniswap_interface ├── change_rpc.py ├── change_chain_id.py ├── scrape_hex_digests.py ├── deploy_interface.py └── modify_addresses.py ├── old ├── interface_installation_draft.md ├── how_to_deploy_uniswap_v1.md └── v2_installation_draft.md ├── uniswap_v2 ├── test_multicall.js ├── query_uniswap_contracts.js └── deploy_uniswap_v2.js ├── uniswap_v1 └── deploy_uniswap_v1.js ├── LICENSE ├── README.md └── erc20.sol /.gitignore: -------------------------------------------------------------------------------- 1 | installation_data.json 2 | -------------------------------------------------------------------------------- /images/toggle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/second-state/how_to_deploy_uniswap/HEAD/images/toggle.png -------------------------------------------------------------------------------- /images/uniswap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/second-state/how_to_deploy_uniswap/HEAD/images/uniswap.png -------------------------------------------------------------------------------- /important_accounts_and_addresses_to_control.md: -------------------------------------------------------------------------------- 1 | # Addresses to control 2 | 3 | Uniswap v2 deployment requires that a `feeToSetter` address is passed in to the factory contract at the time of deployment. This account's security is paramount. Future fees of 0.05% are controlled by this account. -------------------------------------------------------------------------------- /utils/housekeeping.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sudo apt-get update 3 | sudo apt-get -y upgrade 4 | sudo apt-get -y install npm 5 | npm -y install fs 6 | npm install web3 7 | npm install truffle-hdwallet-provider 8 | sudo apt-get -y install apache2 9 | # install Yarn 10 | curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - 11 | echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list 12 | sudo apt update && sudo apt -y install yarn 13 | curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - 14 | sudo apt-get install -y nodejs 15 | sudo apt autoremove 16 | cd ~ 17 | git clone https://github.com/Uniswap/uniswap-interface.git 18 | cd ~ 19 | cd uniswap-interface 20 | git clone https://github.com/second-state/how_to_deploy_uniswap.git 21 | cd how_to_deploy_uniswap/ -------------------------------------------------------------------------------- /uniswap_interface/change_rpc.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import subprocess 4 | 5 | f = open("../installation_data.json", "r") 6 | raw_data = f.read() 7 | json_data = json.loads(raw_data) 8 | 9 | infura = "https\:\/\/mainnet\.infura\.io\/v3\/faa4639b090f46499f29d894da0551a0" 10 | new_rpc = "http\:\/\/oasis-ssvm-demo\.secondstate\.io\:8545" 11 | 12 | sed_command_i_o = 's/' + infura + '/' + new_rpc + '/g' 13 | 14 | # # Update files 15 | dirs_to_process = ['../../src/', '../../build/', '../../node_modules/@uniswap/'] 16 | for individual_dir in dirs_to_process: 17 | for (root, dirs, files) in os.walk(individual_dir): 18 | for name in files: 19 | print("Processing: " + os.path.join(root, name)) 20 | subprocess.call(['sed', '-ir', sed_command_i_o, os.path.join(root, name)]) 21 | # Clean up old files 22 | for individual_dir in dirs_to_process: 23 | for (root, dirs, files) in os.walk(individual_dir): 24 | for name in files: 25 | if name.endswith("r"): 26 | print("Cleaning up old files") 27 | os.remove(os.path.join(root, name)) -------------------------------------------------------------------------------- /old/interface_installation_draft.md: -------------------------------------------------------------------------------- 1 | ** Please note this is a draft and this code is under heavy development. Not to be used in production ** 2 | 3 | ``` 4 | cd ~ 5 | ``` 6 | 7 | ``` 8 | git clone https://github.com/Uniswap/uniswap-interface.git 9 | ``` 10 | 11 | ``` 12 | cd uniswap-interface 13 | ``` 14 | 15 | 16 | ``` 17 | npm install 18 | ``` 19 | # Modify - scrape 20 | 21 | ``` 22 | git clone https://github.com/second-state/how_to_deploy_uniswap.git 23 | ``` 24 | 25 | ``` 26 | cd how_to_deploy_uniswap/uniswap_interface 27 | ``` 28 | Scrape all hex values from the source code to find where transactionIds, contract addresses, accounts and content hashes have been hard coded into the source code. 29 | 30 | ``` 31 | python3 scrape_hex_digests.py '../../src' 32 | ``` 33 | Returns 34 | ``` 35 | Total hex values found: 56 36 | ``` 37 | ``` 38 | python3 scrape_hex_digests.py '../../node_modules/@uniswap' 39 | ``` 40 | Returns 41 | ``` 42 | Total hex values found: 6, 430 43 | ``` 44 | ``` 45 | python3 scrape_hex_digests.py '../../cypress' 46 | ``` 47 | Returns 48 | ``` 49 | Total hex values found: 39 50 | ``` 51 | The above script creates a `hex_values.json` file which shows the filenames and hex values that are present throughout the source code 52 | 53 | # Modify - update 54 | 55 | 56 | # Build 57 | ``` 58 | npm run build 59 | ``` 60 | 61 | # Deploy 62 | * Move to Apache environment 63 | 64 | ``` 65 | cd ~/uniswap-interface 66 | cp -rp build/* /var/www/html/ 67 | ``` -------------------------------------------------------------------------------- /utils/find_init_code_hash.py: -------------------------------------------------------------------------------- 1 | # sudo apt-get -y install python3-pip 2 | # python3.6 -m pip install Web3 3 | # wget https://unpkg.com/@uniswap/v2-core@1.0.0/build/Combined-Json.json 4 | # python3 find_init_code.py 5 | 6 | import json 7 | from web3 import Web3 8 | 9 | f = open("combined_json.json", "r") 10 | raw_data = f.read() 11 | json_data = json.loads(raw_data) 12 | 13 | string_hex = "0x" + json_data["contracts"]["contracts/UniswapV2Pair.sol:UniswapV2Pair"]["bytecode"] 14 | temp_hex = Web3.keccak(hexstr=string_hex).hex() 15 | print(temp_hex) 16 | 17 | # The code below is what helped find the hash that is hard coded into Solidity because it was able to iterate through all of the JSON and hash automatically 18 | # print(json_data); 19 | 20 | # def iterate_multidimensional(my_dict): 21 | # for k,v in my_dict.items(): 22 | # if(isinstance(v,dict)): 23 | # print("Key:" + k) 24 | # iterate_multidimensional(v) 25 | # continue 26 | # if "bytecode" in k: 27 | # if str(v).startswith("0x"): 28 | # temp_hex = Web3.keccak(hexstr=str(v)).hex() 29 | # if "96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f" in temp_hex: 30 | # print("Key: " + k) 31 | # print("Success ... 0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f") 32 | # else: 33 | # temp_hex = Web3.keccak(hexstr="0x" + str(v)).hex() 34 | # if "96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f" in temp_hex: 35 | # print("Key: " + k) 36 | # print("Success ... 96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f") 37 | 38 | # iterate_multidimensional(json_data) 39 | -------------------------------------------------------------------------------- /uniswap_interface/change_chain_id.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | 4 | one_to_two = "MAINNET \= 1" 5 | one_to_two_II = "chainId\:\"1\"" 6 | one_to_two_III = "chainId\:1" 7 | one_to_two_IV ="1\: \'mainnet\'" 8 | one_to_two_V = "1\:\"0xa80171aB64F9913C5d0Df5b06D00030B4febDD6A\"" 9 | one_to_two_VI = "1\: \"0xa80171aB64F9913C5d0Df5b06D00030B4febDD6A\"" 10 | 11 | new_value = "MAINNET \= 2" 12 | new_value_II = "chainId\:\"2\"" 13 | new_value_III = "chainId\:2" 14 | new_value_IV = "2\: \'mainnet\'" 15 | new_value_V = "2\:\"0xa80171aB64F9913C5d0Df5b06D00030B4febDD6A\"" 16 | new_value_VI = "2\:\"0xa80171aB64F9913C5d0Df5b06D00030B4febDD6A\"" 17 | 18 | sed_command_I = 's/' + one_to_two + '/' + new_value + '/g' 19 | sed_command_chain_II = 's/' + one_to_two_II + '/' + new_value_II + '/g' 20 | sed_command_chain_III = 's/' + one_to_two_III + '/' + new_value_III + '/g' 21 | sed_command_chain_IV = 's/' + one_to_two_IV + '/' + new_value_IV + '/g' 22 | sed_command_chain_V = 's/' + one_to_two_V + '/' + new_value_V + '/g' 23 | sed_command_chain_VI = 's/' + one_to_two_VI + '/' + new_value_VI + '/g' 24 | # # Update files 25 | dirs_to_process = ['../../src/', '../../build/', '../../node_modules/@uniswap/'] 26 | for individual_dir in dirs_to_process: 27 | for (root, dirs, files) in os.walk(individual_dir): 28 | for name in files: 29 | print("Processing: " + os.path.join(root, name)) 30 | subprocess.call(['sed', '-ir', sed_command_I, os.path.join(root, name)]) 31 | subprocess.call(['sed', '-ir', sed_command_chain_II, os.path.join(root, name)]) 32 | subprocess.call(['sed', '-ir', sed_command_chain_III, os.path.join(root, name)]) 33 | subprocess.call(['sed', '-ir', sed_command_chain_IV, os.path.join(root, name)]) 34 | subprocess.call(['sed', '-ir', sed_command_chain_V, os.path.join(root, name)]) 35 | subprocess.call(['sed', '-ir', sed_command_chain_VI, os.path.join(root, name)]) 36 | # Clean up old files 37 | for individual_dir in dirs_to_process: 38 | for (root, dirs, files) in os.walk(individual_dir): 39 | for name in files: 40 | if name.endswith("r"): 41 | print("Cleaning up old files") 42 | os.remove(os.path.join(root, name)) 43 | -------------------------------------------------------------------------------- /uniswap_interface/scrape_hex_digests.py: -------------------------------------------------------------------------------- 1 | # ** Please note this is a draft and this code is under heavy development. Not to be used in production ** 2 | 3 | # python3 scrape_hex_digests.py 4 | 5 | # python3 scrape_hex_digests.py '../../build' 6 | import os 7 | import re 8 | import sys 9 | import json 10 | 11 | def main(argv): 12 | print(sys.argv[0]) 13 | print(sys.argv[1]) 14 | dirs_to_process = [] 15 | if len(sys.argv) == 2: 16 | dirs_to_process.append(sys.argv[1]) 17 | else: 18 | dirs_to_process.append('../../public/') 19 | dirs_to_process.append('../../build/') 20 | dirs_to_process.append('../../node_modules') 21 | dirs_to_process.append('../../src') 22 | print("Dirs to process: " + dirs_to_process[0]) 23 | temp_output = {} 24 | counter = 0 25 | print("Starting ...") 26 | hash_40 = re.compile('0x[a-fA-F0-9]{40}') 27 | hash_64 = re.compile('0x[a-fA-F0-9]{64}') 28 | for individual_dir in dirs_to_process: 29 | for (root, dirs, files) in os.walk(individual_dir): 30 | for name in files: 31 | file_path = os.path.join(root, name) 32 | if file_path.endswith(".r") or file_path.endswith(".py"): 33 | print("Skipping " + file_path) 34 | else: 35 | print("Processing: " + file_path) 36 | try: 37 | fr = open(file_path) 38 | fd = fr.read() 39 | print("Reading: " + file_path) 40 | temp_inner_object = {} 41 | hash_40_results = hash_40.findall(fd) 42 | hash_64_results = hash_64.findall(fd) 43 | if len(hash_40_results) > 0 or len(hash_64_results) > 0: 44 | counter = counter + len(hash_40_results) 45 | counter = counter + len(hash_64_results) 46 | temp_inner_object["hash_40"] = hash_40_results 47 | temp_inner_object["hash_64"] = hash_64_results 48 | temp_output[file_path] = temp_inner_object 49 | except: 50 | print("Not valid UTF8, skipping: " + file_path) 51 | fr.close() 52 | json_formatted_str = json.dumps(temp_output, indent=2) 53 | print("Results\n" + json_formatted_str) 54 | print("Writing these results to hex_values.json file ...") 55 | output_file = open('hex_values.json', 'w') 56 | output_file.writelines(json_formatted_str) 57 | output_file.close() 58 | print("Total hex values found: " + str(counter)) 59 | print("Success!") 60 | 61 | if __name__ == "__main__": 62 | main(sys.argv[1:]) 63 | 64 | -------------------------------------------------------------------------------- /old/how_to_deploy_uniswap_v1.md: -------------------------------------------------------------------------------- 1 | ** Please note this is a draft and this code is under heavy development. Not to be used in production ** 2 | 3 | # How to deploy Uniswap 4 | 5 | ## Background 6 | This article provides step-by-step instructions for installing [Uniswap](https://uniswap.org/) V1 on any [Ethereum](https://ethereum.org/en/) compatible blockchain. 7 | 8 | Some [Ethereum](https://ethereum.org/en/) compatible blockchains include: 9 | * [ParaTime](https://docs.oasis.dev/general/faq/oasis-network-faq) - built in collaboration by [Oasis Foundation](https://oasisprotocol.org/) & [SecondState](https://www.secondstate.io/) as announced [here](https://medium.com/oasis-protocol-project/ethereum-support-on-the-oasis-blockchain-3add9e13556). 10 | * [CyberMiles](https://www.cybermiles.io/en-us/) - a public blockchain for E-commerce. 11 | * [Ethereum Classic](https://ethereumclassic.org/) - Ethereum (ETH) blockchain network initially released on 30 July 2015, now known as Ethereum Classic (ETC). 12 | 13 | ### Uniswap V1 14 | [Uniswap V1](https://uniswap.org/docs/v1/), was [launched in November 2018](https://twitter.com/haydenzadams/status/1058376395108376577) on the Ethereum mainnet as a set of 2 [Vyper](https://vyper.readthedocs.io/en/stable/) smart contracts. Uniswap is an automated liquidity protocol which facilitates token exchanges on the Ethereum blockchain network. Uniswap has seen daily trading volumes of well beyond four hundred million dollars ($400, 000, 000 / day). 15 | 16 | [This tweet](https://twitter.com/haydenzadams/status/1300034164830408704) shows that Uniswap surpasses the daily Coinbase trade volume on occasion. 17 | 18 | #### Smart contracts 19 | The [Factory](https://github.com/Uniswap/uniswap-v1/blob/master/contracts/uniswap_factory.vy) and [Exchange](https://github.com/Uniswap/uniswap-v1/blob/master/contracts/uniswap_exchange.vy) Vyper smart contracts of Uniswap V1 contain all of the logic for the Uniswap protocol. These smart contracts are permissionless in nature and therefore Uniswap V1 will exist for as long as Ethereum does. 20 | 21 | ## Uniswap V2 22 | The most recent version of Uniswap, V2, includes a number of tangible improvements over V1. Uniswap V2 was [launched in May 2020](https://uniswap.org/blog/launch-uniswap-v2/) on the Ethereum mainnet [at block 10000835](https://etherscan.io/address/0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f#code) as a single [Solidity](https://github.com/ethereum/solidity) smart contract. 23 | 24 | #### Smart contracts 25 | Uniswap V2's [core Solidity smart contracts](https://github.com/Uniswap/uniswap-v2-core/tree/master/contracts) contain the logic which allows the Uniswap automated liquidity protocol to operate. 26 | 27 | ### Front-end 28 | Whilst it is posible to interact with Uniswap via smart contract function executions (in the command line/terminal), the official [front-end web application](https://github.com/Uniswap/uniswap-interface) provides a much nicer user experience; facilitating trading via mouse clicks and also facilitating wallet integration via browser extensions such as [Metamask](https://metamask.io/). 29 | 30 | ![Uniswap frontend](../images/uniswap.png) 31 | 32 | The image above shows the [entry point to the official Uniswap interface](https://uniswap.org/). This front end allows users on the web to switch between Uniswap V1 and Uniswap V2 using a simple `V1` `V2` toggle (as shown in the upper right corner of the image below). 33 | 34 | 35 | ![Uniswap frontend](../images/toggle.png) 36 | 37 | ## Installation 38 | 39 | To install Uniswap, 40 | 41 | -------------------------------------------------------------------------------- /uniswap_interface/deploy_interface.py: -------------------------------------------------------------------------------- 1 | # ** Please note this is a draft and this code is under heavy development. Not to be used in production ** 2 | 3 | 4 | # This file will update the chainid and contract addresses that are hard coded into npm dependencies which Uniswap Interface uses 5 | # We have non control over the npm libraries that the Uniswap Interface developers created and we are not wanting to fork this code because we will loose ability to update 6 | # Instead we just target const/concrete details like chainid and factory address etc. as a final step before hosting our interface implementation 7 | 8 | # Change to the uniswap-interface directory where you just ran `npm run build` 9 | # Execute this file at that location i.e. `python deploy_interface.py` 10 | 11 | import os 12 | import json 13 | import subprocess 14 | 15 | f = open("../installation_data.json", "r") 16 | raw_data = f.read() 17 | json_data = json.loads(raw_data) 18 | 19 | # Use this API to get ABI and Bytecode 20 | # http://api.etherscan.io/api?module=contract&action=getabi&address=0xTODO&format=raw 21 | v1_mainnet_factory_address = "0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95" 22 | v2_mainnet_factory_address = "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f" 23 | v2_mainnet_router_address = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D" 24 | v2_mainnet_multicall_address = "0xeefBa1e63905eF1D7ACbA5a8513c70307C1cE441" 25 | v2_mainnet_migrator_address = "0x16D4F26C15f3658ec65B1126ff27DD3dF2a2996b" 26 | v2_mainnet_weth_address = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" 27 | v2_mainnet_registry_address = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e" 28 | 29 | # Factory 30 | sed_command_v1_fac = 's/' + v1_mainnet_factory_address + '/' + json_data["contract_address"]["uniswap_factory"] + '/g' 31 | sed_command_v2_fac = 's/' + v2_mainnet_factory_address + '/' + json_data["contract_address"]["uniswap_v2"] + '/g' 32 | sed_command_v2_rou = 's/' + v2_mainnet_router_address + '/' + json_data["contract_address"]["router"] + '/g' 33 | sed_command_v2_mul = 's/' + v2_mainnet_multicall_address + '/' + json_data["contract_address"]["multicall"] + '/g' 34 | sed_command_v2_mig = 's/' + v2_mainnet_migrator_address + '/' + json_data["contract_address"]["migrator"] + '/g' 35 | sed_command_v2_wet = 's/' + v2_mainnet_weth_address + '/' + json_data["contract_address"]["weth"] + '/g' 36 | sed_command_v2_reg = 's/' + v2_mainnet_registry_address + '/' + json_data["contract_address"]["ens_registry"] + '/g' 37 | 38 | # # Update files 39 | dirs_to_process = ['../../src/', '../../build/', '../../node_modules/@uniswap/'] 40 | for individual_dir in dirs_to_process: 41 | for (root, dirs, files) in os.walk(individual_dir): 42 | for name in files: 43 | if name.endswith("rr"): 44 | print("Cleaning up old files") 45 | os.remove(os.path.join(root, name)) 46 | else: 47 | print("Processing: " + os.path.join(root, name)) 48 | subprocess.call(['sed', '-ir', sed_command_v1_fac, os.path.join(root, name)]) 49 | subprocess.call(['sed', '-ir', sed_command_v2_fac, os.path.join(root, name)]) 50 | subprocess.call(['sed', '-ir', sed_command_v2_rou, os.path.join(root, name)]) 51 | subprocess.call(['sed', '-ir', sed_command_v2_mul, os.path.join(root, name)]) 52 | subprocess.call(['sed', '-ir', sed_command_v2_mig, os.path.join(root, name)]) 53 | subprocess.call(['sed', '-ir', sed_command_v2_wet, os.path.join(root, name)]) 54 | subprocess.call(['sed', '-ir', sed_command_v2_reg, os.path.join(root, name)]) -------------------------------------------------------------------------------- /uniswap_v2/test_multicall.js: -------------------------------------------------------------------------------- 1 | // cd ~ 2 | // yarn add @makerdao/multicall 3 | // git clone https://github.com/makerdao/multicall.js.git 4 | // cd multicall.js 5 | // vi the package.json file in the multicall.js directory 6 | // change the test "examples/es-example.js" to the location of this file i.e. /home/me/how_to.../uni.../test_multicall.js 7 | // change the "../installation_data.js" value in the "fs.readFile" section and hard code the full path the the installatin_data.js file in the same fashion as above i.e. /home/me ... 8 | // yarn 9 | // yarn example 10 | var mc = require("@makerdao/multicall") 11 | const fs = require('fs'); 12 | 13 | function get_data() { 14 | return new Promise(function(resolve, reject) { 15 | fs.readFile('../installation_data.json', (err, data) => { 16 | if (err) throw err; 17 | resolve(data); 18 | }); 19 | }); 20 | } 21 | 22 | (async () => { 23 | // Read in the configuration information 24 | var data = await get_data(); 25 | var data_object = JSON.parse(data); 26 | // 27 | const config = { 28 | rpcUrl: data_object.provider.rpc_endpoint, 29 | multicallAddress: data_object.contract_address.multicall 30 | }; 31 | console.log("Creating watcher"); 32 | const watcher = await mc.createWatcher( 33 | [{ 34 | call: [ 35 | 'getEthBalance(address)(uint256)', 36 | data_object.public_key.alice 37 | ], 38 | returns: [ 39 | ['ETH_BALANCE', val => val / 10 ** 18] 40 | ] 41 | }, 42 | { 43 | call: ['getBlockHash(uint256)(bytes32)', 150], 44 | returns: [ 45 | ['SPECIFIC_BLOCK_HASH_0xFF4DB'] 46 | ] 47 | }, 48 | { 49 | call: ['getLastBlockHash()(bytes32)'], 50 | returns: [ 51 | ['LAST_BLOCK_HASH'] 52 | ] 53 | }, 54 | { 55 | call: ['getCurrentBlockTimestamp()(uint256)'], 56 | returns: [ 57 | ['CURRENT_BLOCK_TIMESTAMP'] 58 | ] 59 | }, 60 | { 61 | call: ['getCurrentBlockDifficulty()(uint256)'], 62 | returns: [ 63 | ['CURRENT_BLOCK_DIFFICULTY'] 64 | ] 65 | }, 66 | { 67 | call: ['getCurrentBlockGasLimit()(uint256)'], 68 | returns: [ 69 | ['CURRENT_BLOCK_GASLIMIT'] 70 | ] 71 | }, 72 | { 73 | call: ['getCurrentBlockCoinbase()(address)'], 74 | returns: [ 75 | ['CURRENT_BLOCK_COINBASE'] 76 | ] 77 | } 78 | ], 79 | config 80 | ); 81 | 82 | 83 | // Subscribe to state updates 84 | watcher.subscribe(update => { 85 | console.log(`Update: ${update.type} = ${update.value}`); 86 | }); 87 | 88 | // Subscribe to batched state updates 89 | watcher.batch().subscribe(updates => { 90 | console.log("Updates: " + JSON.stringify(updates)); 91 | // Handle batched updates here 92 | // Updates are returned as { type, value } objects, e.g: 93 | // { type: 'BALANCE_OF_MKR_WHALE', value: 70000 } 94 | }); 95 | 96 | // Subscribe to new block number updates 97 | watcher.onNewBlock(blockNumber => { 98 | console.log('New block:', blockNumber); 99 | }); 100 | 101 | // Start the watcher polling 102 | console.log("Starting watcher"); 103 | watcher.start(); 104 | 105 | })(); -------------------------------------------------------------------------------- /uniswap_interface/modify_addresses.py: -------------------------------------------------------------------------------- 1 | # ** Please note this is a draft and this code is under heavy development. Not to be used in production ** 2 | 3 | 4 | # This file will update the chainid and contract addresses that are hard coded into npm dependencies which Uniswap Interface uses 5 | # We have non control over the npm libraries that the Uniswap Interface developers created and we are not wanting to fork this code because we will loose ability to update 6 | # Instead we just target const/concrete details like chainid and factory address etc. as a final step before hosting our interface implementation 7 | 8 | # Change to the uniswap-interface directory where you just ran `npm run build` 9 | # Execute this file at that location i.e. `python deploy_interface.py` 10 | 11 | import os 12 | import json 13 | import subprocess 14 | 15 | f = open("../installation_data.json", "r") 16 | raw_data = f.read() 17 | json_data = json.loads(raw_data) 18 | 19 | # Use this API to get ABI and Bytecode 20 | # http://api.etherscan.io/api?module=contract&action=getabi&address=0xTODO&format=raw 21 | v1_mainnet_factory_address = "0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95" 22 | v2_mainnet_factory_address = "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f" 23 | v2_mainnet_router_address = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D" 24 | v2_mainnet_multicall_address = "0xeefBa1e63905eF1D7ACbA5a8513c70307C1cE441" 25 | v2_mainnet_migrator_address = "0x16D4F26C15f3658ec65B1126ff27DD3dF2a2996b" 26 | v2_mainnet_weth_address = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" 27 | v2_mainnet_registry_address = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e" 28 | v2_gas_relay_hub_address = "0xD216153c06E857cD7f72665E0aF1d7D82172F494" 29 | 30 | # Factory 31 | sed_command_v1_fac = 's/' + v1_mainnet_factory_address + '/' + json_data["contract_address"]["uniswap_factory"] + '/g' 32 | sed_command_v2_fac = 's/' + v2_mainnet_factory_address + '/' + json_data["contract_address"]["uniswap_v2"] + '/g' 33 | sed_command_v2_rou = 's/' + v2_mainnet_router_address + '/' + json_data["contract_address"]["router"] + '/g' 34 | sed_command_v2_mul = 's/' + v2_mainnet_multicall_address + '/' + json_data["contract_address"]["multicall"] + '/g' 35 | sed_command_v2_mig = 's/' + v2_mainnet_migrator_address + '/' + json_data["contract_address"]["migrator"] + '/g' 36 | sed_command_v2_wet = 's/' + v2_mainnet_weth_address + '/' + json_data["contract_address"]["weth"] + '/g' 37 | sed_command_v2_reg = 's/' + v2_mainnet_registry_address + '/' + json_data["contract_address"]["ens_registry"] + '/g' 38 | sed_command_v2_gas = 's/' + v2_gas_relay_hub_address + '/' + json_data["contract_address"]["gas_relay_hub_address"] + '/g' 39 | 40 | # # Update files 41 | dirs_to_process = ['../../src/', '../../build/', '../../node_modules/@uniswap/'] 42 | for individual_dir in dirs_to_process: 43 | for (root, dirs, files) in os.walk(individual_dir): 44 | for name in files: 45 | print("Processing: " + os.path.join(root, name)) 46 | subprocess.call(['sed', '-ir', sed_command_v1_fac, os.path.join(root, name)]) 47 | subprocess.call(['sed', '-ir', sed_command_v2_fac, os.path.join(root, name)]) 48 | subprocess.call(['sed', '-ir', sed_command_v2_rou, os.path.join(root, name)]) 49 | subprocess.call(['sed', '-ir', sed_command_v2_mul, os.path.join(root, name)]) 50 | subprocess.call(['sed', '-ir', sed_command_v2_mig, os.path.join(root, name)]) 51 | subprocess.call(['sed', '-ir', sed_command_v2_wet, os.path.join(root, name)]) 52 | subprocess.call(['sed', '-ir', sed_command_v2_reg, os.path.join(root, name)]) 53 | subprocess.call(['sed', '-ir', sed_command_v2_gas, os.path.join(root, name)]) 54 | # # Clean up r files 55 | the_dict = {} 56 | for individual_dir in dirs_to_process: 57 | for (root, dirs, files) in os.walk(individual_dir): 58 | for name in files: 59 | diff_file = os.path.join(root, name) + "r" 60 | temp = subprocess.call(['diff', '-c', os.path.join(root, name), diff_file]) 61 | the_dict[str(os.path.join(root, name))] = temp 62 | if name.endswith("r"): 63 | print("Cleaning up old files") 64 | os.remove(os.path.join(root, name)) 65 | print("Files changed ...") 66 | print(the_dict) -------------------------------------------------------------------------------- /uniswap_v2/query_uniswap_contracts.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const Web3 = require("web3"); 3 | 4 | function get_data() { 5 | return new Promise(function(resolve, reject) { 6 | fs.readFile('../installation_data.json', (err, data) => { 7 | if (err) throw err; 8 | resolve(data); 9 | }); 10 | }); 11 | } 12 | 13 | 14 | (async () => { 15 | // Read the config 16 | var data = await get_data(); 17 | var data_object = JSON.parse(data); 18 | 19 | // Dynamically fetch provider 20 | const URL = data_object.provider.rpc_endpoint; 21 | const web3 = new Web3(new Web3.providers.HttpProvider(URL)); 22 | 23 | await web3.eth.net.isListening(); 24 | console.log('Web3 is connected.'); 25 | 26 | // gas_relay_hub_address 27 | var gas_relay_hub_address = new web3.eth.Contract(data_object.abi.gas_relay_hub_address, data_object.contract_address.gas_relay_hub_address); 28 | var version = gas_relay_hub_address.methods.version().call() 29 | version.then(function(resultgas_relay_hub_address) { 30 | console.log("Gas relay hub address version is set to: " + resultgas_relay_hub_address); 31 | }) 32 | 33 | // uniswap_factory 34 | var uniswapV1Contract = new web3.eth.Contract(data_object.abi.uniswap_factory, data_object.contract_address.uniswap_factory); 35 | var feeTo = uniswapV1Contract.methods.exchangeTemplate().call() 36 | feeTo.then(function(resultexchangeTemplate) { 37 | console.log("V1 exchangeTemplate is set to: " + resultexchangeTemplate); 38 | }) 39 | 40 | // Factory 41 | var uniswapFactoryContract = new web3.eth.Contract(data_object.abi.uniswap_v2, data_object.contract_address.uniswap_v2); 42 | var feeTo = uniswapFactoryContract.methods.feeTo().call() 43 | feeTo.then(function(resultFeeTo) { 44 | console.log("V2 Factory feeTo is currently set to: " + resultFeeTo); 45 | }) 46 | var feeToSetter = uniswapFactoryContract.methods.feeToSetter().call() 47 | feeToSetter.then(function(resultFeeToSetter) { 48 | console.log("v2 Factory feeToSetter is currently set to: " + resultFeeToSetter); 49 | }) 50 | var allPairsLength = uniswapFactoryContract.methods.allPairsLength().call() 51 | allPairsLength.then(function(resultallPairsLength) { 52 | console.log("v2 Factory allPairsLength is currently set to: " + resultallPairsLength); 53 | }) 54 | 55 | // Router 56 | var uniswapRouterContract = new web3.eth.Contract(data_object.abi.router, data_object.contract_address.router); 57 | var factory = uniswapRouterContract.methods.factory().call() 58 | factory.then(function(resultfactory) { 59 | console.log("V2 Router02 factory is currently set to: " + resultfactory); 60 | }) 61 | var factory = uniswapRouterContract.methods.WETH().call() 62 | factory.then(function(resultWETH) { 63 | console.log("V2 Router02 WETH is currently set to: " + resultWETH); 64 | }) 65 | 66 | // WETH 67 | var uniswapWethContract = new web3.eth.Contract(data_object.abi.weth, data_object.contract_address.weth); 68 | var feeTo = uniswapWethContract.methods.name().call() 69 | feeTo.then(function(resultname) { 70 | console.log("WETH name is set to: " + resultname); 71 | }) 72 | var name = uniswapWethContract.methods.totalSupply().call() 73 | name.then(function(resultTotalSupply) { 74 | console.log("WETH totalSupply is set to: " + resultTotalSupply); 75 | }) 76 | // Multicall 77 | var uniswapMilticallContract = new web3.eth.Contract(data_object.abi.multicall, data_object.contract_address.multicall); 78 | var getBlockHash = uniswapMilticallContract.methods.getBlockHash(538).call() 79 | getBlockHash.then(function(resultgetBlockHash) { 80 | console.log("Multicall getBlockHash is set to: " + resultgetBlockHash); 81 | }) 82 | var getLastBlockHash = uniswapMilticallContract.methods.getLastBlockHash().call() 83 | getLastBlockHash.then(function(resultgetLastBlockHash) { 84 | console.log("Multicall getLastBlockHash is set to: " + resultgetLastBlockHash); 85 | }) 86 | var getCurrentBlockTimestamp = uniswapMilticallContract.methods.getCurrentBlockTimestamp().call() 87 | getCurrentBlockTimestamp.then(function(resultgetCurrentBlockTimestamp) { 88 | console.log("Multicall getCurrentBlockTimestamp is set to: " + resultgetCurrentBlockTimestamp); 89 | }) 90 | var getCurrentBlockDifficulty = uniswapMilticallContract.methods.getCurrentBlockDifficulty().call() 91 | getCurrentBlockDifficulty.then(function(resultgetCurrentBlockDifficulty) { 92 | console.log("Multicall getCurrentBlockDifficulty is set to: " + resultgetCurrentBlockDifficulty); 93 | }) 94 | var getCurrentBlockGasLimit = uniswapMilticallContract.methods.getCurrentBlockGasLimit().call() 95 | getCurrentBlockGasLimit.then(function(resultgetCurrentBlockGasLimit) { 96 | console.log("Multicall getCurrentBlockGasLimit is set to: " + resultgetCurrentBlockGasLimit); 97 | }) 98 | var getCurrentBlockCoinbase = uniswapMilticallContract.methods.getCurrentBlockCoinbase().call() 99 | getCurrentBlockCoinbase.then(function(resultgetCurrentBlockCoinbase) { 100 | console.log("Multicall getCurrentBlockCoinbase is set to: " + resultgetCurrentBlockCoinbase); 101 | }) 102 | 103 | // Migrator 104 | var uniswapMigratorContract = new web3.eth.Contract(data_object.abi.migrator, data_object.contract_address.migrator); 105 | console.log("Migrator: " + JSON.stringify(uniswapMigratorContract.methods)); 106 | 107 | // end await 108 | })(); 109 | -------------------------------------------------------------------------------- /old/v2_installation_draft.md: -------------------------------------------------------------------------------- 1 | ** Please note this is a draft and this code is under heavy development. Not to be used in production ** 2 | 3 | # Draft only 4 | 5 | ## Contracts 6 | 7 | The Uniswap v2 factory contract has a constructor which takes an address for the `feeToSetter` account. 8 | The address which is passed into the v2 factory constructor, can update both the public v2 Factory variables `feeTo` and `setFeeTo`. 9 | At present, the mainnet ETH `feeTo` is set to `0x0000000000000000000000000000000000000000`. 10 | The `feeToSetter` however is set to `0xc0a4272bb5df52134178Df25d77561CfB17ce407`; an unused account (potentially generated completely off-line for safety reasons). 11 | 12 | The account address which is passed into the V2 factory constructor is of paramount importance. It controls who can be the next fee setter and ultimately is responsible for who receives fees in the future. 13 | 14 | ## Draft outline of the V2 interface setup 15 | 16 | Add the rpc endpoint to .env and .env.production files 17 | 18 | ``` 19 | /home/ubuntu/uniswap-interface/.env 20 | ``` 21 | ``` 22 | /home/ubuntu/uniswap-interface/.env.production 23 | ``` 24 | 25 | Ensure that the network id is listed in the `index.ts` file located at `src/connectors/index.ts` for examle ... 26 | 27 | ``` 28 | export const injected = new InjectedConnector({ 29 | supportedChainIds: [2, 3, 4, 5, 42] 30 | }) 31 | 32 | ``` 33 | 34 | 35 | See Appendix A at the end of this file for current contract addresses which are in use on Oasis demo network. 36 | 37 | * Update factory address 38 | 39 | ``` 40 | /home/ubuntu/uniswap-interface/src/constants/v1/index.ts 41 | ``` 42 | 43 | * Update the multicall address at  44 | ``` 45 | /home/ubuntu/uniswap-interface/src/constants/multicall/index.ts 46 | ``` 47 | 48 | * Update the migrator address at  49 | ``` 50 | /home/ubuntu/uniswap-interface/src/constants/abis/migrator.ts 51 | ``` 52 | 53 | * Update the router address  54 | ``` 55 | /home/ubuntu/uniswap-interface/src/constants/index.ts 56 | ``` 57 | 58 | * Update the registrar address in two files ... both 59 | 60 | ``` 61 | /home/ubuntu/uniswap-interface/src/utils/resolveENSContentHash.ts 62 | ``` 63 | and 64 | ``` 65 | /home/ubuntu/uniswap-interface/src/hooks/useContract.ts 66 | ``` 67 | 68 | * Update the Unisocks address in  69 | ``` 70 | /home/ubuntu/uniswap-interface/src/hooks/useContract.ts 71 | ``` 72 | 73 | * Ad-hoc repairs 74 | I had to update the src/hooks/useContracts.ts file like this (remove the `WETH` from this line) 75 | ``` 76 | import { ChainId } from '@uniswap/sdk' 77 | ``` 78 | Then also update the useWETHContract to look like this (where we remove the chainid section and also use the actual address where weth is deployed) 79 | ``` 80 | export function useWETHContract(withSignerIfPossible?: boolean): Contract | null { 81 | return useContract('0x203162AA8b8e6b33c2c3c57246EC05bb46750287', WETH_ABI, withSignerIfPossible) 82 | } 83 | 84 | ``` 85 | * Build 86 | 87 | ``` 88 | npm install 89 | ``` 90 | 91 | ``` 92 | npm run build 93 | ``` 94 | 95 | * Move to Apache environment 96 | 97 | ``` 98 | cp -rp build/* /var/www/html/ 99 | ``` 100 | * Create a token list file 101 | 102 | ``` 103 | { 104 |   "name": "My Token List", 105 |   "logoURI": "ipfs://QmUSNbwUxUYNMvMksKypkgWs8unSm8dX2GjCPBVGZ7GGMr", 106 |   "keywords": [ 107 |     "audited", 108 |     "verified", 109 |     "special tokens" 110 |   ], 111 |   "tags": { 112 |     "Alice": { 113 |       "name": "Testcoin for Alice", 114 |       "description": "Tokens that are for testing" 115 |     }, 116 |     "Bob": { 117 |       "name": "Testcoin for Bob", 118 |       "description": "Tokens that are for testing" 119 |     } 120 |   }, 121 |   "timestamp": "2020-06-12T00:00:00+00:00", 122 |   "tokens": [ 123 |     { 124 |       "chainId": 1, 125 |       "address": "0xeb2eF6b55f603B858cA30ea9bDeaA0Ef37C4625d", 126 |       "symbol": "ALICE", 127 |       "name": "ALICE Coin", 128 |       "decimals": 18, 129 |       "logoURI": "ipfs://QmXfzKRvjZz3u5JRgC4v5mGVbm9ahrUiB4DgzHBsnWbTMM", 130 |       "tags": [ 131 |         "Alice" 132 |       ] 133 |     }, 134 |     { 135 |       "chainId": 1, 136 |       "address": "0xEbd5F1cd48b786c27B8E9afa83771E9251cd0A00", 137 |       "symbol": "BOB", 138 |       "name": "Bob Coin", 139 |       "decimals": 18, 140 |       "logoURI": "ipfs://QmUSNbwUxUYNMvMksKypkgWs8unSm8dX2GjCPBVGZ7GGMr", 141 |       "tags": [ 142 |         "Bob" 143 |       ] 144 |     } 145 |   ], 146 |   "version": { 147 |     "major": 1, 148 |     "minor": 0, 149 |     "patch": 2 150 |   } 151 | } 152 | ``` 153 | 154 | * Upload that to ipfs via a service like pinata which will give you a hash like this 155 | 156 | ``` 157 | QmSqsPSB1YT9vzxQ4gf5hb4jeMRuEfPwSbqidDqgJ32mT4 158 | ``` 159 | 160 | * Paste into uniswap to include the tokens in the interface 161 | 162 | ``` 163 | "ipfs://your_hash_goes_here" 164 | ``` 165 | 166 | In the new interface, the pool and migrate pages are only compatible with uniswap v2 (the interface for these pages requires access to the v2 contracts and the v1 contract) and therefore v2 must be installed to access any v1 liquidity via the interface. 167 | you should only deploy the precompiled Uniswap contracts in the build directories  168 | 169 | ## Pre-compiled contracts are all available here 170 | 171 | https://unpkg.com/@uniswap/v2-core@1.0.1/build/UniswapV2Factory.json 172 | 173 | 174 | # Appendix A 175 | Contract addresses in use on Oasis demo 176 | 177 | ``` 178 | "uniswap_factory": "0x30902E942a4b908Abb36dB4b2FA15BB120Ec14Ac", 179 |     "weth": "0x9F4fD40aC132bAc35a0cacBB60Dd3d46C3281ed9", 180 |     "uniswap_exchange_template": "0x81fD58bD093DDbc4cbEB2f730834c208776b32C1", 181 |     "alice_exchange": "0x1B7396cF2710BC65410299CeE2A2D1113DeDaa11", 182 |     "bob_exchange": "0xB0F2D86db0DF00Bf1FE173dD06EBcA5DCb76aF2f", 183 |     "alice_erc20_token": "0x9Fdf98Ee1b5A2Bd8932a8F8c1f0CF51ac294e583", 184 |     "bob_erc20_token": "0x7b5B7E4095D533b25248667213E6c84289D115bf", 185 |     "uniswap_v2": "0x713fA50D1533DA0922B5381f5dd9eFb88f59dc31", 186 |     "multicall": "0x675BB47BF34C209e3Eb8B82ABd39dB2623A5E8fD", 187 |     "migrator": "0x528adF9F52e3a3Baf7906e53618787702Ad6Aa4B", 188 |     "router": "0x81c62c801f222bC7433AA449C3F891cead41B0e8", 189 |     "ens_registry": "0xDC59c61281A6c16ebb4854b0c6599567830fda19", 190 |     "unisocks": "" 191 | ``` -------------------------------------------------------------------------------- /uniswap_v1/deploy_uniswap_v1.js: -------------------------------------------------------------------------------- 1 | // ** Please note this is a draft and this code is under heavy development. Not to be used in production ** 2 | 3 | 'use strict'; 4 | const fs = require('fs'); 5 | const HDWalletProvider = require('truffle-hdwallet-provider'); 6 | 7 | function get_data(_message) { 8 | return new Promise(function(resolve, reject) { 9 | fs.readFile('../installation_data.json', (err, data) => { 10 | if (err) throw err; 11 | resolve(data); 12 | }); 13 | }); 14 | } 15 | 16 | function write_data(_message) { 17 | return new Promise(function(resolve, reject) { 18 | fs.writeFile('../installation_data.json', _message, (err) => { 19 | if (err) throw err; 20 | console.log('Data written to file'); 21 | resolve(); 22 | }); 23 | }); 24 | } 25 | 26 | var privateKeys = []; 27 | var URL = ""; 28 | 29 | (async () => { 30 | // Read in the configuration information 31 | var data = await get_data(); 32 | var data_object = JSON.parse(data); 33 | // Add keys 34 | console.log("Adding Alice, Bob and Charlie keys ..."); 35 | privateKeys.push(data_object.private_key.alice, data_object.private_key.bob, data_object.private_key.charlie); 36 | // RPC 37 | URL = data_object.provider.rpc_endpoint; 38 | 39 | // Web3 - keys and accounts 40 | const Web3 = require("web3"); 41 | const provider = new HDWalletProvider(privateKeys, URL, 0, 3); 42 | const web3 = new Web3(provider); 43 | await web3.eth.net.isListening(); 44 | console.log('Web3 is connected.'); 45 | //console.log("Private keys: " + privateKeys); 46 | let accounts = await web3.eth.getAccounts(); 47 | console.log(`accounts: ${JSON.stringify(accounts)}`); 48 | 49 | // Add ABIs 50 | // -- ERC20 51 | var erc20Abi = data_object.abi.erc20; 52 | // -- Uniswap 53 | var uniswapFactoryAbi = data_object.abi.uniswap_factory; 54 | var uniswapExchangeAbi = data_object.abi.uniswap_exchange; 55 | // -- Uniswap V2 56 | var uniswapV2Abi = data_object.abi.uniswap_v2; 57 | // Add bytecode 58 | // -- ERC20 59 | var bytecode_alice = data_object.bytecode.alice_erc_20; 60 | var bytecode_bob = data_object.bytecode.bob_erc20; 61 | // -- Uniswap 62 | var uniswapFactoryBytecode = data_object.bytecode.uniswap_factory; 63 | var uniswapExchangeBytecode = data_object.bytecode.uniswap_exchange; 64 | // -- Uniswap V2 65 | var uniswapV2Bytecode = data_object.bytecode.uniswap_v2; 66 | // ERC20 deployment 67 | let aliceToken; 68 | aliceToken = await web3.eth.sendTransaction({ 69 | from: accounts[0], 70 | data: bytecode_alice 71 | }); 72 | let aliceTokenInstance = new web3.eth.Contract(erc20Abi, aliceToken.contractAddress); 73 | console.log(`\nAlice contract created at ${aliceToken.contractAddress}\nPlease store this address for future use ^^^\n`); 74 | data_object.contract_address.alice_erc20_token = aliceToken.contractAddress; 75 | 76 | let aliceBalance; 77 | aliceBalance = await aliceTokenInstance.methods.balanceOf(accounts[0]).call(); 78 | console.log(`aliceTokenInstance.balanceOf(${accounts[0]}) = ${aliceBalance}`); 79 | 80 | let bobToken; 81 | bobToken = await web3.eth.sendTransaction({ 82 | from: accounts[1], 83 | data: bytecode_bob 84 | }); 85 | let bobTokenInstance = new web3.eth.Contract(erc20Abi, bobToken.contractAddress); 86 | console.log(`\nBob contract created at ${bobToken.contractAddress}\nPlease store this address for future use ^^^\n`); 87 | data_object.contract_address.bob_erc20_token = bobToken.contractAddress; 88 | 89 | let bobBalance; 90 | bobBalance = await bobTokenInstance.methods.balanceOf(accounts[1]).call(); 91 | console.log(`bobTokenInstance.balanceOf(${accounts[1]}) = ${bobBalance}`); 92 | 93 | // Factory deployment 94 | let uniswapFactory; 95 | uniswapFactory = await web3.eth.sendTransaction({ 96 | from: accounts[2], 97 | data: uniswapFactoryBytecode 98 | }); // Charlie accounts[2] is the owner 99 | let uniswapFactoryInstance = new web3.eth.Contract(uniswapFactoryAbi, uniswapFactory.contractAddress); 100 | console.log(`\nFactory contract deployed at ${uniswapFactory.contractAddress}`); 101 | console.log(`Please store this factory address for future use ^^^`); 102 | data_object.contract_address.uniswap_factory = uniswapFactory.contractAddress; 103 | 104 | // Exchange template deployment 105 | let uniswapExchangeTemplate; 106 | uniswapExchangeTemplate = await web3.eth.sendTransaction({ 107 | from: accounts[2], 108 | data: uniswapExchangeBytecode 109 | }); // Charlie accounts[2] is the owner 110 | let uniswapExchangeTemplateInstance = new web3.eth.Contract(uniswapExchangeAbi, uniswapExchangeTemplate.contractAddress); 111 | console.log(`\nUniswap Exchange TEMPLATE contract deployed at ${uniswapExchangeTemplate.contractAddress}`); 112 | console.log(`Please store this exchange template address for future use ^^^\n`); 113 | data_object.contract_address.uniswap_exchange_template = uniswapExchangeTemplate.contractAddress; 114 | 115 | // Factory and exchange template linking 116 | var link = await uniswapFactoryInstance.methods.initializeFactory(uniswapExchangeTemplate.contractAddress).send({ 117 | from: accounts[2] 118 | }); // Charlie accounts[2] is the owner 119 | console.log(`\nFactory and exchange templates successfully linked at transaction: ${link}`); 120 | 121 | // ERC20 exchange creation 122 | console.log("Creating the exchange for Alice's " + aliceToken.contractAddress + " token. \nPlease wait ..."); 123 | let aliceExchange = await uniswapFactoryInstance.methods.createExchange(aliceToken.contractAddress).send({ 124 | from: accounts[2] 125 | }); // Charlie accounts[2] is the owner 126 | 127 | let aliceExchangeAddress; 128 | aliceExchangeAddress = await uniswapFactoryInstance.methods.getExchange(aliceToken.contractAddress).call(); 129 | console.log("Alice's Uniswap exchange is now live at: " + aliceExchangeAddress); 130 | console.log(`Please store this factory address for future use ^^^\n`); 131 | data_object.contract_address.alice_exchange = aliceExchangeAddress; 132 | 133 | console.log("Creating the exchange for Bob's " + bobToken.contractAddress + " token. \nPlease wait ..."); 134 | let bobExchange = await uniswapFactoryInstance.methods.createExchange(bobToken.contractAddress).send({ 135 | from: accounts[2] 136 | }); // Charlie accounts[2] is the owner 137 | 138 | let bobExchangeAddress; 139 | bobExchangeAddress = await uniswapFactoryInstance.methods.getExchange(bobToken.contractAddress).call(); 140 | console.log("Bob's Uniswap exchange is now live at: " + bobExchangeAddress); 141 | console.log(`Please store this factory address for future use ^^^\n`); 142 | data_object.contract_address.bob_exchange = bobExchangeAddress; 143 | 144 | /* We can approve via the button in the interface 145 | // Approve user accounts to spend 146 | let approvalForAlice; 147 | approvalForAlice = await aliceTokenInstance.methods.approve(aliceExchangeAddress, web3.utils.toWei('100', 'ether')).send({ 148 | "from": accounts[0] 149 | }); 150 | console.log(approvalForAlice); 151 | 152 | let approvalForBob; 153 | approvalForBob = await bobTokenInstance.methods.approve(bobExchangeAddress, web3.utils.toWei('100', 'ether')).send({ 154 | from: accounts[1] 155 | }); 156 | console.log(approvalForBob); 157 | */ 158 | /* We can add liquidity manually in the interface 159 | // Adding liquidity 160 | var amountOfAliceTokensToDeposit = web3.utils.toWei('100', 'ether'); 161 | var amountOfBobTokensToDeposit = web3.utils.toWei('100', 'ether'); 162 | // The amount of Ether tokens to deposit when adding liquidity - currently set to five thousand 163 | var amountOfEthToDeposit = web3.utils.toWei('10', 'ether'); 164 | 165 | // Create exchange instances 166 | let aliceExchangeTemplateInstance = new web3.eth.Contract(uniswapExchangeAbi, aliceExchangeAddress); 167 | let bobExchangeTemplateInstance = new web3.eth.Contract(uniswapExchangeAbi, bobExchangeAddress); 168 | // Add the liquidity 169 | let aliceLiquidity; 170 | aliceLiquidity = await aliceExchangeTemplateInstance.methods.addLiquidity(0, amountOfAliceTokensToDeposit, 1661840591).send({ 171 | "from": accounts[0], 172 | value: amountOfEthToDeposit, 173 | gas: "400000" 174 | }); 175 | console.log(aliceLiquidity); 176 | let bobLiquidity; 177 | bobLiquidity = await bobExchangeTemplateInstance.methods.addLiquidity(0, amountOfBobTokensToDeposit, 1661840591).send({ 178 | "from": accounts[1], 179 | value: amountOfEthToDeposit, 180 | gas: "400000" 181 | }); 182 | console.log(bobLiquidity); 183 | */ 184 | let data_to_write = JSON.stringify(data_object, null, 2); 185 | await write_data(data_to_write); 186 | 187 | 188 | await provider.engine.stop(); 189 | })(); 190 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | //** Please note this is a draft and this code is under heavy development. Not to be used in production ** 2 | 3 | # How to deploy Uniswap 4 | 5 | --- 6 | 7 | ## Housekeeping 8 | The code in this section is packaged up into a single `./utils/housekeeping.sh` file for your convenience. Below are the details of all of the `./utils/housekeeping.sh` commands for your understanding. 9 | 10 | ``` 11 | sudo apt-get update 12 | sudo apt-get -y upgrade 13 | sudo apt-get install npm 14 | npm install fs 15 | npm install web3 16 | npm install truffle-hdwallet-provider 17 | sudo apt-get install apache2 18 | # install Yarn 19 | curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - 20 | echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list 21 | sudo apt update && sudo apt install yarn 22 | ``` 23 | 24 | Update version of node 25 | ``` 26 | curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - 27 | sudo apt-get install -y nodejs 28 | ``` 29 | 30 | Clone the Uniswap Interface code using Git. 31 | ``` 32 | cd ~ 33 | git clone https://github.com/Uniswap/uniswap-interface.git 34 | ``` 35 | Change into the Uniswap Interface directory. 36 | ``` 37 | cd ~ 38 | cd uniswap-interface 39 | ``` 40 | Now, whilst in the `~/uniswap-interface directory`, clone the "How To Install Uniswap" code using Git. 41 | ``` 42 | git clone https://github.com/second-state/how_to_deploy_uniswap.git 43 | ``` 44 | Change into the `how_to_deploy_uniswap/` directory. 45 | ``` 46 | cd how_to_deploy_uniswap/ 47 | ``` 48 | 49 | --- 50 | 51 | ## Accounts 52 | 53 | Create 3 Ethereum compatible addresses using any method that you are comfortable with i.e. [web3js](https://web3js.readthedocs.io/en/v1.2.11/web3-eth-accounts.html) etc. 54 | 55 | Now paste the **private** and **public** keys of those addresses into the installation_data.json file as shown below. 56 | ``` 57 | vi ~/uniswap-interface/how_to_deploy_uniswap/installation_data.json 58 | ``` 59 | Here is an example of the `private_key` and `public_key` sections of that file. 60 | ``` 61 | "private_key": { 62 | "alice": "your_new_key_here", 63 | "bob": "your_new_key_here", 64 | "charlie": "your_new_key_here" 65 | }, 66 | "public_key": { 67 | "alice": "your_new_key_here", 68 | "bob": "your_new_key_here", 69 | "charlie": "your_new_key_here" 70 | } 71 | ``` 72 | You will need to fund these accounts with network tokens. So depending on your network, please go ahead and send at least 20 network tokens (from a Faucet etc.) to all three of these accounts. 73 | 74 | Now place the RPC URL to your Ethereum compatible network in that same `installation_data.json` file. 75 | ``` 76 | vi ~/uniswap-interface/how_to_deploy_uniswap/installation_data.json 77 | ``` 78 | Here is an example of the `rpc_endpoint` section of that file. 79 | ``` 80 | "provider": { 81 | "rpc_endpoint": "http://rpc_url:port" 82 | } 83 | ``` 84 | 85 | --- 86 | 87 | ## V1 88 | Now run the Uniswap V1 smart contract installer. 89 | ``` 90 | cd ~/uniswap-interface/how_to_deploy_uniswap/uniswap_v1 91 | ``` 92 | ``` 93 | node deploy_uniswap_v1.js 94 | ``` 95 | If you open the `../installation_data.json` file, you will see that the Uniswap V1 contract addresses and the Alice and Bob (ERC20 and ERC20 Exchange) addresses have been automatically filled in. 96 | ``` 97 | "contract_address": { 98 | "uniswap_factory": "0x2DF5e651be537bB564005340EA5D8f6fA763b530", 99 | "weth": "", 100 | "uniswap_exchange_template": "0x68Fc886B0ca3D65AE8Ad21Fde01d8C4E2AD9d86c", 101 | "alice_exchange": "0x4A8f21726434951f5C1baA0F067d50fdA2a297e2", 102 | "bob_exchange": "0x61d82A90455EC7cDEdF7cF7F5267c0aF6657c626", 103 | "alice_erc20_token": "0x240Fc9370709bad1F4402186701C76e36a20848b", 104 | "bob_erc20_token": "0x09cB0AE6dddF68Aaad81b8f6B83c30dfdaA65b48", 105 | "uniswap_v2": "", 106 | "multicall": "", 107 | "migrator": "", 108 | "router": "", 109 | "ens_registry": "", 110 | "unisocks": "" 111 | } 112 | ``` 113 | 114 | --- 115 | 116 | ## V2 117 | 118 | Now run the Uniswap V2 smart contract installation script. 119 | ``` 120 | cd ~/uniswap-interface/how_to_deploy_uniswap/uniswap_v2 121 | ``` 122 | 123 | ### Important Warning 124 | The `feeToSetter` has been hard-coded to the `Charlie` account inside the `deploy_uniswap_v2.js` script (that you are about to run). The `feeToSetter` is the account that is responsible for future profit that result from trades. This account is set to `Charlie` for demonstration purposes only. **If you are running this script, you are responsible for correctly setting the `feeToSetter` account up and managing its private keys.** 125 | 126 | ``` 127 | node deploy_uniswap_v2.js 128 | ``` 129 | Congratulations, the smart contracts are all deployed. You will see that all of the contract addresses in the `installation_data.json` file have been filled out. 130 | ``` 131 | "contract_address": { 132 | "uniswap_factory": "0x2DF5e651be537bB564005340EA5D8f6fA763b530", 133 | "weth": "0x043c7D26e381CB1bb025b4CE0A6E0C63D7767866", 134 | "uniswap_exchange_template": "0x68Fc886B0ca3D65AE8Ad21Fde01d8C4E2AD9d86c", 135 | "alice_exchange": "0x4A8f21726434951f5C1baA0F067d50fdA2a297e2", 136 | "bob_exchange": "0x61d82A90455EC7cDEdF7cF7F5267c0aF6657c626", 137 | "alice_erc20_token": "0x240Fc9370709bad1F4402186701C76e36a20848b", 138 | "bob_erc20_token": "0x09cB0AE6dddF68Aaad81b8f6B83c30dfdaA65b48", 139 | "uniswap_v2": "0x0fA47ae2b7Dee29571678580BBe9A8A88436E393", 140 | "multicall": "0x50F0463B01119Aa954ce40a7f21ecf4573E7605a", 141 | "migrator": "0x3cBe562Fd434aF61601937895000A91D014a49e7", 142 | "router": "0x5c192a0155D504772F3bc2689aF69116E098ECAa", 143 | "ens_registry": "0xA07e2676495eEDEdb5A50b9ba020Ba3A98f87D4E" 144 | } 145 | ``` 146 | 147 | --- 148 | 149 | ## Interface 150 | 151 | Now change into the `uniswap_interface` directory. 152 | ``` 153 | cd ~/uniswap-interface/how_to_deploy_uniswap/uniswap_interface 154 | ``` 155 | Now run the `modify_addresses.py` script 156 | ``` 157 | python3 modify_addresses.py 158 | ``` 159 | Change back to the Uniswap directory so we can build the application. 160 | ``` 161 | cd ~/uniswap-interface/ 162 | ``` 163 | An `ls` should look like this (no build folder yet) 164 | ``` 165 | LICENSE README.md cypress cypress.json how_to_deploy_uniswap node_modules package.json public src tsconfig.json yarn.lock 166 | ``` 167 | Build the application's dependencies using the following command. 168 | ``` 169 | yarn 170 | ``` 171 | 172 | --- 173 | 174 | ### Chain id changes (optional) 175 | 176 | **ChainID** 177 | Please note: the chainId for each network is actuall set [inside the Uniswap SDK's code](https://github.com/Uniswap/uniswap-sdk/blob/v2/src/constants.ts#L7) 178 | You may not need/want to change this but if you do i.e. you are using chainId `2` instead of `1` please perform the following tasks 179 | 180 | Open the `how_to_deploy_uniswap/uniswap_interface/change_chain_id.py` file and edit the `one_to_two` and `one_to_two_II` and `new_value` and `new_value_II` variables to suite your situation i.e. changing from chainId `1` to `2` would look like this. 181 | ``` 182 | one_to_two = "MAINNET = 1" 183 | one_to_two_II = "chainId\:\"1\"" 184 | one_to_two_III = "chainId:1" 185 | one_to_two_IV ="1: 'mainnet'" 186 | 187 | new_value = "MAINNET = 2" 188 | new_value_II = "chainId\:\"2\"" 189 | new_value_III = "chainId:2" 190 | new_value_IV = "2: 'mainnet'" 191 | ``` 192 | 193 | Be sure to escape `/` and `.` and `:` (as shown above) because these will break the command when executed. 194 | 195 | Now run this file 196 | ``` 197 | python3.6 change_chain_id.py 198 | ``` 199 | 200 | In addition to the above change, if your chainId is not standard i.e. your mainnet is not `1`, then you must also modify the `export declare const WETH` section of the `node_modules/@uniswap/sdk/dist/entities/token.d.ts` file. The first position in this enum `1: Token;` represents the MAINNET so go ahead and change it to suit your needs. In our case `1: Token;` 201 | 202 | ``` 203 | export declare const WETH: { 204 | 1: Token; 205 | 3: Token; 206 | 4: Token; 207 | 5: Token; 208 | 42: Token; 209 | }; 210 | 211 | ``` 212 | In addition to the above change, again if your chainId is not standard then go ahead and also update the `src/utils/index.ts` file in the following two places i.e. `1: '',` and `ETHERSCAN_PREFIXES[1]` 213 | 214 | ``` 215 | const ETHERSCAN_PREFIXES: { [chainId in ChainId]: string } = { 216 | 1: '', 217 | 3: 'ropsten.', 218 | 4: 'rinkeby.', 219 | 5: 'goerli.', 220 | 42: 'kovan.' 221 | } 222 | ``` 223 | 224 | ``` 225 | const prefix = `https://${ETHERSCAN_PREFIXES[chainId] || ETHERSCAN_PREFIXES[1]}etherscan.io` 226 | ``` 227 | 228 | In addition to the above change, another file in the Uniswap Interface source code specifies `supportedChainIds`. If your chainId is not in the list then add it like this `vi src/connectors/index.ts` 229 | 230 | ``` 231 | export const injected = new InjectedConnector({ 232 | supportedChainIds: [1, 2, 3, 4, 5, 42] 233 | }) 234 | ``` 235 | In that same file, also change the `1` to your chainId in line 14 i.e. 236 | ``` 237 | export const NETWORK_CHAIN_ID: number = parseInt(process.env.REACT_APP_CHAIN_ID ?? '1') 238 | ``` 239 | 240 | Hopefully you did not have to change the `chainId`. If you are all set then go ahead and build the Uniswap Interface application 241 | 242 | --- 243 | 244 | ### Disable Unisocks (Optional) 245 | This [Unisocks contract](https://etherscan.io/address/0x65770b5283117639760beA3F867b69b3697a91dd#code), this [other Uniswap contract](https://etherscan.io/address/0x23B608675a2B2fB1890d3ABBd85c5775c51691d5) and the [hard-coded Unisocks metadata](https://cloudflare-ipfs.com/ipfs/QmNZEeAN1zk6hLoHHREVkZ7PoPYaoH7n6LR6w9QAcEc29h) are deployed against real-world assets (socks) and therefore it makes no sense to include this in the build. 246 | In order to disable the Unisocks component of this build we need to do the following updates to the code. 247 | 248 | #### useContract.ts 249 | * Comment out the `import UNISOCKS_ABI from '../constants/abis/unisocks.json'` line in the src/hooks/useContract.ts file 250 | 251 | * Comment out the `useSocksController` section of the `./src/hooks/useContract.ts` file 252 | ``` 253 | export function useSocksController(): Contract | null { 254 | const { chainId } = useActiveWeb3React() 255 | return useContract( 256 | chainId === ChainId.MAINNET ? '0x65770b5283117639760beA3F867b69b3697a91dd' : undefined, 257 | UNISOCKS_ABI, 258 | false 259 | ) 260 | } 261 | 262 | ``` 263 | #### useSocksBalance.ts 264 | * `mv src/hooks/useSocksBalance.ts src/hooks/useSocksBalance.ts.orig` 265 | 266 | #### src/components/Web3Status/index.tsx 267 | * Comment out `import { useHasSocks } from '../../hooks/useSocksBalance'` and `const hasSocks = useHasSocks()` which are in the `src/components/Web3Status/index.tsx` file 268 | * Also comment out this block of code 269 | ``` 270 | const SOCK = ( 271 | 272 | 🧦 273 | 274 | ) 275 | ``` 276 | from the `src/components/Web3Status/index.tsx` file 277 | * Also delete the `{hasSocks ? SOCK : null}` line of code which is also in the `src/components/Web3Status/index.tsx` file 278 | 279 | 280 | ### Environment variables 281 | 282 | Open the `.env` and `.env.production` files and update the `REACT_APP_CHAIN_ID` and the `REACT_APP_NETWORK_URL` to suite your needs. 283 | 284 | ### Change the hard-coded RPC 285 | 286 | Open the `how_to_deploy_uniswap/uniswap_interface/change_rpc.py` file and edit the following variables to suite your needs. 287 | 288 | ``` 289 | infura = "https\:\/\/mainnet\.infura\.io\/v3\/faa4639b090f46499f29d894da0551a0" 290 | new_rpc = "http\:\/\/oasis-ssvm-demo\.secondstate\.io\:8545" 291 | ``` 292 | 293 | **Be sure to escape** `/` and `.` and `:` (as shown above) **because these will break the command when executed**. 294 | 295 | Now run this script 296 | ``` 297 | python3.6 change_rpc.py 298 | ``` 299 | 300 | ### Build 301 | 302 | Modify any addresses which are lurking in dependencies etc. 303 | ``` 304 | cd how_to_deploy_uniswap/uniswap_interface/ && python3 modify_addresses.py 305 | cd ../../ 306 | ``` 307 | ``` 308 | yarn run build 309 | ``` 310 | This will generate a new `build` directory as well as some new files, as shown below. 311 | ``` 312 | 450.29 KB build/static/js/4.047da443.chunk.js 313 | 276.48 KB build/static/js/5.5c7ecd7f.chunk.js 314 | 155.14 KB build/static/js/9.1f17fe1e.chunk.js 315 | 95.38 KB build/static/js/main.38d70569.chunk.js 316 | 67.14 KB build/static/js/0.1e3e94eb.chunk.js 317 | 66.33 KB build/static/js/6.e890ef53.chunk.js 318 | 6.56 KB build/static/js/1.5f3a35e8.chunk.js 319 | 1.24 KB build/static/js/runtime-main.c8bb7174.js 320 | 907 B build/static/css/4.996ad921.chunk.css 321 | 165 B build/static/js/8.81f9e545.chunk.js 322 | 164 B build/static/js/7.494e051e.chunk.js 323 | ``` 324 | You will remember that we just ran the `modify_addresses.py` script. We are now going to run that **again** (but this time, over the build folder, which the above build command just created). This is just to make sure that there are no addresses which relate to the original Uniswap source code (but rather our newly created contract addresses). 325 | ``` 326 | cd how_to_deploy_uniswap/uniswap_interface/ && python3 modify_addresses.py 327 | ``` 328 | 329 | Now run the `change_rpc.py` again also. 330 | ``` 331 | python3.6 change_rpc.py 332 | ``` 333 | 334 | --- 335 | 336 | If you are modifying the chainId (if you did the work above), please run this again. 337 | 338 | **WARNING** only run this if you are using a different chainId **!** 339 | ``` 340 | python3.6 change_chain_id.py 341 | ``` 342 | 343 | --- 344 | 345 | Now, we return to the Uniswap directory to copy the modified `build` files over to our Apache2 server, where they will be deployed for the end users. 346 | ``` 347 | cd ../../ && sudo cp -rp build/* /var/www/html/ && sudo /etc/init.d/apache2 restart 348 | ``` 349 | ![Uniswap](./images/toggle.png) 350 | 351 | 352 | # More 353 | 354 | If code changes are made in the source files (i.e. a console.log statement etc.), the following command is a one-stop-shop for a restart 355 | ``` 356 | yarn run build && cd how_to_deploy_uniswap/uniswap_interface/ && python3 modify_addresses.py && cd ../../ && sudo cp -rp build/* /var/www/html/ && sudo /etc/init.d/apache2 restart 357 | ``` 358 | 359 | **v1** 360 | For official information, please see the [official documentation of Uniswap V1](https://uniswap.org/docs/v1/) 361 | 362 | **V2** 363 | For official information, please see the [official documentation of Uniswap V2](https://uniswap.org/docs/v2/) 364 | -------------------------------------------------------------------------------- /uniswap_v2/deploy_uniswap_v2.js: -------------------------------------------------------------------------------- 1 | //** Please note this is a draft and this code is under heavy development. Not to be used in production ** 2 | 'use strict'; 3 | const fs = require('fs'); 4 | const HDWalletProvider = require('truffle-hdwallet-provider'); 5 | 6 | function get_data(_message) { 7 | return new Promise(function(resolve, reject) { 8 | fs.readFile('../installation_data.json', (err, data) => { 9 | if (err) throw err; 10 | resolve(data); 11 | }); 12 | }); 13 | } 14 | 15 | function write_data(_message) { 16 | return new Promise(function(resolve, reject) { 17 | fs.writeFile('../installation_data.json', _message, (err) => { 18 | if (err) throw err; 19 | console.log('Data written to file'); 20 | resolve(); 21 | }); 22 | }); 23 | } 24 | 25 | var privateKeys = []; 26 | var URL = ""; 27 | 28 | 29 | (async () => { 30 | // Read in the configuration information 31 | var data = await get_data(); 32 | var data_object = JSON.parse(data); 33 | // Add keys 34 | console.log("Adding Alice, Bob and Charlie keys ..."); 35 | privateKeys.push(data_object.private_key.alice, data_object.private_key.bob, data_object.private_key.charlie); 36 | // RPC 37 | URL = data_object.provider.rpc_endpoint; 38 | 39 | // Web3 - keys and accounts 40 | const Web3 = require("web3"); 41 | const provider = new HDWalletProvider(privateKeys, URL, 0, 3); 42 | const web3 = new Web3(provider); 43 | await web3.eth.net.isListening(); 44 | console.log('Web3 is connected.'); 45 | let accounts = await web3.eth.getAccounts(); 46 | console.log(`accounts: ${JSON.stringify(accounts)}`); 47 | // -- Uniswap V2 48 | var uniswapV2Bytecode = data_object.bytecode.uniswap_v2; 49 | var uniswapV2Abi = data_object.abi.uniswap_v2; 50 | var uniswapMulticallBytecode = data_object.bytecode.multicall; 51 | var uniswapMulticallAbi = data_object.abi.multicall; 52 | var uniswapMigratorBytecode = data_object.bytecode.migrator; 53 | var uniswapMigratorAbi = data_object.abi.migrator; 54 | var uniswapRouterBytecode = data_object.bytecode.router; 55 | var uniswapRouterAbi = data_object.abi.router; 56 | var uniswapEnsRegistryBytecode = data_object.bytecode.ens_registry; 57 | var uniswapEnsRegistryAbi = data_object.abi.ens_registry; 58 | var uniswapUnisocksBytecode = data_object.bytecode.unisocks; 59 | var uniswapUnisocksAbi = data_object.abi.unisocks; 60 | var uniswapWETHBytecode = data_object.bytecode.weth; 61 | var uniswapWETHAbi = data_object.abi.weth; 62 | var gasRelayHubAddressAbi = data_object.abi.gas_relay_hub_address; 63 | var gasRelayHubAddressBytecode = data_object.bytecode.gas_relay_hub_address; 64 | 65 | // Fee to setter account controls this factory forever. Please choose your feeToSetter account carefully 66 | // Must be secure and preserved; this is paramount 67 | var _feeToSetter = accounts[2]; 68 | // Uniswap V2 69 | // V2 Factory Deployment 70 | console.log("Deploying Uniswap V2 now, please wait ..."); 71 | let uniswapV2; 72 | uniswapV2 = await web3.eth.sendTransaction({ 73 | from: accounts[2], 74 | data: uniswapV2Bytecode 75 | }); // Charlie accounts[2] is the owner 76 | let uniswapV2Instance = new web3.eth.Contract(uniswapV2Abi, uniswapV2.contractAddress); 77 | uniswapV2Instance.deploy({ 78 | data: uniswapV2Bytecode, 79 | arguments: [_feeToSetter] 80 | }) 81 | .send({ 82 | from: accounts[2], 83 | gas: 4700000, 84 | gasPrice: '30000000000' 85 | }, function(error, transactionHash) { 86 | console.log(transactionHash); 87 | }) 88 | .on('error', function(error) { 89 | console.log(error); 90 | }) 91 | .on('transactionHash', function(transactionHash) { 92 | console.log("Transaction hash: " + transactionHash); 93 | }) 94 | .on('receipt', function(receipt) { 95 | console.log("Contract address: " + receipt.contractAddress) // contains the new contract address 96 | data_object.contract_address.uniswap_v2 = receipt.contractAddress; 97 | let data_to_write = JSON.stringify(data_object, null, 2); 98 | write_data(data_to_write); 99 | }) 100 | .then(function(newContractInstance) { 101 | console.log(newContractInstance.options.address) // instance with the new contract address 102 | var feeTo = newContractInstance.methods.feeTo().call() 103 | feeTo.then(function(resultFeeTo) { 104 | console.log("feeTo is currently set to: " + resultFeeTo); 105 | }) 106 | var feeToSetter = newContractInstance.methods.feeToSetter().call() 107 | feeToSetter.then(function(resultFeeToSetter) { 108 | console.log("feeToSetter is currently set to: " + resultFeeToSetter); 109 | }) 110 | }); 111 | // Uniswap V2 WETH 112 | // V2 WETH Deployment 113 | console.log("Deploying WETH now, please wait ..."); 114 | let uniswapWETH; 115 | uniswapWETH = await web3.eth.sendTransaction({ 116 | from: accounts[2], 117 | data: uniswapWETHBytecode 118 | }); // Charlie accounts[2] is the owner 119 | let uniswapWETHInstance = new web3.eth.Contract(uniswapWETHAbi, uniswapWETH.contractAddress); 120 | uniswapWETHInstance.deploy({ 121 | data: uniswapWETHBytecode 122 | }) 123 | .send({ 124 | from: accounts[2], 125 | gas: 4700000, 126 | gasPrice: '30000000000' 127 | }, function(error, transactionHash) { 128 | console.log(transactionHash); 129 | }) 130 | .on('error', function(error) { 131 | console.log(error); 132 | }) 133 | .on('transactionHash', function(transactionHash) { 134 | console.log("Transaction hash: " + transactionHash); 135 | }) 136 | .on('receipt', function(receipt) { 137 | console.log("Contract address: " + receipt.contractAddress) // contains the new contract address 138 | data_object.contract_address.weth = receipt.contractAddress; 139 | let data_to_write = JSON.stringify(data_object, null, 2); 140 | write_data(data_to_write); 141 | }) 142 | .then(function(newContractInstance) { 143 | console.log(newContractInstance.options.address) // instance with the new contract address 144 | var name = newContractInstance.methods.name().call() 145 | name.then(function(resultName) { 146 | console.log("Name set to: " + resultName); 147 | }) 148 | var symbol = newContractInstance.methods.symbol().call() 149 | symbol.then(function(resultSymbol) { 150 | console.log("Symbol set to: " + resultSymbol); 151 | }) 152 | var totalSupply = newContractInstance.methods.totalSupply().call() 153 | totalSupply.then(function(resultTotalSupply) { 154 | console.log("Total Supply set to: " + resultTotalSupply); 155 | }) 156 | }); 157 | 158 | // Uniswap V2 ROUTER2 159 | // V2 ROUTER2 Deployment 160 | console.log("Deploying ROUTER2 now, please wait ..."); 161 | let uniswapROUTER2; 162 | uniswapROUTER2 = await web3.eth.sendTransaction({ 163 | from: accounts[2], 164 | data: uniswapRouterBytecode 165 | }); // Charlie accounts[2] is the owner 166 | let uniswapROUTER2Instance = new web3.eth.Contract(uniswapRouterAbi, uniswapROUTER2.contractAddress); 167 | uniswapROUTER2Instance.deploy({ 168 | data: uniswapRouterBytecode, 169 | arguments: [data_object.contract_address.uniswap_v2, data_object.contract_address.weth] 170 | }) 171 | .send({ 172 | from: accounts[2], 173 | gas: 4700000, 174 | gasPrice: '30000000000' 175 | }, function(error, transactionHash) { 176 | console.log(transactionHash); 177 | }) 178 | .on('error', function(error) { 179 | console.log(error); 180 | }) 181 | .on('transactionHash', function(transactionHash) { 182 | console.log("Transaction hash: " + transactionHash); 183 | }) 184 | .on('receipt', function(receipt) { 185 | console.log("Contract address: " + receipt.contractAddress) // contains the new contract address 186 | data_object.contract_address.router = receipt.contractAddress; 187 | let data_to_write = JSON.stringify(data_object, null, 2); 188 | write_data(data_to_write); 189 | }) 190 | .then(function(newContractInstance) { 191 | console.log(newContractInstance.options.address) // instance with the new contract address 192 | var factoryVar = newContractInstance.methods.factory().call() 193 | factoryVar.then(function(resultFactory) { 194 | console.log("Router2's factory set to: " + resultFactory); 195 | }) 196 | var wethVar = newContractInstance.methods.WETH().call() 197 | wethVar.then(function(resultWeth) { 198 | console.log("Router2's WETH set to: " + resultWeth); 199 | }) 200 | }); 201 | 202 | 203 | // Uniswap V2 Multicall 204 | // V2 Multicall Deployment 205 | console.log("Deploying Multicall now, please wait ..."); 206 | let uniswapMulticall; 207 | uniswapMulticall = await web3.eth.sendTransaction({ 208 | from: accounts[2], 209 | data: uniswapMulticallBytecode 210 | }); // Charlie accounts[2] is the owner 211 | let uniswapMulticallInstance = new web3.eth.Contract(uniswapMulticallAbi, uniswapMulticall.contractAddress); 212 | uniswapMulticallInstance.deploy({ 213 | data: uniswapMulticallBytecode 214 | }) 215 | .send({ 216 | from: accounts[2], 217 | gas: 4700000, 218 | gasPrice: '30000000000' 219 | }, function(error, transactionHash) { 220 | console.log(transactionHash); 221 | }) 222 | .on('error', function(error) { 223 | console.log(error); 224 | }) 225 | .on('transactionHash', function(transactionHash) { 226 | console.log("Transaction hash: " + transactionHash); 227 | }) 228 | .on('receipt', function(receipt) { 229 | console.log("Contract address: " + receipt.contractAddress) // contains the new contract address 230 | data_object.contract_address.multicall = receipt.contractAddress; 231 | let data_to_write = JSON.stringify(data_object, null, 2); 232 | write_data(data_to_write); 233 | }) 234 | .then(function(newContractInstance) { 235 | console.log(newContractInstance.options.address) // instance with the new contract address 236 | }); 237 | 238 | // Uniswap V2 Migrator 239 | // V2 Migrator Deployment 240 | console.log("Deploying Migrator now, please wait ..."); 241 | let uniswapMigrator; 242 | uniswapMigrator = await web3.eth.sendTransaction({ 243 | from: accounts[2], 244 | data: uniswapMigratorBytecode 245 | }); // Charlie accounts[2] is the owner 246 | let uniswapMigratorInstance = new web3.eth.Contract(uniswapMigratorAbi, uniswapMigrator.contractAddress); 247 | uniswapMigratorInstance.deploy({ 248 | data: uniswapMigratorBytecode, 249 | arguments: [data_object.contract_address.uniswap_factory, data_object.contract_address.router] 250 | }) 251 | .send({ 252 | from: accounts[2], 253 | gas: 4700000, 254 | gasPrice: '30000000000' 255 | }, function(error, transactionHash) { 256 | console.log(transactionHash); 257 | }) 258 | .on('error', function(error) { 259 | console.log(error); 260 | }) 261 | .on('transactionHash', function(transactionHash) { 262 | console.log("Transaction hash: " + transactionHash); 263 | }) 264 | .on('receipt', function(receipt) { 265 | console.log("Contract address: " + receipt.contractAddress) // contains the new contract address 266 | data_object.contract_address.migrator = receipt.contractAddress; 267 | let data_to_write = JSON.stringify(data_object, null, 2); 268 | write_data(data_to_write); 269 | }) 270 | .then(function(newContractInstance) { 271 | console.log(newContractInstance.options.address) // instance with the new contract address 272 | }); 273 | 274 | 275 | // V2 ENS registry Deployment 276 | console.log("Deploying ENS registry now, please wait ..."); 277 | let ensRegistry; 278 | ensRegistry = await web3.eth.sendTransaction({ 279 | from: accounts[2], 280 | data: uniswapEnsRegistryBytecode 281 | }); // Charlie accounts[2] is the owner 282 | let uniswapEnsRegistryInstance = new web3.eth.Contract(uniswapEnsRegistryAbi, ensRegistry.contractAddress); 283 | uniswapEnsRegistryInstance.deploy({ 284 | data: uniswapEnsRegistryBytecode, 285 | arguments: [accounts[2]] 286 | }) 287 | .send({ 288 | from: accounts[2], 289 | gas: 4700000, 290 | gasPrice: '30000000000' 291 | }, function(error, transactionHash) { 292 | console.log(transactionHash); 293 | }) 294 | .on('error', function(error) { 295 | console.log(error); 296 | }) 297 | .on('transactionHash', function(transactionHash) { 298 | console.log("Transaction hash: " + transactionHash); 299 | }) 300 | .on('receipt', function(receipt) { 301 | console.log("Contract address: " + receipt.contractAddress) // contains the new contract address 302 | data_object.contract_address.ens_registry = receipt.contractAddress; 303 | let data_to_write = JSON.stringify(data_object, null, 2); 304 | write_data(data_to_write); 305 | }) 306 | .then(function(newContractInstance) { 307 | console.log(newContractInstance.options.address) // instance with the new contract address 308 | }); 309 | // V2 Gas relay hub address 310 | console.log("Deploying Gas relay hub address contract now, please wait ..."); 311 | let gasRelayHubAddress; 312 | gasRelayHubAddress = await web3.eth.sendTransaction({ 313 | from: accounts[2], 314 | data: gasRelayHubAddressBytecode 315 | }); // Charlie accounts[2] is the owner 316 | let gasRelayHubAddressInstance = new web3.eth.Contract(gasRelayHubAddressAbi, gasRelayHubAddress.contractAddress); 317 | gasRelayHubAddressInstance.deploy({ 318 | data: gasRelayHubAddressBytecode 319 | }) 320 | .send({ 321 | from: accounts[2], 322 | gas: 4700000, 323 | gasPrice: '30000000000' 324 | }, function(error, transactionHash) { 325 | console.log(transactionHash); 326 | }) 327 | .on('error', function(error) { 328 | console.log(error); 329 | }) 330 | .on('transactionHash', function(transactionHash) { 331 | console.log("Transaction hash: " + transactionHash); 332 | }) 333 | .on('receipt', function(receipt) { 334 | console.log("Contract address: " + receipt.contractAddress) // contains the new contract address 335 | data_object.contract_address.gas_relay_hub_address = receipt.contractAddress; 336 | let data_to_write = JSON.stringify(data_object, null, 2); 337 | write_data(data_to_write); 338 | }) 339 | .then(function(newContractInstance) { 340 | console.log(newContractInstance.options.address) // instance with the new contract address 341 | }); 342 | 343 | let data_to_write = JSON.stringify(data_object, null, 2); 344 | await write_data(data_to_write); 345 | await provider.engine.stop(); 346 | })(); 347 | -------------------------------------------------------------------------------- /erc20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity =0.4.26; 2 | 3 | /** 4 | * @dev Wrappers over Solidity's arithmetic operations with added overflow 5 | * checks. 6 | * 7 | * Arithmetic operations in Solidity wrap on overflow. This can easily result 8 | * in bugs, because programmers usually assume that an overflow raises an 9 | * error, which is the standard behavior in high level programming languages. 10 | * `SafeMath` restores this intuition by reverting the transaction when an 11 | * operation overflows. 12 | * 13 | * Using this library instead of the unchecked operations eliminates an entire 14 | * class of bugs, so it's recommended to use it always. 15 | */ 16 | library SafeMath { 17 | /** 18 | * @dev Returns the addition of two unsigned integers, reverting on 19 | * overflow. 20 | * 21 | * Counterpart to Solidity's `+` operator. 22 | * 23 | * Requirements: 24 | * 25 | * - Addition cannot overflow. 26 | */ 27 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 28 | uint256 c = a + b; 29 | require(c >= a, "SafeMath: addition overflow"); 30 | 31 | return c; 32 | } 33 | 34 | /** 35 | * @dev Returns the subtraction of two unsigned integers, reverting on 36 | * overflow (when the result is negative). 37 | * 38 | * Counterpart to Solidity's `-` operator. 39 | * 40 | * Requirements: 41 | * 42 | * - Subtraction cannot overflow. 43 | */ 44 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 45 | return sub(a, b, "SafeMath: subtraction overflow"); 46 | } 47 | 48 | /** 49 | * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 50 | * overflow (when the result is negative). 51 | * 52 | * Counterpart to Solidity's `-` operator. 53 | * 54 | * Requirements: 55 | * 56 | * - Subtraction cannot overflow. 57 | */ 58 | function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 59 | require(b <= a, errorMessage); 60 | uint256 c = a - b; 61 | 62 | return c; 63 | } 64 | 65 | /** 66 | * @dev Returns the multiplication of two unsigned integers, reverting on 67 | * overflow. 68 | * 69 | * Counterpart to Solidity's `*` operator. 70 | * 71 | * Requirements: 72 | * 73 | * - Multiplication cannot overflow. 74 | */ 75 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 76 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 77 | // benefit is lost if 'b' is also tested. 78 | // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 79 | if (a == 0) { 80 | return 0; 81 | } 82 | 83 | uint256 c = a * b; 84 | require(c / a == b, "SafeMath: multiplication overflow"); 85 | 86 | return c; 87 | } 88 | 89 | /** 90 | * @dev Returns the integer division of two unsigned integers. Reverts on 91 | * division by zero. The result is rounded towards zero. 92 | * 93 | * Counterpart to Solidity's `/` operator. Note: this function uses a 94 | * `revert` opcode (which leaves remaining gas untouched) while Solidity 95 | * uses an invalid opcode to revert (consuming all remaining gas). 96 | * 97 | * Requirements: 98 | * 99 | * - The divisor cannot be zero. 100 | */ 101 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 102 | return div(a, b, "SafeMath: division by zero"); 103 | } 104 | 105 | /** 106 | * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 107 | * division by zero. The result is rounded towards zero. 108 | * 109 | * Counterpart to Solidity's `/` operator. Note: this function uses a 110 | * `revert` opcode (which leaves remaining gas untouched) while Solidity 111 | * uses an invalid opcode to revert (consuming all remaining gas). 112 | * 113 | * Requirements: 114 | * 115 | * - The divisor cannot be zero. 116 | */ 117 | function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 118 | require(b > 0, errorMessage); 119 | uint256 c = a / b; 120 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 121 | 122 | return c; 123 | } 124 | 125 | /** 126 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 127 | * Reverts when dividing by zero. 128 | * 129 | * Counterpart to Solidity's `%` operator. This function uses a `revert` 130 | * opcode (which leaves remaining gas untouched) while Solidity uses an 131 | * invalid opcode to revert (consuming all remaining gas). 132 | * 133 | * Requirements: 134 | * 135 | * - The divisor cannot be zero. 136 | */ 137 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 138 | return mod(a, b, "SafeMath: modulo by zero"); 139 | } 140 | 141 | /** 142 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 143 | * Reverts with custom message when dividing by zero. 144 | * 145 | * Counterpart to Solidity's `%` operator. This function uses a `revert` 146 | * opcode (which leaves remaining gas untouched) while Solidity uses an 147 | * invalid opcode to revert (consuming all remaining gas). 148 | * 149 | * Requirements: 150 | * 151 | * - The divisor cannot be zero. 152 | */ 153 | function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 154 | require(b != 0, errorMessage); 155 | return a % b; 156 | } 157 | } 158 | 159 | /** 160 | * @dev Interface of the ERC20 standard as defined in the EIP. 161 | */ 162 | interface IERC20 { 163 | /** 164 | * @dev Returns the amount of tokens in existence. 165 | */ 166 | function totalSupply() external view returns (uint256); 167 | 168 | /** 169 | * @dev Returns the amount of tokens owned by `account`. 170 | */ 171 | function balanceOf(address account) external view returns (uint256); 172 | 173 | /** 174 | * @dev Moves `amount` tokens from the caller's account to `recipient`. 175 | * 176 | * Returns a boolean value indicating whether the operation succeeded. 177 | * 178 | * Emits a {Transfer} event. 179 | */ 180 | function transfer(address recipient, uint256 amount) external returns (bool); 181 | 182 | /** 183 | * @dev Returns the remaining number of tokens that `spender` will be 184 | * allowed to spend on behalf of `owner` through {transferFrom}. This is 185 | * zero by default. 186 | * 187 | * This value changes when {approve} or {transferFrom} are called. 188 | */ 189 | function allowance(address owner, address spender) external view returns (uint256); 190 | 191 | /** 192 | * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 193 | * 194 | * Returns a boolean value indicating whether the operation succeeded. 195 | * 196 | * IMPORTANT: Beware that changing an allowance with this method brings the risk 197 | * that someone may use both the old and the new allowance by unfortunate 198 | * transaction ordering. One possible solution to mitigate this race 199 | * condition is to first reduce the spender's allowance to 0 and set the 200 | * desired value afterwards: 201 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 202 | * 203 | * Emits an {Approval} event. 204 | */ 205 | function approve(address spender, uint256 amount) external returns (bool); 206 | 207 | /** 208 | * @dev Moves `amount` tokens from `sender` to `recipient` using the 209 | * allowance mechanism. `amount` is then deducted from the caller's 210 | * allowance. 211 | * 212 | * Returns a boolean value indicating whether the operation succeeded. 213 | * 214 | * Emits a {Transfer} event. 215 | */ 216 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 217 | 218 | /** 219 | * @dev Emitted when `value` tokens are moved from one account (`from`) to 220 | * another (`to`). 221 | * 222 | * Note that `value` may be zero. 223 | */ 224 | event Transfer(address indexed from, address indexed to, uint256 value); 225 | 226 | /** 227 | * @dev Emitted when the allowance of a `spender` for an `owner` is set by 228 | * a call to {approve}. `value` is the new allowance. 229 | */ 230 | event Approval(address indexed owner, address indexed spender, uint256 value); 231 | } 232 | 233 | /** 234 | * @title Standard ERC20 token 235 | * 236 | * @dev Implementation of the basic standard token. 237 | * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md 238 | * Originally based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol 239 | */ 240 | contract ERC20 is IERC20 { 241 | using SafeMath for uint256; 242 | 243 | mapping (address => uint256) private _balances; 244 | 245 | mapping (address => mapping (address => uint256)) private _allowed; 246 | 247 | uint256 private _totalSupply; 248 | string private _name; 249 | string private _symbol; 250 | uint8 private _decimals; 251 | 252 | constructor(string memory name, string memory symbol) public { 253 | _name = name; 254 | _symbol = symbol; 255 | _decimals = 18; 256 | } 257 | 258 | /** 259 | * @dev Returns the name of the token. 260 | */ 261 | function name() public view returns (string memory) { 262 | return _name; 263 | } 264 | 265 | /** 266 | * @dev Returns the symbol of the token, usually a shorter version of the 267 | * name. 268 | */ 269 | function symbol() public view returns (string memory) { 270 | return _symbol; 271 | } 272 | 273 | /** 274 | * @dev Returns the number of decimals used to get its user representation. 275 | * For example, if `decimals` equals `2`, a balance of `505` tokens should 276 | * be displayed to a user as `5,05` (`505 / 10 ** 2`). 277 | * 278 | * Tokens usually opt for a value of 18, imitating the relationship between 279 | * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 280 | * called. 281 | * 282 | * NOTE: This information is only used for _display_ purposes: it in 283 | * no way affects any of the arithmetic of the contract, including 284 | * {IERC20-balanceOf} and {IERC20-transfer}. 285 | */ 286 | function decimals() public view returns (uint8) { 287 | return _decimals; 288 | } 289 | 290 | /** 291 | * @dev Total number of tokens in existence 292 | */ 293 | function totalSupply() public view returns (uint256) { 294 | return _totalSupply; 295 | } 296 | 297 | /** 298 | * @dev Gets the balance of the specified address. 299 | * @param owner The address to query the balance of. 300 | * @return An uint256 representing the amount owned by the passed address. 301 | */ 302 | function balanceOf(address owner) public view returns (uint256) { 303 | return _balances[owner]; 304 | } 305 | 306 | /** 307 | * @dev Function to check the amount of tokens that an owner allowed to a spender. 308 | * @param owner address The address which owns the funds. 309 | * @param spender address The address which will spend the funds. 310 | * @return A uint256 specifying the amount of tokens still available for the spender. 311 | */ 312 | function allowance( 313 | address owner, 314 | address spender 315 | ) 316 | public 317 | view 318 | returns (uint256) 319 | { 320 | return _allowed[owner][spender]; 321 | } 322 | 323 | /** 324 | * @dev Transfer token for a specified address 325 | * @param to The address to transfer to. 326 | * @param value The amount to be transferred. 327 | */ 328 | function transfer(address to, uint256 value) public returns (bool) { 329 | require(value <= _balances[msg.sender]); 330 | require(to != address(0)); 331 | 332 | _balances[msg.sender] = _balances[msg.sender].sub(value); 333 | _balances[to] = _balances[to].add(value); 334 | emit Transfer(msg.sender, to, value); 335 | return true; 336 | } 337 | 338 | /** 339 | * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. 340 | * Beware that changing an allowance with this method brings the risk that someone may use both the old 341 | * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this 342 | * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: 343 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 344 | * @param spender The address which will spend the funds. 345 | * @param value The amount of tokens to be spent. 346 | */ 347 | function approve(address spender, uint256 value) public returns (bool) { 348 | require(spender != address(0)); 349 | 350 | _allowed[msg.sender][spender] = value; 351 | emit Approval(msg.sender, spender, value); 352 | return true; 353 | } 354 | 355 | /** 356 | * @dev Transfer tokens from one address to another 357 | * @param from address The address which you want to send tokens from 358 | * @param to address The address which you want to transfer to 359 | * @param value uint256 the amount of tokens to be transferred 360 | */ 361 | function transferFrom( 362 | address from, 363 | address to, 364 | uint256 value 365 | ) 366 | public 367 | returns (bool) 368 | { 369 | require(value <= _balances[from]); 370 | require(value <= _allowed[from][msg.sender]); 371 | require(to != address(0)); 372 | 373 | _balances[from] = _balances[from].sub(value); 374 | _balances[to] = _balances[to].add(value); 375 | _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value); 376 | emit Transfer(from, to, value); 377 | return true; 378 | } 379 | 380 | /** 381 | * @dev Increase the amount of tokens that an owner allowed to a spender. 382 | * approve should be called when allowed_[_spender] == 0. To increment 383 | * allowed value is better to use this function to avoid 2 calls (and wait until 384 | * the first transaction is mined) 385 | * From MonolithDAO Token.sol 386 | * @param spender The address which will spend the funds. 387 | * @param addedValue The amount of tokens to increase the allowance by. 388 | */ 389 | function increaseAllowance( 390 | address spender, 391 | uint256 addedValue 392 | ) 393 | public 394 | returns (bool) 395 | { 396 | require(spender != address(0)); 397 | 398 | _allowed[msg.sender][spender] = ( 399 | _allowed[msg.sender][spender].add(addedValue)); 400 | emit Approval(msg.sender, spender, _allowed[msg.sender][spender]); 401 | return true; 402 | } 403 | 404 | /** 405 | * @dev Decrease the amount of tokens that an owner allowed to a spender. 406 | * approve should be called when allowed_[_spender] == 0. To decrement 407 | * allowed value is better to use this function to avoid 2 calls (and wait until 408 | * the first transaction is mined) 409 | * From MonolithDAO Token.sol 410 | * @param spender The address which will spend the funds. 411 | * @param subtractedValue The amount of tokens to decrease the allowance by. 412 | */ 413 | function decreaseAllowance( 414 | address spender, 415 | uint256 subtractedValue 416 | ) 417 | public 418 | returns (bool) 419 | { 420 | require(spender != address(0)); 421 | 422 | _allowed[msg.sender][spender] = ( 423 | _allowed[msg.sender][spender].sub(subtractedValue)); 424 | emit Approval(msg.sender, spender, _allowed[msg.sender][spender]); 425 | return true; 426 | } 427 | 428 | /** 429 | * @dev Internal function that mints an amount of the token and assigns it to 430 | * an account. This encapsulates the modification of balances such that the 431 | * proper events are emitted. 432 | * @param account The account that will receive the created tokens. 433 | * @param amount The amount that will be created. 434 | */ 435 | function _mint(address account, uint256 amount) internal { 436 | require(account != 0); 437 | _totalSupply = _totalSupply.add(amount); 438 | _balances[account] = _balances[account].add(amount); 439 | emit Transfer(address(0), account, amount); 440 | } 441 | 442 | /** 443 | * @dev Internal function that burns an amount of the token of a given 444 | * account. 445 | * @param account The account whose tokens will be burnt. 446 | * @param amount The amount that will be burnt. 447 | */ 448 | function _burn(address account, uint256 amount) internal { 449 | require(account != 0); 450 | require(amount <= _balances[account]); 451 | 452 | _totalSupply = _totalSupply.sub(amount); 453 | _balances[account] = _balances[account].sub(amount); 454 | emit Transfer(account, address(0), amount); 455 | } 456 | 457 | /** 458 | * @dev Internal function that burns an amount of the token of a given 459 | * account, deducting from the sender's allowance for said account. Uses the 460 | * internal burn function. 461 | * @param account The account whose tokens will be burnt. 462 | * @param amount The amount that will be burnt. 463 | */ 464 | function _burnFrom(address account, uint256 amount) internal { 465 | require(amount <= _allowed[account][msg.sender]); 466 | 467 | // Should https://github.com/OpenZeppelin/zeppelin-solidity/issues/707 be accepted, 468 | // this function needs to emit an event with the updated approval. 469 | _allowed[account][msg.sender] = _allowed[account][msg.sender].sub( 470 | amount); 471 | _burn(account, amount); 472 | } 473 | } 474 | 475 | 476 | contract ERC20FixedSupply is ERC20 { 477 | 478 | constructor() public ERC20("Yuan Token", "YUAN") { 479 | _mint(msg.sender, 1000000000000000000000); 480 | } 481 | } --------------------------------------------------------------------------------