├── Example.png ├── riskParameters.json ├── smartContractProxy ├── contracts │ ├── interfaces │ │ ├── V1 │ │ │ ├── IUniswapV1Factory.sol │ │ │ └── IUniswapV1Exchange.sol │ │ ├── IUniswapV2Migrator.sol │ │ ├── IWETH.sol │ │ ├── IERC20.sol │ │ ├── IUniswapV2Router02.sol │ │ └── IUniswapV2Router01.sol │ ├── libraries │ │ ├── SafeMath.sol │ │ ├── UniswapV2OracleLibrary.sol │ │ ├── UniswapV2Library.sol │ │ └── UniswapV2LiquidityMathLibrary.sol │ └── ArbProxy.sol ├── migrations │ └── 1_deploy_contract.js ├── package.json ├── truffle-config.js └── build │ └── contracts │ ├── IUniswapV1Factory.json │ ├── IUniswapV2Migrator.json │ ├── IWETH.json │ └── Migrations.json ├── executionSettings.json ├── views ├── style.css └── tokenList.pug ├── package.json ├── LICENSE ├── bannedERC20.json ├── README.md ├── approvedERC20.json └── pairDL.js /Example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steelep/uniRunner/HEAD/Example.png -------------------------------------------------------------------------------- /riskParameters.json: -------------------------------------------------------------------------------- 1 | {"minProfitUSD":"5.00","minGasGWEI":"75", "maxGasGWEI":"150","maxRiskPassETH":"3", "minTimeLeftDeadlineSeconds":"25","maxTimeLeftDeadlineSeconds":"3000" } -------------------------------------------------------------------------------- /smartContractProxy/contracts/interfaces/V1/IUniswapV1Factory.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | interface IUniswapV1Factory { 4 | function getExchange(address) external view returns (address); 5 | } 6 | -------------------------------------------------------------------------------- /smartContractProxy/contracts/interfaces/IUniswapV2Migrator.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | interface IUniswapV2Migrator { 4 | function migrate(address token, uint amountTokenMin, uint amountETHMin, address to, uint deadline) external; 5 | } 6 | -------------------------------------------------------------------------------- /smartContractProxy/contracts/interfaces/IWETH.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | interface IWETH { 4 | function deposit() external payable; 5 | function transfer(address to, uint value) external returns (bool); 6 | function withdraw(uint) external; 7 | } 8 | -------------------------------------------------------------------------------- /executionSettings.json: -------------------------------------------------------------------------------- 1 | {"accSender":"0xDEADBEEF", 2 | "pvtKey":"enter-here", 3 | "productionServer":"ws://35.173.47.6:8546", 4 | "gasCostUnitsForSC":"300000", 5 | "gasCostUnitsForPricing":"221000", 6 | "ethValUSD":"697", 7 | "deployedContract":"0xDEADBEEF", 8 | "enforceNPV":"true" 9 | } 10 | 11 | 12 | -------------------------------------------------------------------------------- /smartContractProxy/migrations/1_deploy_contract.js: -------------------------------------------------------------------------------- 1 | let ArbProxy = artifacts.require("ArbProxy") 2 | 3 | module.exports = async function (deployer, network) { 4 | try { 5 | await deployer.deploy(ArbProxy) 6 | } catch (e) { 7 | console.log(`Error in migration: ${e.message}`) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /views/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: wheat; 3 | font-size: 20px; 4 | 5 | } 6 | table { 7 | border-collapse: collapse; 8 | } 9 | 10 | td, th { 11 | border: 1px solid rgb(55, 55, 55); 12 | padding: 0.2rem; 13 | text-align: left; 14 | } 15 | 16 | success { 17 | text-decoration-color:yellowgreen; 18 | 19 | } -------------------------------------------------------------------------------- /smartContractProxy/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "truffle-plugin-verify": "^0.5.4" 4 | }, 5 | "dependencies": { 6 | "@truffle/hdwallet-provider": "^1.2.1", 7 | "@uniswap/v2-core": "^1.0.1", 8 | "@uniswap/v2-periphery": "^1.1.0-beta.0", 9 | "dotenv": "^8.2.0", 10 | "truffle": "^5.1.62" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /smartContractProxy/contracts/interfaces/V1/IUniswapV1Exchange.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | interface IUniswapV1Exchange { 4 | function balanceOf(address owner) external view returns (uint); 5 | function transferFrom(address from, address to, uint value) external returns (bool); 6 | function removeLiquidity(uint, uint, uint, uint) external returns (uint, uint); 7 | function tokenToEthSwapInput(uint, uint, uint) external returns (uint); 8 | function ethToTokenSwapInput(uint, uint) external payable returns (uint); 9 | } 10 | -------------------------------------------------------------------------------- /smartContractProxy/contracts/libraries/SafeMath.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.6.6; 2 | 3 | // a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math) 4 | 5 | library SafeMath { 6 | function add(uint x, uint y) internal pure returns (uint z) { 7 | require((z = x + y) >= x, 'ds-math-add-overflow'); 8 | } 9 | 10 | function sub(uint x, uint y) internal pure returns (uint z) { 11 | require((z = x - y) <= x, 'ds-math-sub-underflow'); 12 | } 13 | 14 | function mul(uint x, uint y) internal pure returns (uint z) { 15 | require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow'); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "UniRunner", 3 | "type": "commonjs", 4 | "version": "1.0.0", 5 | "description": "1", 6 | "main": "uniSushi_Pricer.js", 7 | "protocol": "inspector", 8 | "scripts": { 9 | "start": "node uniSushi_Pricer.js" 10 | }, 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "@uniswap/sdk": "^3.0.3", 15 | "eth-revert-reason": "^1.0.3", 16 | "ethereum-input-data-decoder": "^0.3.1", 17 | "ethereumjs-tx": "^2.1.2", 18 | "ethers": "^5.0.19", 19 | "express": "^4.17.1", 20 | "ganache-cli": "^6.12.2", 21 | "jade": "^1.11.0", 22 | "pug": "^3.0.0", 23 | "serve": "^11.3.2", 24 | "web3": "^1.3.0", 25 | "worker-farm": "^1.7.0", 26 | "workerpool": "^6.0.3" 27 | }, 28 | "devDependencies": {} 29 | } 30 | -------------------------------------------------------------------------------- /smartContractProxy/contracts/interfaces/IERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | interface IERC20 { 4 | event Approval(address indexed owner, address indexed spender, uint value); 5 | event Transfer(address indexed from, address indexed to, uint value); 6 | 7 | function name() external view returns (string memory); 8 | function symbol() external view returns (string memory); 9 | function decimals() external view returns (uint8); 10 | function totalSupply() external view returns (uint); 11 | function balanceOf(address owner) external view returns (uint); 12 | function allowance(address owner, address spender) external view returns (uint); 13 | 14 | function approve(address spender, uint value) external returns (bool); 15 | function transfer(address to, uint value) external returns (bool); 16 | function transferFrom(address from, address to, uint value) external returns (bool); 17 | } 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Patrick Steele 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /bannedERC20.json: -------------------------------------------------------------------------------- 1 | [{"tokenAddress":"123456","tokenSymbol":"TEST"},{"tokenAddress":"0x9b4bE493d070cD938Ead642f9046C023655a6A78","tokenSymbol":"BOY"},{"tokenAddress":"0x4c10BD19688B906665fBd53415f279F34b44ECE7","tokenSymbol":"YUI"},{"tokenAddress":"0x4Ed97a85ffcBEbB55856DeFE99e9388E16d36561","tokenSymbol":"UNFI"},{"tokenAddress":"0x692eb773E0b5B7A79EFac5A015C8b36A2577F65c","tokenSymbol":"SWISS"},{"tokenAddress":"0xe6179bB571D2d69837bE731da88C76e377ec4738","tokenSymbol":"WHOLE"},{"tokenAddress":"0xd1755Fd6A4249e0e9a7037134337Fd8B13fb30cF","tokenSymbol":"DENA"},{"tokenAddress":"0xCb5f72d37685C3D5aD0bB5F982443BC8FcdF570E","tokenSymbol":"ROOT"},{"tokenAddress":"0xf12EC0D3Dab64DdEfBdC96474bDe25af3FE1B327","tokenSymbol":"STACY"},{"tokenAddress":"0xe042adDACb20E4B69EAcE5F83D5C25A90Ca5EA4F","tokenSymbol":"UDS"},{"tokenAddress":"0x6322B267E527fad027fC0B933340f4484BaCD51f","tokenSymbol":"ROOT"},{"tokenAddress":"0xb7ec95E38359636c3088e736368DABfcB7ff233f","tokenSymbol":"LIQBURN"},{"tokenAddress":"0x75a26f898697a2C5556AE84993ebcfb25CA2B043","tokenSymbol":"DOLPHIN"},{"tokenAddress":"0xaA19673aA1b483a5c4f73B446B4f851629a7e7D6","tokenSymbol":"xETH"},{"tokenAddress":"0x2F6081E3552b1c86cE4479B80062A1ddA8EF23E3","tokenSymbol":"USD"},{"tokenAddress":"0x0Ae055097C6d159879521C384F1D2123D1f195e6","tokenSymbol":"STAKE"},{"tokenAddress":"0x12D102F06da35cC0111EB58017fd2Cd28537d0e1","tokenSymbol":"VOX"}] -------------------------------------------------------------------------------- /smartContractProxy/contracts/interfaces/IUniswapV2Router02.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.6.2; 2 | 3 | import './IUniswapV2Router01.sol'; 4 | 5 | interface IUniswapV2Router02 is IUniswapV2Router01 { 6 | function removeLiquidityETHSupportingFeeOnTransferTokens( 7 | address token, 8 | uint liquidity, 9 | uint amountTokenMin, 10 | uint amountETHMin, 11 | address to, 12 | uint deadline 13 | ) external returns (uint amountETH); 14 | function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( 15 | address token, 16 | uint liquidity, 17 | uint amountTokenMin, 18 | uint amountETHMin, 19 | address to, 20 | uint deadline, 21 | bool approveMax, uint8 v, bytes32 r, bytes32 s 22 | ) external returns (uint amountETH); 23 | 24 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 25 | uint amountIn, 26 | uint amountOutMin, 27 | address[] calldata path, 28 | address to, 29 | uint deadline 30 | ) external; 31 | function swapExactETHForTokensSupportingFeeOnTransferTokens( 32 | uint amountOutMin, 33 | address[] calldata path, 34 | address to, 35 | uint deadline 36 | ) external payable; 37 | function swapExactTokensForETHSupportingFeeOnTransferTokens( 38 | uint amountIn, 39 | uint amountOutMin, 40 | address[] calldata path, 41 | address to, 42 | uint deadline 43 | ) external; 44 | } 45 | -------------------------------------------------------------------------------- /smartContractProxy/truffle-config.js: -------------------------------------------------------------------------------- 1 | // const path = require("path"); 2 | const HDWalletProvider = require("@truffle/hdwallet-provider") 3 | require("dotenv").config() 4 | 5 | module.exports = { 6 | // See to customize your Truffle configuration! 7 | // contracts_build_directory: path.join(__dirname, "client/src/contracts"), 8 | networks: { 9 | development: { 10 | host: "127.0.0.1", 11 | port: 8545, 12 | // gas: 20000000, 13 | network_id: "*", 14 | skipDryRun: true 15 | }, 16 | ropsten: { 17 | provider: new HDWalletProvider("enter your key", "wss://ropsten.infura.io/ws/v3/8008f1ed67da46b895a65f1200933ff9"), 18 | network_id: 3, 19 | gas: 5000000, 20 | gasPrice: 5000000000, // 5 Gwei 21 | skipDryRun: true, 22 | timeoutBlocks: 50000 23 | 24 | }, 25 | kovan: { 26 | provider: new HDWalletProvider("enter your key", "https://kovan.infura.io/v3/8008f1ed67da46b895a65f1200933ff9"), 27 | network_id: 42, 28 | gas: 5000000, 29 | gasPrice: 5000000000, // 5 Gwei 30 | skipDryRun: true 31 | }, 32 | mainnet: { 33 | provider: new HDWalletProvider("enter your key", "ws://54.251.233.167:8546"), 34 | network_id: 1, 35 | gas: 5000000, 36 | gasPrice: 85000000000, 37 | skipDryRun: true 38 | // 5 Gwei 39 | } 40 | }, 41 | compilers: { 42 | solc: { 43 | version: "0.7.1", 44 | }, 45 | }, 46 | plugins: ["truffle-plugin-verify"], 47 | api_keys: { 48 | etherscan: "enter your etherscan key", 49 | }, 50 | 51 | }; 52 | -------------------------------------------------------------------------------- /smartContractProxy/contracts/libraries/UniswapV2OracleLibrary.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | import '@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol'; 4 | import '@uniswap/lib/contracts/libraries/FixedPoint.sol'; 5 | 6 | // library with helper methods for oracles that are concerned with computing average prices 7 | library UniswapV2OracleLibrary { 8 | using FixedPoint for *; 9 | 10 | // helper function that returns the current block timestamp within the range of uint32, i.e. [0, 2**32 - 1] 11 | function currentBlockTimestamp() internal view returns (uint32) { 12 | return uint32(block.timestamp % 2 ** 32); 13 | } 14 | 15 | // produces the cumulative price using counterfactuals to save gas and avoid a call to sync. 16 | function currentCumulativePrices( 17 | address pair 18 | ) internal view returns (uint price0Cumulative, uint price1Cumulative, uint32 blockTimestamp) { 19 | blockTimestamp = currentBlockTimestamp(); 20 | price0Cumulative = IUniswapV2Pair(pair).price0CumulativeLast(); 21 | price1Cumulative = IUniswapV2Pair(pair).price1CumulativeLast(); 22 | 23 | // if time has elapsed since the last update on the pair, mock the accumulated price values 24 | (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast) = IUniswapV2Pair(pair).getReserves(); 25 | if (blockTimestampLast != blockTimestamp) { 26 | // subtraction overflow is desired 27 | uint32 timeElapsed = blockTimestamp - blockTimestampLast; 28 | // addition overflow is desired 29 | // counterfactual 30 | price0Cumulative += uint(FixedPoint.fraction(reserve1, reserve0)._x) * timeElapsed; 31 | // counterfactual 32 | price1Cumulative += uint(FixedPoint.fraction(reserve0, reserve1)._x) * timeElapsed; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /smartContractProxy/contracts/interfaces/IUniswapV2Router01.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.6.2; 2 | 3 | interface IUniswapV2Router01 { 4 | function factory() external pure returns (address); 5 | function WETH() external pure returns (address); 6 | 7 | function addLiquidity( 8 | address tokenA, 9 | address tokenB, 10 | uint amountADesired, 11 | uint amountBDesired, 12 | uint amountAMin, 13 | uint amountBMin, 14 | address to, 15 | uint deadline 16 | ) external returns (uint amountA, uint amountB, uint liquidity); 17 | function addLiquidityETH( 18 | address token, 19 | uint amountTokenDesired, 20 | uint amountTokenMin, 21 | uint amountETHMin, 22 | address to, 23 | uint deadline 24 | ) external payable returns (uint amountToken, uint amountETH, uint liquidity); 25 | function removeLiquidity( 26 | address tokenA, 27 | address tokenB, 28 | uint liquidity, 29 | uint amountAMin, 30 | uint amountBMin, 31 | address to, 32 | uint deadline 33 | ) external returns (uint amountA, uint amountB); 34 | function removeLiquidityETH( 35 | address token, 36 | uint liquidity, 37 | uint amountTokenMin, 38 | uint amountETHMin, 39 | address to, 40 | uint deadline 41 | ) external returns (uint amountToken, uint amountETH); 42 | function removeLiquidityWithPermit( 43 | address tokenA, 44 | address tokenB, 45 | uint liquidity, 46 | uint amountAMin, 47 | uint amountBMin, 48 | address to, 49 | uint deadline, 50 | bool approveMax, uint8 v, bytes32 r, bytes32 s 51 | ) external returns (uint amountA, uint amountB); 52 | function removeLiquidityETHWithPermit( 53 | address token, 54 | uint liquidity, 55 | uint amountTokenMin, 56 | uint amountETHMin, 57 | address to, 58 | uint deadline, 59 | bool approveMax, uint8 v, bytes32 r, bytes32 s 60 | ) external returns (uint amountToken, uint amountETH); 61 | function swapExactTokensForTokens( 62 | uint amountIn, 63 | uint amountOutMin, 64 | address[] calldata path, 65 | address to, 66 | uint deadline 67 | ) external returns (uint[] memory amounts); 68 | function swapTokensForExactTokens( 69 | uint amountOut, 70 | uint amountInMax, 71 | address[] calldata path, 72 | address to, 73 | uint deadline 74 | ) external returns (uint[] memory amounts); 75 | function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) 76 | external 77 | payable 78 | returns (uint[] memory amounts); 79 | function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) 80 | external 81 | returns (uint[] memory amounts); 82 | function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) 83 | external 84 | returns (uint[] memory amounts); 85 | function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) 86 | external 87 | payable 88 | returns (uint[] memory amounts); 89 | 90 | function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); 91 | function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); 92 | function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); 93 | function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); 94 | function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); 95 | } 96 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UniRunner 2 | 3 | NodeJS tool for identifying and back-running pending high impact mempool transactions across dual listed UniSwap/SushiSwap liquidity pools. Monitoring is via a simple web interface/frontend and chain interactions via smart contract. 4 | 5 | ![](https://i.imgur.com/7GUFY9v.png) 6 | 7 | TLDR docs: 8 | 9 | # The Idea 10 | Trades occurring on dual-listed token pools between UniSwap and SushiSwap frequently cause material price impact, leading to intrablock pricing inefficiencies. 11 | This tool, watches for pending transactions, calculates the pending impact on cross DEX pricing. Identifying if an exploitable pricing inefficiency will exist, if so then it creates and atomically executes a bundled set of transactions (buy/sell legs) via a specially constructed smart contract, immediately after the target transaction occurs (gas -1 wei) in the same block. If the smart contract transaction fails (likely due to placement in the block), both legs revert and gas incurred is minimal. 12 | 13 | # uniSushi_Pricer.js 14 | Subscribes to an ethereum nodes memory pool via WSS, listens for all new transactions, filters for transactions destined for UniSwaps V2 OR SushiSwaps router contracts, filters again for transaction type (e.g. ETHtoTokenSwap or TokenToEthSwap), do a bit of maths (via a quick manifold search) to work out the impact of a pending trade, figures out the next pricing state (impact of pools) on both DEX's after assumed execution, calculate opportunity size, determine PnL, if the opportunity is profitable net of costs and it passes risk checks, then sends a trade via ArbProxy.sol and reports the PnL. Trading halts after a single trade - can be turned back on via web interface. 15 | 16 | Pretrade checks include gas/deadline on the original transaction, followed by a forked in-memory mainnet simulation of the total sequence of trades to confirm the validity of the opportunity (avoid honeypots), checks e.g. max capital required is under a limit, min PnL generated net of fees. Verification simulations when run on the same hardware as the node cost around 115ms in latency. 17 | 18 | # pairDL.js 19 | Simple program to download and precompute all pairs on Sushi and UniSwap V2, finds the intersection of the set where one token is WETH, generates a list of cross DEX dual-listed pairs where arbitrage possibilities can exist and outputs to intersectionWETH.json. This script should be run periodically to capture newly listed pairs. 20 | 21 | # uniApprover.js 22 | To avoid automatically buying tokens that you cannot resell (honeypots) or becoming ensnared in malicious honeypot transaction setups (see the Salmonella attack), I implemented a transaction validator, which forks the ethereum mainnet to memory and simulates the transactions. If the simulated account balance is equal or positive, then the token is added to a whitelist or trade authorised, this means it's eligible to trade on uniSushi_Pricer. Approved contracts are stored in approvedERC20.json and reread at uniSushi_Pricer init. This means some latency the first time a token (2-3 seconds) is ever seen (todo, run checks when reading intersectionWETH.json) 23 | 24 | # ArbProxy.sol 25 | Purpose-built smart contract, atomically executes cross dex uni/sushi arbitrage bundles. Whitelists deployers address as owner and only user. 26 | 27 | # To Run 28 | Requires a private GETH node(s) 29 | - npm install 30 | - Update the executionSettings.json script, enter your private nodes IP/Port, enter your account address and private key 31 | - Confirm the risk parameters are suitable in riskParameters.json 32 | - Update private keys and WSS endpoints in truffle-config.js 33 | - Deploy ArbProxy.sol to mainnet via truffle in ./smartContractProxy/contracts 34 | 35 | Then 36 | - node uniSushi_Pricer.js 37 | 38 | # Next Steps / Status: 39 | This worked in September 2020 briefly before competition (See: Private relay networks, private mempools and the emergence of the "Flashbots" project) made this type of trade much more difficult. The underpinning idea is still sound and likely still to work when peered with a multinode infrastructure for fast transaction propagation. As it stands there are ~2-15 competitor bots for each opportunity primarily composed of MEV pools/relayers who have a structural advantage in capturing these opportunities rendering the current setup uncompetitive. 40 | 41 | 42 | -------------------------------------------------------------------------------- /smartContractProxy/contracts/ArbProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.7.1; 4 | 5 | import "./interfaces/IUniswapV2Router02.sol"; 6 | import "./interfaces/IERC20.sol"; 7 | 8 | 9 | contract ArbProxy { 10 | address internal constant UNISWAP_ROUTER_ADDRESS = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; 11 | address internal constant SUSHISWAP_ROUTER_ADDRESS = 0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F; 12 | address payable owner; 13 | IUniswapV2Router02 public uniswapRouter; 14 | IUniswapV2Router02 public sushiswapRouter; 15 | 16 | constructor() { 17 | uniswapRouter = IUniswapV2Router02(UNISWAP_ROUTER_ADDRESS); 18 | sushiswapRouter = IUniswapV2Router02(SUSHISWAP_ROUTER_ADDRESS); 19 | owner = msg.sender; 20 | 21 | } 22 | 23 | //Uni -> Sushiswap 24 | function convertEthToTokenAndBackUni2Sushi(uint _tokenAmountToBuy, address _tokenAddress, address[] calldata _pathIn, address[] calldata _pathOut, uint _deadline, bool _enforcePositiveEV) public payable { 25 | require(msg.sender == owner); 26 | 27 | //Check if Positive EV TX @ UNI 28 | uint256 estimatedETH = getEstimatedETHForTokenAtSUSHI(_tokenAmountToBuy, _pathOut)[1]; 29 | if(_enforcePositiveEV){ 30 | //Assert that this tx will have a positve expected value otherwise revert and burn gas 31 | require((msg.value) <= estimatedETH, "Not Positive EV"); 32 | } 33 | //Leg one of TX UNI WETH Sell -> UNI Buy Token 34 | uniswapRouter.swapExactETHForTokens{ value: msg.value }(_tokenAmountToBuy, _pathIn, address(this), _deadline); 35 | 36 | //Intermediate Logic, confirm amount of tokens received, approve next exchange to sell 37 | uint256 tokensReceived = IERC20(_tokenAddress).balanceOf(address(this)); 38 | IERC20(_tokenAddress).approve(address(SUSHISWAP_ROUTER_ADDRESS), 2**256 - 1); 39 | sushiswapRouter.swapExactTokensForETH(tokensReceived, estimatedETH, _pathOut, address(this), _deadline); 40 | 41 | // refund leftover ETH to user 42 | (bool success,) = msg.sender.call{ value: address(this).balance }(""); 43 | require(success, "Refund Failed"); 44 | } 45 | 46 | function convertEthToTokenAndBackSushi2Uni(uint _tokenAmountToBuy, address _tokenAddress, address[] calldata _pathIn, address[] calldata _pathOut, uint _deadline, bool _enforcePositiveEV) public payable { 47 | require(msg.sender == owner); 48 | 49 | //Check if Positive EV TX @ UNI 50 | uint256 estimatedETH = getEstimatedETHForTokenAtUNI(_tokenAmountToBuy, _pathOut)[1]; 51 | if(_enforcePositiveEV){ 52 | //Assert that this tx will have a positve expected value otherwise revert and burn gas 53 | require((msg.value) <= estimatedETH, "Not Positive EV"); 54 | } 55 | //Leg one of TX UNI WETH Sell -> UNI Buy Token 56 | sushiswapRouter.swapExactETHForTokens{ value: msg.value }(_tokenAmountToBuy, _pathIn, address(this), _deadline); 57 | 58 | //Intermediate Logic, confirm amount of tokens received, approve next exchange to sell 59 | uint256 tokensReceived = IERC20(_tokenAddress).balanceOf(address(this)); 60 | IERC20(_tokenAddress).approve(address(UNISWAP_ROUTER_ADDRESS), 2**256 - 1); 61 | uniswapRouter.swapExactTokensForETH(tokensReceived, estimatedETH, _pathOut, address(this), _deadline); 62 | 63 | // refund leftover ETH to user 64 | (bool success,) = msg.sender.call{ value: address(this).balance }(""); 65 | require(success, "Refund Failed"); 66 | } 67 | 68 | function getEstimatedETHForTokenAtUNI(uint _tokenAmount, address[] calldata _pathOut) public view returns (uint[] memory) { 69 | require(msg.sender == owner); 70 | return uniswapRouter.getAmountsOut(_tokenAmount, _pathOut); 71 | } 72 | function getEstimatedETHForTokenAtSUSHI(uint _tokenAmount, address[] calldata _pathOut) public view returns (uint[] memory) { 73 | require(msg.sender == owner); 74 | return sushiswapRouter.getAmountsOut(_tokenAmount, _pathOut); 75 | } 76 | 77 | function withdrawBalanceToken(address _tokenAddress) public{ 78 | require(msg.sender == owner); 79 | IERC20(_tokenAddress).transfer(msg.sender, IERC20(_tokenAddress).balanceOf(address(this))); 80 | } 81 | 82 | function changeOwner(address payable _newOwner) public{ 83 | require(msg.sender == owner); 84 | owner = _newOwner; 85 | 86 | } 87 | function withdrawBalanceETH() public{ 88 | // withdraw all eth 89 | require(msg.sender == owner); 90 | msg.sender.call{ value: address(this).balance }(""); 91 | } 92 | 93 | // important to receive ETH 94 | receive() payable external {} 95 | } 96 | -------------------------------------------------------------------------------- /smartContractProxy/contracts/libraries/UniswapV2Library.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | import '@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol'; 4 | 5 | import "./SafeMath.sol"; 6 | 7 | library UniswapV2Library { 8 | using SafeMath for uint; 9 | 10 | // returns sorted token addresses, used to handle return values from pairs sorted in this order 11 | function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) { 12 | require(tokenA != tokenB, 'UniswapV2Library: IDENTICAL_ADDRESSES'); 13 | (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); 14 | require(token0 != address(0), 'UniswapV2Library: ZERO_ADDRESS'); 15 | } 16 | 17 | // calculates the CREATE2 address for a pair without making any external calls 18 | function pairFor(address factory, address tokenA, address tokenB) internal pure returns (address pair) { 19 | (address token0, address token1) = sortTokens(tokenA, tokenB); 20 | pair = address(uint(keccak256(abi.encodePacked( 21 | hex'ff', 22 | factory, 23 | keccak256(abi.encodePacked(token0, token1)), 24 | hex'96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f' // init code hash 25 | )))); 26 | } 27 | 28 | // fetches and sorts the reserves for a pair 29 | function getReserves(address factory, address tokenA, address tokenB) internal view returns (uint reserveA, uint reserveB) { 30 | (address token0,) = sortTokens(tokenA, tokenB); 31 | (uint reserve0, uint reserve1,) = IUniswapV2Pair(pairFor(factory, tokenA, tokenB)).getReserves(); 32 | (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0); 33 | } 34 | 35 | // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset 36 | function quote(uint amountA, uint reserveA, uint reserveB) internal pure returns (uint amountB) { 37 | require(amountA > 0, 'UniswapV2Library: INSUFFICIENT_AMOUNT'); 38 | require(reserveA > 0 && reserveB > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY'); 39 | amountB = amountA.mul(reserveB) / reserveA; 40 | } 41 | 42 | // given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset 43 | function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) { 44 | require(amountIn > 0, 'UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT'); 45 | require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY'); 46 | uint amountInWithFee = amountIn.mul(997); 47 | uint numerator = amountInWithFee.mul(reserveOut); 48 | uint denominator = reserveIn.mul(1000).add(amountInWithFee); 49 | amountOut = numerator / denominator; 50 | } 51 | 52 | // given an output amount of an asset and pair reserves, returns a required input amount of the other asset 53 | function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) internal pure returns (uint amountIn) { 54 | require(amountOut > 0, 'UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT'); 55 | require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY'); 56 | uint numerator = reserveIn.mul(amountOut).mul(1000); 57 | uint denominator = reserveOut.sub(amountOut).mul(997); 58 | amountIn = (numerator / denominator).add(1); 59 | } 60 | 61 | // performs chained getAmountOut calculations on any number of pairs 62 | function getAmountsOut(address factory, uint amountIn, address[] memory path) internal view returns (uint[] memory amounts) { 63 | require(path.length >= 2, 'UniswapV2Library: INVALID_PATH'); 64 | amounts = new uint[](path.length); 65 | amounts[0] = amountIn; 66 | for (uint i; i < path.length - 1; i++) { 67 | (uint reserveIn, uint reserveOut) = getReserves(factory, path[i], path[i + 1]); 68 | amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut); 69 | } 70 | } 71 | 72 | // performs chained getAmountIn calculations on any number of pairs 73 | function getAmountsIn(address factory, uint amountOut, address[] memory path) internal view returns (uint[] memory amounts) { 74 | require(path.length >= 2, 'UniswapV2Library: INVALID_PATH'); 75 | amounts = new uint[](path.length); 76 | amounts[amounts.length - 1] = amountOut; 77 | for (uint i = path.length - 1; i > 0; i--) { 78 | (uint reserveIn, uint reserveOut) = getReserves(factory, path[i - 1], path[i]); 79 | amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /approvedERC20.json: -------------------------------------------------------------------------------- 1 | [{"tokenAddress":"123456","tokenSymbol":"TEST"},{"tokenAddress":"0x09843B9137fc5935B7F3832152F9074Db5D2d1Ee","tokenSymbol":"YFI3"},{"tokenAddress":"0x515d7E9D75E2b76DB60F8a051Cd890eBa23286Bc","tokenSymbol":"GDAO"},{"tokenAddress":"0x0E29e5AbbB5FD88e28b2d355774e73BD47dE3bcd","tokenSymbol":"HAKKA"},{"tokenAddress":"0x1DF6f1Bb7454E5E4BA3BcA882d3148FBf9b5697A","tokenSymbol":"YFSI"},{"tokenAddress":"0xeF9Cd7882c067686691B6fF49e650b43AFBBCC6B","tokenSymbol":"FNX"},{"tokenAddress":"0x5Dc02Ea99285E17656b8350722694c35154DB1E8","tokenSymbol":"BOND"},{"tokenAddress":"0x903bEF1736CDdf2A537176cf3C64579C3867A881","tokenSymbol":"ICHI"},{"tokenAddress":"0x4a527d8fc13C5203AB24BA0944F4Cb14658D1Db6","tokenSymbol":"MITx"},{"tokenAddress":"0xF29992D7b589A0A6bD2de7Be29a97A6EB73EaF85","tokenSymbol":"DMST"},{"tokenAddress":"0x6e36556B3ee5Aa28Def2a8EC3DAe30eC2B208739","tokenSymbol":"BUILD"},{"tokenAddress":"0x5218E472cFCFE0b64A064F055B43b4cdC9EfD3A6","tokenSymbol":"eRSDL"},{"tokenAddress":"0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39","tokenSymbol":"HEX"},{"tokenAddress":"0xeDF6568618A00C6F0908Bf7758A16F76B6E04aF9","tokenSymbol":"ARIA20"},{"tokenAddress":"0x75A1169E51A3C6336Ef854f76cDE949F999720B1","tokenSymbol":"MPH"},{"tokenAddress":"0x25e1474170c4c0aA64fa98123bdc8dB49D7802fa","tokenSymbol":"BID"},{"tokenAddress":"0x617a36Bd36ef8778AA1F12bC32739bFc96cb76E1","tokenSymbol":"BER"},{"tokenAddress":"0x3597bfD533a99c9aa083587B074434E61Eb0A258","tokenSymbol":"DENT"},{"tokenAddress":"0xfF20817765cB7f73d4bde2e66e067E58D11095C2","tokenSymbol":"AMP"},{"tokenAddress":"0x9E78b8274e1D6a76a0dBbf90418894DF27cBCEb5","tokenSymbol":"UniFi"},{"tokenAddress":"0x72e9D9038cE484EE986FEa183f8d8Df93f9aDA13","tokenSymbol":"SMARTCREDIT"},{"tokenAddress":"0x95b3497bBcCcc46a8F45F5Cf54b0878b39f8D96C","tokenSymbol":"UNIDX"},{"tokenAddress":"0xa8c8CfB141A3bB59FEA1E2ea6B79b5ECBCD7b6ca","tokenSymbol":"NOIA"},{"tokenAddress":"0xD82BB924a1707950903e2C0a619824024e254cD1","tokenSymbol":"DAOfi"},{"tokenAddress":"0xfA5047c9c78B8877af97BDcb85Db743fD7313d4a","tokenSymbol":"ROOK"},{"tokenAddress":"0x250a3500f48666561386832f1F1f1019b89a2699","tokenSymbol":"SAFE2"},{"tokenAddress":"0x6BFf2fE249601ed0Db3a87424a2E923118BB0312","tokenSymbol":"FYZ"},{"tokenAddress":"0x0e6a44354D142feb514baE2AA51fa5e558D893f3","tokenSymbol":"eXRD"},{"tokenAddress":"0xB6eD7644C69416d67B522e20bC294A9a9B405B31","tokenSymbol":"0xBTC"},{"tokenAddress":"0x7cA4408137eb639570F8E647d9bD7B7E8717514A","tokenSymbol":"ALPA"},{"tokenAddress":"0x071EcB8A06d60B4D9dc53676ae2d0d7514ed4C3C","tokenSymbol":"wKSA"},{"tokenAddress":"0xC76FB75950536d98FA62ea968E1D6B45ffea2A55","tokenSymbol":"COL"},{"tokenAddress":"0x55A4A8b8D162712E1c125608D6F724498Ae33ea1","tokenSymbol":"DPHR"},{"tokenAddress":"0x20945cA1df56D237fD40036d47E866C7DcCD2114","tokenSymbol":"Nsure"},{"tokenAddress":"0xf4CD3d3Fda8d7Fd6C5a500203e38640A70Bf9577","tokenSymbol":"Yf-DAI"},{"tokenAddress":"0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828","tokenSymbol":"UMA"},{"tokenAddress":"0x1cEB5cB57C4D4E2b2433641b95Dd330A33185A44","tokenSymbol":"KP3R"},{"tokenAddress":"0x83F873388Cd14b83A9f47FabDe3C9850b5C74548","tokenSymbol":"ZUT"},{"tokenAddress":"0xA1B3E61c15b97E85febA33b8F15485389d7836Db","tokenSymbol":"YFIE"},{"tokenAddress":"0x5913D0F34615923552ee913DBe809F9F348e706E","tokenSymbol":"BMJ"},{"tokenAddress":"0x28cb7e841ee97947a86B06fA4090C8451f64c0be","tokenSymbol":"YFL"},{"tokenAddress":"0xb1dC9124c395c1e97773ab855d66E879f053A289","tokenSymbol":"YAX"},{"tokenAddress":"0x2baEcDf43734F22FD5c152DB08E3C27233F0c7d2","tokenSymbol":"OM"},{"tokenAddress":"0xAb1aAFF37DC6ef8Ad422CA7faEce45F329C6E2f9","tokenSymbol":"LPAD"},{"tokenAddress":"0x95bA34760ac3D7fBE98ee8b2AB33b4F1a6D18878","tokenSymbol":"DESH"},{"tokenAddress":"0xaB37e1358b639Fd877f015027Bb62d3ddAa7557E","tokenSymbol":"LIEN"},{"tokenAddress":"0x93ED3FBe21207Ec2E8f2d3c3de6e058Cb73Bc04d","tokenSymbol":"PNK"},{"tokenAddress":"0xc36F33A94D371eF4dfbEAE8D50d3520aC02A41DE","tokenSymbol":"YFIG"},{"tokenAddress":"0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F","tokenSymbol":"SNX"},{"tokenAddress":"0x66d28cb58487a7609877550E1a34691810A6b9FC","tokenSymbol":"KOIN"},{"tokenAddress":"0x7Ef1081Ecc8b5B5B130656a41d4cE4f89dBBCC8c","tokenSymbol":"CP3R"},{"tokenAddress":"0xc3Eb2622190c57429aac3901808994443b64B466","tokenSymbol":"ORO"},{"tokenAddress":"0xa393473d64d2F9F026B60b6Df7859A689715d092","tokenSymbol":"LTX"},{"tokenAddress":"0xb753428af26E81097e7fD17f40c88aaA3E04902c","tokenSymbol":"SFI"},{"tokenAddress":"0xC259Bd68FE764cFA3fD5c04A3Bd24363C7E112Ec","tokenSymbol":"YFIN"},{"tokenAddress":"0x95a4492F028aa1fd432Ea71146b433E7B4446611","tokenSymbol":"APY"},{"tokenAddress":"0x557B933a7C2c45672B610F8954A3deB39a51A8Ca","tokenSymbol":"REVV"},{"tokenAddress":"0x85Eee30c52B0b379b046Fb0F85F4f3Dc3009aFEC","tokenSymbol":"KEEP"},{"tokenAddress":"0xD291E7a03283640FDc51b121aC401383A46cC623","tokenSymbol":"RGT"},{"tokenAddress":"0xD9Ec3ff1f8be459Bb9369b4E79e9Ebcf7141C093","tokenSymbol":"KAI"},{"tokenAddress":"0xa211F450Ce88deb31D3F12Ae3C1EBf6b0e55A5d9","tokenSymbol":"PRQBOOST"},{"tokenAddress":"0x5150956E082C748Ca837a5dFa0a7C10CA4697f9c","tokenSymbol":"ZDEX"},{"tokenAddress":"0x95172ccBe8344fecD73D0a30F54123652981BD6F","tokenSymbol":"LOCK"}] -------------------------------------------------------------------------------- /smartContractProxy/contracts/libraries/UniswapV2LiquidityMathLibrary.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | import '@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol'; 4 | import '@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol'; 5 | import '@uniswap/lib/contracts/libraries/Babylonian.sol'; 6 | import '@uniswap/lib/contracts/libraries/FullMath.sol'; 7 | 8 | import './SafeMath.sol'; 9 | import './UniswapV2Library.sol'; 10 | 11 | // library containing some math for dealing with the liquidity shares of a pair, e.g. computing their exact value 12 | // in terms of the underlying tokens 13 | library UniswapV2LiquidityMathLibrary { 14 | using SafeMath for uint256; 15 | 16 | // computes the direction and magnitude of the profit-maximizing trade 17 | function computeProfitMaximizingTrade( 18 | uint256 truePriceTokenA, 19 | uint256 truePriceTokenB, 20 | uint256 reserveA, 21 | uint256 reserveB 22 | ) pure internal returns (bool aToB, uint256 amountIn) { 23 | aToB = FullMath.mulDiv(reserveA, truePriceTokenB, reserveB) < truePriceTokenA; 24 | 25 | uint256 invariant = reserveA.mul(reserveB); 26 | 27 | uint256 leftSide = Babylonian.sqrt( 28 | FullMath.mulDiv( 29 | invariant.mul(1000), 30 | aToB ? truePriceTokenA : truePriceTokenB, 31 | (aToB ? truePriceTokenB : truePriceTokenA).mul(997) 32 | ) 33 | ); 34 | uint256 rightSide = (aToB ? reserveA.mul(1000) : reserveB.mul(1000)) / 997; 35 | 36 | if (leftSide < rightSide) return (false, 0); 37 | 38 | // compute the amount that must be sent to move the price to the profit-maximizing price 39 | amountIn = leftSide.sub(rightSide); 40 | } 41 | 42 | // gets the reserves after an arbitrage moves the price to the profit-maximizing ratio given an externally observed true price 43 | function getReservesAfterArbitrage( 44 | address factory, 45 | address tokenA, 46 | address tokenB, 47 | uint256 truePriceTokenA, 48 | uint256 truePriceTokenB 49 | ) view internal returns (uint256 reserveA, uint256 reserveB) { 50 | // first get reserves before the swap 51 | (reserveA, reserveB) = UniswapV2Library.getReserves(factory, tokenA, tokenB); 52 | 53 | require(reserveA > 0 && reserveB > 0, 'UniswapV2ArbitrageLibrary: ZERO_PAIR_RESERVES'); 54 | 55 | // then compute how much to swap to arb to the true price 56 | (bool aToB, uint256 amountIn) = computeProfitMaximizingTrade(truePriceTokenA, truePriceTokenB, reserveA, reserveB); 57 | 58 | if (amountIn == 0) { 59 | return (reserveA, reserveB); 60 | } 61 | 62 | // now affect the trade to the reserves 63 | if (aToB) { 64 | uint amountOut = UniswapV2Library.getAmountOut(amountIn, reserveA, reserveB); 65 | reserveA += amountIn; 66 | reserveB -= amountOut; 67 | } else { 68 | uint amountOut = UniswapV2Library.getAmountOut(amountIn, reserveB, reserveA); 69 | reserveB += amountIn; 70 | reserveA -= amountOut; 71 | } 72 | } 73 | 74 | // computes liquidity value given all the parameters of the pair 75 | function computeLiquidityValue( 76 | uint256 reservesA, 77 | uint256 reservesB, 78 | uint256 totalSupply, 79 | uint256 liquidityAmount, 80 | bool feeOn, 81 | uint kLast 82 | ) internal pure returns (uint256 tokenAAmount, uint256 tokenBAmount) { 83 | if (feeOn && kLast > 0) { 84 | uint rootK = Babylonian.sqrt(reservesA.mul(reservesB)); 85 | uint rootKLast = Babylonian.sqrt(kLast); 86 | if (rootK > rootKLast) { 87 | uint numerator1 = totalSupply; 88 | uint numerator2 = rootK.sub(rootKLast); 89 | uint denominator = rootK.mul(5).add(rootKLast); 90 | uint feeLiquidity = FullMath.mulDiv(numerator1, numerator2, denominator); 91 | totalSupply = totalSupply.add(feeLiquidity); 92 | } 93 | } 94 | return (reservesA.mul(liquidityAmount) / totalSupply, reservesB.mul(liquidityAmount) / totalSupply); 95 | } 96 | 97 | // get all current parameters from the pair and compute value of a liquidity amount 98 | // **note this is subject to manipulation, e.g. sandwich attacks**. prefer passing a manipulation resistant price to 99 | // #getLiquidityValueAfterArbitrageToPrice 100 | function getLiquidityValue( 101 | address factory, 102 | address tokenA, 103 | address tokenB, 104 | uint256 liquidityAmount 105 | ) internal view returns (uint256 tokenAAmount, uint256 tokenBAmount) { 106 | (uint256 reservesA, uint256 reservesB) = UniswapV2Library.getReserves(factory, tokenA, tokenB); 107 | IUniswapV2Pair pair = IUniswapV2Pair(UniswapV2Library.pairFor(factory, tokenA, tokenB)); 108 | bool feeOn = IUniswapV2Factory(factory).feeTo() != address(0); 109 | uint kLast = feeOn ? pair.kLast() : 0; 110 | uint totalSupply = pair.totalSupply(); 111 | return computeLiquidityValue(reservesA, reservesB, totalSupply, liquidityAmount, feeOn, kLast); 112 | } 113 | 114 | // given two tokens, tokenA and tokenB, and their "true price", i.e. the observed ratio of value of token A to token B, 115 | // and a liquidity amount, returns the value of the liquidity in terms of tokenA and tokenB 116 | function getLiquidityValueAfterArbitrageToPrice( 117 | address factory, 118 | address tokenA, 119 | address tokenB, 120 | uint256 truePriceTokenA, 121 | uint256 truePriceTokenB, 122 | uint256 liquidityAmount 123 | ) internal view returns ( 124 | uint256 tokenAAmount, 125 | uint256 tokenBAmount 126 | ) { 127 | bool feeOn = IUniswapV2Factory(factory).feeTo() != address(0); 128 | IUniswapV2Pair pair = IUniswapV2Pair(UniswapV2Library.pairFor(factory, tokenA, tokenB)); 129 | uint kLast = feeOn ? pair.kLast() : 0; 130 | uint totalSupply = pair.totalSupply(); 131 | 132 | // this also checks that totalSupply > 0 133 | require(totalSupply >= liquidityAmount && liquidityAmount > 0, 'ComputeLiquidityValue: LIQUIDITY_AMOUNT'); 134 | 135 | (uint reservesA, uint reservesB) = getReservesAfterArbitrage(factory, tokenA, tokenB, truePriceTokenA, truePriceTokenB); 136 | 137 | return computeLiquidityValue(reservesA, reservesB, totalSupply, liquidityAmount, feeOn, kLast); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /views/tokenList.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | style 5 | include ./style.css 6 | 7 | title=title 8 | body 9 | h1 Uni v. Sushi Swap Dual Listed Pairs Arbitrage Trade Oppurtunities 10 | table 11 | 12 | tr 13 | th 14 | h3 Current Block 15 | 16 | th 17 | blockNumber= blockNumber 18 | th 19 | tr 20 | td 21 | h3 ETH/USD ($): 22 | td 23 | ethVal= ethVal 24 | 25 | td 26 | 27 | tr 28 | td 29 | h3 Trading Status: 30 | td 31 | tradingStatus= tradingStatus 32 | td 33 | 34 | tr 35 | td 36 | h3 Market Subscription Status: 37 | td 38 | subscribedStatus= subscribedStatus 39 | td 40 | 41 | tr 42 | td 43 | h3 Dump state to disk 44 | td 45 | p ./dataDump.json 46 | td 47 | 48 | 49 | 50 | 51 | 52 | 53 | h3 Potentially profitable TX's: 54 | 55 | table 56 | thead 57 | th(colspan="9") Exploitable Transaction Details 58 | th(colspan="4") Uni/Sushi Reserves - Chain State 59 | th(colspan="4") Arbitrage Transaction Details/Outcome 60 | th(colspan="4") Pretrade Checks 61 | 62 | tr 63 | th tradeTime 64 | th txHash 65 | th txSender 66 | th symbol0 67 | th symbol1 68 | th origTradeSize 69 | div (eth) 70 | th origGasPrice 71 | div (gwei) 72 | 73 | th origOrderType 74 | th origTradeLocation 75 | 76 | th mispricingOrig 77 | div (bp's) 78 | th mispricingAfterTrade 79 | div (bp's) 80 | th uniLiquidity 81 | div (eth) 82 | th sushiLiquidity 83 | div (eth) 84 | th arbTradeDirection 85 | div (eth) 86 | th gasCost 87 | div ($) 88 | th netArbPnL 89 | div (eth) 90 | th netArbPnL 91 | div ($) 92 | th arbCapitalReqd 93 | div (eth) 94 | th simulationStatus 95 | th preTradeRiskChecks 96 | 97 | 98 | 99 | each item in oppList 100 | if(item.txDetails.tradeDetails.simPnLEth > 0) 101 | tr 102 | 103 | td=item.txDetails.tradeTime 104 | td 105 | a(href='//etherscan.io/tx/' + item.txDetails.txInfo.hash) #{("0x.." + (item.txDetails.txInfo.hash.substr( item.txDetails.txInfo.hash.length - 5)))} 106 | td 107 | a( href='//etherscan.io/address/' + item.txDetails.txInfo.from) #{("0x.." + (item.txDetails.txInfo.from.substr( item.txDetails.txInfo.from.length - 5)))} 108 | 109 | td=item.txDetails.tokenA.symbol 110 | td 111 | a( href='//etherscan.io/address/' + item.txDetails.tokenB.address) #{(item.txDetails.tokenB.symbol)} 112 | td=(item.txDetails.txInfo.value/10e17).toFixed(4) 113 | td=(item.txDetails.txInfo.gasPrice/10e8) 114 | td=item.txDetails.txInputsDecoded.method 115 | 116 | td=item.txDetails.targetLabel 117 | td= ((item.txDetails.unisushiPairOrig - 1) * 100).toFixed(4) 118 | td= ((item.txDetails.unisushiPairAfter - 1) * 100).toFixed(4) 119 | 120 | td 121 | a( href='//etherscan.io/address/' + item.txDetails.uniswapPairAddress) #{(item.txDetails.pairUniSwapOrig.reserveOf(item.txDetails.tokenA).toFixed(4))} 122 | 123 | td 124 | a( href='//etherscan.io/address/' + item.txDetails.sushiswapPairAddress) #{(item.txDetails.pairSushiSwapOrig.reserveOf(item.txDetails.tokenA).toFixed(4))} 125 | 126 | 127 | td=item.txDetails.tradeDetails.ethDirection 128 | td=item.txDetails.tradeDetails.gasCostUSD.toFixed(4) 129 | td=parseFloat(item.txDetails.tradeDetails.simPnLEth).toFixed(4) 130 | td=item.txDetails.tradeDetails.simPnLUSD.toFixed(4) 131 | td=parseFloat(item.txDetails.tradeDetails.tradeSize.raw / 10e17).toFixed(5) 132 | td=item.complianceDetails.externalCompliance.status 133 | td=item.complianceDetails.internalCompliance.internalPreTradePass 134 | 135 | 136 | br 137 | h3 Non profitable TX's 138 | table 139 | thead 140 | th(colspan="9") Exploitable Transaction Details 141 | th(colspan="4") Uni/Sushi Reserves - Chain State 142 | th(colspan="4") Arbitrage Transaction Details/Outcome 143 | th(colspan="4") Pretrade Checks 144 | 145 | tr 146 | th tradeTime 147 | th txHash 148 | th txSender 149 | th symbol0 150 | th symbol1 151 | th origTradeSize 152 | div (eth) 153 | th origGasPrice 154 | div (gwei) 155 | th origOrderType 156 | 157 | th origTradeLocation 158 | 159 | th mispricingOrig 160 | div (bp's) 161 | th mispricingAfterTrade 162 | div (bp's) 163 | th uniLiquidity 164 | div (eth) 165 | th sushiLiquidity 166 | div (eth) 167 | th arbTradeDirection 168 | div (eth) 169 | th gasCost 170 | div ($) 171 | th netArbPnL 172 | div (eth) 173 | th netArbPnL 174 | div ($) 175 | th arbCapitalReqd 176 | div (eth) 177 | th simulationStatus 178 | th preTradeRiskChecks 179 | 180 | 181 | each item in oppList 182 | if(item.txDetails.tradeDetails.simPnLEth <= 0) 183 | tr 184 | 185 | td=item.txDetails.tradeTime 186 | td 187 | a(href='//etherscan.io/tx/' + item.txDetails.txInfo.hash) #{("0x.." + (item.txDetails.txInfo.hash.substr( item.txDetails.txInfo.hash.length - 5)))} 188 | td 189 | a( href='//etherscan.io/address/' + item.txDetails.txInfo.from) #{("0x.." + (item.txDetails.txInfo.from.substr( item.txDetails.txInfo.from.length - 5)))} 190 | 191 | td=item.txDetails.tokenA.symbol 192 | td 193 | a( href='//etherscan.io/address/' + item.txDetails.tokenB.address) #{(item.txDetails.tokenB.symbol)} 194 | td=(item.txDetails.txInfo.value/10e17).toFixed(4) 195 | td=(item.txDetails.txInfo.gasPrice/10e8) 196 | td=item.txDetails.txInputsDecoded.method 197 | td=item.txDetails.targetLabel 198 | td= ((item.txDetails.unisushiPairOrig - 1) * 100).toFixed(4) 199 | td= ((item.txDetails.unisushiPairAfter - 1) * 100).toFixed(4) 200 | 201 | td 202 | a( href='//etherscan.io/address/' + item.txDetails.uniswapPairAddress) #{(item.txDetails.pairUniSwapOrig.reserveOf(item.txDetails.tokenA).toFixed(4))} 203 | 204 | td 205 | a( href='//etherscan.io/address/' + item.txDetails.sushiswapPairAddress) #{(item.txDetails.pairSushiSwapOrig.reserveOf(item.txDetails.tokenA).toFixed(4))} 206 | 207 | 208 | td=item.txDetails.tradeDetails.ethDirection 209 | td=item.txDetails.tradeDetails.gasCostUSD.toFixed(4) 210 | td=parseFloat(item.txDetails.tradeDetails.simPnLEth).toFixed(4) 211 | td=item.txDetails.tradeDetails.simPnLUSD.toFixed(4) 212 | td=parseFloat(item.txDetails.tradeDetails.tradeSize.raw / 10e17).toFixed(5) 213 | td=item.complianceDetails.externalCompliance.status 214 | td=item.complianceDetails.internalCompliance.internalPreTradePass 215 | 216 | 217 | 218 | 219 | -------------------------------------------------------------------------------- /smartContractProxy/build/contracts/IUniswapV1Factory.json: -------------------------------------------------------------------------------- 1 | { 2 | "contractName": "IUniswapV1Factory", 3 | "abi": [ 4 | { 5 | "inputs": [ 6 | { 7 | "internalType": "address", 8 | "name": "", 9 | "type": "address" 10 | } 11 | ], 12 | "name": "getExchange", 13 | "outputs": [ 14 | { 15 | "internalType": "address", 16 | "name": "", 17 | "type": "address" 18 | } 19 | ], 20 | "stateMutability": "view", 21 | "type": "function" 22 | } 23 | ], 24 | "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"getExchange\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"/Users/patricksteele/Desktop/eth/demo/contracts/interfaces/V1/IUniswapV1Factory.sol\":\"IUniswapV1Factory\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"/Users/patricksteele/Desktop/eth/demo/contracts/interfaces/V1/IUniswapV1Factory.sol\":{\"keccak256\":\"0x2a554e26d874fa4b10736f2e2ac1ba6253cd1ad08a97bd941cb0a41015565589\",\"urls\":[\"bzz-raw://bbe29db0ebf08621cb4211219c02262be9c7510fe03bab94f849a38993f957d6\",\"dweb:/ipfs/QmTutAVpjg925m4JLqHTvukdTyoTr77FotAUAA2AzGug1f\"]}},\"version\":1}", 25 | "bytecode": "0x", 26 | "deployedBytecode": "0x", 27 | "immutableReferences": {}, 28 | "sourceMap": "", 29 | "deployedSourceMap": "", 30 | "source": "pragma solidity >=0.5.0;\n\ninterface IUniswapV1Factory {\n function getExchange(address) external view returns (address);\n}\n", 31 | "sourcePath": "/Users/patricksteele/Desktop/eth/demo/contracts/interfaces/V1/IUniswapV1Factory.sol", 32 | "ast": { 33 | "absolutePath": "/Users/patricksteele/Desktop/eth/demo/contracts/interfaces/V1/IUniswapV1Factory.sol", 34 | "exportedSymbols": { 35 | "IUniswapV1Factory": [ 36 | 2652 37 | ] 38 | }, 39 | "id": 2653, 40 | "license": null, 41 | "nodeType": "SourceUnit", 42 | "nodes": [ 43 | { 44 | "id": 2644, 45 | "literals": [ 46 | "solidity", 47 | ">=", 48 | "0.5", 49 | ".0" 50 | ], 51 | "nodeType": "PragmaDirective", 52 | "src": "0:24:8" 53 | }, 54 | { 55 | "abstract": false, 56 | "baseContracts": [], 57 | "contractDependencies": [], 58 | "contractKind": "interface", 59 | "documentation": null, 60 | "fullyImplemented": false, 61 | "id": 2652, 62 | "linearizedBaseContracts": [ 63 | 2652 64 | ], 65 | "name": "IUniswapV1Factory", 66 | "nodeType": "ContractDefinition", 67 | "nodes": [ 68 | { 69 | "body": null, 70 | "documentation": null, 71 | "functionSelector": "06f2bf62", 72 | "id": 2651, 73 | "implemented": false, 74 | "kind": "function", 75 | "modifiers": [], 76 | "name": "getExchange", 77 | "nodeType": "FunctionDefinition", 78 | "overrides": null, 79 | "parameters": { 80 | "id": 2647, 81 | "nodeType": "ParameterList", 82 | "parameters": [ 83 | { 84 | "constant": false, 85 | "id": 2646, 86 | "mutability": "mutable", 87 | "name": "", 88 | "nodeType": "VariableDeclaration", 89 | "overrides": null, 90 | "scope": 2651, 91 | "src": "81:7:8", 92 | "stateVariable": false, 93 | "storageLocation": "default", 94 | "typeDescriptions": { 95 | "typeIdentifier": "t_address", 96 | "typeString": "address" 97 | }, 98 | "typeName": { 99 | "id": 2645, 100 | "name": "address", 101 | "nodeType": "ElementaryTypeName", 102 | "src": "81:7:8", 103 | "stateMutability": "nonpayable", 104 | "typeDescriptions": { 105 | "typeIdentifier": "t_address", 106 | "typeString": "address" 107 | } 108 | }, 109 | "value": null, 110 | "visibility": "internal" 111 | } 112 | ], 113 | "src": "80:9:8" 114 | }, 115 | "returnParameters": { 116 | "id": 2650, 117 | "nodeType": "ParameterList", 118 | "parameters": [ 119 | { 120 | "constant": false, 121 | "id": 2649, 122 | "mutability": "mutable", 123 | "name": "", 124 | "nodeType": "VariableDeclaration", 125 | "overrides": null, 126 | "scope": 2651, 127 | "src": "113:7:8", 128 | "stateVariable": false, 129 | "storageLocation": "default", 130 | "typeDescriptions": { 131 | "typeIdentifier": "t_address", 132 | "typeString": "address" 133 | }, 134 | "typeName": { 135 | "id": 2648, 136 | "name": "address", 137 | "nodeType": "ElementaryTypeName", 138 | "src": "113:7:8", 139 | "stateMutability": "nonpayable", 140 | "typeDescriptions": { 141 | "typeIdentifier": "t_address", 142 | "typeString": "address" 143 | } 144 | }, 145 | "value": null, 146 | "visibility": "internal" 147 | } 148 | ], 149 | "src": "112:9:8" 150 | }, 151 | "scope": 2652, 152 | "src": "60:62:8", 153 | "stateMutability": "view", 154 | "virtual": false, 155 | "visibility": "external" 156 | } 157 | ], 158 | "scope": 2653, 159 | "src": "26:98:8" 160 | } 161 | ], 162 | "src": "0:125:8" 163 | }, 164 | "legacyAST": { 165 | "absolutePath": "/Users/patricksteele/Desktop/eth/demo/contracts/interfaces/V1/IUniswapV1Factory.sol", 166 | "exportedSymbols": { 167 | "IUniswapV1Factory": [ 168 | 2652 169 | ] 170 | }, 171 | "id": 2653, 172 | "license": null, 173 | "nodeType": "SourceUnit", 174 | "nodes": [ 175 | { 176 | "id": 2644, 177 | "literals": [ 178 | "solidity", 179 | ">=", 180 | "0.5", 181 | ".0" 182 | ], 183 | "nodeType": "PragmaDirective", 184 | "src": "0:24:8" 185 | }, 186 | { 187 | "abstract": false, 188 | "baseContracts": [], 189 | "contractDependencies": [], 190 | "contractKind": "interface", 191 | "documentation": null, 192 | "fullyImplemented": false, 193 | "id": 2652, 194 | "linearizedBaseContracts": [ 195 | 2652 196 | ], 197 | "name": "IUniswapV1Factory", 198 | "nodeType": "ContractDefinition", 199 | "nodes": [ 200 | { 201 | "body": null, 202 | "documentation": null, 203 | "functionSelector": "06f2bf62", 204 | "id": 2651, 205 | "implemented": false, 206 | "kind": "function", 207 | "modifiers": [], 208 | "name": "getExchange", 209 | "nodeType": "FunctionDefinition", 210 | "overrides": null, 211 | "parameters": { 212 | "id": 2647, 213 | "nodeType": "ParameterList", 214 | "parameters": [ 215 | { 216 | "constant": false, 217 | "id": 2646, 218 | "mutability": "mutable", 219 | "name": "", 220 | "nodeType": "VariableDeclaration", 221 | "overrides": null, 222 | "scope": 2651, 223 | "src": "81:7:8", 224 | "stateVariable": false, 225 | "storageLocation": "default", 226 | "typeDescriptions": { 227 | "typeIdentifier": "t_address", 228 | "typeString": "address" 229 | }, 230 | "typeName": { 231 | "id": 2645, 232 | "name": "address", 233 | "nodeType": "ElementaryTypeName", 234 | "src": "81:7:8", 235 | "stateMutability": "nonpayable", 236 | "typeDescriptions": { 237 | "typeIdentifier": "t_address", 238 | "typeString": "address" 239 | } 240 | }, 241 | "value": null, 242 | "visibility": "internal" 243 | } 244 | ], 245 | "src": "80:9:8" 246 | }, 247 | "returnParameters": { 248 | "id": 2650, 249 | "nodeType": "ParameterList", 250 | "parameters": [ 251 | { 252 | "constant": false, 253 | "id": 2649, 254 | "mutability": "mutable", 255 | "name": "", 256 | "nodeType": "VariableDeclaration", 257 | "overrides": null, 258 | "scope": 2651, 259 | "src": "113:7:8", 260 | "stateVariable": false, 261 | "storageLocation": "default", 262 | "typeDescriptions": { 263 | "typeIdentifier": "t_address", 264 | "typeString": "address" 265 | }, 266 | "typeName": { 267 | "id": 2648, 268 | "name": "address", 269 | "nodeType": "ElementaryTypeName", 270 | "src": "113:7:8", 271 | "stateMutability": "nonpayable", 272 | "typeDescriptions": { 273 | "typeIdentifier": "t_address", 274 | "typeString": "address" 275 | } 276 | }, 277 | "value": null, 278 | "visibility": "internal" 279 | } 280 | ], 281 | "src": "112:9:8" 282 | }, 283 | "scope": 2652, 284 | "src": "60:62:8", 285 | "stateMutability": "view", 286 | "virtual": false, 287 | "visibility": "external" 288 | } 289 | ], 290 | "scope": 2653, 291 | "src": "26:98:8" 292 | } 293 | ], 294 | "src": "0:125:8" 295 | }, 296 | "compiler": { 297 | "name": "solc", 298 | "version": "0.6.12+commit.27d51765.Emscripten.clang" 299 | }, 300 | "networks": {}, 301 | "schemaVersion": "3.2.5", 302 | "updatedAt": "2021-01-16T02:18:16.083Z", 303 | "devdoc": { 304 | "kind": "dev", 305 | "methods": {}, 306 | "version": 1 307 | }, 308 | "userdoc": { 309 | "kind": "user", 310 | "methods": {}, 311 | "version": 1 312 | } 313 | } -------------------------------------------------------------------------------- /smartContractProxy/build/contracts/IUniswapV2Migrator.json: -------------------------------------------------------------------------------- 1 | { 2 | "contractName": "IUniswapV2Migrator", 3 | "abi": [ 4 | { 5 | "inputs": [ 6 | { 7 | "internalType": "address", 8 | "name": "token", 9 | "type": "address" 10 | }, 11 | { 12 | "internalType": "uint256", 13 | "name": "amountTokenMin", 14 | "type": "uint256" 15 | }, 16 | { 17 | "internalType": "uint256", 18 | "name": "amountETHMin", 19 | "type": "uint256" 20 | }, 21 | { 22 | "internalType": "address", 23 | "name": "to", 24 | "type": "address" 25 | }, 26 | { 27 | "internalType": "uint256", 28 | "name": "deadline", 29 | "type": "uint256" 30 | } 31 | ], 32 | "name": "migrate", 33 | "outputs": [], 34 | "stateMutability": "nonpayable", 35 | "type": "function" 36 | } 37 | ], 38 | "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"migrate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"/Users/patricksteele/Desktop/eth/demo/contracts/interfaces/IUniswapV2Migrator.sol\":\"IUniswapV2Migrator\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"/Users/patricksteele/Desktop/eth/demo/contracts/interfaces/IUniswapV2Migrator.sol\":{\"keccak256\":\"0xa83ac0f597c04134b3ea423fd55d3077e952197c1991e23c4e304bfb35a90124\",\"urls\":[\"bzz-raw://ec1a3358caaa80af192bf4a8913041b037736412d7d6d5e894d58dadfab3a1da\",\"dweb:/ipfs/QmbYVrgxQZVevcBgTcPUFutk5mpj61BAdmTPMXGiBt1vA8\"]}},\"version\":1}", 39 | "bytecode": "0x", 40 | "deployedBytecode": "0x", 41 | "immutableReferences": {}, 42 | "sourceMap": "", 43 | "deployedSourceMap": "", 44 | "source": "pragma solidity >=0.5.0;\n\ninterface IUniswapV2Migrator {\n function migrate(address token, uint amountTokenMin, uint amountETHMin, address to, uint deadline) external;\n}\n", 45 | "sourcePath": "/Users/patricksteele/Desktop/eth/demo/contracts/interfaces/IUniswapV2Migrator.sol", 46 | "ast": { 47 | "absolutePath": "/Users/patricksteele/Desktop/eth/demo/contracts/interfaces/IUniswapV2Migrator.sol", 48 | "exportedSymbols": { 49 | "IUniswapV2Migrator": [ 50 | 2170 51 | ] 52 | }, 53 | "id": 2171, 54 | "license": null, 55 | "nodeType": "SourceUnit", 56 | "nodes": [ 57 | { 58 | "id": 2156, 59 | "literals": [ 60 | "solidity", 61 | ">=", 62 | "0.5", 63 | ".0" 64 | ], 65 | "nodeType": "PragmaDirective", 66 | "src": "0:24:3" 67 | }, 68 | { 69 | "abstract": false, 70 | "baseContracts": [], 71 | "contractDependencies": [], 72 | "contractKind": "interface", 73 | "documentation": null, 74 | "fullyImplemented": false, 75 | "id": 2170, 76 | "linearizedBaseContracts": [ 77 | 2170 78 | ], 79 | "name": "IUniswapV2Migrator", 80 | "nodeType": "ContractDefinition", 81 | "nodes": [ 82 | { 83 | "body": null, 84 | "documentation": null, 85 | "functionSelector": "b7df1d25", 86 | "id": 2169, 87 | "implemented": false, 88 | "kind": "function", 89 | "modifiers": [], 90 | "name": "migrate", 91 | "nodeType": "FunctionDefinition", 92 | "overrides": null, 93 | "parameters": { 94 | "id": 2167, 95 | "nodeType": "ParameterList", 96 | "parameters": [ 97 | { 98 | "constant": false, 99 | "id": 2158, 100 | "mutability": "mutable", 101 | "name": "token", 102 | "nodeType": "VariableDeclaration", 103 | "overrides": null, 104 | "scope": 2169, 105 | "src": "78:13:3", 106 | "stateVariable": false, 107 | "storageLocation": "default", 108 | "typeDescriptions": { 109 | "typeIdentifier": "t_address", 110 | "typeString": "address" 111 | }, 112 | "typeName": { 113 | "id": 2157, 114 | "name": "address", 115 | "nodeType": "ElementaryTypeName", 116 | "src": "78:7:3", 117 | "stateMutability": "nonpayable", 118 | "typeDescriptions": { 119 | "typeIdentifier": "t_address", 120 | "typeString": "address" 121 | } 122 | }, 123 | "value": null, 124 | "visibility": "internal" 125 | }, 126 | { 127 | "constant": false, 128 | "id": 2160, 129 | "mutability": "mutable", 130 | "name": "amountTokenMin", 131 | "nodeType": "VariableDeclaration", 132 | "overrides": null, 133 | "scope": 2169, 134 | "src": "93:19:3", 135 | "stateVariable": false, 136 | "storageLocation": "default", 137 | "typeDescriptions": { 138 | "typeIdentifier": "t_uint256", 139 | "typeString": "uint256" 140 | }, 141 | "typeName": { 142 | "id": 2159, 143 | "name": "uint", 144 | "nodeType": "ElementaryTypeName", 145 | "src": "93:4:3", 146 | "typeDescriptions": { 147 | "typeIdentifier": "t_uint256", 148 | "typeString": "uint256" 149 | } 150 | }, 151 | "value": null, 152 | "visibility": "internal" 153 | }, 154 | { 155 | "constant": false, 156 | "id": 2162, 157 | "mutability": "mutable", 158 | "name": "amountETHMin", 159 | "nodeType": "VariableDeclaration", 160 | "overrides": null, 161 | "scope": 2169, 162 | "src": "114:17:3", 163 | "stateVariable": false, 164 | "storageLocation": "default", 165 | "typeDescriptions": { 166 | "typeIdentifier": "t_uint256", 167 | "typeString": "uint256" 168 | }, 169 | "typeName": { 170 | "id": 2161, 171 | "name": "uint", 172 | "nodeType": "ElementaryTypeName", 173 | "src": "114:4:3", 174 | "typeDescriptions": { 175 | "typeIdentifier": "t_uint256", 176 | "typeString": "uint256" 177 | } 178 | }, 179 | "value": null, 180 | "visibility": "internal" 181 | }, 182 | { 183 | "constant": false, 184 | "id": 2164, 185 | "mutability": "mutable", 186 | "name": "to", 187 | "nodeType": "VariableDeclaration", 188 | "overrides": null, 189 | "scope": 2169, 190 | "src": "133:10:3", 191 | "stateVariable": false, 192 | "storageLocation": "default", 193 | "typeDescriptions": { 194 | "typeIdentifier": "t_address", 195 | "typeString": "address" 196 | }, 197 | "typeName": { 198 | "id": 2163, 199 | "name": "address", 200 | "nodeType": "ElementaryTypeName", 201 | "src": "133:7:3", 202 | "stateMutability": "nonpayable", 203 | "typeDescriptions": { 204 | "typeIdentifier": "t_address", 205 | "typeString": "address" 206 | } 207 | }, 208 | "value": null, 209 | "visibility": "internal" 210 | }, 211 | { 212 | "constant": false, 213 | "id": 2166, 214 | "mutability": "mutable", 215 | "name": "deadline", 216 | "nodeType": "VariableDeclaration", 217 | "overrides": null, 218 | "scope": 2169, 219 | "src": "145:13:3", 220 | "stateVariable": false, 221 | "storageLocation": "default", 222 | "typeDescriptions": { 223 | "typeIdentifier": "t_uint256", 224 | "typeString": "uint256" 225 | }, 226 | "typeName": { 227 | "id": 2165, 228 | "name": "uint", 229 | "nodeType": "ElementaryTypeName", 230 | "src": "145:4:3", 231 | "typeDescriptions": { 232 | "typeIdentifier": "t_uint256", 233 | "typeString": "uint256" 234 | } 235 | }, 236 | "value": null, 237 | "visibility": "internal" 238 | } 239 | ], 240 | "src": "77:82:3" 241 | }, 242 | "returnParameters": { 243 | "id": 2168, 244 | "nodeType": "ParameterList", 245 | "parameters": [], 246 | "src": "168:0:3" 247 | }, 248 | "scope": 2170, 249 | "src": "61:108:3", 250 | "stateMutability": "nonpayable", 251 | "virtual": false, 252 | "visibility": "external" 253 | } 254 | ], 255 | "scope": 2171, 256 | "src": "26:145:3" 257 | } 258 | ], 259 | "src": "0:172:3" 260 | }, 261 | "legacyAST": { 262 | "absolutePath": "/Users/patricksteele/Desktop/eth/demo/contracts/interfaces/IUniswapV2Migrator.sol", 263 | "exportedSymbols": { 264 | "IUniswapV2Migrator": [ 265 | 2170 266 | ] 267 | }, 268 | "id": 2171, 269 | "license": null, 270 | "nodeType": "SourceUnit", 271 | "nodes": [ 272 | { 273 | "id": 2156, 274 | "literals": [ 275 | "solidity", 276 | ">=", 277 | "0.5", 278 | ".0" 279 | ], 280 | "nodeType": "PragmaDirective", 281 | "src": "0:24:3" 282 | }, 283 | { 284 | "abstract": false, 285 | "baseContracts": [], 286 | "contractDependencies": [], 287 | "contractKind": "interface", 288 | "documentation": null, 289 | "fullyImplemented": false, 290 | "id": 2170, 291 | "linearizedBaseContracts": [ 292 | 2170 293 | ], 294 | "name": "IUniswapV2Migrator", 295 | "nodeType": "ContractDefinition", 296 | "nodes": [ 297 | { 298 | "body": null, 299 | "documentation": null, 300 | "functionSelector": "b7df1d25", 301 | "id": 2169, 302 | "implemented": false, 303 | "kind": "function", 304 | "modifiers": [], 305 | "name": "migrate", 306 | "nodeType": "FunctionDefinition", 307 | "overrides": null, 308 | "parameters": { 309 | "id": 2167, 310 | "nodeType": "ParameterList", 311 | "parameters": [ 312 | { 313 | "constant": false, 314 | "id": 2158, 315 | "mutability": "mutable", 316 | "name": "token", 317 | "nodeType": "VariableDeclaration", 318 | "overrides": null, 319 | "scope": 2169, 320 | "src": "78:13:3", 321 | "stateVariable": false, 322 | "storageLocation": "default", 323 | "typeDescriptions": { 324 | "typeIdentifier": "t_address", 325 | "typeString": "address" 326 | }, 327 | "typeName": { 328 | "id": 2157, 329 | "name": "address", 330 | "nodeType": "ElementaryTypeName", 331 | "src": "78:7:3", 332 | "stateMutability": "nonpayable", 333 | "typeDescriptions": { 334 | "typeIdentifier": "t_address", 335 | "typeString": "address" 336 | } 337 | }, 338 | "value": null, 339 | "visibility": "internal" 340 | }, 341 | { 342 | "constant": false, 343 | "id": 2160, 344 | "mutability": "mutable", 345 | "name": "amountTokenMin", 346 | "nodeType": "VariableDeclaration", 347 | "overrides": null, 348 | "scope": 2169, 349 | "src": "93:19:3", 350 | "stateVariable": false, 351 | "storageLocation": "default", 352 | "typeDescriptions": { 353 | "typeIdentifier": "t_uint256", 354 | "typeString": "uint256" 355 | }, 356 | "typeName": { 357 | "id": 2159, 358 | "name": "uint", 359 | "nodeType": "ElementaryTypeName", 360 | "src": "93:4:3", 361 | "typeDescriptions": { 362 | "typeIdentifier": "t_uint256", 363 | "typeString": "uint256" 364 | } 365 | }, 366 | "value": null, 367 | "visibility": "internal" 368 | }, 369 | { 370 | "constant": false, 371 | "id": 2162, 372 | "mutability": "mutable", 373 | "name": "amountETHMin", 374 | "nodeType": "VariableDeclaration", 375 | "overrides": null, 376 | "scope": 2169, 377 | "src": "114:17:3", 378 | "stateVariable": false, 379 | "storageLocation": "default", 380 | "typeDescriptions": { 381 | "typeIdentifier": "t_uint256", 382 | "typeString": "uint256" 383 | }, 384 | "typeName": { 385 | "id": 2161, 386 | "name": "uint", 387 | "nodeType": "ElementaryTypeName", 388 | "src": "114:4:3", 389 | "typeDescriptions": { 390 | "typeIdentifier": "t_uint256", 391 | "typeString": "uint256" 392 | } 393 | }, 394 | "value": null, 395 | "visibility": "internal" 396 | }, 397 | { 398 | "constant": false, 399 | "id": 2164, 400 | "mutability": "mutable", 401 | "name": "to", 402 | "nodeType": "VariableDeclaration", 403 | "overrides": null, 404 | "scope": 2169, 405 | "src": "133:10:3", 406 | "stateVariable": false, 407 | "storageLocation": "default", 408 | "typeDescriptions": { 409 | "typeIdentifier": "t_address", 410 | "typeString": "address" 411 | }, 412 | "typeName": { 413 | "id": 2163, 414 | "name": "address", 415 | "nodeType": "ElementaryTypeName", 416 | "src": "133:7:3", 417 | "stateMutability": "nonpayable", 418 | "typeDescriptions": { 419 | "typeIdentifier": "t_address", 420 | "typeString": "address" 421 | } 422 | }, 423 | "value": null, 424 | "visibility": "internal" 425 | }, 426 | { 427 | "constant": false, 428 | "id": 2166, 429 | "mutability": "mutable", 430 | "name": "deadline", 431 | "nodeType": "VariableDeclaration", 432 | "overrides": null, 433 | "scope": 2169, 434 | "src": "145:13:3", 435 | "stateVariable": false, 436 | "storageLocation": "default", 437 | "typeDescriptions": { 438 | "typeIdentifier": "t_uint256", 439 | "typeString": "uint256" 440 | }, 441 | "typeName": { 442 | "id": 2165, 443 | "name": "uint", 444 | "nodeType": "ElementaryTypeName", 445 | "src": "145:4:3", 446 | "typeDescriptions": { 447 | "typeIdentifier": "t_uint256", 448 | "typeString": "uint256" 449 | } 450 | }, 451 | "value": null, 452 | "visibility": "internal" 453 | } 454 | ], 455 | "src": "77:82:3" 456 | }, 457 | "returnParameters": { 458 | "id": 2168, 459 | "nodeType": "ParameterList", 460 | "parameters": [], 461 | "src": "168:0:3" 462 | }, 463 | "scope": 2170, 464 | "src": "61:108:3", 465 | "stateMutability": "nonpayable", 466 | "virtual": false, 467 | "visibility": "external" 468 | } 469 | ], 470 | "scope": 2171, 471 | "src": "26:145:3" 472 | } 473 | ], 474 | "src": "0:172:3" 475 | }, 476 | "compiler": { 477 | "name": "solc", 478 | "version": "0.6.12+commit.27d51765.Emscripten.clang" 479 | }, 480 | "networks": {}, 481 | "schemaVersion": "3.2.5", 482 | "updatedAt": "2021-01-16T02:18:16.066Z", 483 | "devdoc": { 484 | "kind": "dev", 485 | "methods": {}, 486 | "version": 1 487 | }, 488 | "userdoc": { 489 | "kind": "user", 490 | "methods": {}, 491 | "version": 1 492 | } 493 | } -------------------------------------------------------------------------------- /smartContractProxy/build/contracts/IWETH.json: -------------------------------------------------------------------------------- 1 | { 2 | "contractName": "IWETH", 3 | "abi": [ 4 | { 5 | "inputs": [], 6 | "name": "deposit", 7 | "outputs": [], 8 | "stateMutability": "payable", 9 | "type": "function" 10 | }, 11 | { 12 | "inputs": [ 13 | { 14 | "internalType": "address", 15 | "name": "to", 16 | "type": "address" 17 | }, 18 | { 19 | "internalType": "uint256", 20 | "name": "value", 21 | "type": "uint256" 22 | } 23 | ], 24 | "name": "transfer", 25 | "outputs": [ 26 | { 27 | "internalType": "bool", 28 | "name": "", 29 | "type": "bool" 30 | } 31 | ], 32 | "stateMutability": "nonpayable", 33 | "type": "function" 34 | }, 35 | { 36 | "inputs": [ 37 | { 38 | "internalType": "uint256", 39 | "name": "", 40 | "type": "uint256" 41 | } 42 | ], 43 | "name": "withdraw", 44 | "outputs": [], 45 | "stateMutability": "nonpayable", 46 | "type": "function" 47 | } 48 | ], 49 | "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"/Users/patricksteele/Desktop/eth/demo/contracts/interfaces/IWETH.sol\":\"IWETH\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"/Users/patricksteele/Desktop/eth/demo/contracts/interfaces/IWETH.sol\":{\"keccak256\":\"0xfc10758fd8dba790c39468dccd358cb7cef06ae7c4781832cc7aa76f91f167e6\",\"urls\":[\"bzz-raw://dc22493dea6c60d47835eeba53726f8a6f76f4fcd798d40e54608a1380515d49\",\"dweb:/ipfs/QmS1QVcBRH4TELYNE7XCfjSVQEWFupyaNLKmMkKH7iPjrm\"]}},\"version\":1}", 50 | "bytecode": "0x", 51 | "deployedBytecode": "0x", 52 | "immutableReferences": {}, 53 | "sourceMap": "", 54 | "deployedSourceMap": "", 55 | "source": "pragma solidity >=0.5.0;\n\ninterface IWETH {\n function deposit() external payable;\n function transfer(address to, uint value) external returns (bool);\n function withdraw(uint) external;\n}\n", 56 | "sourcePath": "/Users/patricksteele/Desktop/eth/demo/contracts/interfaces/IWETH.sol", 57 | "ast": { 58 | "absolutePath": "/Users/patricksteele/Desktop/eth/demo/contracts/interfaces/IWETH.sol", 59 | "exportedSymbols": { 60 | "IWETH": [ 61 | 2586 62 | ] 63 | }, 64 | "id": 2587, 65 | "license": null, 66 | "nodeType": "SourceUnit", 67 | "nodes": [ 68 | { 69 | "id": 2568, 70 | "literals": [ 71 | "solidity", 72 | ">=", 73 | "0.5", 74 | ".0" 75 | ], 76 | "nodeType": "PragmaDirective", 77 | "src": "0:24:6" 78 | }, 79 | { 80 | "abstract": false, 81 | "baseContracts": [], 82 | "contractDependencies": [], 83 | "contractKind": "interface", 84 | "documentation": null, 85 | "fullyImplemented": false, 86 | "id": 2586, 87 | "linearizedBaseContracts": [ 88 | 2586 89 | ], 90 | "name": "IWETH", 91 | "nodeType": "ContractDefinition", 92 | "nodes": [ 93 | { 94 | "body": null, 95 | "documentation": null, 96 | "functionSelector": "d0e30db0", 97 | "id": 2571, 98 | "implemented": false, 99 | "kind": "function", 100 | "modifiers": [], 101 | "name": "deposit", 102 | "nodeType": "FunctionDefinition", 103 | "overrides": null, 104 | "parameters": { 105 | "id": 2569, 106 | "nodeType": "ParameterList", 107 | "parameters": [], 108 | "src": "64:2:6" 109 | }, 110 | "returnParameters": { 111 | "id": 2570, 112 | "nodeType": "ParameterList", 113 | "parameters": [], 114 | "src": "83:0:6" 115 | }, 116 | "scope": 2586, 117 | "src": "48:36:6", 118 | "stateMutability": "payable", 119 | "virtual": false, 120 | "visibility": "external" 121 | }, 122 | { 123 | "body": null, 124 | "documentation": null, 125 | "functionSelector": "a9059cbb", 126 | "id": 2580, 127 | "implemented": false, 128 | "kind": "function", 129 | "modifiers": [], 130 | "name": "transfer", 131 | "nodeType": "FunctionDefinition", 132 | "overrides": null, 133 | "parameters": { 134 | "id": 2576, 135 | "nodeType": "ParameterList", 136 | "parameters": [ 137 | { 138 | "constant": false, 139 | "id": 2573, 140 | "mutability": "mutable", 141 | "name": "to", 142 | "nodeType": "VariableDeclaration", 143 | "overrides": null, 144 | "scope": 2580, 145 | "src": "107:10:6", 146 | "stateVariable": false, 147 | "storageLocation": "default", 148 | "typeDescriptions": { 149 | "typeIdentifier": "t_address", 150 | "typeString": "address" 151 | }, 152 | "typeName": { 153 | "id": 2572, 154 | "name": "address", 155 | "nodeType": "ElementaryTypeName", 156 | "src": "107:7:6", 157 | "stateMutability": "nonpayable", 158 | "typeDescriptions": { 159 | "typeIdentifier": "t_address", 160 | "typeString": "address" 161 | } 162 | }, 163 | "value": null, 164 | "visibility": "internal" 165 | }, 166 | { 167 | "constant": false, 168 | "id": 2575, 169 | "mutability": "mutable", 170 | "name": "value", 171 | "nodeType": "VariableDeclaration", 172 | "overrides": null, 173 | "scope": 2580, 174 | "src": "119:10:6", 175 | "stateVariable": false, 176 | "storageLocation": "default", 177 | "typeDescriptions": { 178 | "typeIdentifier": "t_uint256", 179 | "typeString": "uint256" 180 | }, 181 | "typeName": { 182 | "id": 2574, 183 | "name": "uint", 184 | "nodeType": "ElementaryTypeName", 185 | "src": "119:4:6", 186 | "typeDescriptions": { 187 | "typeIdentifier": "t_uint256", 188 | "typeString": "uint256" 189 | } 190 | }, 191 | "value": null, 192 | "visibility": "internal" 193 | } 194 | ], 195 | "src": "106:24:6" 196 | }, 197 | "returnParameters": { 198 | "id": 2579, 199 | "nodeType": "ParameterList", 200 | "parameters": [ 201 | { 202 | "constant": false, 203 | "id": 2578, 204 | "mutability": "mutable", 205 | "name": "", 206 | "nodeType": "VariableDeclaration", 207 | "overrides": null, 208 | "scope": 2580, 209 | "src": "149:4:6", 210 | "stateVariable": false, 211 | "storageLocation": "default", 212 | "typeDescriptions": { 213 | "typeIdentifier": "t_bool", 214 | "typeString": "bool" 215 | }, 216 | "typeName": { 217 | "id": 2577, 218 | "name": "bool", 219 | "nodeType": "ElementaryTypeName", 220 | "src": "149:4:6", 221 | "typeDescriptions": { 222 | "typeIdentifier": "t_bool", 223 | "typeString": "bool" 224 | } 225 | }, 226 | "value": null, 227 | "visibility": "internal" 228 | } 229 | ], 230 | "src": "148:6:6" 231 | }, 232 | "scope": 2586, 233 | "src": "89:66:6", 234 | "stateMutability": "nonpayable", 235 | "virtual": false, 236 | "visibility": "external" 237 | }, 238 | { 239 | "body": null, 240 | "documentation": null, 241 | "functionSelector": "2e1a7d4d", 242 | "id": 2585, 243 | "implemented": false, 244 | "kind": "function", 245 | "modifiers": [], 246 | "name": "withdraw", 247 | "nodeType": "FunctionDefinition", 248 | "overrides": null, 249 | "parameters": { 250 | "id": 2583, 251 | "nodeType": "ParameterList", 252 | "parameters": [ 253 | { 254 | "constant": false, 255 | "id": 2582, 256 | "mutability": "mutable", 257 | "name": "", 258 | "nodeType": "VariableDeclaration", 259 | "overrides": null, 260 | "scope": 2585, 261 | "src": "178:4:6", 262 | "stateVariable": false, 263 | "storageLocation": "default", 264 | "typeDescriptions": { 265 | "typeIdentifier": "t_uint256", 266 | "typeString": "uint256" 267 | }, 268 | "typeName": { 269 | "id": 2581, 270 | "name": "uint", 271 | "nodeType": "ElementaryTypeName", 272 | "src": "178:4:6", 273 | "typeDescriptions": { 274 | "typeIdentifier": "t_uint256", 275 | "typeString": "uint256" 276 | } 277 | }, 278 | "value": null, 279 | "visibility": "internal" 280 | } 281 | ], 282 | "src": "177:6:6" 283 | }, 284 | "returnParameters": { 285 | "id": 2584, 286 | "nodeType": "ParameterList", 287 | "parameters": [], 288 | "src": "192:0:6" 289 | }, 290 | "scope": 2586, 291 | "src": "160:33:6", 292 | "stateMutability": "nonpayable", 293 | "virtual": false, 294 | "visibility": "external" 295 | } 296 | ], 297 | "scope": 2587, 298 | "src": "26:169:6" 299 | } 300 | ], 301 | "src": "0:196:6" 302 | }, 303 | "legacyAST": { 304 | "absolutePath": "/Users/patricksteele/Desktop/eth/demo/contracts/interfaces/IWETH.sol", 305 | "exportedSymbols": { 306 | "IWETH": [ 307 | 2586 308 | ] 309 | }, 310 | "id": 2587, 311 | "license": null, 312 | "nodeType": "SourceUnit", 313 | "nodes": [ 314 | { 315 | "id": 2568, 316 | "literals": [ 317 | "solidity", 318 | ">=", 319 | "0.5", 320 | ".0" 321 | ], 322 | "nodeType": "PragmaDirective", 323 | "src": "0:24:6" 324 | }, 325 | { 326 | "abstract": false, 327 | "baseContracts": [], 328 | "contractDependencies": [], 329 | "contractKind": "interface", 330 | "documentation": null, 331 | "fullyImplemented": false, 332 | "id": 2586, 333 | "linearizedBaseContracts": [ 334 | 2586 335 | ], 336 | "name": "IWETH", 337 | "nodeType": "ContractDefinition", 338 | "nodes": [ 339 | { 340 | "body": null, 341 | "documentation": null, 342 | "functionSelector": "d0e30db0", 343 | "id": 2571, 344 | "implemented": false, 345 | "kind": "function", 346 | "modifiers": [], 347 | "name": "deposit", 348 | "nodeType": "FunctionDefinition", 349 | "overrides": null, 350 | "parameters": { 351 | "id": 2569, 352 | "nodeType": "ParameterList", 353 | "parameters": [], 354 | "src": "64:2:6" 355 | }, 356 | "returnParameters": { 357 | "id": 2570, 358 | "nodeType": "ParameterList", 359 | "parameters": [], 360 | "src": "83:0:6" 361 | }, 362 | "scope": 2586, 363 | "src": "48:36:6", 364 | "stateMutability": "payable", 365 | "virtual": false, 366 | "visibility": "external" 367 | }, 368 | { 369 | "body": null, 370 | "documentation": null, 371 | "functionSelector": "a9059cbb", 372 | "id": 2580, 373 | "implemented": false, 374 | "kind": "function", 375 | "modifiers": [], 376 | "name": "transfer", 377 | "nodeType": "FunctionDefinition", 378 | "overrides": null, 379 | "parameters": { 380 | "id": 2576, 381 | "nodeType": "ParameterList", 382 | "parameters": [ 383 | { 384 | "constant": false, 385 | "id": 2573, 386 | "mutability": "mutable", 387 | "name": "to", 388 | "nodeType": "VariableDeclaration", 389 | "overrides": null, 390 | "scope": 2580, 391 | "src": "107:10:6", 392 | "stateVariable": false, 393 | "storageLocation": "default", 394 | "typeDescriptions": { 395 | "typeIdentifier": "t_address", 396 | "typeString": "address" 397 | }, 398 | "typeName": { 399 | "id": 2572, 400 | "name": "address", 401 | "nodeType": "ElementaryTypeName", 402 | "src": "107:7:6", 403 | "stateMutability": "nonpayable", 404 | "typeDescriptions": { 405 | "typeIdentifier": "t_address", 406 | "typeString": "address" 407 | } 408 | }, 409 | "value": null, 410 | "visibility": "internal" 411 | }, 412 | { 413 | "constant": false, 414 | "id": 2575, 415 | "mutability": "mutable", 416 | "name": "value", 417 | "nodeType": "VariableDeclaration", 418 | "overrides": null, 419 | "scope": 2580, 420 | "src": "119:10:6", 421 | "stateVariable": false, 422 | "storageLocation": "default", 423 | "typeDescriptions": { 424 | "typeIdentifier": "t_uint256", 425 | "typeString": "uint256" 426 | }, 427 | "typeName": { 428 | "id": 2574, 429 | "name": "uint", 430 | "nodeType": "ElementaryTypeName", 431 | "src": "119:4:6", 432 | "typeDescriptions": { 433 | "typeIdentifier": "t_uint256", 434 | "typeString": "uint256" 435 | } 436 | }, 437 | "value": null, 438 | "visibility": "internal" 439 | } 440 | ], 441 | "src": "106:24:6" 442 | }, 443 | "returnParameters": { 444 | "id": 2579, 445 | "nodeType": "ParameterList", 446 | "parameters": [ 447 | { 448 | "constant": false, 449 | "id": 2578, 450 | "mutability": "mutable", 451 | "name": "", 452 | "nodeType": "VariableDeclaration", 453 | "overrides": null, 454 | "scope": 2580, 455 | "src": "149:4:6", 456 | "stateVariable": false, 457 | "storageLocation": "default", 458 | "typeDescriptions": { 459 | "typeIdentifier": "t_bool", 460 | "typeString": "bool" 461 | }, 462 | "typeName": { 463 | "id": 2577, 464 | "name": "bool", 465 | "nodeType": "ElementaryTypeName", 466 | "src": "149:4:6", 467 | "typeDescriptions": { 468 | "typeIdentifier": "t_bool", 469 | "typeString": "bool" 470 | } 471 | }, 472 | "value": null, 473 | "visibility": "internal" 474 | } 475 | ], 476 | "src": "148:6:6" 477 | }, 478 | "scope": 2586, 479 | "src": "89:66:6", 480 | "stateMutability": "nonpayable", 481 | "virtual": false, 482 | "visibility": "external" 483 | }, 484 | { 485 | "body": null, 486 | "documentation": null, 487 | "functionSelector": "2e1a7d4d", 488 | "id": 2585, 489 | "implemented": false, 490 | "kind": "function", 491 | "modifiers": [], 492 | "name": "withdraw", 493 | "nodeType": "FunctionDefinition", 494 | "overrides": null, 495 | "parameters": { 496 | "id": 2583, 497 | "nodeType": "ParameterList", 498 | "parameters": [ 499 | { 500 | "constant": false, 501 | "id": 2582, 502 | "mutability": "mutable", 503 | "name": "", 504 | "nodeType": "VariableDeclaration", 505 | "overrides": null, 506 | "scope": 2585, 507 | "src": "178:4:6", 508 | "stateVariable": false, 509 | "storageLocation": "default", 510 | "typeDescriptions": { 511 | "typeIdentifier": "t_uint256", 512 | "typeString": "uint256" 513 | }, 514 | "typeName": { 515 | "id": 2581, 516 | "name": "uint", 517 | "nodeType": "ElementaryTypeName", 518 | "src": "178:4:6", 519 | "typeDescriptions": { 520 | "typeIdentifier": "t_uint256", 521 | "typeString": "uint256" 522 | } 523 | }, 524 | "value": null, 525 | "visibility": "internal" 526 | } 527 | ], 528 | "src": "177:6:6" 529 | }, 530 | "returnParameters": { 531 | "id": 2584, 532 | "nodeType": "ParameterList", 533 | "parameters": [], 534 | "src": "192:0:6" 535 | }, 536 | "scope": 2586, 537 | "src": "160:33:6", 538 | "stateMutability": "nonpayable", 539 | "virtual": false, 540 | "visibility": "external" 541 | } 542 | ], 543 | "scope": 2587, 544 | "src": "26:169:6" 545 | } 546 | ], 547 | "src": "0:196:6" 548 | }, 549 | "compiler": { 550 | "name": "solc", 551 | "version": "0.6.12+commit.27d51765.Emscripten.clang" 552 | }, 553 | "networks": {}, 554 | "schemaVersion": "3.2.5", 555 | "updatedAt": "2021-01-16T02:18:16.072Z", 556 | "devdoc": { 557 | "kind": "dev", 558 | "methods": {}, 559 | "version": 1 560 | }, 561 | "userdoc": { 562 | "kind": "user", 563 | "methods": {}, 564 | "version": 1 565 | } 566 | } -------------------------------------------------------------------------------- /smartContractProxy/build/contracts/Migrations.json: -------------------------------------------------------------------------------- 1 | { 2 | "contractName": "Migrations", 3 | "abi": [ 4 | { 5 | "inputs": [], 6 | "name": "last_completed_migration", 7 | "outputs": [ 8 | { 9 | "internalType": "uint256", 10 | "name": "", 11 | "type": "uint256" 12 | } 13 | ], 14 | "stateMutability": "view", 15 | "type": "function", 16 | "constant": true 17 | }, 18 | { 19 | "inputs": [], 20 | "name": "owner", 21 | "outputs": [ 22 | { 23 | "internalType": "address", 24 | "name": "", 25 | "type": "address" 26 | } 27 | ], 28 | "stateMutability": "view", 29 | "type": "function", 30 | "constant": true 31 | }, 32 | { 33 | "inputs": [ 34 | { 35 | "internalType": "uint256", 36 | "name": "completed", 37 | "type": "uint256" 38 | } 39 | ], 40 | "name": "setCompleted", 41 | "outputs": [], 42 | "stateMutability": "nonpayable", 43 | "type": "function" 44 | } 45 | ], 46 | "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"last_completed_migration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"completed\",\"type\":\"uint256\"}],\"name\":\"setCompleted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"/Users/patricksteele/Desktop/eth/demo/contracts/Migrations.sol\":\"Migrations\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"/Users/patricksteele/Desktop/eth/demo/contracts/Migrations.sol\":{\"keccak256\":\"0x7797e159bfd6b953422b4bd6d5de5946971d8b5ed74c4b1f6517d61fe236b851\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://56bdf6130f3ced3e78baa0f3e7f34cb4c5131d90721326056bbf0dd202d8539d\",\"dweb:/ipfs/QmZqRKebKwn6YXejnnPribsyiXLmrAx32JpatFhvS76NKp\"]}},\"version\":1}", 47 | "bytecode": "0x6080604052336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561005057600080fd5b50610207806100606000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063445df0ac146100465780638da5cb5b14610064578063fdacd57614610098575b600080fd5b61004e6100c6565b6040518082815260200191505060405180910390f35b61006c6100cc565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100c4600480360360208110156100ae57600080fd5b81019080803590602001909291905050506100f0565b005b60015481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610194576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603381526020018061019f6033913960400191505060405180910390fd5b806001819055505056fe546869732066756e6374696f6e206973207265737472696374656420746f2074686520636f6e74726163742773206f776e6572a26469706673582212209781b3411a6d0a567493d39c6f0f55641f5a3811784d4ca3cccc8fd28286b93864736f6c634300060c0033", 48 | "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c8063445df0ac146100465780638da5cb5b14610064578063fdacd57614610098575b600080fd5b61004e6100c6565b6040518082815260200191505060405180910390f35b61006c6100cc565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100c4600480360360208110156100ae57600080fd5b81019080803590602001909291905050506100f0565b005b60015481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610194576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603381526020018061019f6033913960400191505060405180910390fd5b806001819055505056fe546869732066756e6374696f6e206973207265737472696374656420746f2074686520636f6e74726163742773206f776e6572a26469706673582212209781b3411a6d0a567493d39c6f0f55641f5a3811784d4ca3cccc8fd28286b93864736f6c634300060c0033", 49 | "immutableReferences": {}, 50 | "sourceMap": "66:352:0:-:0;;;113:10;90:33;;;;;;;;;;;;;;;;;;;;66:352;;;;;;;;;;;;;;;;", 51 | "deployedSourceMap": "66:352:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;127:36;;;:::i;:::-;;;;;;;;;;;;;;;;;;;90:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;313:103;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;127:36;;;;:::o;90:33::-;;;;;;;;;;;;:::o;313:103::-;225:5;;;;;;;;;;211:19;;:10;:19;;;196:101;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;402:9:::1;375:24;:36;;;;313:103:::0;:::o", 52 | "source": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.8.0;\n\ncontract Migrations {\n address public owner = msg.sender;\n uint public last_completed_migration;\n\n modifier restricted() {\n require(\n msg.sender == owner,\n \"This function is restricted to the contract's owner\"\n );\n _;\n }\n\n function setCompleted(uint completed) public restricted {\n last_completed_migration = completed;\n }\n}\n", 53 | "sourcePath": "/Users/patricksteele/Desktop/eth/demo/contracts/Migrations.sol", 54 | "ast": { 55 | "absolutePath": "/Users/patricksteele/Desktop/eth/demo/contracts/Migrations.sol", 56 | "exportedSymbols": { 57 | "Migrations": [ 58 | 32 59 | ] 60 | }, 61 | "id": 33, 62 | "license": "MIT", 63 | "nodeType": "SourceUnit", 64 | "nodes": [ 65 | { 66 | "id": 1, 67 | "literals": [ 68 | "solidity", 69 | ">=", 70 | "0.4", 71 | ".22", 72 | "<", 73 | "0.8", 74 | ".0" 75 | ], 76 | "nodeType": "PragmaDirective", 77 | "src": "32:32:0" 78 | }, 79 | { 80 | "abstract": false, 81 | "baseContracts": [], 82 | "contractDependencies": [], 83 | "contractKind": "contract", 84 | "documentation": null, 85 | "fullyImplemented": true, 86 | "id": 32, 87 | "linearizedBaseContracts": [ 88 | 32 89 | ], 90 | "name": "Migrations", 91 | "nodeType": "ContractDefinition", 92 | "nodes": [ 93 | { 94 | "constant": false, 95 | "functionSelector": "8da5cb5b", 96 | "id": 5, 97 | "mutability": "mutable", 98 | "name": "owner", 99 | "nodeType": "VariableDeclaration", 100 | "overrides": null, 101 | "scope": 32, 102 | "src": "90:33:0", 103 | "stateVariable": true, 104 | "storageLocation": "default", 105 | "typeDescriptions": { 106 | "typeIdentifier": "t_address", 107 | "typeString": "address" 108 | }, 109 | "typeName": { 110 | "id": 2, 111 | "name": "address", 112 | "nodeType": "ElementaryTypeName", 113 | "src": "90:7:0", 114 | "stateMutability": "nonpayable", 115 | "typeDescriptions": { 116 | "typeIdentifier": "t_address", 117 | "typeString": "address" 118 | } 119 | }, 120 | "value": { 121 | "argumentTypes": null, 122 | "expression": { 123 | "argumentTypes": null, 124 | "id": 3, 125 | "name": "msg", 126 | "nodeType": "Identifier", 127 | "overloadedDeclarations": [], 128 | "referencedDeclaration": -15, 129 | "src": "113:3:0", 130 | "typeDescriptions": { 131 | "typeIdentifier": "t_magic_message", 132 | "typeString": "msg" 133 | } 134 | }, 135 | "id": 4, 136 | "isConstant": false, 137 | "isLValue": false, 138 | "isPure": false, 139 | "lValueRequested": false, 140 | "memberName": "sender", 141 | "nodeType": "MemberAccess", 142 | "referencedDeclaration": null, 143 | "src": "113:10:0", 144 | "typeDescriptions": { 145 | "typeIdentifier": "t_address_payable", 146 | "typeString": "address payable" 147 | } 148 | }, 149 | "visibility": "public" 150 | }, 151 | { 152 | "constant": false, 153 | "functionSelector": "445df0ac", 154 | "id": 7, 155 | "mutability": "mutable", 156 | "name": "last_completed_migration", 157 | "nodeType": "VariableDeclaration", 158 | "overrides": null, 159 | "scope": 32, 160 | "src": "127:36:0", 161 | "stateVariable": true, 162 | "storageLocation": "default", 163 | "typeDescriptions": { 164 | "typeIdentifier": "t_uint256", 165 | "typeString": "uint256" 166 | }, 167 | "typeName": { 168 | "id": 6, 169 | "name": "uint", 170 | "nodeType": "ElementaryTypeName", 171 | "src": "127:4:0", 172 | "typeDescriptions": { 173 | "typeIdentifier": "t_uint256", 174 | "typeString": "uint256" 175 | } 176 | }, 177 | "value": null, 178 | "visibility": "public" 179 | }, 180 | { 181 | "body": { 182 | "id": 18, 183 | "nodeType": "Block", 184 | "src": "190:119:0", 185 | "statements": [ 186 | { 187 | "expression": { 188 | "argumentTypes": null, 189 | "arguments": [ 190 | { 191 | "argumentTypes": null, 192 | "commonType": { 193 | "typeIdentifier": "t_address", 194 | "typeString": "address" 195 | }, 196 | "id": 13, 197 | "isConstant": false, 198 | "isLValue": false, 199 | "isPure": false, 200 | "lValueRequested": false, 201 | "leftExpression": { 202 | "argumentTypes": null, 203 | "expression": { 204 | "argumentTypes": null, 205 | "id": 10, 206 | "name": "msg", 207 | "nodeType": "Identifier", 208 | "overloadedDeclarations": [], 209 | "referencedDeclaration": -15, 210 | "src": "211:3:0", 211 | "typeDescriptions": { 212 | "typeIdentifier": "t_magic_message", 213 | "typeString": "msg" 214 | } 215 | }, 216 | "id": 11, 217 | "isConstant": false, 218 | "isLValue": false, 219 | "isPure": false, 220 | "lValueRequested": false, 221 | "memberName": "sender", 222 | "nodeType": "MemberAccess", 223 | "referencedDeclaration": null, 224 | "src": "211:10:0", 225 | "typeDescriptions": { 226 | "typeIdentifier": "t_address_payable", 227 | "typeString": "address payable" 228 | } 229 | }, 230 | "nodeType": "BinaryOperation", 231 | "operator": "==", 232 | "rightExpression": { 233 | "argumentTypes": null, 234 | "id": 12, 235 | "name": "owner", 236 | "nodeType": "Identifier", 237 | "overloadedDeclarations": [], 238 | "referencedDeclaration": 5, 239 | "src": "225:5:0", 240 | "typeDescriptions": { 241 | "typeIdentifier": "t_address", 242 | "typeString": "address" 243 | } 244 | }, 245 | "src": "211:19:0", 246 | "typeDescriptions": { 247 | "typeIdentifier": "t_bool", 248 | "typeString": "bool" 249 | } 250 | }, 251 | { 252 | "argumentTypes": null, 253 | "hexValue": "546869732066756e6374696f6e206973207265737472696374656420746f2074686520636f6e74726163742773206f776e6572", 254 | "id": 14, 255 | "isConstant": false, 256 | "isLValue": false, 257 | "isPure": true, 258 | "kind": "string", 259 | "lValueRequested": false, 260 | "nodeType": "Literal", 261 | "src": "238:53:0", 262 | "subdenomination": null, 263 | "typeDescriptions": { 264 | "typeIdentifier": "t_stringliteral_f60fe2d9d123295bf92ecf95167f1fa709e374da35e4c083bd39dc2d82acd8b1", 265 | "typeString": "literal_string \"This function is restricted to the contract's owner\"" 266 | }, 267 | "value": "This function is restricted to the contract's owner" 268 | } 269 | ], 270 | "expression": { 271 | "argumentTypes": [ 272 | { 273 | "typeIdentifier": "t_bool", 274 | "typeString": "bool" 275 | }, 276 | { 277 | "typeIdentifier": "t_stringliteral_f60fe2d9d123295bf92ecf95167f1fa709e374da35e4c083bd39dc2d82acd8b1", 278 | "typeString": "literal_string \"This function is restricted to the contract's owner\"" 279 | } 280 | ], 281 | "id": 9, 282 | "name": "require", 283 | "nodeType": "Identifier", 284 | "overloadedDeclarations": [ 285 | -18, 286 | -18 287 | ], 288 | "referencedDeclaration": -18, 289 | "src": "196:7:0", 290 | "typeDescriptions": { 291 | "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", 292 | "typeString": "function (bool,string memory) pure" 293 | } 294 | }, 295 | "id": 15, 296 | "isConstant": false, 297 | "isLValue": false, 298 | "isPure": false, 299 | "kind": "functionCall", 300 | "lValueRequested": false, 301 | "names": [], 302 | "nodeType": "FunctionCall", 303 | "src": "196:101:0", 304 | "tryCall": false, 305 | "typeDescriptions": { 306 | "typeIdentifier": "t_tuple$__$", 307 | "typeString": "tuple()" 308 | } 309 | }, 310 | "id": 16, 311 | "nodeType": "ExpressionStatement", 312 | "src": "196:101:0" 313 | }, 314 | { 315 | "id": 17, 316 | "nodeType": "PlaceholderStatement", 317 | "src": "303:1:0" 318 | } 319 | ] 320 | }, 321 | "documentation": null, 322 | "id": 19, 323 | "name": "restricted", 324 | "nodeType": "ModifierDefinition", 325 | "overrides": null, 326 | "parameters": { 327 | "id": 8, 328 | "nodeType": "ParameterList", 329 | "parameters": [], 330 | "src": "187:2:0" 331 | }, 332 | "src": "168:141:0", 333 | "virtual": false, 334 | "visibility": "internal" 335 | }, 336 | { 337 | "body": { 338 | "id": 30, 339 | "nodeType": "Block", 340 | "src": "369:47:0", 341 | "statements": [ 342 | { 343 | "expression": { 344 | "argumentTypes": null, 345 | "id": 28, 346 | "isConstant": false, 347 | "isLValue": false, 348 | "isPure": false, 349 | "lValueRequested": false, 350 | "leftHandSide": { 351 | "argumentTypes": null, 352 | "id": 26, 353 | "name": "last_completed_migration", 354 | "nodeType": "Identifier", 355 | "overloadedDeclarations": [], 356 | "referencedDeclaration": 7, 357 | "src": "375:24:0", 358 | "typeDescriptions": { 359 | "typeIdentifier": "t_uint256", 360 | "typeString": "uint256" 361 | } 362 | }, 363 | "nodeType": "Assignment", 364 | "operator": "=", 365 | "rightHandSide": { 366 | "argumentTypes": null, 367 | "id": 27, 368 | "name": "completed", 369 | "nodeType": "Identifier", 370 | "overloadedDeclarations": [], 371 | "referencedDeclaration": 21, 372 | "src": "402:9:0", 373 | "typeDescriptions": { 374 | "typeIdentifier": "t_uint256", 375 | "typeString": "uint256" 376 | } 377 | }, 378 | "src": "375:36:0", 379 | "typeDescriptions": { 380 | "typeIdentifier": "t_uint256", 381 | "typeString": "uint256" 382 | } 383 | }, 384 | "id": 29, 385 | "nodeType": "ExpressionStatement", 386 | "src": "375:36:0" 387 | } 388 | ] 389 | }, 390 | "documentation": null, 391 | "functionSelector": "fdacd576", 392 | "id": 31, 393 | "implemented": true, 394 | "kind": "function", 395 | "modifiers": [ 396 | { 397 | "arguments": null, 398 | "id": 24, 399 | "modifierName": { 400 | "argumentTypes": null, 401 | "id": 23, 402 | "name": "restricted", 403 | "nodeType": "Identifier", 404 | "overloadedDeclarations": [], 405 | "referencedDeclaration": 19, 406 | "src": "358:10:0", 407 | "typeDescriptions": { 408 | "typeIdentifier": "t_modifier$__$", 409 | "typeString": "modifier ()" 410 | } 411 | }, 412 | "nodeType": "ModifierInvocation", 413 | "src": "358:10:0" 414 | } 415 | ], 416 | "name": "setCompleted", 417 | "nodeType": "FunctionDefinition", 418 | "overrides": null, 419 | "parameters": { 420 | "id": 22, 421 | "nodeType": "ParameterList", 422 | "parameters": [ 423 | { 424 | "constant": false, 425 | "id": 21, 426 | "mutability": "mutable", 427 | "name": "completed", 428 | "nodeType": "VariableDeclaration", 429 | "overrides": null, 430 | "scope": 31, 431 | "src": "335:14:0", 432 | "stateVariable": false, 433 | "storageLocation": "default", 434 | "typeDescriptions": { 435 | "typeIdentifier": "t_uint256", 436 | "typeString": "uint256" 437 | }, 438 | "typeName": { 439 | "id": 20, 440 | "name": "uint", 441 | "nodeType": "ElementaryTypeName", 442 | "src": "335:4:0", 443 | "typeDescriptions": { 444 | "typeIdentifier": "t_uint256", 445 | "typeString": "uint256" 446 | } 447 | }, 448 | "value": null, 449 | "visibility": "internal" 450 | } 451 | ], 452 | "src": "334:16:0" 453 | }, 454 | "returnParameters": { 455 | "id": 25, 456 | "nodeType": "ParameterList", 457 | "parameters": [], 458 | "src": "369:0:0" 459 | }, 460 | "scope": 32, 461 | "src": "313:103:0", 462 | "stateMutability": "nonpayable", 463 | "virtual": false, 464 | "visibility": "public" 465 | } 466 | ], 467 | "scope": 33, 468 | "src": "66:352:0" 469 | } 470 | ], 471 | "src": "32:387:0" 472 | }, 473 | "legacyAST": { 474 | "absolutePath": "/Users/patricksteele/Desktop/eth/demo/contracts/Migrations.sol", 475 | "exportedSymbols": { 476 | "Migrations": [ 477 | 32 478 | ] 479 | }, 480 | "id": 33, 481 | "license": "MIT", 482 | "nodeType": "SourceUnit", 483 | "nodes": [ 484 | { 485 | "id": 1, 486 | "literals": [ 487 | "solidity", 488 | ">=", 489 | "0.4", 490 | ".22", 491 | "<", 492 | "0.8", 493 | ".0" 494 | ], 495 | "nodeType": "PragmaDirective", 496 | "src": "32:32:0" 497 | }, 498 | { 499 | "abstract": false, 500 | "baseContracts": [], 501 | "contractDependencies": [], 502 | "contractKind": "contract", 503 | "documentation": null, 504 | "fullyImplemented": true, 505 | "id": 32, 506 | "linearizedBaseContracts": [ 507 | 32 508 | ], 509 | "name": "Migrations", 510 | "nodeType": "ContractDefinition", 511 | "nodes": [ 512 | { 513 | "constant": false, 514 | "functionSelector": "8da5cb5b", 515 | "id": 5, 516 | "mutability": "mutable", 517 | "name": "owner", 518 | "nodeType": "VariableDeclaration", 519 | "overrides": null, 520 | "scope": 32, 521 | "src": "90:33:0", 522 | "stateVariable": true, 523 | "storageLocation": "default", 524 | "typeDescriptions": { 525 | "typeIdentifier": "t_address", 526 | "typeString": "address" 527 | }, 528 | "typeName": { 529 | "id": 2, 530 | "name": "address", 531 | "nodeType": "ElementaryTypeName", 532 | "src": "90:7:0", 533 | "stateMutability": "nonpayable", 534 | "typeDescriptions": { 535 | "typeIdentifier": "t_address", 536 | "typeString": "address" 537 | } 538 | }, 539 | "value": { 540 | "argumentTypes": null, 541 | "expression": { 542 | "argumentTypes": null, 543 | "id": 3, 544 | "name": "msg", 545 | "nodeType": "Identifier", 546 | "overloadedDeclarations": [], 547 | "referencedDeclaration": -15, 548 | "src": "113:3:0", 549 | "typeDescriptions": { 550 | "typeIdentifier": "t_magic_message", 551 | "typeString": "msg" 552 | } 553 | }, 554 | "id": 4, 555 | "isConstant": false, 556 | "isLValue": false, 557 | "isPure": false, 558 | "lValueRequested": false, 559 | "memberName": "sender", 560 | "nodeType": "MemberAccess", 561 | "referencedDeclaration": null, 562 | "src": "113:10:0", 563 | "typeDescriptions": { 564 | "typeIdentifier": "t_address_payable", 565 | "typeString": "address payable" 566 | } 567 | }, 568 | "visibility": "public" 569 | }, 570 | { 571 | "constant": false, 572 | "functionSelector": "445df0ac", 573 | "id": 7, 574 | "mutability": "mutable", 575 | "name": "last_completed_migration", 576 | "nodeType": "VariableDeclaration", 577 | "overrides": null, 578 | "scope": 32, 579 | "src": "127:36:0", 580 | "stateVariable": true, 581 | "storageLocation": "default", 582 | "typeDescriptions": { 583 | "typeIdentifier": "t_uint256", 584 | "typeString": "uint256" 585 | }, 586 | "typeName": { 587 | "id": 6, 588 | "name": "uint", 589 | "nodeType": "ElementaryTypeName", 590 | "src": "127:4:0", 591 | "typeDescriptions": { 592 | "typeIdentifier": "t_uint256", 593 | "typeString": "uint256" 594 | } 595 | }, 596 | "value": null, 597 | "visibility": "public" 598 | }, 599 | { 600 | "body": { 601 | "id": 18, 602 | "nodeType": "Block", 603 | "src": "190:119:0", 604 | "statements": [ 605 | { 606 | "expression": { 607 | "argumentTypes": null, 608 | "arguments": [ 609 | { 610 | "argumentTypes": null, 611 | "commonType": { 612 | "typeIdentifier": "t_address", 613 | "typeString": "address" 614 | }, 615 | "id": 13, 616 | "isConstant": false, 617 | "isLValue": false, 618 | "isPure": false, 619 | "lValueRequested": false, 620 | "leftExpression": { 621 | "argumentTypes": null, 622 | "expression": { 623 | "argumentTypes": null, 624 | "id": 10, 625 | "name": "msg", 626 | "nodeType": "Identifier", 627 | "overloadedDeclarations": [], 628 | "referencedDeclaration": -15, 629 | "src": "211:3:0", 630 | "typeDescriptions": { 631 | "typeIdentifier": "t_magic_message", 632 | "typeString": "msg" 633 | } 634 | }, 635 | "id": 11, 636 | "isConstant": false, 637 | "isLValue": false, 638 | "isPure": false, 639 | "lValueRequested": false, 640 | "memberName": "sender", 641 | "nodeType": "MemberAccess", 642 | "referencedDeclaration": null, 643 | "src": "211:10:0", 644 | "typeDescriptions": { 645 | "typeIdentifier": "t_address_payable", 646 | "typeString": "address payable" 647 | } 648 | }, 649 | "nodeType": "BinaryOperation", 650 | "operator": "==", 651 | "rightExpression": { 652 | "argumentTypes": null, 653 | "id": 12, 654 | "name": "owner", 655 | "nodeType": "Identifier", 656 | "overloadedDeclarations": [], 657 | "referencedDeclaration": 5, 658 | "src": "225:5:0", 659 | "typeDescriptions": { 660 | "typeIdentifier": "t_address", 661 | "typeString": "address" 662 | } 663 | }, 664 | "src": "211:19:0", 665 | "typeDescriptions": { 666 | "typeIdentifier": "t_bool", 667 | "typeString": "bool" 668 | } 669 | }, 670 | { 671 | "argumentTypes": null, 672 | "hexValue": "546869732066756e6374696f6e206973207265737472696374656420746f2074686520636f6e74726163742773206f776e6572", 673 | "id": 14, 674 | "isConstant": false, 675 | "isLValue": false, 676 | "isPure": true, 677 | "kind": "string", 678 | "lValueRequested": false, 679 | "nodeType": "Literal", 680 | "src": "238:53:0", 681 | "subdenomination": null, 682 | "typeDescriptions": { 683 | "typeIdentifier": "t_stringliteral_f60fe2d9d123295bf92ecf95167f1fa709e374da35e4c083bd39dc2d82acd8b1", 684 | "typeString": "literal_string \"This function is restricted to the contract's owner\"" 685 | }, 686 | "value": "This function is restricted to the contract's owner" 687 | } 688 | ], 689 | "expression": { 690 | "argumentTypes": [ 691 | { 692 | "typeIdentifier": "t_bool", 693 | "typeString": "bool" 694 | }, 695 | { 696 | "typeIdentifier": "t_stringliteral_f60fe2d9d123295bf92ecf95167f1fa709e374da35e4c083bd39dc2d82acd8b1", 697 | "typeString": "literal_string \"This function is restricted to the contract's owner\"" 698 | } 699 | ], 700 | "id": 9, 701 | "name": "require", 702 | "nodeType": "Identifier", 703 | "overloadedDeclarations": [ 704 | -18, 705 | -18 706 | ], 707 | "referencedDeclaration": -18, 708 | "src": "196:7:0", 709 | "typeDescriptions": { 710 | "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", 711 | "typeString": "function (bool,string memory) pure" 712 | } 713 | }, 714 | "id": 15, 715 | "isConstant": false, 716 | "isLValue": false, 717 | "isPure": false, 718 | "kind": "functionCall", 719 | "lValueRequested": false, 720 | "names": [], 721 | "nodeType": "FunctionCall", 722 | "src": "196:101:0", 723 | "tryCall": false, 724 | "typeDescriptions": { 725 | "typeIdentifier": "t_tuple$__$", 726 | "typeString": "tuple()" 727 | } 728 | }, 729 | "id": 16, 730 | "nodeType": "ExpressionStatement", 731 | "src": "196:101:0" 732 | }, 733 | { 734 | "id": 17, 735 | "nodeType": "PlaceholderStatement", 736 | "src": "303:1:0" 737 | } 738 | ] 739 | }, 740 | "documentation": null, 741 | "id": 19, 742 | "name": "restricted", 743 | "nodeType": "ModifierDefinition", 744 | "overrides": null, 745 | "parameters": { 746 | "id": 8, 747 | "nodeType": "ParameterList", 748 | "parameters": [], 749 | "src": "187:2:0" 750 | }, 751 | "src": "168:141:0", 752 | "virtual": false, 753 | "visibility": "internal" 754 | }, 755 | { 756 | "body": { 757 | "id": 30, 758 | "nodeType": "Block", 759 | "src": "369:47:0", 760 | "statements": [ 761 | { 762 | "expression": { 763 | "argumentTypes": null, 764 | "id": 28, 765 | "isConstant": false, 766 | "isLValue": false, 767 | "isPure": false, 768 | "lValueRequested": false, 769 | "leftHandSide": { 770 | "argumentTypes": null, 771 | "id": 26, 772 | "name": "last_completed_migration", 773 | "nodeType": "Identifier", 774 | "overloadedDeclarations": [], 775 | "referencedDeclaration": 7, 776 | "src": "375:24:0", 777 | "typeDescriptions": { 778 | "typeIdentifier": "t_uint256", 779 | "typeString": "uint256" 780 | } 781 | }, 782 | "nodeType": "Assignment", 783 | "operator": "=", 784 | "rightHandSide": { 785 | "argumentTypes": null, 786 | "id": 27, 787 | "name": "completed", 788 | "nodeType": "Identifier", 789 | "overloadedDeclarations": [], 790 | "referencedDeclaration": 21, 791 | "src": "402:9:0", 792 | "typeDescriptions": { 793 | "typeIdentifier": "t_uint256", 794 | "typeString": "uint256" 795 | } 796 | }, 797 | "src": "375:36:0", 798 | "typeDescriptions": { 799 | "typeIdentifier": "t_uint256", 800 | "typeString": "uint256" 801 | } 802 | }, 803 | "id": 29, 804 | "nodeType": "ExpressionStatement", 805 | "src": "375:36:0" 806 | } 807 | ] 808 | }, 809 | "documentation": null, 810 | "functionSelector": "fdacd576", 811 | "id": 31, 812 | "implemented": true, 813 | "kind": "function", 814 | "modifiers": [ 815 | { 816 | "arguments": null, 817 | "id": 24, 818 | "modifierName": { 819 | "argumentTypes": null, 820 | "id": 23, 821 | "name": "restricted", 822 | "nodeType": "Identifier", 823 | "overloadedDeclarations": [], 824 | "referencedDeclaration": 19, 825 | "src": "358:10:0", 826 | "typeDescriptions": { 827 | "typeIdentifier": "t_modifier$__$", 828 | "typeString": "modifier ()" 829 | } 830 | }, 831 | "nodeType": "ModifierInvocation", 832 | "src": "358:10:0" 833 | } 834 | ], 835 | "name": "setCompleted", 836 | "nodeType": "FunctionDefinition", 837 | "overrides": null, 838 | "parameters": { 839 | "id": 22, 840 | "nodeType": "ParameterList", 841 | "parameters": [ 842 | { 843 | "constant": false, 844 | "id": 21, 845 | "mutability": "mutable", 846 | "name": "completed", 847 | "nodeType": "VariableDeclaration", 848 | "overrides": null, 849 | "scope": 31, 850 | "src": "335:14:0", 851 | "stateVariable": false, 852 | "storageLocation": "default", 853 | "typeDescriptions": { 854 | "typeIdentifier": "t_uint256", 855 | "typeString": "uint256" 856 | }, 857 | "typeName": { 858 | "id": 20, 859 | "name": "uint", 860 | "nodeType": "ElementaryTypeName", 861 | "src": "335:4:0", 862 | "typeDescriptions": { 863 | "typeIdentifier": "t_uint256", 864 | "typeString": "uint256" 865 | } 866 | }, 867 | "value": null, 868 | "visibility": "internal" 869 | } 870 | ], 871 | "src": "334:16:0" 872 | }, 873 | "returnParameters": { 874 | "id": 25, 875 | "nodeType": "ParameterList", 876 | "parameters": [], 877 | "src": "369:0:0" 878 | }, 879 | "scope": 32, 880 | "src": "313:103:0", 881 | "stateMutability": "nonpayable", 882 | "virtual": false, 883 | "visibility": "public" 884 | } 885 | ], 886 | "scope": 33, 887 | "src": "66:352:0" 888 | } 889 | ], 890 | "src": "32:387:0" 891 | }, 892 | "compiler": { 893 | "name": "solc", 894 | "version": "0.6.12+commit.27d51765.Emscripten.clang" 895 | }, 896 | "networks": { 897 | "3": { 898 | "events": {}, 899 | "links": {}, 900 | "address": "0x7683b7CBA71350FA000Edc2e8ea156926970f95d", 901 | "transactionHash": "0xb7603d3035ffe9666799f014a3826bbff3112a1ca5f4aaaae1325ba537692183" 902 | } 903 | }, 904 | "schemaVersion": "3.2.5", 905 | "updatedAt": "2021-01-22T08:36:01.597Z", 906 | "networkType": "ethereum", 907 | "devdoc": { 908 | "kind": "dev", 909 | "methods": {}, 910 | "version": 1 911 | }, 912 | "userdoc": { 913 | "kind": "user", 914 | "methods": {}, 915 | "version": 1 916 | } 917 | } -------------------------------------------------------------------------------- /pairDL.js: -------------------------------------------------------------------------------- 1 | //Precomputes possible trading routes of interest for dual listed pair arbitrage 2 | //Queries Uniswap and SushiSwap for all pairs 3 | //Then constructs a list of dual listed pairs and returns a intersection of both lists 4 | 5 | var InputDataDecoder = require( "ethereum-input-data-decoder"); 6 | var Web3 = require( "web3"); 7 | var pkg = require( '@uniswap/sdk'); 8 | var ethers = require( 'ethers'); 9 | var ganacheCLI = require( 'ganache-cli'); 10 | var fs = require('fs'); 11 | const getRevertReason = require('eth-revert-reason') 12 | var Tx = require('ethereumjs-tx').Transaction 13 | var ethersSol = require( '@ethersproject/solidity') 14 | var ethersAdd = require ('@ethersproject/address') 15 | var uSDK = require ( '@uniswap/sdk'); 16 | 17 | const { INIT_CODE_HASH } = uSDK; 18 | const { pack, keccak256 } = ethersSol; 19 | const { getCreate2Address } = ethersAdd; 20 | 21 | const { ChainId, JSBI, BigintIsh, Fetcher, WETH, Route, Token, Pair, Price, Trade, Fractions, TokenAmount, TradeType, Percent } = pkg; 22 | const chainId = ChainId.MAINNET; 23 | const ethValUSD = 550 24 | 25 | let wsProvider = new ethers.providers.WebSocketProvider("ws://54.251.236.136:8546",chainId); //Needed for uniswapV2 JS SDK, not compatible with Web3 26 | var productionServer = "ws://54.251.236.136:8546"; //Amazon private GETH MainNet Node 27 | var web3 = new Web3(productionServer); // same output as with option below 28 | var BN = web3.utils.BN 29 | let sushiMasterDB = require('./sushiPairs.json'); //assumes the program has already run 30 | let uniMasterDB = require('./uniPairs.json'); //assumes the program has already run 31 | 32 | //let ABPairsWithWETH = require('./pairWETH.json'); 33 | var ABPairsWithIntersection = [] 34 | 35 | 36 | const UniSwapV2PairABI =[{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount0Out","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1Out","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint112","name":"reserve0","type":"uint112"},{"indexed":false,"internalType":"uint112","name":"reserve1","type":"uint112"}],"name":"Sync","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"constant":true,"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MINIMUM_LIQUIDITY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"burn","outputs":[{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getReserves","outputs":[{"internalType":"uint112","name":"_reserve0","type":"uint112"},{"internalType":"uint112","name":"_reserve1","type":"uint112"},{"internalType":"uint32","name":"_blockTimestampLast","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_token0","type":"address"},{"internalType":"address","name":"_token1","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"kLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"liquidity","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"price0CumulativeLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"price1CumulativeLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"skim","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount0Out","type":"uint256"},{"internalType":"uint256","name":"amount1Out","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"swap","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"sync","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"token0","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"token1","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}] 37 | const decoder = new InputDataDecoder([{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"amountADesired","type":"uint256"},{"internalType":"uint256","name":"amountBDesired","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountTokenDesired","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsIn","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsOut","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"reserveA","type":"uint256"},{"internalType":"uint256","name":"reserveB","type":"uint256"}],"name":"quote","outputs":[{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETHSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermit","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityWithPermit","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapETHForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETHSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]); 38 | const ERC20TransferABI = [{ "constant": true, "inputs": [], "name": "name", "outputs": [ { "name": "", "type": "string" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": false, "inputs": [ { "name": "_spender", "type": "address" }, { "name": "_value", "type": "uint256" } ], "name": "approve", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": true, "inputs": [], "name": "totalSupply", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": false, "inputs": [ { "name": "_from", "type": "address" }, { "name": "_to", "type": "address" }, { "name": "_value", "type": "uint256" } ], "name": "transferFrom", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": true, "inputs": [], "name": "decimals", "outputs": [ { "name": "", "type": "uint8" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [ { "name": "_owner", "type": "address" } ], "name": "balanceOf", "outputs": [ { "name": "balance", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "symbol", "outputs": [ { "name": "", "type": "string" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": false, "inputs": [ { "name": "_to", "type": "address" }, { "name": "_value", "type": "uint256" } ], "name": "transfer", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": true, "inputs": [ { "name": "_owner", "type": "address" }, { "name": "_spender", "type": "address" } ], "name": "allowance", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "payable": true, "stateMutability": "payable", "type": "fallback" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "owner", "type": "address" }, { "indexed": true, "name": "spender", "type": "address" }, { "indexed": false, "name": "value", "type": "uint256" } ], "name": "Approval", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "from", "type": "address" }, { "indexed": true, "name": "to", "type": "address" }, { "indexed": false, "name": "value", "type": "uint256" } ], "name": "Transfer", "type": "event" } ] 39 | const UniSwapV2RouterABI = [{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"amountADesired","type":"uint256"},{"internalType":"uint256","name":"amountBDesired","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountTokenDesired","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsIn","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsOut","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"reserveA","type":"uint256"},{"internalType":"uint256","name":"reserveB","type":"uint256"}],"name":"quote","outputs":[{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETHSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermit","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityWithPermit","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapETHForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETHSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]; 40 | const UniSWapFactoryABI = [{"inputs":[{"internalType":"address","name":"_feeToSetter","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token0","type":"address"},{"indexed":true,"internalType":"address","name":"token1","type":"address"},{"indexed":false,"internalType":"address","name":"pair","type":"address"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"}],"name":"PairCreated","type":"event"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allPairs","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"allPairsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"name":"createPair","outputs":[{"internalType":"address","name":"pair","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"feeTo","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"feeToSetter","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"getPair","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_feeTo","type":"address"}],"name":"setFeeTo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_feeToSetter","type":"address"}],"name":"setFeeToSetter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}] 41 | const UNISWAP_ROUTERV2_ADDRESS = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D" 42 | const UNISWAP_FACTORY_ADDRESS = "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f" 43 | const WETH_ERC20_ADDRESS = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" 44 | const SUSHISWAP_FACTORY_ADDRESS = "0xc0aee478e3658e2610c5f7a4a2e1777ce9e4f2ac" 45 | 46 | const SushiSWapFactoryABI = [{"inputs":[{"internalType":"address","name":"_feeToSetter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token0","type":"address"},{"indexed":true,"internalType":"address","name":"token1","type":"address"},{"indexed":false,"internalType":"address","name":"pair","type":"address"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"}],"name":"PairCreated","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allPairs","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allPairsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"name":"createPair","outputs":[{"internalType":"address","name":"pair","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeToSetter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"getPair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"migrator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pairCodeHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_feeTo","type":"address"}],"name":"setFeeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeToSetter","type":"address"}],"name":"setFeeToSetter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_migrator","type":"address"}],"name":"setMigrator","outputs":[],"stateMutability":"nonpayable","type":"function"}] 47 | 48 | var pairMaster = [] 49 | let intersectionDB = require('./intersectionAll.json') 50 | 51 | 52 | var uniAddress = "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984" 53 | 54 | const uniswapFactoryContract = new web3.eth.Contract(UniSWapFactoryABI, UNISWAP_FACTORY_ADDRESS) 55 | const sushiswapFactoryContract = new web3.eth.Contract(SushiSWapFactoryABI, SUSHISWAP_FACTORY_ADDRESS) 56 | 57 | 58 | //console.log(pairExists(uniAddress, WETH_ERC20_ADDRESS)) 59 | 60 | function pairExists(_token0, _token1){ 61 | var r = uniMasterDB.some(i => i.pairAddress.includes(getPairAddress(_token0, _token1))); 62 | return r 63 | } 64 | 65 | function getPairAddress(_token0, _token1){ 66 | return getCreate2Address(UNISWAP_FACTORY_ADDRESS, keccak256(['bytes'], [pack(['address', 'address'], [_token0, _token1])]),INIT_CODE_HASH) 67 | } 68 | 69 | 70 | function generateSushiUniPairs(){ //includes combo's of other stable pairs USDC's etc, no liquidity filtering, no weth only filtering 71 | for(let i = 0; i< sushiMasterDB.length; i++){ 72 | if(pairExists(sushiMasterDB[i].pairToken0, sushiMasterDB[i].pairToken1)){ 73 | 74 | var index = uniMasterDB.map(e => e.pairAddress).indexOf(getPairAddress(sushiMasterDB[i].pairToken0, sushiMasterDB[i].pairToken1)) 75 | 76 | ABPairsWithIntersection.push({"sushi":sushiMasterDB[i], "uni":uniMasterDB[index], "order":"true"}) 77 | console.log(i, ABPairsWithIntersection.length, "A") 78 | 79 | } 80 | if(pairExists(sushiMasterDB[i].pairToken1, sushiMasterDB[i].pairToken0)){ 81 | 82 | var index = uniMasterDB.map(e => e.pairAddress).indexOf(getPairAddress(sushiMasterDB[i].pairToken1, sushiMasterDB[i].pairToken0)) 83 | 84 | ABPairsWithIntersection.push({"sushi":sushiMasterDB[i], "uni":uniMasterDB[index], "order":"false"}) 85 | console.log(i, ABPairsWithIntersection.length, "B") 86 | 87 | } 88 | //} 89 | } 90 | writeInterSectionPairList(ABPairsWithIntersection) 91 | 92 | } 93 | 94 | 95 | var debugPrint = false 96 | 97 | //generateSushiUniPairs() 98 | generateWETHPairs() 99 | 100 | function generateWETHPairs(){ //includes combo's of other stable pairs USDC's etc, no liquidity filtering 101 | for(let i = 0; i< intersectionDB.length; i++){ 102 | if((intersectionDB[i].sushi.pairToken0 == WETH_ERC20_ADDRESS || intersectionDB[i].sushi.pairToken1 == WETH_ERC20_ADDRESS)){ //check if one of the tokens is WETH, if yes abort 103 | ABPairsWithIntersection.push(intersectionDB[i]) 104 | console.log("Ligma", i, ABPairsWithIntersection.length) 105 | } 106 | } 107 | console.log(ABPairsWithIntersection) 108 | writeInterSectionPairListWETHD(ABPairsWithIntersection) 109 | 110 | } 111 | 112 | 113 | async function queryPairsList(){ 114 | 115 | //factoryContract = uniswapFactoryContract // need to 116 | factoryContract = sushiswapFactoryContract 117 | 118 | var pairLength = await factoryContract.methods.allPairsLength().call() 119 | console.log(pairLength) 120 | for(let i = 1; i< pairLength; i++){ 121 | factoryContract.methods.allPairs(i).call().then((pairAddress) =>{ 122 | var pairContract = new web3.eth.Contract(UniSwapV2PairABI, pairAddress) 123 | pairContract.methods.token0().call().then((pairToken0) => { 124 | pairContract.methods.token1().call().then((pairToken1) => { 125 | new web3.eth.Contract(ERC20TransferABI, pairToken0).methods.symbol().call().then((symbol0) => { 126 | new web3.eth.Contract(ERC20TransferABI, pairToken1).methods.symbol().call().then((symbol1) => { 127 | new web3.eth.Contract(ERC20TransferABI, pairToken0).methods.decimals().call().then((decimal0) => { 128 | new web3.eth.Contract(ERC20TransferABI, pairToken1).methods.decimals().call().then((decimal1) => { 129 | var toWrite = {"pairAddress":pairAddress, "pairToken0":pairToken0, "pairToken1":pairToken1, "decimals0":decimal0, "decimals1":decimal1,"symbol0":symbol0, "symbol1":symbol1} 130 | pairMaster.push(toWrite) 131 | console.log(i) 132 | //{"pairAddress":pairAddress, "pairToken0":pairToken0, "pairToken1":pairToken1, "decimals0":decimal0, "decimals1":decimal1,"symbol0":symbol0, "symbol1":symbol1}) 133 | 134 | // console.log("Index: "+i,{"pairAddress":pairAddress, "pairToken0":pairToken0, "pairToken1":pairToken1, "decimals0":decimal0, "decimals1":decimal1,"symbol0":symbol0, "symbol1":symbol1}) 135 | }) 136 | }) 137 | }) 138 | }) 139 | }) 140 | }) 141 | }) 142 | } 143 | } 144 | 145 | 146 | 147 | setTimeout(function(){ 148 | writePairList(pairMaster) 149 | console.log(pairMaster) 150 | console.log("Finished") 151 | }, 90000); 152 | 153 | function writePairList(_pairMaster){ 154 | fs.writeFile('./rupal2.json',JSON.stringify(_pairMaster),function(err){ 155 | if(err) throw err; 156 | }) 157 | } 158 | function writeInterSectionPairList(_pairIntMaster){ 159 | fs.writeFile('./intersectionAll.json',JSON.stringify(_pairIntMaster),function(err){ 160 | if(err) throw err; 161 | }) 162 | } 163 | 164 | function writeInterSectionPairListWETHD(_pairIntMaster){ 165 | fs.writeFile('./intersectionWETH.json',JSON.stringify(_pairIntMaster),function(err){ 166 | if(err) throw err; 167 | }) 168 | } 169 | 170 | setInterval(function(){ 171 | 172 | }, 20000); 173 | --------------------------------------------------------------------------------