├── deployments ├── boba │ └── .chainId ├── bsc │ └── .chainId ├── bttc │ └── .chainId ├── fuse │ ├── .chainId │ └── solcInputs │ │ └── f0d855948f39faa7f1111cd889006c3c.json ├── goerli │ └── .chainId ├── heco │ └── .chainId ├── kovan │ └── .chainId ├── okex │ └── .chainId ├── telos │ └── .chainId ├── xdai │ └── .chainId ├── base │ └── .chainId ├── blast │ └── .chainId ├── celo │ ├── .chainId │ └── UniswapV2Router02.json ├── core │ └── .chainId ├── ethereum │ ├── .chainId │ └── UniswapV2Factory.json ├── fantom │ └── .chainId ├── filecoin │ └── .chainId ├── fuji │ └── .chainId ├── haqq │ └── .chainId ├── hemi │ └── .chainId ├── kava │ └── .chainId ├── linea │ └── .chainId ├── matic │ └── .chainId ├── metis │ └── .chainId ├── moonbeam │ ├── .chainId │ └── solcInputs │ │ └── af42c9b78f9459eb1f47e4c296c8d1f4.json ├── mumbai │ └── .chainId ├── optimism │ └── .chainId ├── rinkeby │ └── .chainId ├── rootstock │ └── .chainId ├── ropsten │ └── .chainId ├── scroll │ └── .chainId ├── sonic │ └── .chainId ├── arbitrum │ ├── .chainId │ └── solcInputs │ │ ├── af42c9b78f9459eb1f47e4c296c8d1f4.json │ │ └── ea2b048f03db764f4dadc9d3f9ffaac6.json ├── avalanche │ └── .chainId ├── boba-avax │ └── .chainId ├── boba-bnb │ └── .chainId ├── bsc-testnet │ └── .chainId ├── harmony │ └── .chainId ├── heco-testnet │ └── .chainId ├── localhost │ ├── .chainId │ ├── solcInputs │ │ └── 07facc9fad1266fbe84e2dac07a80c89.json │ └── WETH9.json ├── moonriver │ └── .chainId ├── okex-testnet │ └── .chainId ├── palm │ ├── .chainId │ └── solcInputs │ │ └── af42c9b78f9459eb1f47e4c296c8d1f4.json ├── polygonzkevm │ └── .chainId ├── sepolia │ └── .chainId ├── thundercore │ └── .chainId ├── zetachain │ └── .chainId ├── arbitrum-nova │ └── .chainId ├── skale-europa │ └── .chainId └── harmony-testnet │ └── .chainId ├── .eslintignore ├── .eslintrc.cjs ├── FUNDING.json ├── README.md ├── CHANGELOG.md ├── contracts ├── mocks │ ├── SushiSwapPair.sol │ ├── SushiSwapFactory.sol │ └── WETH9.sol ├── interfaces │ ├── IUniswapV2Callee.sol │ ├── IWETH.sol │ ├── IUniswapV2Factory.sol │ ├── IERC20.sol │ ├── IUniswapV2ERC20.sol │ ├── IUniswapV2Router02.sol │ ├── IUniswapV2Pair.sol │ └── IUniswapV2Router01.sol ├── README.md ├── libraries │ ├── SafeMath.sol │ ├── UQ112x112.sol │ ├── Math.sol │ ├── TransferHelper.sol │ └── UniswapV2Library.sol ├── UniswapV2Factory.sol ├── UniswapV2ERC20.sol ├── SushiRoll.sol ├── UniswapV2Pair.sol ├── UniswapV2Router02.sol └── UniswapV2Router02Celo.sol ├── .env.example ├── tsconfig.json ├── .gitignore ├── deploy ├── WETH9.ts ├── UniswapV2Factory.ts ├── UniswapV2Router02.ts └── SushiRoll.ts ├── package.json └── hardhat.config.ts /deployments/boba/.chainId: -------------------------------------------------------------------------------- 1 | 288 -------------------------------------------------------------------------------- /deployments/bsc/.chainId: -------------------------------------------------------------------------------- 1 | 56 -------------------------------------------------------------------------------- /deployments/bttc/.chainId: -------------------------------------------------------------------------------- 1 | 199 -------------------------------------------------------------------------------- /deployments/fuse/.chainId: -------------------------------------------------------------------------------- 1 | 122 -------------------------------------------------------------------------------- /deployments/goerli/.chainId: -------------------------------------------------------------------------------- 1 | 5 -------------------------------------------------------------------------------- /deployments/heco/.chainId: -------------------------------------------------------------------------------- 1 | 128 -------------------------------------------------------------------------------- /deployments/kovan/.chainId: -------------------------------------------------------------------------------- 1 | 42 -------------------------------------------------------------------------------- /deployments/okex/.chainId: -------------------------------------------------------------------------------- 1 | 66 -------------------------------------------------------------------------------- /deployments/telos/.chainId: -------------------------------------------------------------------------------- 1 | 40 -------------------------------------------------------------------------------- /deployments/xdai/.chainId: -------------------------------------------------------------------------------- 1 | 100 -------------------------------------------------------------------------------- /deployments/base/.chainId: -------------------------------------------------------------------------------- 1 | 8453 -------------------------------------------------------------------------------- /deployments/blast/.chainId: -------------------------------------------------------------------------------- 1 | 81457 -------------------------------------------------------------------------------- /deployments/celo/.chainId: -------------------------------------------------------------------------------- 1 | 42220 -------------------------------------------------------------------------------- /deployments/core/.chainId: -------------------------------------------------------------------------------- 1 | 1116 -------------------------------------------------------------------------------- /deployments/ethereum/.chainId: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /deployments/fantom/.chainId: -------------------------------------------------------------------------------- 1 | 250 -------------------------------------------------------------------------------- /deployments/filecoin/.chainId: -------------------------------------------------------------------------------- 1 | 314 -------------------------------------------------------------------------------- /deployments/fuji/.chainId: -------------------------------------------------------------------------------- 1 | 43113 -------------------------------------------------------------------------------- /deployments/haqq/.chainId: -------------------------------------------------------------------------------- 1 | 11235 -------------------------------------------------------------------------------- /deployments/hemi/.chainId: -------------------------------------------------------------------------------- 1 | 43111 -------------------------------------------------------------------------------- /deployments/kava/.chainId: -------------------------------------------------------------------------------- 1 | 2222 -------------------------------------------------------------------------------- /deployments/linea/.chainId: -------------------------------------------------------------------------------- 1 | 59144 -------------------------------------------------------------------------------- /deployments/matic/.chainId: -------------------------------------------------------------------------------- 1 | 137 -------------------------------------------------------------------------------- /deployments/metis/.chainId: -------------------------------------------------------------------------------- 1 | 1088 -------------------------------------------------------------------------------- /deployments/moonbeam/.chainId: -------------------------------------------------------------------------------- 1 | 1284 -------------------------------------------------------------------------------- /deployments/mumbai/.chainId: -------------------------------------------------------------------------------- 1 | 80001 -------------------------------------------------------------------------------- /deployments/optimism/.chainId: -------------------------------------------------------------------------------- 1 | 10 -------------------------------------------------------------------------------- /deployments/rinkeby/.chainId: -------------------------------------------------------------------------------- 1 | 4 -------------------------------------------------------------------------------- /deployments/rootstock/.chainId: -------------------------------------------------------------------------------- 1 | 30 -------------------------------------------------------------------------------- /deployments/ropsten/.chainId: -------------------------------------------------------------------------------- 1 | 3 -------------------------------------------------------------------------------- /deployments/scroll/.chainId: -------------------------------------------------------------------------------- 1 | 534352 -------------------------------------------------------------------------------- /deployments/sonic/.chainId: -------------------------------------------------------------------------------- 1 | 146 -------------------------------------------------------------------------------- /deployments/arbitrum/.chainId: -------------------------------------------------------------------------------- 1 | 42161 -------------------------------------------------------------------------------- /deployments/avalanche/.chainId: -------------------------------------------------------------------------------- 1 | 43114 -------------------------------------------------------------------------------- /deployments/boba-avax/.chainId: -------------------------------------------------------------------------------- 1 | 43288 -------------------------------------------------------------------------------- /deployments/boba-bnb/.chainId: -------------------------------------------------------------------------------- 1 | 56288 -------------------------------------------------------------------------------- /deployments/bsc-testnet/.chainId: -------------------------------------------------------------------------------- 1 | 97 -------------------------------------------------------------------------------- /deployments/harmony/.chainId: -------------------------------------------------------------------------------- 1 | 1666600000 -------------------------------------------------------------------------------- /deployments/heco-testnet/.chainId: -------------------------------------------------------------------------------- 1 | 256 -------------------------------------------------------------------------------- /deployments/localhost/.chainId: -------------------------------------------------------------------------------- 1 | 31337 -------------------------------------------------------------------------------- /deployments/moonriver/.chainId: -------------------------------------------------------------------------------- 1 | 1285 -------------------------------------------------------------------------------- /deployments/okex-testnet/.chainId: -------------------------------------------------------------------------------- 1 | 65 -------------------------------------------------------------------------------- /deployments/palm/.chainId: -------------------------------------------------------------------------------- 1 | 11297108109 -------------------------------------------------------------------------------- /deployments/polygonzkevm/.chainId: -------------------------------------------------------------------------------- 1 | 1101 -------------------------------------------------------------------------------- /deployments/sepolia/.chainId: -------------------------------------------------------------------------------- 1 | 11155111 -------------------------------------------------------------------------------- /deployments/thundercore/.chainId: -------------------------------------------------------------------------------- 1 | 108 -------------------------------------------------------------------------------- /deployments/zetachain/.chainId: -------------------------------------------------------------------------------- 1 | 7000 -------------------------------------------------------------------------------- /deployments/arbitrum-nova/.chainId: -------------------------------------------------------------------------------- 1 | 42170 -------------------------------------------------------------------------------- /deployments/skale-europa/.chainId: -------------------------------------------------------------------------------- 1 | 2046399126 -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | soljson-v0.6.12+commit.27d51765.js -------------------------------------------------------------------------------- /deployments/harmony-testnet/.chainId: -------------------------------------------------------------------------------- 1 | 1666700000 -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | const { default: config } = require('@sushiswap/eslint-config/hardhat') 2 | 3 | module.exports = config 4 | -------------------------------------------------------------------------------- /FUNDING.json: -------------------------------------------------------------------------------- 1 | { 2 | "opRetro": { 3 | "projectId": "0x41b2ae8a2ead458ff7c85549a9a11380353e1ae4b234666312d495326636f77a" 4 | } 5 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SushiSwap V2 2 | 3 | This repository contains the core smart contracts for the SushiSwap V2 Protocol. 4 | 5 | ## Deploy 6 | 7 | pnpm exec hardhat --network base deploy --tags AMM 8 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @sushiswap/sushiswap 2 | 3 | ## 0.1.1 4 | 5 | ### Patch Changes 6 | 7 | - 074ec9ebc: initial publish chunk 8 | 9 | ## 0.1.0 10 | 11 | ### Minor Changes 12 | 13 | - 82c96649: initial release 14 | -------------------------------------------------------------------------------- /contracts/mocks/SushiSwapPair.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity >=0.6.12; 4 | 5 | import "../UniswapV2Pair.sol"; 6 | 7 | contract SushiSwapPair is UniswapV2Pair { 8 | constructor() public UniswapV2Pair() {} 9 | } -------------------------------------------------------------------------------- /contracts/interfaces/IUniswapV2Callee.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity >=0.5.0; 4 | 5 | interface IUniswapV2Callee { 6 | function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data) external; 7 | } 8 | -------------------------------------------------------------------------------- /contracts/mocks/SushiSwapFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity >=0.6.12; 4 | 5 | import "../UniswapV2Factory.sol"; 6 | 7 | contract SushiSwapFactory is UniswapV2Factory { 8 | constructor() public UniswapV2Factory(msg.sender) {} 9 | } -------------------------------------------------------------------------------- /contracts/interfaces/IWETH.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity >=0.5.0; 4 | 5 | interface IWETH { 6 | function deposit() external payable; 7 | function transfer(address to, uint value) external returns (bool); 8 | function withdraw(uint) external; 9 | } -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | TENDERLY_USERNAME= 2 | TENDERLY_PROJECT=sushiswap 3 | 4 | ETHERSCAN_API_KEY= 5 | BSCSCAN_API_KEY= 6 | HECOINFO_API_KEY= 7 | FTMSCAN_API_KEY= 8 | OPTIMISTIC_ETHERSCAN_API_KEY= 9 | POLYGONSCAN_API_KEY= 10 | ARBISCAN_API_KEY= 11 | SNOWTRACE_API_KEY= 12 | MOONBEAM_MOONSCAN_API_KEY= 13 | MOONRIVER_MOONSCAN_API_KEY= 14 | MOONBASE_MOONSCAN_API_KEY= 15 | HARMONY_API_KEY= 16 | 17 | HTTP_PROXY= 18 | HTTPS_PROXY= -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2018", 4 | "module": "commonjs", 5 | "strict": true, 6 | "esModuleInterop": true, 7 | "resolveJsonModule": true, 8 | "outDir": "dist", 9 | "typeRoots": [ 10 | "./typechain", 11 | "./node_modules/@types" 12 | ], 13 | "types": [ 14 | "@nomiclabs/hardhat-ethers", 15 | "@nomiclabs/hardhat-waffle" 16 | ] 17 | }, 18 | "include": [ 19 | "./test" 20 | ], 21 | "files": [ 22 | "./hardhat.config.ts" 23 | ] 24 | } -------------------------------------------------------------------------------- /contracts/README.md: -------------------------------------------------------------------------------- 1 | # Uniswap V2 Area 2 | 3 | Code from [Uniswap V2](https://github.com/Uniswap/uniswap-v2-core/tree/27f6354bae6685612c182c3bc7577e61bc8717e3/contracts) with the following modifications. 4 | 5 | 1. Change contract version to 0.6.12 and do the necessary patching. 6 | 2. Add `migrator` member in `UniswapV2Factory` which can be set by `feeToSetter`. 7 | 3. Allow `migrator` to specify the amount of `liquidity` during the first mint. Disallow first mint if migrator is set. 8 | 9 | To see all diffs: 10 | 11 | ``` 12 | $ git diff 4c4bf551417e3df09a25aa0dbb6941cccbbac11a . 13 | ``` 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | .pnp 6 | .pnp.js 7 | 8 | # testing 9 | coverage 10 | 11 | # misc 12 | .DS_Store 13 | *.pem 14 | 15 | # debug 16 | .pnpm-debug.log* 17 | 18 | 19 | # webstorm 20 | .idea 21 | 22 | # env 23 | .env 24 | 25 | # typechain 26 | typechain 27 | 28 | # exports 29 | exports 30 | 31 | # cache 32 | cache 33 | 34 | # generated 35 | generated 36 | 37 | # artifacts 38 | artifacts 39 | 40 | # artifacts zk 41 | artifacts-zk 42 | 43 | # cache zk 44 | cache-zk 45 | 46 | # typescript 47 | *.tsbuildinfo 48 | next-env.d.ts -------------------------------------------------------------------------------- /contracts/libraries/SafeMath.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity =0.6.12; 4 | 5 | // a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math) 6 | 7 | library SafeMathUniswap { 8 | function add(uint x, uint y) internal pure returns (uint z) { 9 | require((z = x + y) >= x, 'ds-math-add-overflow'); 10 | } 11 | 12 | function sub(uint x, uint y) internal pure returns (uint z) { 13 | require((z = x - y) <= x, 'ds-math-sub-underflow'); 14 | } 15 | 16 | function mul(uint x, uint y) internal pure returns (uint z) { 17 | require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow'); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/libraries/UQ112x112.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity =0.6.12; 4 | 5 | // a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format)) 6 | 7 | // range: [0, 2**112 - 1] 8 | // resolution: 1 / 2**112 9 | 10 | library UQ112x112 { 11 | uint224 constant Q112 = 2**112; 12 | 13 | // encode a uint112 as a UQ112x112 14 | function encode(uint112 y) internal pure returns (uint224 z) { 15 | z = uint224(y) * Q112; // never overflows 16 | } 17 | 18 | // divide a UQ112x112 by a uint112, returning a UQ112x112 19 | function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) { 20 | z = x / uint224(y); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /contracts/libraries/Math.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity =0.6.12; 4 | 5 | // a library for performing various math operations 6 | 7 | library Math { 8 | function min(uint x, uint y) internal pure returns (uint z) { 9 | z = x < y ? x : y; 10 | } 11 | 12 | // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) 13 | function sqrt(uint y) internal pure returns (uint z) { 14 | if (y > 3) { 15 | z = y; 16 | uint x = y / 2 + 1; 17 | while (x < z) { 18 | z = x; 19 | x = (y / x + x) / 2; 20 | } 21 | } else if (y != 0) { 22 | z = 1; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /deploy/WETH9.ts: -------------------------------------------------------------------------------- 1 | import type { HardhatRuntimeEnvironment } from 'hardhat/types' 2 | import type { DeployFunction } from 'hardhat-deploy/types' 3 | 4 | const func: DeployFunction = async function ({ deployments, ethers, getNamedAccounts }: HardhatRuntimeEnvironment) { 5 | const { deploy } = deployments 6 | 7 | const { deployer } = await getNamedAccounts() 8 | 9 | await deploy('WETH9', { 10 | from: deployer, 11 | deterministicDeployment: false, 12 | }) 13 | } 14 | 15 | export default func 16 | 17 | func.tags = ['WETH9'] 18 | 19 | func.skip = ({ getChainId }) => 20 | new Promise(async (resolve, reject) => { 21 | try { 22 | const chainId = await getChainId() 23 | resolve(chainId !== '31337') 24 | } catch (error) { 25 | reject(error) 26 | } 27 | }) 28 | -------------------------------------------------------------------------------- /contracts/interfaces/IUniswapV2Factory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity >=0.5.0; 4 | 5 | interface IUniswapV2Factory { 6 | event PairCreated(address indexed token0, address indexed token1, address pair, uint); 7 | 8 | function feeTo() external view returns (address); 9 | function feeToSetter() external view returns (address); 10 | function migrator() external view returns (address); 11 | 12 | function getPair(address tokenA, address tokenB) external view returns (address pair); 13 | function allPairs(uint) external view returns (address pair); 14 | function allPairsLength() external view returns (uint); 15 | 16 | function createPair(address tokenA, address tokenB) external returns (address pair); 17 | 18 | function setFeeTo(address) external; 19 | function setFeeToSetter(address) external; 20 | function setMigrator(address) external; 21 | } 22 | -------------------------------------------------------------------------------- /deploy/UniswapV2Factory.ts: -------------------------------------------------------------------------------- 1 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | 4 | // Defining bytecode and abi from original contract on mainnet to ensure bytecode matches and it produces the same pair code hash 5 | import { abi, bytecode } from "../deployments/ethereum/UniswapV2Factory.json"; 6 | 7 | const func: DeployFunction = async function ({ 8 | ethers, 9 | getNamedAccounts, 10 | deployments, 11 | getChainId, 12 | }: HardhatRuntimeEnvironment) { 13 | const { deploy } = deployments; 14 | 15 | const { deployer, dev } = await getNamedAccounts(); 16 | 17 | await deploy("UniswapV2Factory", { 18 | contract: { 19 | abi, 20 | bytecode, 21 | }, 22 | from: deployer, 23 | args: [dev], 24 | log: true, 25 | deterministicDeployment: false, 26 | }); 27 | }; 28 | 29 | func.tags = ["UniswapV2Factory", "AMM"]; 30 | 31 | export default func; 32 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity >=0.5.0; 4 | 5 | interface IERC20Uniswap { 6 | event Approval(address indexed owner, address indexed spender, uint value); 7 | event Transfer(address indexed from, address indexed to, uint value); 8 | 9 | function name() external view returns (string memory); 10 | function symbol() external view returns (string memory); 11 | function decimals() external view returns (uint8); 12 | function totalSupply() external view returns (uint); 13 | function balanceOf(address owner) external view returns (uint); 14 | function allowance(address owner, address spender) external view returns (uint); 15 | 16 | function approve(address spender, uint value) external returns (bool); 17 | function transfer(address to, uint value) external returns (bool); 18 | function transferFrom(address from, address to, uint value) external returns (bool); 19 | } 20 | -------------------------------------------------------------------------------- /deploy/UniswapV2Router02.ts: -------------------------------------------------------------------------------- 1 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | 4 | const func: DeployFunction = async function ({ 5 | getNamedAccounts, 6 | deployments, 7 | getChainId, 8 | ethers, 9 | }: HardhatRuntimeEnvironment) { 10 | const { deploy } = deployments; 11 | 12 | const { deployer } = await getNamedAccounts(); 13 | 14 | const chainId = parseInt(await getChainId()); 15 | 16 | if (!process.env.WNATIVE_ADDRESS) { 17 | throw Error(`No WNATIVE_ADDRESS for chain #${chainId}!`); 18 | } 19 | 20 | const factory = await ethers.getContract("UniswapV2Factory"); 21 | 22 | await deploy(chainId === 42220 ? "UniswapV2Router02Celo" : "UniswapV2Router02", { 23 | from: deployer, 24 | args: [factory.address, process.env.WNATIVE_ADDRESS], 25 | log: true, 26 | deterministicDeployment: false, 27 | }); 28 | }; 29 | 30 | func.tags = ["UniswapV2Router02", "AMM"]; 31 | 32 | func.dependencies = ["UniswapV2Factory", "WETH9"]; 33 | 34 | export default func; 35 | -------------------------------------------------------------------------------- /contracts/interfaces/IUniswapV2ERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity >=0.5.0; 4 | 5 | interface IUniswapV2ERC20 { 6 | event Approval(address indexed owner, address indexed spender, uint value); 7 | event Transfer(address indexed from, address indexed to, uint value); 8 | 9 | function name() external pure returns (string memory); 10 | function symbol() external pure returns (string memory); 11 | function decimals() external pure returns (uint8); 12 | function totalSupply() external view returns (uint); 13 | function balanceOf(address owner) external view returns (uint); 14 | function allowance(address owner, address spender) external view returns (uint); 15 | 16 | function approve(address spender, uint value) external returns (bool); 17 | function transfer(address to, uint value) external returns (bool); 18 | function transferFrom(address from, address to, uint value) external returns (bool); 19 | 20 | function DOMAIN_SEPARATOR() external view returns (bytes32); 21 | function PERMIT_TYPEHASH() external pure returns (bytes32); 22 | function nonces(address owner) external view returns (uint); 23 | 24 | function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; 25 | } -------------------------------------------------------------------------------- /contracts/interfaces/IUniswapV2Router02.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity >=0.6.2; 4 | 5 | import './IUniswapV2Router01.sol'; 6 | 7 | interface IUniswapV2Router02 is IUniswapV2Router01 { 8 | function removeLiquidityETHSupportingFeeOnTransferTokens( 9 | address token, 10 | uint liquidity, 11 | uint amountTokenMin, 12 | uint amountETHMin, 13 | address to, 14 | uint deadline 15 | ) external returns (uint amountETH); 16 | function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( 17 | address token, 18 | uint liquidity, 19 | uint amountTokenMin, 20 | uint amountETHMin, 21 | address to, 22 | uint deadline, 23 | bool approveMax, uint8 v, bytes32 r, bytes32 s 24 | ) external returns (uint amountETH); 25 | 26 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 27 | uint amountIn, 28 | uint amountOutMin, 29 | address[] calldata path, 30 | address to, 31 | uint deadline 32 | ) external; 33 | function swapExactETHForTokensSupportingFeeOnTransferTokens( 34 | uint amountOutMin, 35 | address[] calldata path, 36 | address to, 37 | uint deadline 38 | ) external payable; 39 | function swapExactTokensForETHSupportingFeeOnTransferTokens( 40 | uint amountIn, 41 | uint amountOutMin, 42 | address[] calldata path, 43 | address to, 44 | uint deadline 45 | ) external; 46 | } -------------------------------------------------------------------------------- /deploy/SushiRoll.ts: -------------------------------------------------------------------------------- 1 | import { HardhatRuntimeEnvironment } from 'hardhat/types' 2 | import { DeployFunction } from 'hardhat-deploy/types' 3 | 4 | const UNISWAP_ROUTER = new Map() 5 | UNISWAP_ROUTER.set('1', '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D') 6 | UNISWAP_ROUTER.set('3', '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D') 7 | UNISWAP_ROUTER.set('4', '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D') 8 | UNISWAP_ROUTER.set('5', '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D') 9 | UNISWAP_ROUTER.set('42', '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D') 10 | UNISWAP_ROUTER.set('1287', '0x2823caf546C7d09a4832bd1da14f2C6b6E665e05') 11 | UNISWAP_ROUTER.set('79377087078960', '0x0B72c0193CD598b536210299d358A5b720A262b8') 12 | 13 | const func: DeployFunction = async function ({ getNamedAccounts, getChainId, deployments }: HardhatRuntimeEnvironment) { 14 | const { deploy } = deployments 15 | 16 | const { deployer } = await getNamedAccounts() 17 | 18 | const chainId = await getChainId() 19 | 20 | if (!UNISWAP_ROUTER.has(chainId)) { 21 | throw Error('No UniswapV2Route') 22 | } 23 | 24 | const uniswapRouterAddress = UNISWAP_ROUTER.get(chainId) 25 | 26 | const sushiswapRouterAddress = (await deployments.get('UniswapV2Router02')).address 27 | 28 | await deploy('SushiRoll', { 29 | from: deployer, 30 | args: [uniswapRouterAddress, sushiswapRouterAddress], 31 | log: true, 32 | deterministicDeployment: false, 33 | }) 34 | } 35 | 36 | func.tags = ['SushiRoll'] 37 | 38 | func.dependencies = ['UniswapV2Router02'] 39 | 40 | export default func 41 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sushiswap/v2-core", 3 | "version": "1.0.0", 4 | "description": "SushiSwap", 5 | "keywords": [ 6 | "sushi", 7 | "swap" 8 | ], 9 | "homepage": "https://github.com/sushiswap/sushiswap/protocols/sushiswap#readme", 10 | "bugs": { 11 | "url": "https://github.com/sushiswap/sushiswap/issues" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/sushiswap/sushiswap.git", 16 | "directory": "protocols/sushiswap" 17 | }, 18 | "license": "MIT", 19 | "main": "exports/exports.js", 20 | "types": "exports/exports.d.ts", 21 | "author": "Matthew Lilley ", 22 | "files": [ 23 | "artifacts", 24 | "contracts", 25 | "deploy", 26 | "deployments", 27 | "exports", 28 | "typechain" 29 | ], 30 | "scripts": { 31 | "build": "TS_NODE_TRANSPILE_ONLY=1 hardhat compile", 32 | "clean": "rm -rf .turbo node_modules artifacts cache exports typechain", 33 | "export": "hardhat export --export-all exports.json && tsc -p tsconfig.exports.json --declaration", 34 | "node": "hardhat node" 35 | }, 36 | "devDependencies": { 37 | "@nomiclabs/hardhat-ethers": "npm:hardhat-deploy-ethers@0.3.0-beta.13", 38 | "@openzeppelin/contracts": "3.1.0", 39 | "@tenderly/hardhat-tenderly": "^1.0.13", 40 | "@types/node": "18.11.18", 41 | "dotenv": "16.3.1", 42 | "eslint": "8.41.0", 43 | "hardhat": "2.12.4", 44 | "hardhat-deploy": "0.11.22", 45 | "ts-node": "10.9.1", 46 | "typescript": "5.0.4" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /contracts/libraries/TransferHelper.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity >=0.6.0; 4 | 5 | // helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false 6 | library TransferHelper { 7 | function safeApprove(address token, address to, uint value) internal { 8 | // bytes4(keccak256(bytes('approve(address,uint256)'))); 9 | (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); 10 | require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED'); 11 | } 12 | 13 | function safeTransfer(address token, address to, uint value) internal { 14 | // bytes4(keccak256(bytes('transfer(address,uint256)'))); 15 | (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); 16 | require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED'); 17 | } 18 | 19 | function safeTransferFrom(address token, address from, address to, uint value) internal { 20 | // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); 21 | (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); 22 | require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED'); 23 | } 24 | 25 | function safeTransferETH(address to, uint value) internal { 26 | (bool success,) = to.call{value:value}(new bytes(0)); 27 | require(success, 'TransferHelper: ETH_TRANSFER_FAILED'); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /contracts/mocks/WETH9.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | 3 | pragma solidity 0.6.12; 4 | 5 | contract WETH9 { 6 | string public name = "Wrapped Ether"; 7 | string public symbol = "WETH"; 8 | uint8 public decimals = 18; 9 | 10 | event Approval(address indexed src, address indexed guy, uint256 wad); 11 | event Transfer(address indexed src, address indexed dst, uint256 wad); 12 | event Deposit(address indexed dst, uint256 wad); 13 | event Withdrawal(address indexed src, uint256 wad); 14 | 15 | mapping(address => uint256) public balanceOf; 16 | mapping(address => mapping(address => uint256)) public allowance; 17 | 18 | /*fallback () external payable { 19 | deposit(); 20 | }*/ 21 | function deposit() public payable { 22 | balanceOf[msg.sender] += msg.value; 23 | emit Deposit(msg.sender, msg.value); 24 | } 25 | 26 | function withdraw(uint256 wad) public { 27 | require(balanceOf[msg.sender] >= wad, "WETH9: Error"); 28 | balanceOf[msg.sender] -= wad; 29 | msg.sender.transfer(wad); 30 | emit Withdrawal(msg.sender, wad); 31 | } 32 | 33 | function totalSupply() public view returns (uint256) { 34 | return address(this).balance; 35 | } 36 | 37 | function approve(address guy, uint256 wad) public returns (bool) { 38 | allowance[msg.sender][guy] = wad; 39 | emit Approval(msg.sender, guy, wad); 40 | return true; 41 | } 42 | 43 | function transfer(address dst, uint256 wad) public returns (bool) { 44 | return transferFrom(msg.sender, dst, wad); 45 | } 46 | 47 | function transferFrom( 48 | address src, 49 | address dst, 50 | uint256 wad 51 | ) public returns (bool) { 52 | require(balanceOf[src] >= wad, "WETH9: Error"); 53 | 54 | if (src != msg.sender && allowance[src][msg.sender] != uint256(-1)) { 55 | require(allowance[src][msg.sender] >= wad, "WETH9: Error"); 56 | allowance[src][msg.sender] -= wad; 57 | } 58 | 59 | balanceOf[src] -= wad; 60 | balanceOf[dst] += wad; 61 | 62 | emit Transfer(src, dst, wad); 63 | 64 | return true; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /contracts/UniswapV2Factory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity =0.6.12; 4 | 5 | import './interfaces/IUniswapV2Factory.sol'; 6 | import './UniswapV2Pair.sol'; 7 | 8 | contract UniswapV2Factory is IUniswapV2Factory { 9 | address public override feeTo; 10 | address public override feeToSetter; 11 | address public override migrator; 12 | 13 | mapping(address => mapping(address => address)) public override getPair; 14 | address[] public override allPairs; 15 | 16 | event PairCreated(address indexed token0, address indexed token1, address pair, uint); 17 | 18 | constructor(address _feeToSetter) public { 19 | feeToSetter = _feeToSetter; 20 | } 21 | 22 | function allPairsLength() external override view returns (uint) { 23 | return allPairs.length; 24 | } 25 | 26 | function pairCodeHash() external pure returns (bytes32) { 27 | return keccak256(type(UniswapV2Pair).creationCode); 28 | } 29 | 30 | function createPair(address tokenA, address tokenB) external override returns (address pair) { 31 | require(tokenA != tokenB, 'UniswapV2: IDENTICAL_ADDRESSES'); 32 | (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); 33 | require(token0 != address(0), 'UniswapV2: ZERO_ADDRESS'); 34 | require(getPair[token0][token1] == address(0), 'UniswapV2: PAIR_EXISTS'); // single check is sufficient 35 | bytes memory bytecode = type(UniswapV2Pair).creationCode; 36 | bytes32 salt = keccak256(abi.encodePacked(token0, token1)); 37 | assembly { 38 | pair := create2(0, add(bytecode, 32), mload(bytecode), salt) 39 | } 40 | UniswapV2Pair(pair).initialize(token0, token1); 41 | getPair[token0][token1] = pair; 42 | getPair[token1][token0] = pair; // populate mapping in the reverse direction 43 | allPairs.push(pair); 44 | emit PairCreated(token0, token1, pair, allPairs.length); 45 | } 46 | 47 | function setFeeTo(address _feeTo) external override { 48 | require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN'); 49 | feeTo = _feeTo; 50 | } 51 | 52 | function setMigrator(address _migrator) external override { 53 | require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN'); 54 | migrator = _migrator; 55 | } 56 | 57 | function setFeeToSetter(address _feeToSetter) external override { 58 | require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN'); 59 | feeToSetter = _feeToSetter; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /contracts/interfaces/IUniswapV2Pair.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity >=0.5.0; 4 | 5 | interface IUniswapV2Pair { 6 | event Approval(address indexed owner, address indexed spender, uint value); 7 | event Transfer(address indexed from, address indexed to, uint value); 8 | 9 | function name() external pure returns (string memory); 10 | function symbol() external pure returns (string memory); 11 | function decimals() external pure returns (uint8); 12 | function totalSupply() external view returns (uint); 13 | function balanceOf(address owner) external view returns (uint); 14 | function allowance(address owner, address spender) external view returns (uint); 15 | 16 | function approve(address spender, uint value) external returns (bool); 17 | function transfer(address to, uint value) external returns (bool); 18 | function transferFrom(address from, address to, uint value) external returns (bool); 19 | 20 | function DOMAIN_SEPARATOR() external view returns (bytes32); 21 | function PERMIT_TYPEHASH() external pure returns (bytes32); 22 | function nonces(address owner) external view returns (uint); 23 | 24 | function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; 25 | 26 | event Mint(address indexed sender, uint amount0, uint amount1); 27 | event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); 28 | event Swap( 29 | address indexed sender, 30 | uint amount0In, 31 | uint amount1In, 32 | uint amount0Out, 33 | uint amount1Out, 34 | address indexed to 35 | ); 36 | event Sync(uint112 reserve0, uint112 reserve1); 37 | 38 | function MINIMUM_LIQUIDITY() external pure returns (uint); 39 | function factory() external view returns (address); 40 | function token0() external view returns (address); 41 | function token1() external view returns (address); 42 | function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); 43 | function price0CumulativeLast() external view returns (uint); 44 | function price1CumulativeLast() external view returns (uint); 45 | function kLast() external view returns (uint); 46 | 47 | function mint(address to) external returns (uint liquidity); 48 | function burn(address to) external returns (uint amount0, uint amount1); 49 | function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; 50 | function skim(address to) external; 51 | function sync() external; 52 | 53 | function initialize(address, address) external; 54 | } -------------------------------------------------------------------------------- /deployments/localhost/solcInputs/07facc9fad1266fbe84e2dac07a80c89.json: -------------------------------------------------------------------------------- 1 | { 2 | "language": "Solidity", 3 | "sources": { 4 | "contracts/mocks/WETH9.sol": { 5 | "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity 0.6.12;\n\ncontract WETH9 {\n string public name = \"Wrapped Ether\";\n string public symbol = \"WETH\";\n uint8 public decimals = 18;\n\n event Approval(address indexed src, address indexed guy, uint256 wad);\n event Transfer(address indexed src, address indexed dst, uint256 wad);\n event Deposit(address indexed dst, uint256 wad);\n event Withdrawal(address indexed src, uint256 wad);\n\n mapping(address => uint256) public balanceOf;\n mapping(address => mapping(address => uint256)) public allowance;\n\n /*fallback () external payable {\n deposit();\n }*/\n function deposit() public payable {\n balanceOf[msg.sender] += msg.value;\n emit Deposit(msg.sender, msg.value);\n }\n\n function withdraw(uint256 wad) public {\n require(balanceOf[msg.sender] >= wad, \"WETH9: Error\");\n balanceOf[msg.sender] -= wad;\n msg.sender.transfer(wad);\n emit Withdrawal(msg.sender, wad);\n }\n\n function totalSupply() public view returns (uint256) {\n return address(this).balance;\n }\n\n function approve(address guy, uint256 wad) public returns (bool) {\n allowance[msg.sender][guy] = wad;\n emit Approval(msg.sender, guy, wad);\n return true;\n }\n\n function transfer(address dst, uint256 wad) public returns (bool) {\n return transferFrom(msg.sender, dst, wad);\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) public returns (bool) {\n require(balanceOf[src] >= wad, \"WETH9: Error\");\n\n if (src != msg.sender && allowance[src][msg.sender] != uint256(-1)) {\n require(allowance[src][msg.sender] >= wad, \"WETH9: Error\");\n allowance[src][msg.sender] -= wad;\n }\n\n balanceOf[src] -= wad;\n balanceOf[dst] += wad;\n\n emit Transfer(src, dst, wad);\n\n return true;\n }\n}\n" 6 | } 7 | }, 8 | "settings": { 9 | "optimizer": { 10 | "enabled": true, 11 | "runs": 200 12 | }, 13 | "outputSelection": { 14 | "*": { 15 | "*": [ 16 | "abi", 17 | "evm.bytecode", 18 | "evm.deployedBytecode", 19 | "evm.methodIdentifiers", 20 | "metadata", 21 | "devdoc", 22 | "userdoc", 23 | "storageLayout", 24 | "evm.gasEstimates" 25 | ], 26 | "": ["ast"] 27 | } 28 | }, 29 | "metadata": { 30 | "useLiteralContent": true 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /contracts/UniswapV2ERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity =0.6.12; 4 | 5 | import './libraries/SafeMath.sol'; 6 | 7 | contract UniswapV2ERC20 { 8 | using SafeMathUniswap for uint; 9 | 10 | string public constant name = 'SushiSwap LP Token'; 11 | string public constant symbol = 'SLP'; 12 | uint8 public constant decimals = 18; 13 | uint public totalSupply; 14 | mapping(address => uint) public balanceOf; 15 | mapping(address => mapping(address => uint)) public allowance; 16 | 17 | bytes32 public DOMAIN_SEPARATOR; 18 | // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); 19 | bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; 20 | mapping(address => uint) public nonces; 21 | 22 | event Approval(address indexed owner, address indexed spender, uint value); 23 | event Transfer(address indexed from, address indexed to, uint value); 24 | 25 | constructor() public { 26 | uint chainId; 27 | assembly { 28 | chainId := chainid() 29 | } 30 | DOMAIN_SEPARATOR = keccak256( 31 | abi.encode( 32 | keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'), 33 | keccak256(bytes(name)), 34 | keccak256(bytes('1')), 35 | chainId, 36 | address(this) 37 | ) 38 | ); 39 | } 40 | 41 | function _mint(address to, uint value) internal { 42 | totalSupply = totalSupply.add(value); 43 | balanceOf[to] = balanceOf[to].add(value); 44 | emit Transfer(address(0), to, value); 45 | } 46 | 47 | function _burn(address from, uint value) internal { 48 | balanceOf[from] = balanceOf[from].sub(value); 49 | totalSupply = totalSupply.sub(value); 50 | emit Transfer(from, address(0), value); 51 | } 52 | 53 | function _approve(address owner, address spender, uint value) private { 54 | allowance[owner][spender] = value; 55 | emit Approval(owner, spender, value); 56 | } 57 | 58 | function _transfer(address from, address to, uint value) private { 59 | balanceOf[from] = balanceOf[from].sub(value); 60 | balanceOf[to] = balanceOf[to].add(value); 61 | emit Transfer(from, to, value); 62 | } 63 | 64 | function approve(address spender, uint value) external returns (bool) { 65 | _approve(msg.sender, spender, value); 66 | return true; 67 | } 68 | 69 | function transfer(address to, uint value) external returns (bool) { 70 | _transfer(msg.sender, to, value); 71 | return true; 72 | } 73 | 74 | function transferFrom(address from, address to, uint value) external returns (bool) { 75 | if (allowance[from][msg.sender] != uint(-1)) { 76 | allowance[from][msg.sender] = allowance[from][msg.sender].sub(value); 77 | } 78 | _transfer(from, to, value); 79 | return true; 80 | } 81 | 82 | function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external { 83 | require(deadline >= block.timestamp, 'UniswapV2: EXPIRED'); 84 | bytes32 digest = keccak256( 85 | abi.encodePacked( 86 | '\x19\x01', 87 | DOMAIN_SEPARATOR, 88 | keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline)) 89 | ) 90 | ); 91 | address recoveredAddress = ecrecover(digest, v, r, s); 92 | require(recoveredAddress != address(0) && recoveredAddress == owner, 'UniswapV2: INVALID_SIGNATURE'); 93 | _approve(owner, spender, value); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /deployments/arbitrum/solcInputs/af42c9b78f9459eb1f47e4c296c8d1f4.json: -------------------------------------------------------------------------------- 1 | { 2 | "language": "Solidity", 3 | "sources": { 4 | "contracts/Multicall2.sol": { 5 | "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @title Multicall2 - Aggregate results from multiple read-only function calls\n/// @author Michael Elliot \n/// @author Joshua Levine \n/// @author Nick Johnson \n\ncontract Multicall2 {\n struct Call {\n address target;\n bytes callData;\n }\n struct Result {\n bool success;\n bytes returnData;\n }\n\n function aggregate(Call[] memory calls) public returns (uint256 blockNumber, bytes[] memory returnData) {\n blockNumber = block.number;\n returnData = new bytes[](calls.length);\n for(uint256 i = 0; i < calls.length; i++) {\n (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);\n require(success, \"Multicall aggregate: call failed\");\n returnData[i] = ret;\n }\n }\n function blockAndAggregate(Call[] memory calls) public returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {\n (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);\n }\n function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {\n blockHash = blockhash(blockNumber);\n }\n function getBlockNumber() public view returns (uint256 blockNumber) {\n blockNumber = block.number;\n }\n function getCurrentBlockCoinbase() public view returns (address coinbase) {\n coinbase = block.coinbase;\n }\n function getCurrentBlockDifficulty() public view returns (uint256 difficulty) {\n difficulty = block.difficulty;\n }\n function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {\n gaslimit = block.gaslimit;\n }\n function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {\n timestamp = block.timestamp;\n }\n function getEthBalance(address addr) public view returns (uint256 balance) {\n balance = addr.balance;\n }\n function getLastBlockHash() public view returns (bytes32 blockHash) {\n blockHash = blockhash(block.number - 1);\n }\n function tryAggregate(bool requireSuccess, Call[] memory calls) public returns (Result[] memory returnData) {\n returnData = new Result[](calls.length);\n for(uint256 i = 0; i < calls.length; i++) {\n (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);\n\n if (requireSuccess) {\n require(success, \"Multicall2 aggregate: call failed\");\n }\n\n returnData[i] = Result(success, ret);\n }\n }\n function tryBlockAndAggregate(bool requireSuccess, Call[] memory calls) public returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {\n blockNumber = block.number;\n blockHash = blockhash(block.number);\n returnData = tryAggregate(requireSuccess, calls);\n }\n}" 6 | } 7 | }, 8 | "settings": { 9 | "optimizer": { 10 | "enabled": true, 11 | "runs": 200 12 | }, 13 | "outputSelection": { 14 | "*": { 15 | "*": [ 16 | "abi", 17 | "evm.bytecode", 18 | "evm.deployedBytecode", 19 | "evm.methodIdentifiers", 20 | "metadata", 21 | "devdoc", 22 | "userdoc", 23 | "storageLayout", 24 | "evm.gasEstimates" 25 | ], 26 | "": ["ast"] 27 | } 28 | }, 29 | "metadata": { 30 | "useLiteralContent": true 31 | }, 32 | "libraries": { 33 | "": { 34 | "__CACHE_BREAKER__": "0x00000000d41867734bbee4c6863d9255b2b06ac1" 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /deployments/moonbeam/solcInputs/af42c9b78f9459eb1f47e4c296c8d1f4.json: -------------------------------------------------------------------------------- 1 | { 2 | "language": "Solidity", 3 | "sources": { 4 | "contracts/Multicall2.sol": { 5 | "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @title Multicall2 - Aggregate results from multiple read-only function calls\n/// @author Michael Elliot \n/// @author Joshua Levine \n/// @author Nick Johnson \n\ncontract Multicall2 {\n struct Call {\n address target;\n bytes callData;\n }\n struct Result {\n bool success;\n bytes returnData;\n }\n\n function aggregate(Call[] memory calls) public returns (uint256 blockNumber, bytes[] memory returnData) {\n blockNumber = block.number;\n returnData = new bytes[](calls.length);\n for(uint256 i = 0; i < calls.length; i++) {\n (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);\n require(success, \"Multicall aggregate: call failed\");\n returnData[i] = ret;\n }\n }\n function blockAndAggregate(Call[] memory calls) public returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {\n (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);\n }\n function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {\n blockHash = blockhash(blockNumber);\n }\n function getBlockNumber() public view returns (uint256 blockNumber) {\n blockNumber = block.number;\n }\n function getCurrentBlockCoinbase() public view returns (address coinbase) {\n coinbase = block.coinbase;\n }\n function getCurrentBlockDifficulty() public view returns (uint256 difficulty) {\n difficulty = block.difficulty;\n }\n function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {\n gaslimit = block.gaslimit;\n }\n function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {\n timestamp = block.timestamp;\n }\n function getEthBalance(address addr) public view returns (uint256 balance) {\n balance = addr.balance;\n }\n function getLastBlockHash() public view returns (bytes32 blockHash) {\n blockHash = blockhash(block.number - 1);\n }\n function tryAggregate(bool requireSuccess, Call[] memory calls) public returns (Result[] memory returnData) {\n returnData = new Result[](calls.length);\n for(uint256 i = 0; i < calls.length; i++) {\n (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);\n\n if (requireSuccess) {\n require(success, \"Multicall2 aggregate: call failed\");\n }\n\n returnData[i] = Result(success, ret);\n }\n }\n function tryBlockAndAggregate(bool requireSuccess, Call[] memory calls) public returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {\n blockNumber = block.number;\n blockHash = blockhash(block.number);\n returnData = tryAggregate(requireSuccess, calls);\n }\n}" 6 | } 7 | }, 8 | "settings": { 9 | "optimizer": { 10 | "enabled": true, 11 | "runs": 200 12 | }, 13 | "outputSelection": { 14 | "*": { 15 | "*": [ 16 | "abi", 17 | "evm.bytecode", 18 | "evm.deployedBytecode", 19 | "evm.methodIdentifiers", 20 | "metadata", 21 | "devdoc", 22 | "userdoc", 23 | "storageLayout", 24 | "evm.gasEstimates" 25 | ], 26 | "": ["ast"] 27 | } 28 | }, 29 | "metadata": { 30 | "useLiteralContent": true 31 | }, 32 | "libraries": { 33 | "": { 34 | "__CACHE_BREAKER__": "0x00000000d41867734bbee4c6863d9255b2b06ac1" 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /deployments/palm/solcInputs/af42c9b78f9459eb1f47e4c296c8d1f4.json: -------------------------------------------------------------------------------- 1 | { 2 | "language": "Solidity", 3 | "sources": { 4 | "contracts/Multicall2.sol": { 5 | "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @title Multicall2 - Aggregate results from multiple read-only function calls\n/// @author Michael Elliot \n/// @author Joshua Levine \n/// @author Nick Johnson \n\ncontract Multicall2 {\n struct Call {\n address target;\n bytes callData;\n }\n struct Result {\n bool success;\n bytes returnData;\n }\n\n function aggregate(Call[] memory calls) public returns (uint256 blockNumber, bytes[] memory returnData) {\n blockNumber = block.number;\n returnData = new bytes[](calls.length);\n for(uint256 i = 0; i < calls.length; i++) {\n (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);\n require(success, \"Multicall aggregate: call failed\");\n returnData[i] = ret;\n }\n }\n function blockAndAggregate(Call[] memory calls) public returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {\n (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);\n }\n function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {\n blockHash = blockhash(blockNumber);\n }\n function getBlockNumber() public view returns (uint256 blockNumber) {\n blockNumber = block.number;\n }\n function getCurrentBlockCoinbase() public view returns (address coinbase) {\n coinbase = block.coinbase;\n }\n function getCurrentBlockDifficulty() public view returns (uint256 difficulty) {\n difficulty = block.difficulty;\n }\n function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {\n gaslimit = block.gaslimit;\n }\n function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {\n timestamp = block.timestamp;\n }\n function getEthBalance(address addr) public view returns (uint256 balance) {\n balance = addr.balance;\n }\n function getLastBlockHash() public view returns (bytes32 blockHash) {\n blockHash = blockhash(block.number - 1);\n }\n function tryAggregate(bool requireSuccess, Call[] memory calls) public returns (Result[] memory returnData) {\n returnData = new Result[](calls.length);\n for(uint256 i = 0; i < calls.length; i++) {\n (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);\n\n if (requireSuccess) {\n require(success, \"Multicall2 aggregate: call failed\");\n }\n\n returnData[i] = Result(success, ret);\n }\n }\n function tryBlockAndAggregate(bool requireSuccess, Call[] memory calls) public returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {\n blockNumber = block.number;\n blockHash = blockhash(block.number);\n returnData = tryAggregate(requireSuccess, calls);\n }\n}" 6 | } 7 | }, 8 | "settings": { 9 | "optimizer": { 10 | "enabled": true, 11 | "runs": 200 12 | }, 13 | "outputSelection": { 14 | "*": { 15 | "*": [ 16 | "abi", 17 | "evm.bytecode", 18 | "evm.deployedBytecode", 19 | "evm.methodIdentifiers", 20 | "metadata", 21 | "devdoc", 22 | "userdoc", 23 | "storageLayout", 24 | "evm.gasEstimates" 25 | ], 26 | "": ["ast"] 27 | } 28 | }, 29 | "metadata": { 30 | "useLiteralContent": true 31 | }, 32 | "libraries": { 33 | "": { 34 | "__CACHE_BREAKER__": "0x00000000d41867734bbee4c6863d9255b2b06ac1" 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /contracts/interfaces/IUniswapV2Router01.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity >=0.6.2; 4 | 5 | interface IUniswapV2Router01 { 6 | function factory() external pure returns (address); 7 | function WETH() external pure returns (address); 8 | 9 | function addLiquidity( 10 | address tokenA, 11 | address tokenB, 12 | uint amountADesired, 13 | uint amountBDesired, 14 | uint amountAMin, 15 | uint amountBMin, 16 | address to, 17 | uint deadline 18 | ) external returns (uint amountA, uint amountB, uint liquidity); 19 | function addLiquidityETH( 20 | address token, 21 | uint amountTokenDesired, 22 | uint amountTokenMin, 23 | uint amountETHMin, 24 | address to, 25 | uint deadline 26 | ) external payable returns (uint amountToken, uint amountETH, uint liquidity); 27 | function removeLiquidity( 28 | address tokenA, 29 | address tokenB, 30 | uint liquidity, 31 | uint amountAMin, 32 | uint amountBMin, 33 | address to, 34 | uint deadline 35 | ) external returns (uint amountA, uint amountB); 36 | function removeLiquidityETH( 37 | address token, 38 | uint liquidity, 39 | uint amountTokenMin, 40 | uint amountETHMin, 41 | address to, 42 | uint deadline 43 | ) external returns (uint amountToken, uint amountETH); 44 | function removeLiquidityWithPermit( 45 | address tokenA, 46 | address tokenB, 47 | uint liquidity, 48 | uint amountAMin, 49 | uint amountBMin, 50 | address to, 51 | uint deadline, 52 | bool approveMax, uint8 v, bytes32 r, bytes32 s 53 | ) external returns (uint amountA, uint amountB); 54 | function removeLiquidityETHWithPermit( 55 | address token, 56 | uint liquidity, 57 | uint amountTokenMin, 58 | uint amountETHMin, 59 | address to, 60 | uint deadline, 61 | bool approveMax, uint8 v, bytes32 r, bytes32 s 62 | ) external returns (uint amountToken, uint amountETH); 63 | function swapExactTokensForTokens( 64 | uint amountIn, 65 | uint amountOutMin, 66 | address[] calldata path, 67 | address to, 68 | uint deadline 69 | ) external returns (uint[] memory amounts); 70 | function swapTokensForExactTokens( 71 | uint amountOut, 72 | uint amountInMax, 73 | address[] calldata path, 74 | address to, 75 | uint deadline 76 | ) external returns (uint[] memory amounts); 77 | function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) 78 | external 79 | payable 80 | returns (uint[] memory amounts); 81 | function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) 82 | external 83 | returns (uint[] memory amounts); 84 | function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) 85 | external 86 | returns (uint[] memory amounts); 87 | function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) 88 | external 89 | payable 90 | returns (uint[] memory amounts); 91 | 92 | function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); 93 | function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); 94 | function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); 95 | function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); 96 | function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); 97 | } -------------------------------------------------------------------------------- /deployments/arbitrum/solcInputs/ea2b048f03db764f4dadc9d3f9ffaac6.json: -------------------------------------------------------------------------------- 1 | { 2 | "language": "Solidity", 3 | "sources": { 4 | "contracts/Multicall2.sol": { 5 | "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\ninterface ArbSys {\n /**\n * @notice Get Arbitrum block number (distinct from L1 block number; Arbitrum genesis block has block number 0)\n * @return block number as int\n */ \n function arbBlockNumber() external view returns (uint);\n}\n\n/// @title Multicall2 - Aggregate results from multiple read-only function calls\n/// @author Michael Elliot \n/// @author Joshua Levine \n/// @author Nick Johnson \n\ncontract Multicall2 {\n struct Call {\n address target;\n bytes callData;\n }\n struct Result {\n bool success;\n bytes returnData;\n }\n\n function aggregate(Call[] memory calls) public returns (uint256 blockNumber, bytes[] memory returnData) {\n blockNumber = ArbSys(address(100)).arbBlockNumber();\n returnData = new bytes[](calls.length);\n for(uint256 i = 0; i < calls.length; i++) {\n (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);\n require(success, \"Multicall aggregate: call failed\");\n returnData[i] = ret;\n }\n }\n function blockAndAggregate(Call[] memory calls) public returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {\n (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);\n }\n function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {\n blockHash = blockhash(blockNumber);\n }\n function getBlockNumber() public view returns (uint256 blockNumber) {\n blockNumber = ArbSys(address(100)).arbBlockNumber();\n }\n function getCurrentBlockCoinbase() public view returns (address coinbase) {\n coinbase = block.coinbase;\n }\n function getCurrentBlockDifficulty() public view returns (uint256 difficulty) {\n difficulty = block.difficulty;\n }\n function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {\n gaslimit = block.gaslimit;\n }\n function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {\n timestamp = block.timestamp;\n }\n function getEthBalance(address addr) public view returns (uint256 balance) {\n balance = addr.balance;\n }\n function getLastBlockHash() public view returns (bytes32 blockHash) {\n blockHash = blockhash(ArbSys(address(100)).arbBlockNumber() - 1);\n }\n function tryAggregate(bool requireSuccess, Call[] memory calls) public returns (Result[] memory returnData) {\n returnData = new Result[](calls.length);\n for(uint256 i = 0; i < calls.length; i++) {\n (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);\n\n if (requireSuccess) {\n require(success, \"Multicall2 aggregate: call failed\");\n }\n\n returnData[i] = Result(success, ret);\n }\n }\n function tryBlockAndAggregate(bool requireSuccess, Call[] memory calls) public returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {\n blockNumber = ArbSys(address(100)).arbBlockNumber();\n blockHash = blockhash(ArbSys(address(100)).arbBlockNumber());\n returnData = tryAggregate(requireSuccess, calls);\n }\n}" 6 | } 7 | }, 8 | "settings": { 9 | "optimizer": { 10 | "enabled": true, 11 | "runs": 200 12 | }, 13 | "outputSelection": { 14 | "*": { 15 | "*": [ 16 | "abi", 17 | "evm.bytecode", 18 | "evm.deployedBytecode", 19 | "evm.methodIdentifiers", 20 | "metadata", 21 | "devdoc", 22 | "userdoc", 23 | "storageLayout", 24 | "evm.gasEstimates" 25 | ], 26 | "": ["ast"] 27 | } 28 | }, 29 | "metadata": { 30 | "useLiteralContent": true 31 | }, 32 | "libraries": { 33 | "": { 34 | "__CACHE_BREAKER__": "0x00000000d41867734bbee4c6863d9255b2b06ac1" 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /deployments/fuse/solcInputs/f0d855948f39faa7f1111cd889006c3c.json: -------------------------------------------------------------------------------- 1 | { 2 | "language": "Solidity", 3 | "sources": { 4 | "contracts/Multicall2.sol": { 5 | "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @title Multicall2 - Aggregate results from multiple read-only function calls\n/// @author Michael Elliot \n/// @author Joshua Levine \n/// @author Nick Johnson \n\ncontract Multicall2 {\n struct Call {\n address target;\n bytes callData;\n }\n struct Result {\n bool success;\n bytes returnData;\n }\n\n function aggregate(Call[] memory calls)\n public\n returns (uint256 blockNumber, bytes[] memory returnData)\n {\n blockNumber = block.number;\n returnData = new bytes[](calls.length);\n for (uint256 i = 0; i < calls.length; i++) {\n (bool success, bytes memory ret) =\n calls[i].target.call(calls[i].callData);\n require(success, \"Multicall aggregate: call failed\");\n returnData[i] = ret;\n }\n }\n\n function blockAndAggregate(Call[] memory calls)\n public\n returns (\n uint256 blockNumber,\n bytes32 blockHash,\n Result[] memory returnData\n )\n {\n (blockNumber, blockHash, returnData) = tryBlockAndAggregate(\n true,\n calls\n );\n }\n\n function getBlockHash(uint256 blockNumber)\n public\n view\n returns (bytes32 blockHash)\n {\n blockHash = blockhash(blockNumber);\n }\n\n function getBlockNumber() public view returns (uint256 blockNumber) {\n blockNumber = block.number;\n }\n\n function getCurrentBlockCoinbase() public view returns (address coinbase) {\n coinbase = block.coinbase;\n }\n\n function getCurrentBlockDifficulty()\n public\n view\n returns (uint256 difficulty)\n {\n difficulty = block.difficulty;\n }\n\n function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {\n gaslimit = block.gaslimit;\n }\n\n function getCurrentBlockTimestamp()\n public\n view\n returns (uint256 timestamp)\n {\n timestamp = block.timestamp;\n }\n\n function getEthBalance(address addr) public view returns (uint256 balance) {\n balance = addr.balance;\n }\n\n function getLastBlockHash() public view returns (bytes32 blockHash) {\n blockHash = blockhash(block.number - 1);\n }\n\n function tryAggregate(bool requireSuccess, Call[] memory calls)\n public\n returns (Result[] memory returnData)\n {\n returnData = new Result[](calls.length);\n for (uint256 i = 0; i < calls.length; i++) {\n (bool success, bytes memory ret) =\n calls[i].target.call(calls[i].callData);\n\n if (requireSuccess) {\n require(success, \"Multicall2 aggregate: call failed\");\n }\n\n returnData[i] = Result(success, ret);\n }\n }\n\n function tryBlockAndAggregate(bool requireSuccess, Call[] memory calls)\n public\n returns (\n uint256 blockNumber,\n bytes32 blockHash,\n Result[] memory returnData\n )\n {\n blockNumber = block.number;\n blockHash = blockhash(block.number);\n returnData = tryAggregate(requireSuccess, calls);\n }\n}\n" 6 | } 7 | }, 8 | "settings": { 9 | "optimizer": { 10 | "enabled": true, 11 | "runs": 200 12 | }, 13 | "outputSelection": { 14 | "*": { 15 | "*": [ 16 | "abi", 17 | "evm.bytecode", 18 | "evm.deployedBytecode", 19 | "evm.methodIdentifiers", 20 | "metadata", 21 | "devdoc", 22 | "userdoc", 23 | "storageLayout", 24 | "evm.gasEstimates" 25 | ], 26 | "": ["ast"] 27 | } 28 | }, 29 | "metadata": { 30 | "useLiteralContent": true 31 | }, 32 | "libraries": { 33 | "": { 34 | "__CACHE_BREAKER__": "0x00000000d41867734bbee4c6863d9255b2b06ac1" 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /contracts/libraries/UniswapV2Library.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity >=0.5.0; 4 | 5 | import '../interfaces/IUniswapV2Pair.sol'; 6 | 7 | import "./SafeMath.sol"; 8 | 9 | library UniswapV2Library { 10 | using SafeMathUniswap for uint; 11 | 12 | // returns sorted token addresses, used to handle return values from pairs sorted in this order 13 | function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) { 14 | require(tokenA != tokenB, 'UniswapV2Library: IDENTICAL_ADDRESSES'); 15 | (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); 16 | require(token0 != address(0), 'UniswapV2Library: ZERO_ADDRESS'); 17 | } 18 | 19 | // calculates the CREATE2 address for a pair without making any external calls 20 | function pairFor(address factory, address tokenA, address tokenB) internal pure returns (address pair) { 21 | (address token0, address token1) = sortTokens(tokenA, tokenB); 22 | pair = address(uint(keccak256(abi.encodePacked( 23 | hex'ff', 24 | factory, 25 | keccak256(abi.encodePacked(token0, token1)), 26 | hex'e18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303' // init code hash 27 | )))); 28 | } 29 | 30 | // fetches and sorts the reserves for a pair 31 | function getReserves(address factory, address tokenA, address tokenB) internal view returns (uint reserveA, uint reserveB) { 32 | (address token0,) = sortTokens(tokenA, tokenB); 33 | (uint reserve0, uint reserve1,) = IUniswapV2Pair(pairFor(factory, tokenA, tokenB)).getReserves(); 34 | (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0); 35 | } 36 | 37 | // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset 38 | function quote(uint amountA, uint reserveA, uint reserveB) internal pure returns (uint amountB) { 39 | require(amountA > 0, 'UniswapV2Library: INSUFFICIENT_AMOUNT'); 40 | require(reserveA > 0 && reserveB > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY'); 41 | amountB = amountA.mul(reserveB) / reserveA; 42 | } 43 | 44 | // given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset 45 | function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) { 46 | require(amountIn > 0, 'UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT'); 47 | require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY'); 48 | uint amountInWithFee = amountIn.mul(997); 49 | uint numerator = amountInWithFee.mul(reserveOut); 50 | uint denominator = reserveIn.mul(1000).add(amountInWithFee); 51 | amountOut = numerator / denominator; 52 | } 53 | 54 | // given an output amount of an asset and pair reserves, returns a required input amount of the other asset 55 | function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) internal pure returns (uint amountIn) { 56 | require(amountOut > 0, 'UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT'); 57 | require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY'); 58 | uint numerator = reserveIn.mul(amountOut).mul(1000); 59 | uint denominator = reserveOut.sub(amountOut).mul(997); 60 | amountIn = (numerator / denominator).add(1); 61 | } 62 | 63 | // performs chained getAmountOut calculations on any number of pairs 64 | function getAmountsOut(address factory, uint amountIn, address[] memory path) internal view returns (uint[] memory amounts) { 65 | require(path.length >= 2, 'UniswapV2Library: INVALID_PATH'); 66 | amounts = new uint[](path.length); 67 | amounts[0] = amountIn; 68 | for (uint i; i < path.length - 1; i++) { 69 | (uint reserveIn, uint reserveOut) = getReserves(factory, path[i], path[i + 1]); 70 | amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut); 71 | } 72 | } 73 | 74 | // performs chained getAmountIn calculations on any number of pairs 75 | function getAmountsIn(address factory, uint amountOut, address[] memory path) internal view returns (uint[] memory amounts) { 76 | require(path.length >= 2, 'UniswapV2Library: INVALID_PATH'); 77 | amounts = new uint[](path.length); 78 | amounts[amounts.length - 1] = amountOut; 79 | for (uint i = path.length - 1; i > 0; i--) { 80 | (uint reserveIn, uint reserveOut) = getReserves(factory, path[i - 1], path[i]); 81 | amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /contracts/SushiRoll.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; 6 | import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol'; 7 | import './interfaces/IUniswapV2Pair.sol'; 8 | import './interfaces/IUniswapV2Router01.sol'; 9 | import './interfaces/IUniswapV2Factory.sol'; 10 | import './libraries/UniswapV2Library.sol'; 11 | 12 | // SushiRoll helps your migrate your existing Uniswap LP tokens to SushiSwap LP ones 13 | contract SushiRoll { 14 | using SafeERC20 for IERC20; 15 | 16 | IUniswapV2Router01 public oldRouter; 17 | IUniswapV2Router01 public router; 18 | 19 | constructor(IUniswapV2Router01 _oldRouter, IUniswapV2Router01 _router) public { 20 | oldRouter = _oldRouter; 21 | router = _router; 22 | } 23 | 24 | function migrateWithPermit( 25 | address tokenA, 26 | address tokenB, 27 | uint256 liquidity, 28 | uint256 amountADesired, 29 | uint256 amountBDesired, 30 | uint256 amountAMin, 31 | uint256 amountBMin, 32 | uint256 deadline, 33 | uint8 v, 34 | bytes32 r, 35 | bytes32 s 36 | ) public { 37 | IUniswapV2Pair pair = IUniswapV2Pair(pairForOldRouter(tokenA, tokenB)); 38 | pair.permit(msg.sender, address(this), liquidity, deadline, v, r, s); 39 | 40 | migrate(tokenA, tokenB, liquidity, amountADesired, amountBDesired, amountAMin, amountBMin, deadline); 41 | } 42 | 43 | // msg.sender should have approved 'liquidity' amount of LP token of 'tokenA' and 'tokenB' 44 | function migrate( 45 | address tokenA, 46 | address tokenB, 47 | uint256 liquidity, 48 | uint256 amountADesired, 49 | uint256 amountBDesired, 50 | uint256 amountAMin, 51 | uint256 amountBMin, 52 | uint256 deadline 53 | ) public { 54 | require(deadline >= block.timestamp, 'SushiSwap: EXPIRED'); 55 | 56 | // Remove liquidity from the old router with permit 57 | (uint256 amountA, uint256 amountB) = removeLiquidity(tokenA, tokenB, liquidity, amountAMin, amountBMin); 58 | 59 | // Add liquidity to the new router 60 | (uint256 pooledAmountA, uint256 pooledAmountB) = _addLiquidity( 61 | tokenA, 62 | tokenB, 63 | amountADesired, 64 | amountBDesired, 65 | amountAMin, 66 | amountBMin 67 | ); 68 | 69 | // Send remaining tokens to msg.sender 70 | if (amountA > pooledAmountA) { 71 | IERC20(tokenA).safeTransfer(msg.sender, amountA - pooledAmountA); 72 | } 73 | if (amountB > pooledAmountB) { 74 | IERC20(tokenB).safeTransfer(msg.sender, amountB - pooledAmountB); 75 | } 76 | } 77 | 78 | function removeLiquidity( 79 | address tokenA, 80 | address tokenB, 81 | uint256 liquidity, 82 | uint256 amountAMin, 83 | uint256 amountBMin 84 | ) internal returns (uint256 amountA, uint256 amountB) { 85 | IUniswapV2Pair pair = IUniswapV2Pair(pairForOldRouter(tokenA, tokenB)); 86 | pair.transferFrom(msg.sender, address(pair), liquidity); 87 | (uint256 amount0, uint256 amount1) = pair.burn(address(this)); 88 | (address token0, ) = UniswapV2Library.sortTokens(tokenA, tokenB); 89 | (amountA, amountB) = tokenA == token0 ? (amount0, amount1) : (amount1, amount0); 90 | require(amountA >= amountAMin, 'SushiRoll: INSUFFICIENT_A_AMOUNT'); 91 | require(amountB >= amountBMin, 'SushiRoll: INSUFFICIENT_B_AMOUNT'); 92 | } 93 | 94 | // calculates the CREATE2 address for a pair without making any external calls 95 | function pairForOldRouter(address tokenA, address tokenB) internal view returns (address pair) { 96 | (address token0, address token1) = UniswapV2Library.sortTokens(tokenA, tokenB); 97 | pair = address( 98 | uint256( 99 | keccak256( 100 | abi.encodePacked( 101 | hex'ff', 102 | oldRouter.factory(), 103 | keccak256(abi.encodePacked(token0, token1)), 104 | hex'96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f' // init code hash 105 | ) 106 | ) 107 | ) 108 | ); 109 | } 110 | 111 | function addLiquidity( 112 | address tokenA, 113 | address tokenB, 114 | uint256 amountADesired, 115 | uint256 amountBDesired, 116 | uint256 amountAMin, 117 | uint256 amountBMin, 118 | address to, 119 | uint256 deadline 120 | ) 121 | internal 122 | returns ( 123 | uint256 amountA, 124 | uint256 amountB, 125 | uint256 liquidity 126 | ) 127 | { 128 | require(deadline >= block.timestamp, 'SushiSwap: EXPIRED'); 129 | (amountA, amountB) = _addLiquidity(tokenA, tokenB, amountADesired, amountBDesired, amountAMin, amountBMin); 130 | address pair = UniswapV2Library.pairFor(router.factory(), tokenA, tokenB); 131 | IERC20(tokenA).safeTransferFrom(msg.sender, pair, amountA); 132 | IERC20(tokenB).safeTransferFrom(msg.sender, pair, amountB); 133 | liquidity = IUniswapV2Pair(pair).mint(to); 134 | } 135 | 136 | function _addLiquidity( 137 | address tokenA, 138 | address tokenB, 139 | uint256 amountADesired, 140 | uint256 amountBDesired, 141 | uint256 amountAMin, 142 | uint256 amountBMin 143 | ) internal returns (uint256 amountA, uint256 amountB) { 144 | // create the pair if it doesn't exist yet 145 | IUniswapV2Factory factory = IUniswapV2Factory(router.factory()); 146 | if (factory.getPair(tokenA, tokenB) == address(0)) { 147 | factory.createPair(tokenA, tokenB); 148 | } 149 | (uint256 reserveA, uint256 reserveB) = UniswapV2Library.getReserves(address(factory), tokenA, tokenB); 150 | if (reserveA == 0 && reserveB == 0) { 151 | (amountA, amountB) = (amountADesired, amountBDesired); 152 | } else { 153 | uint256 amountBOptimal = UniswapV2Library.quote(amountADesired, reserveA, reserveB); 154 | if (amountBOptimal <= amountBDesired) { 155 | require(amountBOptimal >= amountBMin, 'UniswapV2Router: INSUFFICIENT_B_AMOUNT'); 156 | (amountA, amountB) = (amountADesired, amountBOptimal); 157 | } else { 158 | uint256 amountAOptimal = UniswapV2Library.quote(amountBDesired, reserveB, reserveA); 159 | assert(amountAOptimal <= amountADesired); 160 | require(amountAOptimal >= amountAMin, 'UniswapV2Router: INSUFFICIENT_A_AMOUNT'); 161 | (amountA, amountB) = (amountAOptimal, amountBDesired); 162 | } 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /hardhat.config.ts: -------------------------------------------------------------------------------- 1 | import "dotenv/config"; 2 | import "@nomiclabs/hardhat-ethers"; 3 | import "@nomiclabs/hardhat-ethers"; 4 | import "hardhat-deploy"; 5 | 6 | const accounts = { 7 | mnemonic: 8 | process.env.MNEMONIC || 9 | "test test test test test test test test test test test junk", 10 | accountsBalance: "990000000000000000000", 11 | }; 12 | 13 | const config = { 14 | networks: { 15 | base: { 16 | url: "https://developer-access-mainnet.base.org", 17 | accounts, 18 | chainId: 8453, 19 | live: true, 20 | saveDeployments: true, 21 | }, 22 | celo: { 23 | url: 'https://forno.celo.org', 24 | accounts, 25 | chainId: 42220, 26 | live: true, 27 | saveDeployments: true, 28 | }, 29 | kava: { 30 | url: 'https://evm.kava.io', 31 | accounts, 32 | chainId: 2222, 33 | live: true, 34 | saveDeployments: true, 35 | }, 36 | metis: { 37 | url: 'https://andromeda.metis.io/?owner=1088', 38 | accounts, 39 | chainId: 1088, 40 | live: true, 41 | saveDeployments: true, 42 | }, 43 | linea: { 44 | url: 'https://rpc.linea.build', 45 | accounts, 46 | chainId: 59144, 47 | live: true, 48 | saveDeployments: true, 49 | }, 50 | optimism: { 51 | url: 'https://mainnet.optimism.io', 52 | accounts, 53 | chainId: 10, 54 | live: true, 55 | saveDeployments: true, 56 | }, 57 | bttc: { 58 | url: 'https://rpc.bittorrentchain.io', 59 | accounts, 60 | chainId: 199, 61 | live: true, 62 | saveDeployments: true, 63 | }, 64 | polygonzkevm: { 65 | url: 'https://zkevm-rpc.com', 66 | accounts, 67 | chainId: 1101, 68 | live: true, 69 | saveDeployments: true, 70 | }, 71 | thundercore: { 72 | url: 'https://mainnet-rpc.thundertoken.net', 73 | accounts, 74 | chainId: 108, 75 | live: true, 76 | saveDeployments: true, 77 | }, 78 | core: { 79 | url: 'https://rpc.coredao.org', 80 | accounts, 81 | chainId: 1116, 82 | live: true, 83 | saveDeployments: true, 84 | }, 85 | scroll: { 86 | url: 'https://rpc.scroll.io/', 87 | accounts, 88 | chainId: 534352, 89 | live: true, 90 | saveDeployments: true, 91 | }, 92 | filecoin: { 93 | url: 'https://api.node.glif.io/rpc/v1', 94 | accounts, 95 | chainId: 314, 96 | live: true, 97 | saveDeployments: true, 98 | }, 99 | haqq: { 100 | url: 'https://haqq-evm.publicnode.com ', 101 | accounts, 102 | chainId: 11235, 103 | live: true, 104 | saveDeployments: true, 105 | }, 106 | zetachain: { 107 | url: 'https://zetachain-evm.blockpi.network/v1/rpc/public', 108 | accounts, 109 | chainId: 7000, 110 | live: true, 111 | saveDeployments: true 112 | } 113 | }, 114 | namedAccounts: { 115 | // e.g. ledger://0x18dd4e0Eb8699eA4fee238dE41ecF115e32272F8 116 | deployer: process.env.LEDGER || { default: 0 }, 117 | alice: { 118 | default: 1, 119 | }, 120 | bob: { 121 | default: 2, 122 | }, 123 | carol: { 124 | default: 3, 125 | }, 126 | dev: { 127 | default: 4, 128 | }, 129 | feeTo: { 130 | default: 5, 131 | }, 132 | }, 133 | 134 | solidity: { 135 | compilers: [ 136 | { 137 | version: "0.6.12", 138 | settings: { 139 | optimizer: { 140 | enabled: true, 141 | runs: 200, 142 | }, 143 | }, 144 | }, 145 | ], 146 | }, 147 | 148 | etherscan: { 149 | customChains: [ 150 | { 151 | network: 'kava', 152 | chainId: 2222, 153 | urls: { 154 | apiURL: 'https://explorer.kava.io/api', 155 | browserURL: 'https://explorer.kava.io', 156 | }, 157 | }, 158 | { 159 | network: 'metis', 160 | chainId: 1088, 161 | urls: { 162 | apiURL: 'https://andromeda-explorer.metis.io/api', 163 | browserURL: 'https://andromeda-explorer.metis.io', 164 | }, 165 | }, 166 | { 167 | network: 'linea', 168 | chainId: 59144, 169 | urls: { 170 | apiURL: 'https://api.lineascan.build/api', 171 | browserURL: 'https://lineascan.build', 172 | }, 173 | }, 174 | { 175 | network: 'bttc', 176 | chainId: 199, 177 | urls: { 178 | apiURL: 'https://api.bttcscan.com/api', 179 | browserURL: 'https://bttcscan.com/', 180 | }, 181 | }, 182 | { 183 | network: 'polygonzkevm', 184 | chainId: 1101, 185 | urls: { 186 | apiURL: 'https://api-zkevm.polygonscan.com/api', 187 | browserURL: 'https://zkevm.polygonscan.com/', 188 | } 189 | }, 190 | { 191 | network: 'scroll', 192 | chainId: 534352, 193 | urls: { 194 | apiURL: 'https://api.scrollscan.com/api', 195 | browserURL: 'https://scrollscan.com/', 196 | } 197 | } 198 | ], 199 | apiKey: { 200 | mainnet: process.env.ETHERSCAN_API_KEY || '', 201 | ropsten: process.env.ETHERSCAN_API_KEY || '', 202 | rinkeby: process.env.ETHERSCAN_API_KEY || '', 203 | goerli: process.env.ETHERSCAN_API_KEY || '', 204 | kovan: process.env.ETHERSCAN_API_KEY || '', 205 | // binance smart chain 206 | bsc: process.env.BSCSCAN_API_KEY || '', 207 | bscTestnet: process.env.BSCSCAN_API_KEY || '', 208 | // huobi eco chain 209 | heco: process.env.HECOINFO_API_KEY || '', 210 | hecoTestnet: process.env.HECOINFO_API_KEY || '', 211 | // fantom mainnet 212 | opera: process.env.FTMSCAN_API_KEY || '', 213 | ftmTestnet: process.env.FTMSCAN_API_KEY || '', 214 | // optimism 215 | optimisticEthereum: process.env.OPTIMISTIC_ETHERSCAN_API_KEY || '', 216 | // optimisticKovan: process.env.OPTIMISTIC_ETHERSCAN_API_KEY || '', 217 | // polygon 218 | polygon: process.env.POLYGONSCAN_API_KEY || '', 219 | polygonMumbai: process.env.POLYGONSCAN_API_KEY || '', 220 | // arbitrum 221 | arbitrumOne: process.env.ARBISCAN_API_KEY || '', 222 | arbitrumTestnet: process.env.ARBISCAN_API_KEY || '', 223 | // avalanche 224 | avalanche: process.env.SNOWTRACE_API_KEY || '', 225 | avalancheFujiTestnet: process.env.SNOWTRACE_API_KEY || '', 226 | // moonbeam 227 | moonbeam: process.env.MOONBEAM_MOONSCAN_API_KEY || '', 228 | moonriver: process.env.MOONRIVER_MOONSCAN_API_KEY || '', 229 | moonbaseAlpha: process.env.MOONBASE_MOONSCAN_API_KEY || '', 230 | // harmony 231 | harmony: process.env.HARMONY_API_KEY || '', 232 | harmonyTest: process.env.HARMONY_API_KEY || '', 233 | // xdai and sokol don't need an API key, but you still need 234 | // to specify one; any string placeholder will work 235 | xdai: 'api-key', 236 | sokol: 'api-key', 237 | aurora: 'api-key', 238 | auroraTestnet: 'api-key', 239 | metis: 'api-key', 240 | kava: 'api-key', 241 | // bobaAvax: 'api-key', 242 | bttc: process.env.BTTC_API_KEY || '', 243 | gnosis: process.env.GNOSIS_API_KEY || '', 244 | linea: process.env.LINEA_API_KEY || '', 245 | polygonzkevm: process.env.POLYGON_ZKEVM_API_KEY || '', 246 | scroll: process.env.SCROLL_API_KEY || '' 247 | }, 248 | }, 249 | }; 250 | 251 | export default config; 252 | -------------------------------------------------------------------------------- /contracts/UniswapV2Pair.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity =0.6.12; 4 | 5 | import './UniswapV2ERC20.sol'; 6 | import './libraries/Math.sol'; 7 | import './libraries/UQ112x112.sol'; 8 | import './interfaces/IERC20.sol'; 9 | import './interfaces/IUniswapV2Factory.sol'; 10 | import './interfaces/IUniswapV2Callee.sol'; 11 | 12 | interface IMigrator { 13 | // Return the desired amount of liquidity token that the migrator wants. 14 | function desiredLiquidity() external view returns (uint256); 15 | } 16 | 17 | contract UniswapV2Pair is UniswapV2ERC20 { 18 | using SafeMathUniswap for uint; 19 | using UQ112x112 for uint224; 20 | 21 | uint public constant MINIMUM_LIQUIDITY = 10**3; 22 | bytes4 private constant SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)'))); 23 | 24 | address public factory; 25 | address public token0; 26 | address public token1; 27 | 28 | uint112 private reserve0; // uses single storage slot, accessible via getReserves 29 | uint112 private reserve1; // uses single storage slot, accessible via getReserves 30 | uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves 31 | 32 | uint public price0CumulativeLast; 33 | uint public price1CumulativeLast; 34 | uint public kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event 35 | 36 | uint private unlocked = 1; 37 | modifier lock() { 38 | require(unlocked == 1, 'UniswapV2: LOCKED'); 39 | unlocked = 0; 40 | _; 41 | unlocked = 1; 42 | } 43 | 44 | function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) { 45 | _reserve0 = reserve0; 46 | _reserve1 = reserve1; 47 | _blockTimestampLast = blockTimestampLast; 48 | } 49 | 50 | function _safeTransfer(address token, address to, uint value) private { 51 | (bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value)); 52 | require(success && (data.length == 0 || abi.decode(data, (bool))), 'UniswapV2: TRANSFER_FAILED'); 53 | } 54 | 55 | event Mint(address indexed sender, uint amount0, uint amount1); 56 | event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); 57 | event Swap( 58 | address indexed sender, 59 | uint amount0In, 60 | uint amount1In, 61 | uint amount0Out, 62 | uint amount1Out, 63 | address indexed to 64 | ); 65 | event Sync(uint112 reserve0, uint112 reserve1); 66 | 67 | constructor() public { 68 | factory = msg.sender; 69 | } 70 | 71 | // called once by the factory at time of deployment 72 | function initialize(address _token0, address _token1) external { 73 | require(msg.sender == factory, 'UniswapV2: FORBIDDEN'); // sufficient check 74 | token0 = _token0; 75 | token1 = _token1; 76 | } 77 | 78 | // update reserves and, on the first call per block, price accumulators 79 | function _update(uint balance0, uint balance1, uint112 _reserve0, uint112 _reserve1) private { 80 | require(balance0 <= uint112(-1) && balance1 <= uint112(-1), 'UniswapV2: OVERFLOW'); 81 | uint32 blockTimestamp = uint32(block.timestamp % 2**32); 82 | uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired 83 | if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) { 84 | // * never overflows, and + overflow is desired 85 | price0CumulativeLast += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed; 86 | price1CumulativeLast += uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed; 87 | } 88 | reserve0 = uint112(balance0); 89 | reserve1 = uint112(balance1); 90 | blockTimestampLast = blockTimestamp; 91 | emit Sync(reserve0, reserve1); 92 | } 93 | 94 | // if fee is on, mint liquidity equivalent to 1/6th of the growth in sqrt(k) 95 | function _mintFee(uint112 _reserve0, uint112 _reserve1) private returns (bool feeOn) { 96 | address feeTo = IUniswapV2Factory(factory).feeTo(); 97 | feeOn = feeTo != address(0); 98 | uint _kLast = kLast; // gas savings 99 | if (feeOn) { 100 | if (_kLast != 0) { 101 | uint rootK = Math.sqrt(uint(_reserve0).mul(_reserve1)); 102 | uint rootKLast = Math.sqrt(_kLast); 103 | if (rootK > rootKLast) { 104 | uint numerator = totalSupply.mul(rootK.sub(rootKLast)); 105 | uint denominator = rootK.mul(5).add(rootKLast); 106 | uint liquidity = numerator / denominator; 107 | if (liquidity > 0) _mint(feeTo, liquidity); 108 | } 109 | } 110 | } else if (_kLast != 0) { 111 | kLast = 0; 112 | } 113 | } 114 | 115 | // this low-level function should be called from a contract which performs important safety checks 116 | function mint(address to) external lock returns (uint liquidity) { 117 | (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings 118 | uint balance0 = IERC20Uniswap(token0).balanceOf(address(this)); 119 | uint balance1 = IERC20Uniswap(token1).balanceOf(address(this)); 120 | uint amount0 = balance0.sub(_reserve0); 121 | uint amount1 = balance1.sub(_reserve1); 122 | 123 | bool feeOn = _mintFee(_reserve0, _reserve1); 124 | uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee 125 | if (_totalSupply == 0) { 126 | address migrator = IUniswapV2Factory(factory).migrator(); 127 | if (msg.sender == migrator) { 128 | liquidity = IMigrator(migrator).desiredLiquidity(); 129 | require(liquidity > 0 && liquidity != uint256(-1), "Bad desired liquidity"); 130 | } else { 131 | require(migrator == address(0), "Must not have migrator"); 132 | liquidity = Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY); 133 | _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens 134 | } 135 | } else { 136 | liquidity = Math.min(amount0.mul(_totalSupply) / _reserve0, amount1.mul(_totalSupply) / _reserve1); 137 | } 138 | require(liquidity > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_MINTED'); 139 | _mint(to, liquidity); 140 | 141 | _update(balance0, balance1, _reserve0, _reserve1); 142 | if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date 143 | emit Mint(msg.sender, amount0, amount1); 144 | } 145 | 146 | // this low-level function should be called from a contract which performs important safety checks 147 | function burn(address to) external lock returns (uint amount0, uint amount1) { 148 | (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings 149 | address _token0 = token0; // gas savings 150 | address _token1 = token1; // gas savings 151 | uint balance0 = IERC20Uniswap(_token0).balanceOf(address(this)); 152 | uint balance1 = IERC20Uniswap(_token1).balanceOf(address(this)); 153 | uint liquidity = balanceOf[address(this)]; 154 | 155 | bool feeOn = _mintFee(_reserve0, _reserve1); 156 | uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee 157 | amount0 = liquidity.mul(balance0) / _totalSupply; // using balances ensures pro-rata distribution 158 | amount1 = liquidity.mul(balance1) / _totalSupply; // using balances ensures pro-rata distribution 159 | require(amount0 > 0 && amount1 > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_BURNED'); 160 | _burn(address(this), liquidity); 161 | _safeTransfer(_token0, to, amount0); 162 | _safeTransfer(_token1, to, amount1); 163 | balance0 = IERC20Uniswap(_token0).balanceOf(address(this)); 164 | balance1 = IERC20Uniswap(_token1).balanceOf(address(this)); 165 | 166 | _update(balance0, balance1, _reserve0, _reserve1); 167 | if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date 168 | emit Burn(msg.sender, amount0, amount1, to); 169 | } 170 | 171 | // this low-level function should be called from a contract which performs important safety checks 172 | function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock { 173 | require(amount0Out > 0 || amount1Out > 0, 'UniswapV2: INSUFFICIENT_OUTPUT_AMOUNT'); 174 | (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings 175 | require(amount0Out < _reserve0 && amount1Out < _reserve1, 'UniswapV2: INSUFFICIENT_LIQUIDITY'); 176 | 177 | uint balance0; 178 | uint balance1; 179 | { // scope for _token{0,1}, avoids stack too deep errors 180 | address _token0 = token0; 181 | address _token1 = token1; 182 | require(to != _token0 && to != _token1, 'UniswapV2: INVALID_TO'); 183 | if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens 184 | if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens 185 | if (data.length > 0) IUniswapV2Callee(to).uniswapV2Call(msg.sender, amount0Out, amount1Out, data); 186 | balance0 = IERC20Uniswap(_token0).balanceOf(address(this)); 187 | balance1 = IERC20Uniswap(_token1).balanceOf(address(this)); 188 | } 189 | uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0; 190 | uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0; 191 | require(amount0In > 0 || amount1In > 0, 'UniswapV2: INSUFFICIENT_INPUT_AMOUNT'); 192 | { // scope for reserve{0,1}Adjusted, avoids stack too deep errors 193 | uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3)); 194 | uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3)); 195 | require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(1000**2), 'UniswapV2: K'); 196 | } 197 | 198 | _update(balance0, balance1, _reserve0, _reserve1); 199 | emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to); 200 | } 201 | 202 | // force balances to match reserves 203 | function skim(address to) external lock { 204 | address _token0 = token0; // gas savings 205 | address _token1 = token1; // gas savings 206 | _safeTransfer(_token0, to, IERC20Uniswap(_token0).balanceOf(address(this)).sub(reserve0)); 207 | _safeTransfer(_token1, to, IERC20Uniswap(_token1).balanceOf(address(this)).sub(reserve1)); 208 | } 209 | 210 | // force reserves to match balances 211 | function sync() external lock { 212 | _update(IERC20Uniswap(token0).balanceOf(address(this)), IERC20Uniswap(token1).balanceOf(address(this)), reserve0, reserve1); 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /contracts/UniswapV2Router02.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity =0.6.12; 4 | 5 | import './libraries/UniswapV2Library.sol'; 6 | import './libraries/SafeMath.sol'; 7 | import './libraries/TransferHelper.sol'; 8 | import './interfaces/IUniswapV2Router02.sol'; 9 | import './interfaces/IUniswapV2Factory.sol'; 10 | import './interfaces/IERC20.sol'; 11 | import './interfaces/IWETH.sol'; 12 | 13 | contract UniswapV2Router02 is IUniswapV2Router02 { 14 | using SafeMathUniswap for uint; 15 | 16 | address public immutable override factory; 17 | address public immutable override WETH; 18 | 19 | modifier ensure(uint deadline) { 20 | require(deadline >= block.timestamp, 'UniswapV2Router: EXPIRED'); 21 | _; 22 | } 23 | 24 | constructor(address _factory, address _WETH) public { 25 | factory = _factory; 26 | WETH = _WETH; 27 | } 28 | 29 | receive() external payable { 30 | assert(msg.sender == WETH); // only accept ETH via fallback from the WETH contract 31 | } 32 | 33 | // **** ADD LIQUIDITY **** 34 | function _addLiquidity( 35 | address tokenA, 36 | address tokenB, 37 | uint amountADesired, 38 | uint amountBDesired, 39 | uint amountAMin, 40 | uint amountBMin 41 | ) internal virtual returns (uint amountA, uint amountB) { 42 | // create the pair if it doesn't exist yet 43 | if (IUniswapV2Factory(factory).getPair(tokenA, tokenB) == address(0)) { 44 | IUniswapV2Factory(factory).createPair(tokenA, tokenB); 45 | } 46 | (uint reserveA, uint reserveB) = UniswapV2Library.getReserves(factory, tokenA, tokenB); 47 | if (reserveA == 0 && reserveB == 0) { 48 | (amountA, amountB) = (amountADesired, amountBDesired); 49 | } else { 50 | uint amountBOptimal = UniswapV2Library.quote(amountADesired, reserveA, reserveB); 51 | if (amountBOptimal <= amountBDesired) { 52 | require(amountBOptimal >= amountBMin, 'UniswapV2Router: INSUFFICIENT_B_AMOUNT'); 53 | (amountA, amountB) = (amountADesired, amountBOptimal); 54 | } else { 55 | uint amountAOptimal = UniswapV2Library.quote(amountBDesired, reserveB, reserveA); 56 | assert(amountAOptimal <= amountADesired); 57 | require(amountAOptimal >= amountAMin, 'UniswapV2Router: INSUFFICIENT_A_AMOUNT'); 58 | (amountA, amountB) = (amountAOptimal, amountBDesired); 59 | } 60 | } 61 | } 62 | function addLiquidity( 63 | address tokenA, 64 | address tokenB, 65 | uint amountADesired, 66 | uint amountBDesired, 67 | uint amountAMin, 68 | uint amountBMin, 69 | address to, 70 | uint deadline 71 | ) external virtual override ensure(deadline) returns (uint amountA, uint amountB, uint liquidity) { 72 | (amountA, amountB) = _addLiquidity(tokenA, tokenB, amountADesired, amountBDesired, amountAMin, amountBMin); 73 | address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB); 74 | TransferHelper.safeTransferFrom(tokenA, msg.sender, pair, amountA); 75 | TransferHelper.safeTransferFrom(tokenB, msg.sender, pair, amountB); 76 | liquidity = IUniswapV2Pair(pair).mint(to); 77 | } 78 | function addLiquidityETH( 79 | address token, 80 | uint amountTokenDesired, 81 | uint amountTokenMin, 82 | uint amountETHMin, 83 | address to, 84 | uint deadline 85 | ) external virtual override payable ensure(deadline) returns (uint amountToken, uint amountETH, uint liquidity) { 86 | (amountToken, amountETH) = _addLiquidity( 87 | token, 88 | WETH, 89 | amountTokenDesired, 90 | msg.value, 91 | amountTokenMin, 92 | amountETHMin 93 | ); 94 | address pair = UniswapV2Library.pairFor(factory, token, WETH); 95 | TransferHelper.safeTransferFrom(token, msg.sender, pair, amountToken); 96 | IWETH(WETH).deposit{value: amountETH}(); 97 | assert(IWETH(WETH).transfer(pair, amountETH)); 98 | liquidity = IUniswapV2Pair(pair).mint(to); 99 | // refund dust eth, if any 100 | if (msg.value > amountETH) TransferHelper.safeTransferETH(msg.sender, msg.value - amountETH); 101 | } 102 | 103 | // **** REMOVE LIQUIDITY **** 104 | function removeLiquidity( 105 | address tokenA, 106 | address tokenB, 107 | uint liquidity, 108 | uint amountAMin, 109 | uint amountBMin, 110 | address to, 111 | uint deadline 112 | ) public virtual override ensure(deadline) returns (uint amountA, uint amountB) { 113 | address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB); 114 | IUniswapV2Pair(pair).transferFrom(msg.sender, pair, liquidity); // send liquidity to pair 115 | (uint amount0, uint amount1) = IUniswapV2Pair(pair).burn(to); 116 | (address token0,) = UniswapV2Library.sortTokens(tokenA, tokenB); 117 | (amountA, amountB) = tokenA == token0 ? (amount0, amount1) : (amount1, amount0); 118 | require(amountA >= amountAMin, 'UniswapV2Router: INSUFFICIENT_A_AMOUNT'); 119 | require(amountB >= amountBMin, 'UniswapV2Router: INSUFFICIENT_B_AMOUNT'); 120 | } 121 | function removeLiquidityETH( 122 | address token, 123 | uint liquidity, 124 | uint amountTokenMin, 125 | uint amountETHMin, 126 | address to, 127 | uint deadline 128 | ) public virtual override ensure(deadline) returns (uint amountToken, uint amountETH) { 129 | (amountToken, amountETH) = removeLiquidity( 130 | token, 131 | WETH, 132 | liquidity, 133 | amountTokenMin, 134 | amountETHMin, 135 | address(this), 136 | deadline 137 | ); 138 | TransferHelper.safeTransfer(token, to, amountToken); 139 | IWETH(WETH).withdraw(amountETH); 140 | TransferHelper.safeTransferETH(to, amountETH); 141 | } 142 | function removeLiquidityWithPermit( 143 | address tokenA, 144 | address tokenB, 145 | uint liquidity, 146 | uint amountAMin, 147 | uint amountBMin, 148 | address to, 149 | uint deadline, 150 | bool approveMax, uint8 v, bytes32 r, bytes32 s 151 | ) external virtual override returns (uint amountA, uint amountB) { 152 | address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB); 153 | uint value = approveMax ? uint(-1) : liquidity; 154 | IUniswapV2Pair(pair).permit(msg.sender, address(this), value, deadline, v, r, s); 155 | (amountA, amountB) = removeLiquidity(tokenA, tokenB, liquidity, amountAMin, amountBMin, to, deadline); 156 | } 157 | function removeLiquidityETHWithPermit( 158 | address token, 159 | uint liquidity, 160 | uint amountTokenMin, 161 | uint amountETHMin, 162 | address to, 163 | uint deadline, 164 | bool approveMax, uint8 v, bytes32 r, bytes32 s 165 | ) external virtual override returns (uint amountToken, uint amountETH) { 166 | address pair = UniswapV2Library.pairFor(factory, token, WETH); 167 | uint value = approveMax ? uint(-1) : liquidity; 168 | IUniswapV2Pair(pair).permit(msg.sender, address(this), value, deadline, v, r, s); 169 | (amountToken, amountETH) = removeLiquidityETH(token, liquidity, amountTokenMin, amountETHMin, to, deadline); 170 | } 171 | 172 | // **** REMOVE LIQUIDITY (supporting fee-on-transfer tokens) **** 173 | function removeLiquidityETHSupportingFeeOnTransferTokens( 174 | address token, 175 | uint liquidity, 176 | uint amountTokenMin, 177 | uint amountETHMin, 178 | address to, 179 | uint deadline 180 | ) public virtual override ensure(deadline) returns (uint amountETH) { 181 | (, amountETH) = removeLiquidity( 182 | token, 183 | WETH, 184 | liquidity, 185 | amountTokenMin, 186 | amountETHMin, 187 | address(this), 188 | deadline 189 | ); 190 | TransferHelper.safeTransfer(token, to, IERC20Uniswap(token).balanceOf(address(this))); 191 | IWETH(WETH).withdraw(amountETH); 192 | TransferHelper.safeTransferETH(to, amountETH); 193 | } 194 | function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( 195 | address token, 196 | uint liquidity, 197 | uint amountTokenMin, 198 | uint amountETHMin, 199 | address to, 200 | uint deadline, 201 | bool approveMax, uint8 v, bytes32 r, bytes32 s 202 | ) external virtual override returns (uint amountETH) { 203 | address pair = UniswapV2Library.pairFor(factory, token, WETH); 204 | uint value = approveMax ? uint(-1) : liquidity; 205 | IUniswapV2Pair(pair).permit(msg.sender, address(this), value, deadline, v, r, s); 206 | amountETH = removeLiquidityETHSupportingFeeOnTransferTokens( 207 | token, liquidity, amountTokenMin, amountETHMin, to, deadline 208 | ); 209 | } 210 | 211 | // **** SWAP **** 212 | // requires the initial amount to have already been sent to the first pair 213 | function _swap(uint[] memory amounts, address[] memory path, address _to) internal virtual { 214 | for (uint i; i < path.length - 1; i++) { 215 | (address input, address output) = (path[i], path[i + 1]); 216 | (address token0,) = UniswapV2Library.sortTokens(input, output); 217 | uint amountOut = amounts[i + 1]; 218 | (uint amount0Out, uint amount1Out) = input == token0 ? (uint(0), amountOut) : (amountOut, uint(0)); 219 | address to = i < path.length - 2 ? UniswapV2Library.pairFor(factory, output, path[i + 2]) : _to; 220 | IUniswapV2Pair(UniswapV2Library.pairFor(factory, input, output)).swap( 221 | amount0Out, amount1Out, to, new bytes(0) 222 | ); 223 | } 224 | } 225 | function swapExactTokensForTokens( 226 | uint amountIn, 227 | uint amountOutMin, 228 | address[] calldata path, 229 | address to, 230 | uint deadline 231 | ) external virtual override ensure(deadline) returns (uint[] memory amounts) { 232 | amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path); 233 | require(amounts[amounts.length - 1] >= amountOutMin, 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT'); 234 | TransferHelper.safeTransferFrom( 235 | path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0] 236 | ); 237 | _swap(amounts, path, to); 238 | } 239 | function swapTokensForExactTokens( 240 | uint amountOut, 241 | uint amountInMax, 242 | address[] calldata path, 243 | address to, 244 | uint deadline 245 | ) external virtual override ensure(deadline) returns (uint[] memory amounts) { 246 | amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path); 247 | require(amounts[0] <= amountInMax, 'UniswapV2Router: EXCESSIVE_INPUT_AMOUNT'); 248 | TransferHelper.safeTransferFrom( 249 | path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0] 250 | ); 251 | _swap(amounts, path, to); 252 | } 253 | function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) 254 | external 255 | virtual 256 | override 257 | payable 258 | ensure(deadline) 259 | returns (uint[] memory amounts) 260 | { 261 | require(path[0] == WETH, 'UniswapV2Router: INVALID_PATH'); 262 | amounts = UniswapV2Library.getAmountsOut(factory, msg.value, path); 263 | require(amounts[amounts.length - 1] >= amountOutMin, 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT'); 264 | IWETH(WETH).deposit{value: amounts[0]}(); 265 | assert(IWETH(WETH).transfer(UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0])); 266 | _swap(amounts, path, to); 267 | } 268 | function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) 269 | external 270 | virtual 271 | override 272 | ensure(deadline) 273 | returns (uint[] memory amounts) 274 | { 275 | require(path[path.length - 1] == WETH, 'UniswapV2Router: INVALID_PATH'); 276 | amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path); 277 | require(amounts[0] <= amountInMax, 'UniswapV2Router: EXCESSIVE_INPUT_AMOUNT'); 278 | TransferHelper.safeTransferFrom( 279 | path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0] 280 | ); 281 | _swap(amounts, path, address(this)); 282 | IWETH(WETH).withdraw(amounts[amounts.length - 1]); 283 | TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]); 284 | } 285 | function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) 286 | external 287 | virtual 288 | override 289 | ensure(deadline) 290 | returns (uint[] memory amounts) 291 | { 292 | require(path[path.length - 1] == WETH, 'UniswapV2Router: INVALID_PATH'); 293 | amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path); 294 | require(amounts[amounts.length - 1] >= amountOutMin, 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT'); 295 | TransferHelper.safeTransferFrom( 296 | path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0] 297 | ); 298 | _swap(amounts, path, address(this)); 299 | IWETH(WETH).withdraw(amounts[amounts.length - 1]); 300 | TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]); 301 | } 302 | function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) 303 | external 304 | virtual 305 | override 306 | payable 307 | ensure(deadline) 308 | returns (uint[] memory amounts) 309 | { 310 | require(path[0] == WETH, 'UniswapV2Router: INVALID_PATH'); 311 | amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path); 312 | require(amounts[0] <= msg.value, 'UniswapV2Router: EXCESSIVE_INPUT_AMOUNT'); 313 | IWETH(WETH).deposit{value: amounts[0]}(); 314 | assert(IWETH(WETH).transfer(UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0])); 315 | _swap(amounts, path, to); 316 | // refund dust eth, if any 317 | if (msg.value > amounts[0]) TransferHelper.safeTransferETH(msg.sender, msg.value - amounts[0]); 318 | } 319 | 320 | // **** SWAP (supporting fee-on-transfer tokens) **** 321 | // requires the initial amount to have already been sent to the first pair 322 | function _swapSupportingFeeOnTransferTokens(address[] memory path, address _to) internal virtual { 323 | for (uint i; i < path.length - 1; i++) { 324 | (address input, address output) = (path[i], path[i + 1]); 325 | (address token0,) = UniswapV2Library.sortTokens(input, output); 326 | IUniswapV2Pair pair = IUniswapV2Pair(UniswapV2Library.pairFor(factory, input, output)); 327 | uint amountInput; 328 | uint amountOutput; 329 | { // scope to avoid stack too deep errors 330 | (uint reserve0, uint reserve1,) = pair.getReserves(); 331 | (uint reserveInput, uint reserveOutput) = input == token0 ? (reserve0, reserve1) : (reserve1, reserve0); 332 | amountInput = IERC20Uniswap(input).balanceOf(address(pair)).sub(reserveInput); 333 | amountOutput = UniswapV2Library.getAmountOut(amountInput, reserveInput, reserveOutput); 334 | } 335 | (uint amount0Out, uint amount1Out) = input == token0 ? (uint(0), amountOutput) : (amountOutput, uint(0)); 336 | address to = i < path.length - 2 ? UniswapV2Library.pairFor(factory, output, path[i + 2]) : _to; 337 | pair.swap(amount0Out, amount1Out, to, new bytes(0)); 338 | } 339 | } 340 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 341 | uint amountIn, 342 | uint amountOutMin, 343 | address[] calldata path, 344 | address to, 345 | uint deadline 346 | ) external virtual override ensure(deadline) { 347 | TransferHelper.safeTransferFrom( 348 | path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amountIn 349 | ); 350 | uint balanceBefore = IERC20Uniswap(path[path.length - 1]).balanceOf(to); 351 | _swapSupportingFeeOnTransferTokens(path, to); 352 | require( 353 | IERC20Uniswap(path[path.length - 1]).balanceOf(to).sub(balanceBefore) >= amountOutMin, 354 | 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT' 355 | ); 356 | } 357 | function swapExactETHForTokensSupportingFeeOnTransferTokens( 358 | uint amountOutMin, 359 | address[] calldata path, 360 | address to, 361 | uint deadline 362 | ) 363 | external 364 | virtual 365 | override 366 | payable 367 | ensure(deadline) 368 | { 369 | require(path[0] == WETH, 'UniswapV2Router: INVALID_PATH'); 370 | uint amountIn = msg.value; 371 | IWETH(WETH).deposit{value: amountIn}(); 372 | assert(IWETH(WETH).transfer(UniswapV2Library.pairFor(factory, path[0], path[1]), amountIn)); 373 | uint balanceBefore = IERC20Uniswap(path[path.length - 1]).balanceOf(to); 374 | _swapSupportingFeeOnTransferTokens(path, to); 375 | require( 376 | IERC20Uniswap(path[path.length - 1]).balanceOf(to).sub(balanceBefore) >= amountOutMin, 377 | 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT' 378 | ); 379 | } 380 | function swapExactTokensForETHSupportingFeeOnTransferTokens( 381 | uint amountIn, 382 | uint amountOutMin, 383 | address[] calldata path, 384 | address to, 385 | uint deadline 386 | ) 387 | external 388 | virtual 389 | override 390 | ensure(deadline) 391 | { 392 | require(path[path.length - 1] == WETH, 'UniswapV2Router: INVALID_PATH'); 393 | TransferHelper.safeTransferFrom( 394 | path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amountIn 395 | ); 396 | _swapSupportingFeeOnTransferTokens(path, address(this)); 397 | uint amountOut = IERC20Uniswap(WETH).balanceOf(address(this)); 398 | require(amountOut >= amountOutMin, 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT'); 399 | IWETH(WETH).withdraw(amountOut); 400 | TransferHelper.safeTransferETH(to, amountOut); 401 | } 402 | 403 | // **** LIBRARY FUNCTIONS **** 404 | function quote(uint amountA, uint reserveA, uint reserveB) public pure virtual override returns (uint amountB) { 405 | return UniswapV2Library.quote(amountA, reserveA, reserveB); 406 | } 407 | 408 | function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) 409 | public 410 | pure 411 | virtual 412 | override 413 | returns (uint amountOut) 414 | { 415 | return UniswapV2Library.getAmountOut(amountIn, reserveIn, reserveOut); 416 | } 417 | 418 | function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) 419 | public 420 | pure 421 | virtual 422 | override 423 | returns (uint amountIn) 424 | { 425 | return UniswapV2Library.getAmountIn(amountOut, reserveIn, reserveOut); 426 | } 427 | 428 | function getAmountsOut(uint amountIn, address[] memory path) 429 | public 430 | view 431 | virtual 432 | override 433 | returns (uint[] memory amounts) 434 | { 435 | return UniswapV2Library.getAmountsOut(factory, amountIn, path); 436 | } 437 | 438 | function getAmountsIn(uint amountOut, address[] memory path) 439 | public 440 | view 441 | virtual 442 | override 443 | returns (uint[] memory amounts) 444 | { 445 | return UniswapV2Library.getAmountsIn(factory, amountOut, path); 446 | } 447 | } 448 | -------------------------------------------------------------------------------- /contracts/UniswapV2Router02Celo.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity =0.6.12; 4 | 5 | import "./libraries/UniswapV2Library.sol"; 6 | import "./libraries/SafeMath.sol"; 7 | import "./libraries/TransferHelper.sol"; 8 | import "./interfaces/IUniswapV2Router02.sol"; 9 | import "./interfaces/IUniswapV2Factory.sol"; 10 | import "./interfaces/IERC20.sol"; 11 | import "./interfaces/IWETH.sol"; 12 | 13 | contract UniswapV2Router02Celo is IUniswapV2Router02 { 14 | using SafeMathUniswap for uint256; 15 | 16 | address public immutable override factory; 17 | address public immutable override WETH; 18 | 19 | modifier ensure(uint256 deadline) { 20 | require(deadline >= block.timestamp, "UniswapV2Router: EXPIRED"); 21 | _; 22 | } 23 | 24 | constructor(address _factory, address _WETH) public { 25 | factory = _factory; 26 | WETH = _WETH; 27 | } 28 | 29 | receive() external payable { 30 | assert(msg.sender == WETH); // only accept ETH via fallback from the WETH contract 31 | } 32 | 33 | // **** ADD LIQUIDITY **** 34 | function _addLiquidity( 35 | address tokenA, 36 | address tokenB, 37 | uint256 amountADesired, 38 | uint256 amountBDesired, 39 | uint256 amountAMin, 40 | uint256 amountBMin 41 | ) internal virtual returns (uint256 amountA, uint256 amountB) { 42 | // create the pair if it doesn't exist yet 43 | if (IUniswapV2Factory(factory).getPair(tokenA, tokenB) == address(0)) { 44 | IUniswapV2Factory(factory).createPair(tokenA, tokenB); 45 | } 46 | (uint256 reserveA, uint256 reserveB) = UniswapV2Library.getReserves( 47 | factory, 48 | tokenA, 49 | tokenB 50 | ); 51 | if (reserveA == 0 && reserveB == 0) { 52 | (amountA, amountB) = (amountADesired, amountBDesired); 53 | } else { 54 | uint256 amountBOptimal = UniswapV2Library.quote( 55 | amountADesired, 56 | reserveA, 57 | reserveB 58 | ); 59 | if (amountBOptimal <= amountBDesired) { 60 | require( 61 | amountBOptimal >= amountBMin, 62 | "UniswapV2Router: INSUFFICIENT_B_AMOUNT" 63 | ); 64 | (amountA, amountB) = (amountADesired, amountBOptimal); 65 | } else { 66 | uint256 amountAOptimal = UniswapV2Library.quote( 67 | amountBDesired, 68 | reserveB, 69 | reserveA 70 | ); 71 | assert(amountAOptimal <= amountADesired); 72 | require( 73 | amountAOptimal >= amountAMin, 74 | "UniswapV2Router: INSUFFICIENT_A_AMOUNT" 75 | ); 76 | (amountA, amountB) = (amountAOptimal, amountBDesired); 77 | } 78 | } 79 | } 80 | 81 | function addLiquidity( 82 | address tokenA, 83 | address tokenB, 84 | uint256 amountADesired, 85 | uint256 amountBDesired, 86 | uint256 amountAMin, 87 | uint256 amountBMin, 88 | address to, 89 | uint256 deadline 90 | ) 91 | external 92 | virtual 93 | override 94 | ensure(deadline) 95 | returns (uint256 amountA, uint256 amountB, uint256 liquidity) 96 | { 97 | (amountA, amountB) = _addLiquidity( 98 | tokenA, 99 | tokenB, 100 | amountADesired, 101 | amountBDesired, 102 | amountAMin, 103 | amountBMin 104 | ); 105 | address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB); 106 | TransferHelper.safeTransferFrom(tokenA, msg.sender, pair, amountA); 107 | TransferHelper.safeTransferFrom(tokenB, msg.sender, pair, amountB); 108 | liquidity = IUniswapV2Pair(pair).mint(to); 109 | } 110 | 111 | function addLiquidityETH( 112 | address token, 113 | uint256 amountTokenDesired, 114 | uint256 amountTokenMin, 115 | uint256 amountETHMin, 116 | address to, 117 | uint256 deadline 118 | ) 119 | external 120 | payable 121 | virtual 122 | override 123 | ensure(deadline) 124 | returns (uint256 amountToken, uint256 amountETH, uint256 liquidity) 125 | { 126 | (amountToken, amountETH) = _addLiquidity( 127 | token, 128 | WETH, 129 | amountTokenDesired, 130 | msg.value, 131 | amountTokenMin, 132 | amountETHMin 133 | ); 134 | address pair = UniswapV2Library.pairFor(factory, token, WETH); 135 | TransferHelper.safeTransferFrom(token, msg.sender, pair, amountToken); 136 | TransferHelper.safeTransfer(WETH, pair, amountETH); 137 | liquidity = IUniswapV2Pair(pair).mint(to); 138 | // refund dust eth, if any 139 | if (msg.value > amountETH) 140 | TransferHelper.safeTransferETH(msg.sender, msg.value - amountETH); 141 | } 142 | 143 | // **** REMOVE LIQUIDITY **** 144 | function removeLiquidity( 145 | address tokenA, 146 | address tokenB, 147 | uint256 liquidity, 148 | uint256 amountAMin, 149 | uint256 amountBMin, 150 | address to, 151 | uint256 deadline 152 | ) 153 | public 154 | virtual 155 | override 156 | ensure(deadline) 157 | returns (uint256 amountA, uint256 amountB) 158 | { 159 | address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB); 160 | IUniswapV2Pair(pair).transferFrom(msg.sender, pair, liquidity); // send liquidity to pair 161 | (uint256 amount0, uint256 amount1) = IUniswapV2Pair(pair).burn(to); 162 | (address token0, ) = UniswapV2Library.sortTokens(tokenA, tokenB); 163 | (amountA, amountB) = tokenA == token0 164 | ? (amount0, amount1) 165 | : (amount1, amount0); 166 | require( 167 | amountA >= amountAMin, 168 | "UniswapV2Router: INSUFFICIENT_A_AMOUNT" 169 | ); 170 | require( 171 | amountB >= amountBMin, 172 | "UniswapV2Router: INSUFFICIENT_B_AMOUNT" 173 | ); 174 | } 175 | 176 | function removeLiquidityETH( 177 | address token, 178 | uint256 liquidity, 179 | uint256 amountTokenMin, 180 | uint256 amountETHMin, 181 | address to, 182 | uint256 deadline 183 | ) 184 | public 185 | virtual 186 | override 187 | ensure(deadline) 188 | returns (uint256 amountToken, uint256 amountETH) 189 | { 190 | (amountToken, amountETH) = removeLiquidity( 191 | token, 192 | WETH, 193 | liquidity, 194 | amountTokenMin, 195 | amountETHMin, 196 | address(this), 197 | deadline 198 | ); 199 | TransferHelper.safeTransfer(token, to, amountToken); 200 | TransferHelper.safeTransfer(WETH, to, amountETH); 201 | } 202 | 203 | function removeLiquidityWithPermit( 204 | address tokenA, 205 | address tokenB, 206 | uint256 liquidity, 207 | uint256 amountAMin, 208 | uint256 amountBMin, 209 | address to, 210 | uint256 deadline, 211 | bool approveMax, 212 | uint8 v, 213 | bytes32 r, 214 | bytes32 s 215 | ) external virtual override returns (uint256 amountA, uint256 amountB) { 216 | address pair = UniswapV2Library.pairFor(factory, tokenA, tokenB); 217 | uint256 value = approveMax ? uint256(-1) : liquidity; 218 | IUniswapV2Pair(pair).permit( 219 | msg.sender, 220 | address(this), 221 | value, 222 | deadline, 223 | v, 224 | r, 225 | s 226 | ); 227 | (amountA, amountB) = removeLiquidity( 228 | tokenA, 229 | tokenB, 230 | liquidity, 231 | amountAMin, 232 | amountBMin, 233 | to, 234 | deadline 235 | ); 236 | } 237 | 238 | function removeLiquidityETHWithPermit( 239 | address token, 240 | uint256 liquidity, 241 | uint256 amountTokenMin, 242 | uint256 amountETHMin, 243 | address to, 244 | uint256 deadline, 245 | bool approveMax, 246 | uint8 v, 247 | bytes32 r, 248 | bytes32 s 249 | ) 250 | external 251 | virtual 252 | override 253 | returns (uint256 amountToken, uint256 amountETH) 254 | { 255 | address pair = UniswapV2Library.pairFor(factory, token, WETH); 256 | uint256 value = approveMax ? uint256(-1) : liquidity; 257 | IUniswapV2Pair(pair).permit( 258 | msg.sender, 259 | address(this), 260 | value, 261 | deadline, 262 | v, 263 | r, 264 | s 265 | ); 266 | (amountToken, amountETH) = removeLiquidityETH( 267 | token, 268 | liquidity, 269 | amountTokenMin, 270 | amountETHMin, 271 | to, 272 | deadline 273 | ); 274 | } 275 | 276 | // **** REMOVE LIQUIDITY (supporting fee-on-transfer tokens) **** 277 | function removeLiquidityETHSupportingFeeOnTransferTokens( 278 | address token, 279 | uint256 liquidity, 280 | uint256 amountTokenMin, 281 | uint256 amountETHMin, 282 | address to, 283 | uint256 deadline 284 | ) public virtual override ensure(deadline) returns (uint256 amountETH) { 285 | (, amountETH) = removeLiquidity( 286 | token, 287 | WETH, 288 | liquidity, 289 | amountTokenMin, 290 | amountETHMin, 291 | address(this), 292 | deadline 293 | ); 294 | TransferHelper.safeTransfer( 295 | token, 296 | to, 297 | IERC20Uniswap(token).balanceOf(address(this)) 298 | ); 299 | TransferHelper.safeTransfer(WETH, to, amountETH); 300 | } 301 | 302 | function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( 303 | address token, 304 | uint256 liquidity, 305 | uint256 amountTokenMin, 306 | uint256 amountETHMin, 307 | address to, 308 | uint256 deadline, 309 | bool approveMax, 310 | uint8 v, 311 | bytes32 r, 312 | bytes32 s 313 | ) external virtual override returns (uint256 amountETH) { 314 | address pair = UniswapV2Library.pairFor(factory, token, WETH); 315 | uint256 value = approveMax ? uint256(-1) : liquidity; 316 | IUniswapV2Pair(pair).permit( 317 | msg.sender, 318 | address(this), 319 | value, 320 | deadline, 321 | v, 322 | r, 323 | s 324 | ); 325 | amountETH = removeLiquidityETHSupportingFeeOnTransferTokens( 326 | token, 327 | liquidity, 328 | amountTokenMin, 329 | amountETHMin, 330 | to, 331 | deadline 332 | ); 333 | } 334 | 335 | // **** SWAP **** 336 | // requires the initial amount to have already been sent to the first pair 337 | function _swap( 338 | uint256[] memory amounts, 339 | address[] memory path, 340 | address _to 341 | ) internal virtual { 342 | for (uint256 i; i < path.length - 1; i++) { 343 | (address input, address output) = (path[i], path[i + 1]); 344 | (address token0, ) = UniswapV2Library.sortTokens(input, output); 345 | uint256 amountOut = amounts[i + 1]; 346 | (uint256 amount0Out, uint256 amount1Out) = input == token0 347 | ? (uint256(0), amountOut) 348 | : (amountOut, uint256(0)); 349 | address to = i < path.length - 2 350 | ? UniswapV2Library.pairFor(factory, output, path[i + 2]) 351 | : _to; 352 | IUniswapV2Pair(UniswapV2Library.pairFor(factory, input, output)) 353 | .swap(amount0Out, amount1Out, to, new bytes(0)); 354 | } 355 | } 356 | 357 | function swapExactTokensForTokens( 358 | uint256 amountIn, 359 | uint256 amountOutMin, 360 | address[] calldata path, 361 | address to, 362 | uint256 deadline 363 | ) 364 | external 365 | virtual 366 | override 367 | ensure(deadline) 368 | returns (uint256[] memory amounts) 369 | { 370 | amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path); 371 | require( 372 | amounts[amounts.length - 1] >= amountOutMin, 373 | "UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT" 374 | ); 375 | TransferHelper.safeTransferFrom( 376 | path[0], 377 | msg.sender, 378 | UniswapV2Library.pairFor(factory, path[0], path[1]), 379 | amounts[0] 380 | ); 381 | _swap(amounts, path, to); 382 | } 383 | 384 | function swapTokensForExactTokens( 385 | uint256 amountOut, 386 | uint256 amountInMax, 387 | address[] calldata path, 388 | address to, 389 | uint256 deadline 390 | ) 391 | external 392 | virtual 393 | override 394 | ensure(deadline) 395 | returns (uint256[] memory amounts) 396 | { 397 | amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path); 398 | require( 399 | amounts[0] <= amountInMax, 400 | "UniswapV2Router: EXCESSIVE_INPUT_AMOUNT" 401 | ); 402 | TransferHelper.safeTransferFrom( 403 | path[0], 404 | msg.sender, 405 | UniswapV2Library.pairFor(factory, path[0], path[1]), 406 | amounts[0] 407 | ); 408 | _swap(amounts, path, to); 409 | } 410 | 411 | function swapExactETHForTokens( 412 | uint256 amountOutMin, 413 | address[] calldata path, 414 | address to, 415 | uint256 deadline 416 | ) 417 | external 418 | payable 419 | virtual 420 | override 421 | ensure(deadline) 422 | returns (uint256[] memory amounts) 423 | { 424 | require(path[0] == WETH, "UniswapV2Router: INVALID_PATH"); 425 | amounts = UniswapV2Library.getAmountsOut(factory, msg.value, path); 426 | require( 427 | amounts[amounts.length - 1] >= amountOutMin, 428 | "UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT" 429 | ); 430 | TransferHelper.safeTransfer( 431 | WETH, 432 | UniswapV2Library.pairFor(factory, path[0], path[1]), 433 | amounts[0] 434 | ); 435 | _swap(amounts, path, to); 436 | } 437 | 438 | function swapTokensForExactETH( 439 | uint256 amountOut, 440 | uint256 amountInMax, 441 | address[] calldata path, 442 | address to, 443 | uint256 deadline 444 | ) 445 | external 446 | virtual 447 | override 448 | ensure(deadline) 449 | returns (uint256[] memory amounts) 450 | { 451 | require(path[path.length - 1] == WETH, "UniswapV2Router: INVALID_PATH"); 452 | amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path); 453 | require( 454 | amounts[0] <= amountInMax, 455 | "UniswapV2Router: EXCESSIVE_INPUT_AMOUNT" 456 | ); 457 | TransferHelper.safeTransferFrom( 458 | path[0], 459 | msg.sender, 460 | UniswapV2Library.pairFor(factory, path[0], path[1]), 461 | amounts[0] 462 | ); 463 | _swap(amounts, path, address(this)); 464 | TransferHelper.safeTransfer(WETH, to, amounts[amounts.length - 1]); 465 | } 466 | 467 | function swapExactTokensForETH( 468 | uint256 amountIn, 469 | uint256 amountOutMin, 470 | address[] calldata path, 471 | address to, 472 | uint256 deadline 473 | ) 474 | external 475 | virtual 476 | override 477 | ensure(deadline) 478 | returns (uint256[] memory amounts) 479 | { 480 | require(path[path.length - 1] == WETH, "UniswapV2Router: INVALID_PATH"); 481 | amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path); 482 | require( 483 | amounts[amounts.length - 1] >= amountOutMin, 484 | "UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT" 485 | ); 486 | TransferHelper.safeTransferFrom( 487 | path[0], 488 | msg.sender, 489 | UniswapV2Library.pairFor(factory, path[0], path[1]), 490 | amounts[0] 491 | ); 492 | _swap(amounts, path, address(this)); 493 | TransferHelper.safeTransfer(WETH, to, amounts[amounts.length - 1]); 494 | } 495 | 496 | function swapETHForExactTokens( 497 | uint256 amountOut, 498 | address[] calldata path, 499 | address to, 500 | uint256 deadline 501 | ) 502 | external 503 | payable 504 | virtual 505 | override 506 | ensure(deadline) 507 | returns (uint256[] memory amounts) 508 | { 509 | require(path[0] == WETH, "UniswapV2Router: INVALID_PATH"); 510 | amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path); 511 | require( 512 | amounts[0] <= msg.value, 513 | "UniswapV2Router: EXCESSIVE_INPUT_AMOUNT" 514 | ); 515 | TransferHelper.safeTransfer( 516 | WETH, 517 | UniswapV2Library.pairFor(factory, path[0], path[1]), 518 | amounts[0] 519 | ); 520 | _swap(amounts, path, to); 521 | // refund dust eth, if any 522 | if (msg.value > amounts[0]) 523 | TransferHelper.safeTransferETH(msg.sender, msg.value - amounts[0]); 524 | } 525 | 526 | // **** SWAP (supporting fee-on-transfer tokens) **** 527 | // requires the initial amount to have already been sent to the first pair 528 | function _swapSupportingFeeOnTransferTokens( 529 | address[] memory path, 530 | address _to 531 | ) internal virtual { 532 | for (uint256 i; i < path.length - 1; i++) { 533 | (address input, address output) = (path[i], path[i + 1]); 534 | (address token0, ) = UniswapV2Library.sortTokens(input, output); 535 | IUniswapV2Pair pair = IUniswapV2Pair( 536 | UniswapV2Library.pairFor(factory, input, output) 537 | ); 538 | uint256 amountInput; 539 | uint256 amountOutput; 540 | { 541 | // scope to avoid stack too deep errors 542 | (uint256 reserve0, uint256 reserve1, ) = pair.getReserves(); 543 | (uint256 reserveInput, uint256 reserveOutput) = input == token0 544 | ? (reserve0, reserve1) 545 | : (reserve1, reserve0); 546 | amountInput = IERC20Uniswap(input).balanceOf(address(pair)).sub( 547 | reserveInput 548 | ); 549 | amountOutput = UniswapV2Library.getAmountOut( 550 | amountInput, 551 | reserveInput, 552 | reserveOutput 553 | ); 554 | } 555 | (uint256 amount0Out, uint256 amount1Out) = input == token0 556 | ? (uint256(0), amountOutput) 557 | : (amountOutput, uint256(0)); 558 | address to = i < path.length - 2 559 | ? UniswapV2Library.pairFor(factory, output, path[i + 2]) 560 | : _to; 561 | pair.swap(amount0Out, amount1Out, to, new bytes(0)); 562 | } 563 | } 564 | 565 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 566 | uint256 amountIn, 567 | uint256 amountOutMin, 568 | address[] calldata path, 569 | address to, 570 | uint256 deadline 571 | ) external virtual override ensure(deadline) { 572 | TransferHelper.safeTransferFrom( 573 | path[0], 574 | msg.sender, 575 | UniswapV2Library.pairFor(factory, path[0], path[1]), 576 | amountIn 577 | ); 578 | uint256 balanceBefore = IERC20Uniswap(path[path.length - 1]).balanceOf( 579 | to 580 | ); 581 | _swapSupportingFeeOnTransferTokens(path, to); 582 | require( 583 | IERC20Uniswap(path[path.length - 1]).balanceOf(to).sub( 584 | balanceBefore 585 | ) >= amountOutMin, 586 | "UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT" 587 | ); 588 | } 589 | 590 | function swapExactETHForTokensSupportingFeeOnTransferTokens( 591 | uint256 amountOutMin, 592 | address[] calldata path, 593 | address to, 594 | uint256 deadline 595 | ) external payable virtual override ensure(deadline) { 596 | require(path[0] == WETH, "UniswapV2Router: INVALID_PATH"); 597 | uint256 amountIn = msg.value; 598 | TransferHelper.safeTransfer( 599 | WETH, 600 | UniswapV2Library.pairFor(factory, path[0], path[1]), 601 | amountIn 602 | ); 603 | 604 | uint256 balanceBefore = IERC20Uniswap(path[path.length - 1]).balanceOf( 605 | to 606 | ); 607 | _swapSupportingFeeOnTransferTokens(path, to); 608 | require( 609 | IERC20Uniswap(path[path.length - 1]).balanceOf(to).sub( 610 | balanceBefore 611 | ) >= amountOutMin, 612 | "UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT" 613 | ); 614 | } 615 | 616 | function swapExactTokensForETHSupportingFeeOnTransferTokens( 617 | uint256 amountIn, 618 | uint256 amountOutMin, 619 | address[] calldata path, 620 | address to, 621 | uint256 deadline 622 | ) external virtual override ensure(deadline) { 623 | require(path[path.length - 1] == WETH, "UniswapV2Router: INVALID_PATH"); 624 | TransferHelper.safeTransferFrom( 625 | path[0], 626 | msg.sender, 627 | UniswapV2Library.pairFor(factory, path[0], path[1]), 628 | amountIn 629 | ); 630 | _swapSupportingFeeOnTransferTokens(path, address(this)); 631 | uint256 amountOut = IERC20Uniswap(WETH).balanceOf(address(this)); 632 | require( 633 | amountOut >= amountOutMin, 634 | "UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT" 635 | ); 636 | TransferHelper.safeTransfer(WETH, to, amountOut); 637 | } 638 | 639 | // **** LIBRARY FUNCTIONS **** 640 | function quote( 641 | uint256 amountA, 642 | uint256 reserveA, 643 | uint256 reserveB 644 | ) public pure virtual override returns (uint256 amountB) { 645 | return UniswapV2Library.quote(amountA, reserveA, reserveB); 646 | } 647 | 648 | function getAmountOut( 649 | uint256 amountIn, 650 | uint256 reserveIn, 651 | uint256 reserveOut 652 | ) public pure virtual override returns (uint256 amountOut) { 653 | return UniswapV2Library.getAmountOut(amountIn, reserveIn, reserveOut); 654 | } 655 | 656 | function getAmountIn( 657 | uint256 amountOut, 658 | uint256 reserveIn, 659 | uint256 reserveOut 660 | ) public pure virtual override returns (uint256 amountIn) { 661 | return UniswapV2Library.getAmountIn(amountOut, reserveIn, reserveOut); 662 | } 663 | 664 | function getAmountsOut( 665 | uint256 amountIn, 666 | address[] memory path 667 | ) public view virtual override returns (uint256[] memory amounts) { 668 | return UniswapV2Library.getAmountsOut(factory, amountIn, path); 669 | } 670 | 671 | function getAmountsIn( 672 | uint256 amountOut, 673 | address[] memory path 674 | ) public view virtual override returns (uint256[] memory amounts) { 675 | return UniswapV2Library.getAmountsIn(factory, amountOut, path); 676 | } 677 | } 678 | -------------------------------------------------------------------------------- /deployments/localhost/WETH9.json: -------------------------------------------------------------------------------- 1 | { 2 | "address": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512", 3 | "abi": [ 4 | { 5 | "anonymous": false, 6 | "inputs": [ 7 | { 8 | "indexed": true, 9 | "internalType": "address", 10 | "name": "src", 11 | "type": "address" 12 | }, 13 | { 14 | "indexed": true, 15 | "internalType": "address", 16 | "name": "guy", 17 | "type": "address" 18 | }, 19 | { 20 | "indexed": false, 21 | "internalType": "uint256", 22 | "name": "wad", 23 | "type": "uint256" 24 | } 25 | ], 26 | "name": "Approval", 27 | "type": "event" 28 | }, 29 | { 30 | "anonymous": false, 31 | "inputs": [ 32 | { 33 | "indexed": true, 34 | "internalType": "address", 35 | "name": "dst", 36 | "type": "address" 37 | }, 38 | { 39 | "indexed": false, 40 | "internalType": "uint256", 41 | "name": "wad", 42 | "type": "uint256" 43 | } 44 | ], 45 | "name": "Deposit", 46 | "type": "event" 47 | }, 48 | { 49 | "anonymous": false, 50 | "inputs": [ 51 | { 52 | "indexed": true, 53 | "internalType": "address", 54 | "name": "src", 55 | "type": "address" 56 | }, 57 | { 58 | "indexed": true, 59 | "internalType": "address", 60 | "name": "dst", 61 | "type": "address" 62 | }, 63 | { 64 | "indexed": false, 65 | "internalType": "uint256", 66 | "name": "wad", 67 | "type": "uint256" 68 | } 69 | ], 70 | "name": "Transfer", 71 | "type": "event" 72 | }, 73 | { 74 | "anonymous": false, 75 | "inputs": [ 76 | { 77 | "indexed": true, 78 | "internalType": "address", 79 | "name": "src", 80 | "type": "address" 81 | }, 82 | { 83 | "indexed": false, 84 | "internalType": "uint256", 85 | "name": "wad", 86 | "type": "uint256" 87 | } 88 | ], 89 | "name": "Withdrawal", 90 | "type": "event" 91 | }, 92 | { 93 | "inputs": [ 94 | { 95 | "internalType": "address", 96 | "name": "", 97 | "type": "address" 98 | }, 99 | { 100 | "internalType": "address", 101 | "name": "", 102 | "type": "address" 103 | } 104 | ], 105 | "name": "allowance", 106 | "outputs": [ 107 | { 108 | "internalType": "uint256", 109 | "name": "", 110 | "type": "uint256" 111 | } 112 | ], 113 | "stateMutability": "view", 114 | "type": "function" 115 | }, 116 | { 117 | "inputs": [ 118 | { 119 | "internalType": "address", 120 | "name": "guy", 121 | "type": "address" 122 | }, 123 | { 124 | "internalType": "uint256", 125 | "name": "wad", 126 | "type": "uint256" 127 | } 128 | ], 129 | "name": "approve", 130 | "outputs": [ 131 | { 132 | "internalType": "bool", 133 | "name": "", 134 | "type": "bool" 135 | } 136 | ], 137 | "stateMutability": "nonpayable", 138 | "type": "function" 139 | }, 140 | { 141 | "inputs": [ 142 | { 143 | "internalType": "address", 144 | "name": "", 145 | "type": "address" 146 | } 147 | ], 148 | "name": "balanceOf", 149 | "outputs": [ 150 | { 151 | "internalType": "uint256", 152 | "name": "", 153 | "type": "uint256" 154 | } 155 | ], 156 | "stateMutability": "view", 157 | "type": "function" 158 | }, 159 | { 160 | "inputs": [], 161 | "name": "decimals", 162 | "outputs": [ 163 | { 164 | "internalType": "uint8", 165 | "name": "", 166 | "type": "uint8" 167 | } 168 | ], 169 | "stateMutability": "view", 170 | "type": "function" 171 | }, 172 | { 173 | "inputs": [], 174 | "name": "deposit", 175 | "outputs": [], 176 | "stateMutability": "payable", 177 | "type": "function" 178 | }, 179 | { 180 | "inputs": [], 181 | "name": "name", 182 | "outputs": [ 183 | { 184 | "internalType": "string", 185 | "name": "", 186 | "type": "string" 187 | } 188 | ], 189 | "stateMutability": "view", 190 | "type": "function" 191 | }, 192 | { 193 | "inputs": [], 194 | "name": "symbol", 195 | "outputs": [ 196 | { 197 | "internalType": "string", 198 | "name": "", 199 | "type": "string" 200 | } 201 | ], 202 | "stateMutability": "view", 203 | "type": "function" 204 | }, 205 | { 206 | "inputs": [], 207 | "name": "totalSupply", 208 | "outputs": [ 209 | { 210 | "internalType": "uint256", 211 | "name": "", 212 | "type": "uint256" 213 | } 214 | ], 215 | "stateMutability": "view", 216 | "type": "function" 217 | }, 218 | { 219 | "inputs": [ 220 | { 221 | "internalType": "address", 222 | "name": "dst", 223 | "type": "address" 224 | }, 225 | { 226 | "internalType": "uint256", 227 | "name": "wad", 228 | "type": "uint256" 229 | } 230 | ], 231 | "name": "transfer", 232 | "outputs": [ 233 | { 234 | "internalType": "bool", 235 | "name": "", 236 | "type": "bool" 237 | } 238 | ], 239 | "stateMutability": "nonpayable", 240 | "type": "function" 241 | }, 242 | { 243 | "inputs": [ 244 | { 245 | "internalType": "address", 246 | "name": "src", 247 | "type": "address" 248 | }, 249 | { 250 | "internalType": "address", 251 | "name": "dst", 252 | "type": "address" 253 | }, 254 | { 255 | "internalType": "uint256", 256 | "name": "wad", 257 | "type": "uint256" 258 | } 259 | ], 260 | "name": "transferFrom", 261 | "outputs": [ 262 | { 263 | "internalType": "bool", 264 | "name": "", 265 | "type": "bool" 266 | } 267 | ], 268 | "stateMutability": "nonpayable", 269 | "type": "function" 270 | }, 271 | { 272 | "inputs": [ 273 | { 274 | "internalType": "uint256", 275 | "name": "wad", 276 | "type": "uint256" 277 | } 278 | ], 279 | "name": "withdraw", 280 | "outputs": [], 281 | "stateMutability": "nonpayable", 282 | "type": "function" 283 | } 284 | ], 285 | "transactionHash": "0xb80ddd41e101f4518d07f59355ea4174cb11cb44da65fa86f252ce39e03bb8b7", 286 | "receipt": { 287 | "to": null, 288 | "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", 289 | "contractAddress": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512", 290 | "transactionIndex": 0, 291 | "gasUsed": "541812", 292 | "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 293 | "blockHash": "0x7fb45a9bf353ba3a690da922deb7289aea31672c956d6499b3f9773e4e12c1da", 294 | "transactionHash": "0xb80ddd41e101f4518d07f59355ea4174cb11cb44da65fa86f252ce39e03bb8b7", 295 | "logs": [], 296 | "blockNumber": 2, 297 | "cumulativeGasUsed": "541812", 298 | "status": 1, 299 | "byzantium": true 300 | }, 301 | "args": [], 302 | "numDeployments": 1, 303 | "solcInputHash": "07facc9fad1266fbe84e2dac07a80c89", 304 | "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"guy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Withdrawal\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"guy\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/mocks/WETH9.sol\":\"WETH9\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/mocks/WETH9.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-only\\npragma solidity 0.6.12;\\n\\ncontract WETH9 {\\n string public name = \\\"Wrapped Ether\\\";\\n string public symbol = \\\"WETH\\\";\\n uint8 public decimals = 18;\\n\\n event Approval(address indexed src, address indexed guy, uint256 wad);\\n event Transfer(address indexed src, address indexed dst, uint256 wad);\\n event Deposit(address indexed dst, uint256 wad);\\n event Withdrawal(address indexed src, uint256 wad);\\n\\n mapping(address => uint256) public balanceOf;\\n mapping(address => mapping(address => uint256)) public allowance;\\n\\n /*fallback () external payable {\\n deposit();\\n }*/\\n function deposit() public payable {\\n balanceOf[msg.sender] += msg.value;\\n emit Deposit(msg.sender, msg.value);\\n }\\n\\n function withdraw(uint256 wad) public {\\n require(balanceOf[msg.sender] >= wad, \\\"WETH9: Error\\\");\\n balanceOf[msg.sender] -= wad;\\n msg.sender.transfer(wad);\\n emit Withdrawal(msg.sender, wad);\\n }\\n\\n function totalSupply() public view returns (uint256) {\\n return address(this).balance;\\n }\\n\\n function approve(address guy, uint256 wad) public returns (bool) {\\n allowance[msg.sender][guy] = wad;\\n emit Approval(msg.sender, guy, wad);\\n return true;\\n }\\n\\n function transfer(address dst, uint256 wad) public returns (bool) {\\n return transferFrom(msg.sender, dst, wad);\\n }\\n\\n function transferFrom(\\n address src,\\n address dst,\\n uint256 wad\\n ) public returns (bool) {\\n require(balanceOf[src] >= wad, \\\"WETH9: Error\\\");\\n\\n if (src != msg.sender && allowance[src][msg.sender] != uint256(-1)) {\\n require(allowance[src][msg.sender] >= wad, \\\"WETH9: Error\\\");\\n allowance[src][msg.sender] -= wad;\\n }\\n\\n balanceOf[src] -= wad;\\n balanceOf[dst] += wad;\\n\\n emit Transfer(src, dst, wad);\\n\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x9240d3110f11cc79963de281d12ddb76b51cab3bb4ecbebc41a564ed0ff441db\",\"license\":\"GPL-3.0-only\"}},\"version\":1}", 305 | "bytecode": "0x60c0604052600d60808190526c2bb930b83832b21022ba3432b960991b60a090815261002e916000919061007a565b50604080518082019091526004808252630ae8aa8960e31b602090920191825261005a9160019161007a565b506002805460ff1916601217905534801561007457600080fd5b5061010d565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100bb57805160ff19168380011785556100e8565b828001600101855582156100e8579182015b828111156100e85782518255916020019190600101906100cd565b506100f49291506100f8565b5090565b5b808211156100f457600081556001016100f9565b61078e8061011c6000396000f3fe60806040526004361061009c5760003560e01c8063313ce56711610064578063313ce5671461020e57806370a082311461023957806395d89b411461026c578063a9059cbb14610281578063d0e30db0146102ba578063dd62ed3e146102c25761009c565b806306fdde03146100a1578063095ea7b31461012b57806318160ddd1461017857806323b872dd1461019f5780632e1a7d4d146101e2575b600080fd5b3480156100ad57600080fd5b506100b66102fd565b6040805160208082528351818301528351919283929083019185019080838360005b838110156100f05781810151838201526020016100d8565b50505050905090810190601f16801561011d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561013757600080fd5b506101646004803603604081101561014e57600080fd5b506001600160a01b03813516906020013561038b565b604080519115158252519081900360200190f35b34801561018457600080fd5b5061018d6103f1565b60408051918252519081900360200190f35b3480156101ab57600080fd5b50610164600480360360608110156101c257600080fd5b506001600160a01b038135811691602081013590911690604001356103f5565b3480156101ee57600080fd5b5061020c6004803603602081101561020557600080fd5b5035610597565b005b34801561021a57600080fd5b50610223610663565b6040805160ff9092168252519081900360200190f35b34801561024557600080fd5b5061018d6004803603602081101561025c57600080fd5b50356001600160a01b031661066c565b34801561027857600080fd5b506100b661067e565b34801561028d57600080fd5b50610164600480360360408110156102a457600080fd5b506001600160a01b0381351690602001356106d8565b61020c6106ec565b3480156102ce57600080fd5b5061018d600480360360408110156102e557600080fd5b506001600160a01b038135811691602001351661073b565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103835780601f1061035857610100808354040283529160200191610383565b820191906000526020600020905b81548152906001019060200180831161036657829003601f168201915b505050505081565b3360008181526004602090815260408083206001600160a01b038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b4790565b6001600160a01b038316600090815260036020526040812054821115610451576040805162461bcd60e51b815260206004820152600c60248201526b2ba2aa241c9d1022b93937b960a11b604482015290519081900360640190fd5b6001600160a01b038416331480159061048f57506001600160a01b038416600090815260046020908152604080832033845290915290205460001914155b15610526576001600160a01b03841660009081526004602090815260408083203384529091529020548211156104fb576040805162461bcd60e51b815260206004820152600c60248201526b2ba2aa241c9d1022b93937b960a11b604482015290519081900360640190fd5b6001600160a01b03841660009081526004602090815260408083203384529091529020805483900390555b6001600160a01b03808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b336000908152600360205260409020548111156105ea576040805162461bcd60e51b815260206004820152600c60248201526b2ba2aa241c9d1022b93937b960a11b604482015290519081900360640190fd5b33600081815260036020526040808220805485900390555183156108fc0291849190818181858888f19350505050158015610629573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103835780601f1061035857610100808354040283529160200191610383565b60006106e53384846103f5565b9392505050565b33600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b60046020908152600092835260408084209091529082529020548156fea26469706673582212205dcf80b078c329fbf12ff5a9adda74ca2d6bb8d3688bc129c225e0336cdcc1b064736f6c634300060c0033", 306 | "deployedBytecode": "0x60806040526004361061009c5760003560e01c8063313ce56711610064578063313ce5671461020e57806370a082311461023957806395d89b411461026c578063a9059cbb14610281578063d0e30db0146102ba578063dd62ed3e146102c25761009c565b806306fdde03146100a1578063095ea7b31461012b57806318160ddd1461017857806323b872dd1461019f5780632e1a7d4d146101e2575b600080fd5b3480156100ad57600080fd5b506100b66102fd565b6040805160208082528351818301528351919283929083019185019080838360005b838110156100f05781810151838201526020016100d8565b50505050905090810190601f16801561011d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561013757600080fd5b506101646004803603604081101561014e57600080fd5b506001600160a01b03813516906020013561038b565b604080519115158252519081900360200190f35b34801561018457600080fd5b5061018d6103f1565b60408051918252519081900360200190f35b3480156101ab57600080fd5b50610164600480360360608110156101c257600080fd5b506001600160a01b038135811691602081013590911690604001356103f5565b3480156101ee57600080fd5b5061020c6004803603602081101561020557600080fd5b5035610597565b005b34801561021a57600080fd5b50610223610663565b6040805160ff9092168252519081900360200190f35b34801561024557600080fd5b5061018d6004803603602081101561025c57600080fd5b50356001600160a01b031661066c565b34801561027857600080fd5b506100b661067e565b34801561028d57600080fd5b50610164600480360360408110156102a457600080fd5b506001600160a01b0381351690602001356106d8565b61020c6106ec565b3480156102ce57600080fd5b5061018d600480360360408110156102e557600080fd5b506001600160a01b038135811691602001351661073b565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103835780601f1061035857610100808354040283529160200191610383565b820191906000526020600020905b81548152906001019060200180831161036657829003601f168201915b505050505081565b3360008181526004602090815260408083206001600160a01b038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b4790565b6001600160a01b038316600090815260036020526040812054821115610451576040805162461bcd60e51b815260206004820152600c60248201526b2ba2aa241c9d1022b93937b960a11b604482015290519081900360640190fd5b6001600160a01b038416331480159061048f57506001600160a01b038416600090815260046020908152604080832033845290915290205460001914155b15610526576001600160a01b03841660009081526004602090815260408083203384529091529020548211156104fb576040805162461bcd60e51b815260206004820152600c60248201526b2ba2aa241c9d1022b93937b960a11b604482015290519081900360640190fd5b6001600160a01b03841660009081526004602090815260408083203384529091529020805483900390555b6001600160a01b03808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b336000908152600360205260409020548111156105ea576040805162461bcd60e51b815260206004820152600c60248201526b2ba2aa241c9d1022b93937b960a11b604482015290519081900360640190fd5b33600081815260036020526040808220805485900390555183156108fc0291849190818181858888f19350505050158015610629573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103835780601f1061035857610100808354040283529160200191610383565b60006106e53384846103f5565b9392505050565b33600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b60046020908152600092835260408084209091529082529020548156fea26469706673582212205dcf80b078c329fbf12ff5a9adda74ca2d6bb8d3688bc129c225e0336cdcc1b064736f6c634300060c0033", 307 | "devdoc": { 308 | "kind": "dev", 309 | "methods": {}, 310 | "version": 1 311 | }, 312 | "userdoc": { 313 | "kind": "user", 314 | "methods": {}, 315 | "version": 1 316 | }, 317 | "storageLayout": { 318 | "storage": [ 319 | { 320 | "astId": 4, 321 | "contract": "contracts/mocks/WETH9.sol:WETH9", 322 | "label": "name", 323 | "offset": 0, 324 | "slot": "0", 325 | "type": "t_string_storage" 326 | }, 327 | { 328 | "astId": 7, 329 | "contract": "contracts/mocks/WETH9.sol:WETH9", 330 | "label": "symbol", 331 | "offset": 0, 332 | "slot": "1", 333 | "type": "t_string_storage" 334 | }, 335 | { 336 | "astId": 10, 337 | "contract": "contracts/mocks/WETH9.sol:WETH9", 338 | "label": "decimals", 339 | "offset": 0, 340 | "slot": "2", 341 | "type": "t_uint8" 342 | }, 343 | { 344 | "astId": 42, 345 | "contract": "contracts/mocks/WETH9.sol:WETH9", 346 | "label": "balanceOf", 347 | "offset": 0, 348 | "slot": "3", 349 | "type": "t_mapping(t_address,t_uint256)" 350 | }, 351 | { 352 | "astId": 48, 353 | "contract": "contracts/mocks/WETH9.sol:WETH9", 354 | "label": "allowance", 355 | "offset": 0, 356 | "slot": "4", 357 | "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" 358 | } 359 | ], 360 | "types": { 361 | "t_address": { 362 | "encoding": "inplace", 363 | "label": "address", 364 | "numberOfBytes": "20" 365 | }, 366 | "t_mapping(t_address,t_mapping(t_address,t_uint256))": { 367 | "encoding": "mapping", 368 | "key": "t_address", 369 | "label": "mapping(address => mapping(address => uint256))", 370 | "numberOfBytes": "32", 371 | "value": "t_mapping(t_address,t_uint256)" 372 | }, 373 | "t_mapping(t_address,t_uint256)": { 374 | "encoding": "mapping", 375 | "key": "t_address", 376 | "label": "mapping(address => uint256)", 377 | "numberOfBytes": "32", 378 | "value": "t_uint256" 379 | }, 380 | "t_string_storage": { 381 | "encoding": "bytes", 382 | "label": "string", 383 | "numberOfBytes": "32" 384 | }, 385 | "t_uint256": { 386 | "encoding": "inplace", 387 | "label": "uint256", 388 | "numberOfBytes": "32" 389 | }, 390 | "t_uint8": { 391 | "encoding": "inplace", 392 | "label": "uint8", 393 | "numberOfBytes": "1" 394 | } 395 | } 396 | } 397 | } 398 | -------------------------------------------------------------------------------- /deployments/celo/UniswapV2Router02.json: -------------------------------------------------------------------------------- 1 | { 2 | "address": "0x1421bDe4B10e8dd459b3BCb598810B1337D56842", 3 | "abi": [ 4 | { 5 | "inputs": [ 6 | { 7 | "internalType": "address", 8 | "name": "_factory", 9 | "type": "address" 10 | }, 11 | { 12 | "internalType": "address", 13 | "name": "_WETH", 14 | "type": "address" 15 | } 16 | ], 17 | "stateMutability": "nonpayable", 18 | "type": "constructor" 19 | }, 20 | { 21 | "inputs": [], 22 | "name": "WETH", 23 | "outputs": [ 24 | { 25 | "internalType": "address", 26 | "name": "", 27 | "type": "address" 28 | } 29 | ], 30 | "stateMutability": "view", 31 | "type": "function" 32 | }, 33 | { 34 | "inputs": [ 35 | { 36 | "internalType": "address", 37 | "name": "tokenA", 38 | "type": "address" 39 | }, 40 | { 41 | "internalType": "address", 42 | "name": "tokenB", 43 | "type": "address" 44 | }, 45 | { 46 | "internalType": "uint256", 47 | "name": "amountADesired", 48 | "type": "uint256" 49 | }, 50 | { 51 | "internalType": "uint256", 52 | "name": "amountBDesired", 53 | "type": "uint256" 54 | }, 55 | { 56 | "internalType": "uint256", 57 | "name": "amountAMin", 58 | "type": "uint256" 59 | }, 60 | { 61 | "internalType": "uint256", 62 | "name": "amountBMin", 63 | "type": "uint256" 64 | }, 65 | { 66 | "internalType": "address", 67 | "name": "to", 68 | "type": "address" 69 | }, 70 | { 71 | "internalType": "uint256", 72 | "name": "deadline", 73 | "type": "uint256" 74 | } 75 | ], 76 | "name": "addLiquidity", 77 | "outputs": [ 78 | { 79 | "internalType": "uint256", 80 | "name": "amountA", 81 | "type": "uint256" 82 | }, 83 | { 84 | "internalType": "uint256", 85 | "name": "amountB", 86 | "type": "uint256" 87 | }, 88 | { 89 | "internalType": "uint256", 90 | "name": "liquidity", 91 | "type": "uint256" 92 | } 93 | ], 94 | "stateMutability": "nonpayable", 95 | "type": "function" 96 | }, 97 | { 98 | "inputs": [ 99 | { 100 | "internalType": "address", 101 | "name": "token", 102 | "type": "address" 103 | }, 104 | { 105 | "internalType": "uint256", 106 | "name": "amountTokenDesired", 107 | "type": "uint256" 108 | }, 109 | { 110 | "internalType": "uint256", 111 | "name": "amountTokenMin", 112 | "type": "uint256" 113 | }, 114 | { 115 | "internalType": "uint256", 116 | "name": "amountETHMin", 117 | "type": "uint256" 118 | }, 119 | { 120 | "internalType": "address", 121 | "name": "to", 122 | "type": "address" 123 | }, 124 | { 125 | "internalType": "uint256", 126 | "name": "deadline", 127 | "type": "uint256" 128 | } 129 | ], 130 | "name": "addLiquidityETH", 131 | "outputs": [ 132 | { 133 | "internalType": "uint256", 134 | "name": "amountToken", 135 | "type": "uint256" 136 | }, 137 | { 138 | "internalType": "uint256", 139 | "name": "amountETH", 140 | "type": "uint256" 141 | }, 142 | { 143 | "internalType": "uint256", 144 | "name": "liquidity", 145 | "type": "uint256" 146 | } 147 | ], 148 | "stateMutability": "payable", 149 | "type": "function" 150 | }, 151 | { 152 | "inputs": [], 153 | "name": "factory", 154 | "outputs": [ 155 | { 156 | "internalType": "address", 157 | "name": "", 158 | "type": "address" 159 | } 160 | ], 161 | "stateMutability": "view", 162 | "type": "function" 163 | }, 164 | { 165 | "inputs": [ 166 | { 167 | "internalType": "uint256", 168 | "name": "amountOut", 169 | "type": "uint256" 170 | }, 171 | { 172 | "internalType": "uint256", 173 | "name": "reserveIn", 174 | "type": "uint256" 175 | }, 176 | { 177 | "internalType": "uint256", 178 | "name": "reserveOut", 179 | "type": "uint256" 180 | } 181 | ], 182 | "name": "getAmountIn", 183 | "outputs": [ 184 | { 185 | "internalType": "uint256", 186 | "name": "amountIn", 187 | "type": "uint256" 188 | } 189 | ], 190 | "stateMutability": "pure", 191 | "type": "function" 192 | }, 193 | { 194 | "inputs": [ 195 | { 196 | "internalType": "uint256", 197 | "name": "amountIn", 198 | "type": "uint256" 199 | }, 200 | { 201 | "internalType": "uint256", 202 | "name": "reserveIn", 203 | "type": "uint256" 204 | }, 205 | { 206 | "internalType": "uint256", 207 | "name": "reserveOut", 208 | "type": "uint256" 209 | } 210 | ], 211 | "name": "getAmountOut", 212 | "outputs": [ 213 | { 214 | "internalType": "uint256", 215 | "name": "amountOut", 216 | "type": "uint256" 217 | } 218 | ], 219 | "stateMutability": "pure", 220 | "type": "function" 221 | }, 222 | { 223 | "inputs": [ 224 | { 225 | "internalType": "uint256", 226 | "name": "amountOut", 227 | "type": "uint256" 228 | }, 229 | { 230 | "internalType": "address[]", 231 | "name": "path", 232 | "type": "address[]" 233 | } 234 | ], 235 | "name": "getAmountsIn", 236 | "outputs": [ 237 | { 238 | "internalType": "uint256[]", 239 | "name": "amounts", 240 | "type": "uint256[]" 241 | } 242 | ], 243 | "stateMutability": "view", 244 | "type": "function" 245 | }, 246 | { 247 | "inputs": [ 248 | { 249 | "internalType": "uint256", 250 | "name": "amountIn", 251 | "type": "uint256" 252 | }, 253 | { 254 | "internalType": "address[]", 255 | "name": "path", 256 | "type": "address[]" 257 | } 258 | ], 259 | "name": "getAmountsOut", 260 | "outputs": [ 261 | { 262 | "internalType": "uint256[]", 263 | "name": "amounts", 264 | "type": "uint256[]" 265 | } 266 | ], 267 | "stateMutability": "view", 268 | "type": "function" 269 | }, 270 | { 271 | "inputs": [ 272 | { 273 | "internalType": "uint256", 274 | "name": "amountA", 275 | "type": "uint256" 276 | }, 277 | { 278 | "internalType": "uint256", 279 | "name": "reserveA", 280 | "type": "uint256" 281 | }, 282 | { 283 | "internalType": "uint256", 284 | "name": "reserveB", 285 | "type": "uint256" 286 | } 287 | ], 288 | "name": "quote", 289 | "outputs": [ 290 | { 291 | "internalType": "uint256", 292 | "name": "amountB", 293 | "type": "uint256" 294 | } 295 | ], 296 | "stateMutability": "pure", 297 | "type": "function" 298 | }, 299 | { 300 | "inputs": [ 301 | { 302 | "internalType": "address", 303 | "name": "tokenA", 304 | "type": "address" 305 | }, 306 | { 307 | "internalType": "address", 308 | "name": "tokenB", 309 | "type": "address" 310 | }, 311 | { 312 | "internalType": "uint256", 313 | "name": "liquidity", 314 | "type": "uint256" 315 | }, 316 | { 317 | "internalType": "uint256", 318 | "name": "amountAMin", 319 | "type": "uint256" 320 | }, 321 | { 322 | "internalType": "uint256", 323 | "name": "amountBMin", 324 | "type": "uint256" 325 | }, 326 | { 327 | "internalType": "address", 328 | "name": "to", 329 | "type": "address" 330 | }, 331 | { 332 | "internalType": "uint256", 333 | "name": "deadline", 334 | "type": "uint256" 335 | } 336 | ], 337 | "name": "removeLiquidity", 338 | "outputs": [ 339 | { 340 | "internalType": "uint256", 341 | "name": "amountA", 342 | "type": "uint256" 343 | }, 344 | { 345 | "internalType": "uint256", 346 | "name": "amountB", 347 | "type": "uint256" 348 | } 349 | ], 350 | "stateMutability": "nonpayable", 351 | "type": "function" 352 | }, 353 | { 354 | "inputs": [ 355 | { 356 | "internalType": "address", 357 | "name": "token", 358 | "type": "address" 359 | }, 360 | { 361 | "internalType": "uint256", 362 | "name": "liquidity", 363 | "type": "uint256" 364 | }, 365 | { 366 | "internalType": "uint256", 367 | "name": "amountTokenMin", 368 | "type": "uint256" 369 | }, 370 | { 371 | "internalType": "uint256", 372 | "name": "amountETHMin", 373 | "type": "uint256" 374 | }, 375 | { 376 | "internalType": "address", 377 | "name": "to", 378 | "type": "address" 379 | }, 380 | { 381 | "internalType": "uint256", 382 | "name": "deadline", 383 | "type": "uint256" 384 | } 385 | ], 386 | "name": "removeLiquidityETH", 387 | "outputs": [ 388 | { 389 | "internalType": "uint256", 390 | "name": "amountToken", 391 | "type": "uint256" 392 | }, 393 | { 394 | "internalType": "uint256", 395 | "name": "amountETH", 396 | "type": "uint256" 397 | } 398 | ], 399 | "stateMutability": "nonpayable", 400 | "type": "function" 401 | }, 402 | { 403 | "inputs": [ 404 | { 405 | "internalType": "address", 406 | "name": "token", 407 | "type": "address" 408 | }, 409 | { 410 | "internalType": "uint256", 411 | "name": "liquidity", 412 | "type": "uint256" 413 | }, 414 | { 415 | "internalType": "uint256", 416 | "name": "amountTokenMin", 417 | "type": "uint256" 418 | }, 419 | { 420 | "internalType": "uint256", 421 | "name": "amountETHMin", 422 | "type": "uint256" 423 | }, 424 | { 425 | "internalType": "address", 426 | "name": "to", 427 | "type": "address" 428 | }, 429 | { 430 | "internalType": "uint256", 431 | "name": "deadline", 432 | "type": "uint256" 433 | } 434 | ], 435 | "name": "removeLiquidityETHSupportingFeeOnTransferTokens", 436 | "outputs": [ 437 | { 438 | "internalType": "uint256", 439 | "name": "amountETH", 440 | "type": "uint256" 441 | } 442 | ], 443 | "stateMutability": "nonpayable", 444 | "type": "function" 445 | }, 446 | { 447 | "inputs": [ 448 | { 449 | "internalType": "address", 450 | "name": "token", 451 | "type": "address" 452 | }, 453 | { 454 | "internalType": "uint256", 455 | "name": "liquidity", 456 | "type": "uint256" 457 | }, 458 | { 459 | "internalType": "uint256", 460 | "name": "amountTokenMin", 461 | "type": "uint256" 462 | }, 463 | { 464 | "internalType": "uint256", 465 | "name": "amountETHMin", 466 | "type": "uint256" 467 | }, 468 | { 469 | "internalType": "address", 470 | "name": "to", 471 | "type": "address" 472 | }, 473 | { 474 | "internalType": "uint256", 475 | "name": "deadline", 476 | "type": "uint256" 477 | }, 478 | { 479 | "internalType": "bool", 480 | "name": "approveMax", 481 | "type": "bool" 482 | }, 483 | { 484 | "internalType": "uint8", 485 | "name": "v", 486 | "type": "uint8" 487 | }, 488 | { 489 | "internalType": "bytes32", 490 | "name": "r", 491 | "type": "bytes32" 492 | }, 493 | { 494 | "internalType": "bytes32", 495 | "name": "s", 496 | "type": "bytes32" 497 | } 498 | ], 499 | "name": "removeLiquidityETHWithPermit", 500 | "outputs": [ 501 | { 502 | "internalType": "uint256", 503 | "name": "amountToken", 504 | "type": "uint256" 505 | }, 506 | { 507 | "internalType": "uint256", 508 | "name": "amountETH", 509 | "type": "uint256" 510 | } 511 | ], 512 | "stateMutability": "nonpayable", 513 | "type": "function" 514 | }, 515 | { 516 | "inputs": [ 517 | { 518 | "internalType": "address", 519 | "name": "token", 520 | "type": "address" 521 | }, 522 | { 523 | "internalType": "uint256", 524 | "name": "liquidity", 525 | "type": "uint256" 526 | }, 527 | { 528 | "internalType": "uint256", 529 | "name": "amountTokenMin", 530 | "type": "uint256" 531 | }, 532 | { 533 | "internalType": "uint256", 534 | "name": "amountETHMin", 535 | "type": "uint256" 536 | }, 537 | { 538 | "internalType": "address", 539 | "name": "to", 540 | "type": "address" 541 | }, 542 | { 543 | "internalType": "uint256", 544 | "name": "deadline", 545 | "type": "uint256" 546 | }, 547 | { 548 | "internalType": "bool", 549 | "name": "approveMax", 550 | "type": "bool" 551 | }, 552 | { 553 | "internalType": "uint8", 554 | "name": "v", 555 | "type": "uint8" 556 | }, 557 | { 558 | "internalType": "bytes32", 559 | "name": "r", 560 | "type": "bytes32" 561 | }, 562 | { 563 | "internalType": "bytes32", 564 | "name": "s", 565 | "type": "bytes32" 566 | } 567 | ], 568 | "name": "removeLiquidityETHWithPermitSupportingFeeOnTransferTokens", 569 | "outputs": [ 570 | { 571 | "internalType": "uint256", 572 | "name": "amountETH", 573 | "type": "uint256" 574 | } 575 | ], 576 | "stateMutability": "nonpayable", 577 | "type": "function" 578 | }, 579 | { 580 | "inputs": [ 581 | { 582 | "internalType": "address", 583 | "name": "tokenA", 584 | "type": "address" 585 | }, 586 | { 587 | "internalType": "address", 588 | "name": "tokenB", 589 | "type": "address" 590 | }, 591 | { 592 | "internalType": "uint256", 593 | "name": "liquidity", 594 | "type": "uint256" 595 | }, 596 | { 597 | "internalType": "uint256", 598 | "name": "amountAMin", 599 | "type": "uint256" 600 | }, 601 | { 602 | "internalType": "uint256", 603 | "name": "amountBMin", 604 | "type": "uint256" 605 | }, 606 | { 607 | "internalType": "address", 608 | "name": "to", 609 | "type": "address" 610 | }, 611 | { 612 | "internalType": "uint256", 613 | "name": "deadline", 614 | "type": "uint256" 615 | }, 616 | { 617 | "internalType": "bool", 618 | "name": "approveMax", 619 | "type": "bool" 620 | }, 621 | { 622 | "internalType": "uint8", 623 | "name": "v", 624 | "type": "uint8" 625 | }, 626 | { 627 | "internalType": "bytes32", 628 | "name": "r", 629 | "type": "bytes32" 630 | }, 631 | { 632 | "internalType": "bytes32", 633 | "name": "s", 634 | "type": "bytes32" 635 | } 636 | ], 637 | "name": "removeLiquidityWithPermit", 638 | "outputs": [ 639 | { 640 | "internalType": "uint256", 641 | "name": "amountA", 642 | "type": "uint256" 643 | }, 644 | { 645 | "internalType": "uint256", 646 | "name": "amountB", 647 | "type": "uint256" 648 | } 649 | ], 650 | "stateMutability": "nonpayable", 651 | "type": "function" 652 | }, 653 | { 654 | "inputs": [ 655 | { 656 | "internalType": "uint256", 657 | "name": "amountOut", 658 | "type": "uint256" 659 | }, 660 | { 661 | "internalType": "address[]", 662 | "name": "path", 663 | "type": "address[]" 664 | }, 665 | { 666 | "internalType": "address", 667 | "name": "to", 668 | "type": "address" 669 | }, 670 | { 671 | "internalType": "uint256", 672 | "name": "deadline", 673 | "type": "uint256" 674 | } 675 | ], 676 | "name": "swapETHForExactTokens", 677 | "outputs": [ 678 | { 679 | "internalType": "uint256[]", 680 | "name": "amounts", 681 | "type": "uint256[]" 682 | } 683 | ], 684 | "stateMutability": "payable", 685 | "type": "function" 686 | }, 687 | { 688 | "inputs": [ 689 | { 690 | "internalType": "uint256", 691 | "name": "amountOutMin", 692 | "type": "uint256" 693 | }, 694 | { 695 | "internalType": "address[]", 696 | "name": "path", 697 | "type": "address[]" 698 | }, 699 | { 700 | "internalType": "address", 701 | "name": "to", 702 | "type": "address" 703 | }, 704 | { 705 | "internalType": "uint256", 706 | "name": "deadline", 707 | "type": "uint256" 708 | } 709 | ], 710 | "name": "swapExactETHForTokens", 711 | "outputs": [ 712 | { 713 | "internalType": "uint256[]", 714 | "name": "amounts", 715 | "type": "uint256[]" 716 | } 717 | ], 718 | "stateMutability": "payable", 719 | "type": "function" 720 | }, 721 | { 722 | "inputs": [ 723 | { 724 | "internalType": "uint256", 725 | "name": "amountOutMin", 726 | "type": "uint256" 727 | }, 728 | { 729 | "internalType": "address[]", 730 | "name": "path", 731 | "type": "address[]" 732 | }, 733 | { 734 | "internalType": "address", 735 | "name": "to", 736 | "type": "address" 737 | }, 738 | { 739 | "internalType": "uint256", 740 | "name": "deadline", 741 | "type": "uint256" 742 | } 743 | ], 744 | "name": "swapExactETHForTokensSupportingFeeOnTransferTokens", 745 | "outputs": [], 746 | "stateMutability": "payable", 747 | "type": "function" 748 | }, 749 | { 750 | "inputs": [ 751 | { 752 | "internalType": "uint256", 753 | "name": "amountIn", 754 | "type": "uint256" 755 | }, 756 | { 757 | "internalType": "uint256", 758 | "name": "amountOutMin", 759 | "type": "uint256" 760 | }, 761 | { 762 | "internalType": "address[]", 763 | "name": "path", 764 | "type": "address[]" 765 | }, 766 | { 767 | "internalType": "address", 768 | "name": "to", 769 | "type": "address" 770 | }, 771 | { 772 | "internalType": "uint256", 773 | "name": "deadline", 774 | "type": "uint256" 775 | } 776 | ], 777 | "name": "swapExactTokensForETH", 778 | "outputs": [ 779 | { 780 | "internalType": "uint256[]", 781 | "name": "amounts", 782 | "type": "uint256[]" 783 | } 784 | ], 785 | "stateMutability": "nonpayable", 786 | "type": "function" 787 | }, 788 | { 789 | "inputs": [ 790 | { 791 | "internalType": "uint256", 792 | "name": "amountIn", 793 | "type": "uint256" 794 | }, 795 | { 796 | "internalType": "uint256", 797 | "name": "amountOutMin", 798 | "type": "uint256" 799 | }, 800 | { 801 | "internalType": "address[]", 802 | "name": "path", 803 | "type": "address[]" 804 | }, 805 | { 806 | "internalType": "address", 807 | "name": "to", 808 | "type": "address" 809 | }, 810 | { 811 | "internalType": "uint256", 812 | "name": "deadline", 813 | "type": "uint256" 814 | } 815 | ], 816 | "name": "swapExactTokensForETHSupportingFeeOnTransferTokens", 817 | "outputs": [], 818 | "stateMutability": "nonpayable", 819 | "type": "function" 820 | }, 821 | { 822 | "inputs": [ 823 | { 824 | "internalType": "uint256", 825 | "name": "amountIn", 826 | "type": "uint256" 827 | }, 828 | { 829 | "internalType": "uint256", 830 | "name": "amountOutMin", 831 | "type": "uint256" 832 | }, 833 | { 834 | "internalType": "address[]", 835 | "name": "path", 836 | "type": "address[]" 837 | }, 838 | { 839 | "internalType": "address", 840 | "name": "to", 841 | "type": "address" 842 | }, 843 | { 844 | "internalType": "uint256", 845 | "name": "deadline", 846 | "type": "uint256" 847 | } 848 | ], 849 | "name": "swapExactTokensForTokens", 850 | "outputs": [ 851 | { 852 | "internalType": "uint256[]", 853 | "name": "amounts", 854 | "type": "uint256[]" 855 | } 856 | ], 857 | "stateMutability": "nonpayable", 858 | "type": "function" 859 | }, 860 | { 861 | "inputs": [ 862 | { 863 | "internalType": "uint256", 864 | "name": "amountIn", 865 | "type": "uint256" 866 | }, 867 | { 868 | "internalType": "uint256", 869 | "name": "amountOutMin", 870 | "type": "uint256" 871 | }, 872 | { 873 | "internalType": "address[]", 874 | "name": "path", 875 | "type": "address[]" 876 | }, 877 | { 878 | "internalType": "address", 879 | "name": "to", 880 | "type": "address" 881 | }, 882 | { 883 | "internalType": "uint256", 884 | "name": "deadline", 885 | "type": "uint256" 886 | } 887 | ], 888 | "name": "swapExactTokensForTokensSupportingFeeOnTransferTokens", 889 | "outputs": [], 890 | "stateMutability": "nonpayable", 891 | "type": "function" 892 | }, 893 | { 894 | "inputs": [ 895 | { 896 | "internalType": "uint256", 897 | "name": "amountOut", 898 | "type": "uint256" 899 | }, 900 | { 901 | "internalType": "uint256", 902 | "name": "amountInMax", 903 | "type": "uint256" 904 | }, 905 | { 906 | "internalType": "address[]", 907 | "name": "path", 908 | "type": "address[]" 909 | }, 910 | { 911 | "internalType": "address", 912 | "name": "to", 913 | "type": "address" 914 | }, 915 | { 916 | "internalType": "uint256", 917 | "name": "deadline", 918 | "type": "uint256" 919 | } 920 | ], 921 | "name": "swapTokensForExactETH", 922 | "outputs": [ 923 | { 924 | "internalType": "uint256[]", 925 | "name": "amounts", 926 | "type": "uint256[]" 927 | } 928 | ], 929 | "stateMutability": "nonpayable", 930 | "type": "function" 931 | }, 932 | { 933 | "inputs": [ 934 | { 935 | "internalType": "uint256", 936 | "name": "amountOut", 937 | "type": "uint256" 938 | }, 939 | { 940 | "internalType": "uint256", 941 | "name": "amountInMax", 942 | "type": "uint256" 943 | }, 944 | { 945 | "internalType": "address[]", 946 | "name": "path", 947 | "type": "address[]" 948 | }, 949 | { 950 | "internalType": "address", 951 | "name": "to", 952 | "type": "address" 953 | }, 954 | { 955 | "internalType": "uint256", 956 | "name": "deadline", 957 | "type": "uint256" 958 | } 959 | ], 960 | "name": "swapTokensForExactTokens", 961 | "outputs": [ 962 | { 963 | "internalType": "uint256[]", 964 | "name": "amounts", 965 | "type": "uint256[]" 966 | } 967 | ], 968 | "stateMutability": "nonpayable", 969 | "type": "function" 970 | }, 971 | { 972 | "stateMutability": "payable", 973 | "type": "receive" 974 | } 975 | ] 976 | } 977 | -------------------------------------------------------------------------------- /deployments/ethereum/UniswapV2Factory.json: -------------------------------------------------------------------------------- 1 | { 2 | "address": "0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac", 3 | "abi": [ 4 | { 5 | "inputs": [ 6 | { 7 | "internalType": "address", 8 | "name": "_feeToSetter", 9 | "type": "address" 10 | } 11 | ], 12 | "stateMutability": "nonpayable", 13 | "type": "constructor" 14 | }, 15 | { 16 | "anonymous": false, 17 | "inputs": [ 18 | { 19 | "indexed": true, 20 | "internalType": "address", 21 | "name": "token0", 22 | "type": "address" 23 | }, 24 | { 25 | "indexed": true, 26 | "internalType": "address", 27 | "name": "token1", 28 | "type": "address" 29 | }, 30 | { 31 | "indexed": false, 32 | "internalType": "address", 33 | "name": "pair", 34 | "type": "address" 35 | }, 36 | { 37 | "indexed": false, 38 | "internalType": "uint256", 39 | "name": "", 40 | "type": "uint256" 41 | } 42 | ], 43 | "name": "PairCreated", 44 | "type": "event" 45 | }, 46 | { 47 | "inputs": [ 48 | { 49 | "internalType": "uint256", 50 | "name": "", 51 | "type": "uint256" 52 | } 53 | ], 54 | "name": "allPairs", 55 | "outputs": [ 56 | { 57 | "internalType": "address", 58 | "name": "", 59 | "type": "address" 60 | } 61 | ], 62 | "stateMutability": "view", 63 | "type": "function" 64 | }, 65 | { 66 | "inputs": [], 67 | "name": "allPairsLength", 68 | "outputs": [ 69 | { 70 | "internalType": "uint256", 71 | "name": "", 72 | "type": "uint256" 73 | } 74 | ], 75 | "stateMutability": "view", 76 | "type": "function" 77 | }, 78 | { 79 | "inputs": [ 80 | { 81 | "internalType": "address", 82 | "name": "tokenA", 83 | "type": "address" 84 | }, 85 | { 86 | "internalType": "address", 87 | "name": "tokenB", 88 | "type": "address" 89 | } 90 | ], 91 | "name": "createPair", 92 | "outputs": [ 93 | { 94 | "internalType": "address", 95 | "name": "pair", 96 | "type": "address" 97 | } 98 | ], 99 | "stateMutability": "nonpayable", 100 | "type": "function" 101 | }, 102 | { 103 | "inputs": [], 104 | "name": "feeTo", 105 | "outputs": [ 106 | { 107 | "internalType": "address", 108 | "name": "", 109 | "type": "address" 110 | } 111 | ], 112 | "stateMutability": "view", 113 | "type": "function" 114 | }, 115 | { 116 | "inputs": [], 117 | "name": "feeToSetter", 118 | "outputs": [ 119 | { 120 | "internalType": "address", 121 | "name": "", 122 | "type": "address" 123 | } 124 | ], 125 | "stateMutability": "view", 126 | "type": "function" 127 | }, 128 | { 129 | "inputs": [ 130 | { 131 | "internalType": "address", 132 | "name": "", 133 | "type": "address" 134 | }, 135 | { 136 | "internalType": "address", 137 | "name": "", 138 | "type": "address" 139 | } 140 | ], 141 | "name": "getPair", 142 | "outputs": [ 143 | { 144 | "internalType": "address", 145 | "name": "", 146 | "type": "address" 147 | } 148 | ], 149 | "stateMutability": "view", 150 | "type": "function" 151 | }, 152 | { 153 | "inputs": [], 154 | "name": "migrator", 155 | "outputs": [ 156 | { 157 | "internalType": "address", 158 | "name": "", 159 | "type": "address" 160 | } 161 | ], 162 | "stateMutability": "view", 163 | "type": "function" 164 | }, 165 | { 166 | "inputs": [], 167 | "name": "pairCodeHash", 168 | "outputs": [ 169 | { 170 | "internalType": "bytes32", 171 | "name": "", 172 | "type": "bytes32" 173 | } 174 | ], 175 | "stateMutability": "pure", 176 | "type": "function" 177 | }, 178 | { 179 | "inputs": [ 180 | { 181 | "internalType": "address", 182 | "name": "_feeTo", 183 | "type": "address" 184 | } 185 | ], 186 | "name": "setFeeTo", 187 | "outputs": [], 188 | "stateMutability": "nonpayable", 189 | "type": "function" 190 | }, 191 | { 192 | "inputs": [ 193 | { 194 | "internalType": "address", 195 | "name": "_feeToSetter", 196 | "type": "address" 197 | } 198 | ], 199 | "name": "setFeeToSetter", 200 | "outputs": [], 201 | "stateMutability": "nonpayable", 202 | "type": "function" 203 | }, 204 | { 205 | "inputs": [ 206 | { 207 | "internalType": "address", 208 | "name": "_migrator", 209 | "type": "address" 210 | } 211 | ], 212 | "name": "setMigrator", 213 | "outputs": [], 214 | "stateMutability": "nonpayable", 215 | "type": "function" 216 | } 217 | ], 218 | "bytecode": "608060405234801561001057600080fd5b50604051612c63380380612c638339818101604052602081101561003357600080fd5b5051600180546001600160a01b0319166001600160a01b03909216919091179055612c00806100636000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80637cd07e47116100715780637cd07e47146101395780639aab924814610141578063a2e74af614610149578063c9c653961461016f578063e6a439051461019d578063f46901ed146101cb576100a9565b8063017e7e58146100ae578063094b7415146100d25780631e3dd18b146100da57806323cf3118146100f7578063574f2ba31461011f575b600080fd5b6100b66101f1565b604080516001600160a01b039092168252519081900360200190f35b6100b6610200565b6100b6600480360360208110156100f057600080fd5b503561020f565b61011d6004803603602081101561010d57600080fd5b50356001600160a01b0316610236565b005b6101276102ae565b60408051918252519081900360200190f35b6100b66102b4565b6101276102c3565b61011d6004803603602081101561015f57600080fd5b50356001600160a01b03166102f5565b6100b66004803603604081101561018557600080fd5b506001600160a01b038135811691602001351661036d565b6100b6600480360360408110156101b357600080fd5b506001600160a01b0381358116916020013516610698565b61011d600480360360208110156101e157600080fd5b50356001600160a01b03166106be565b6000546001600160a01b031681565b6001546001600160a01b031681565b6004818154811061021c57fe5b6000918252602090912001546001600160a01b0316905081565b6001546001600160a01b0316331461028c576040805162461bcd60e51b81526020600482015260146024820152732ab734b9bbb0b82b191d102327a92124a22222a760611b604482015290519081900360640190fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b60045490565b6002546001600160a01b031681565b6000604051806020016102d590610736565b6020820181038252601f19601f8201166040525080519060200120905090565b6001546001600160a01b0316331461034b576040805162461bcd60e51b81526020600482015260146024820152732ab734b9bbb0b82b191d102327a92124a22222a760611b604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000816001600160a01b0316836001600160a01b031614156103d6576040805162461bcd60e51b815260206004820152601e60248201527f556e697377617056323a204944454e544943414c5f4144445245535345530000604482015290519081900360640190fd5b600080836001600160a01b0316856001600160a01b0316106103f95783856103fc565b84845b90925090506001600160a01b03821661045c576040805162461bcd60e51b815260206004820152601760248201527f556e697377617056323a205a45524f5f41444452455353000000000000000000604482015290519081900360640190fd5b6001600160a01b038281166000908152600360209081526040808320858516845290915290205416156104cf576040805162461bcd60e51b8152602060048201526016602482015275556e697377617056323a20504149525f45584953545360501b604482015290519081900360640190fd5b6060604051806020016104e190610736565b6020820181038252601f19601f8201166040525090506000838360405160200180836001600160a01b031660601b8152601401826001600160a01b031660601b815260140192505050604051602081830303815290604052805190602001209050808251602084016000f59450846001600160a01b031663485cc95585856040518363ffffffff1660e01b815260040180836001600160a01b03168152602001826001600160a01b0316815260200192505050600060405180830381600087803b1580156105ae57600080fd5b505af11580156105c2573d6000803e3d6000fd5b505050506001600160a01b0384811660008181526003602081815260408084208987168086529083528185208054978d166001600160a01b031998891681179091559383528185208686528352818520805488168517905560048054600181018255958190527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b90950180549097168417909655925483519283529082015281517f0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9929181900390910190a35050505092915050565b60036020908152600092835260408084209091529082529020546001600160a01b031681565b6001546001600160a01b03163314610714576040805162461bcd60e51b81526020600482015260146024820152732ab734b9bbb0b82b191d102327a92124a22222a760611b604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b612487806107448339019056fe60806040526001600c5534801561001557600080fd5b50604080518082018252601281527129bab9b434a9bbb0b8102628102a37b5b2b760711b6020918201528151808301835260018152603160f81b9082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818301527fefbffe65652a145845c9bc8d0532945be6b9830fe1e9966c887bd298e551ac83818401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a0808301919091528351808303909101815260c09091019092528151910120600355600580546001600160a01b03191633179055612377806101106000396000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c80636a627842116100f9578063ba9a7a5611610097578063d21220a711610071578063d21220a714610534578063d505accf1461053c578063dd62ed3e1461058d578063fff6cae9146105bb576101a9565b8063ba9a7a56146104fe578063bc25cf7714610506578063c45a01551461052c576101a9565b80637ecebe00116100d35780637ecebe001461046557806389afcb441461048b57806395d89b41146104ca578063a9059cbb146104d2576101a9565b80636a6278421461041157806370a08231146104375780637464fc3d1461045d576101a9565b806323b872dd116101665780633644e515116101405780633644e515146103cb578063485cc955146103d35780635909c0d5146104015780635a3d549314610409576101a9565b806323b872dd1461036f57806330adf81f146103a5578063313ce567146103ad576101a9565b8063022c0d9f146101ae57806306fdde031461023c5780630902f1ac146102b9578063095ea7b3146102f15780630dfe16811461033157806318160ddd14610355575b600080fd5b61023a600480360360808110156101c457600080fd5b8135916020810135916001600160a01b0360408301351691908101906080810160608201356401000000008111156101fb57600080fd5b82018360208201111561020d57600080fd5b8035906020019184600183028401116401000000008311171561022f57600080fd5b5090925090506105c3565b005b610244610acb565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561027e578181015183820152602001610266565b50505050905090810190601f1680156102ab5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102c1610af9565b604080516001600160701b03948516815292909316602083015263ffffffff168183015290519081900360600190f35b61031d6004803603604081101561030757600080fd5b506001600160a01b038135169060200135610b23565b604080519115158252519081900360200190f35b610339610b3a565b604080516001600160a01b039092168252519081900360200190f35b61035d610b49565b60408051918252519081900360200190f35b61031d6004803603606081101561038557600080fd5b506001600160a01b03813581169160208101359091169060400135610b4f565b61035d610be3565b6103b5610c07565b6040805160ff9092168252519081900360200190f35b61035d610c0c565b61023a600480360360408110156103e957600080fd5b506001600160a01b0381358116916020013516610c12565b61035d610c96565b61035d610c9c565b61035d6004803603602081101561042757600080fd5b50356001600160a01b0316610ca2565b61035d6004803603602081101561044d57600080fd5b50356001600160a01b031661111e565b61035d611130565b61035d6004803603602081101561047b57600080fd5b50356001600160a01b0316611136565b6104b1600480360360208110156104a157600080fd5b50356001600160a01b0316611148565b6040805192835260208301919091528051918290030190f35b6102446114dc565b61031d600480360360408110156104e857600080fd5b506001600160a01b0381351690602001356114fb565b61035d611508565b61023a6004803603602081101561051c57600080fd5b50356001600160a01b031661150e565b610339611680565b61033961168f565b61023a600480360360e081101561055257600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c0013561169e565b61035d600480360360408110156105a357600080fd5b506001600160a01b03813581169160200135166118a0565b61023a6118bd565b600c5460011461060e576040805162461bcd60e51b8152602060048201526011602482015270155b9a5cddd85c158c8e881313d0d2d151607a1b604482015290519081900360640190fd5b6000600c55841515806106215750600084115b61065c5760405162461bcd60e51b81526004018080602001828103825260258152602001806122886025913960400191505060405180910390fd5b600080610667610af9565b5091509150816001600160701b03168710801561068c5750806001600160701b031686105b6106c75760405162461bcd60e51b81526004018080602001828103825260218152602001806122d16021913960400191505060405180910390fd5b60065460075460009182916001600160a01b039182169190811690891682148015906107055750806001600160a01b0316896001600160a01b031614155b61074e576040805162461bcd60e51b8152602060048201526015602482015274556e697377617056323a20494e56414c49445f544f60581b604482015290519081900360640190fd5b8a1561075f5761075f828a8d611a1f565b891561077057610770818a8c611a1f565b861561082257886001600160a01b03166310d1e85c338d8d8c8c6040518663ffffffff1660e01b815260040180866001600160a01b03168152602001858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509650505050505050600060405180830381600087803b15801561080957600080fd5b505af115801561081d573d6000803e3d6000fd5b505050505b604080516370a0823160e01b815230600482015290516001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561086857600080fd5b505afa15801561087c573d6000803e3d6000fd5b505050506040513d602081101561089257600080fd5b5051604080516370a0823160e01b815230600482015290519195506001600160a01b038316916370a0823191602480820192602092909190829003018186803b1580156108de57600080fd5b505afa1580156108f2573d6000803e3d6000fd5b505050506040513d602081101561090857600080fd5b5051925060009150506001600160701b0385168a9003831161092b57600061093a565b89856001600160701b03160383035b9050600089856001600160701b0316038311610957576000610966565b89856001600160701b03160383035b905060008211806109775750600081115b6109b25760405162461bcd60e51b81526004018080602001828103825260248152602001806122ad6024913960400191505060405180910390fd5b60006109d46109c2846003611bb9565b6109ce876103e8611bb9565b90611c1c565b905060006109e66109c2846003611bb9565b9050610a0b620f4240610a056001600160701b038b8116908b16611bb9565b90611bb9565b610a158383611bb9565b1015610a57576040805162461bcd60e51b815260206004820152600c60248201526b556e697377617056323a204b60a01b604482015290519081900360640190fd5b5050610a6584848888611c6c565b60408051838152602081018390528082018d9052606081018c905290516001600160a01b038b169133917fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229181900360800190a350506001600c55505050505050505050565b6040518060400160405280601281526020017129bab9b434a9bbb0b8102628102a37b5b2b760711b81525081565b6008546001600160701b0380821692600160701b830490911691600160e01b900463ffffffff1690565b6000610b30338484611e2b565b5060015b92915050565b6006546001600160a01b031681565b60005481565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001914610bce576001600160a01b0384166000908152600260209081526040808320338452909152902054610ba99083611c1c565b6001600160a01b03851660009081526002602090815260408083203384529091529020555b610bd9848484611e8d565b5060019392505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b601281565b60035481565b6005546001600160a01b03163314610c68576040805162461bcd60e51b81526020600482015260146024820152732ab734b9bbb0b82b191d102327a92124a22222a760611b604482015290519081900360640190fd5b600680546001600160a01b039384166001600160a01b03199182161790915560078054929093169116179055565b60095481565b600a5481565b6000600c54600114610cef576040805162461bcd60e51b8152602060048201526011602482015270155b9a5cddd85c158c8e881313d0d2d151607a1b604482015290519081900360640190fd5b6000600c81905580610cff610af9565b50600654604080516370a0823160e01b815230600482015290519395509193506000926001600160a01b03909116916370a08231916024808301926020929190829003018186803b158015610d5357600080fd5b505afa158015610d67573d6000803e3d6000fd5b505050506040513d6020811015610d7d57600080fd5b5051600754604080516370a0823160e01b815230600482015290519293506000926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015610dd057600080fd5b505afa158015610de4573d6000803e3d6000fd5b505050506040513d6020811015610dfa57600080fd5b505190506000610e13836001600160701b038716611c1c565b90506000610e2a836001600160701b038716611c1c565b90506000610e388787611f3b565b6000549091508061100f5760055460408051637cd07e4760e01b815290516000926001600160a01b031691637cd07e47916004808301926020929190829003018186803b158015610e8857600080fd5b505afa158015610e9c573d6000803e3d6000fd5b505050506040513d6020811015610eb257600080fd5b50519050336001600160a01b0382161415610f8d57806001600160a01b03166340dc0e376040518163ffffffff1660e01b815260040160206040518083038186803b158015610f0057600080fd5b505afa158015610f14573d6000803e3d6000fd5b505050506040513d6020811015610f2a57600080fd5b505199508915801590610f3f57506000198a14155b610f88576040805162461bcd60e51b81526020600482015260156024820152744261642064657369726564206c697175696469747960581b604482015290519081900360640190fd5b611009565b6001600160a01b03811615610fe2576040805162461bcd60e51b815260206004820152601660248201527526bab9ba103737ba103430bb329036b4b3b930ba37b960511b604482015290519081900360640190fd5b610ffa6103e86109ce610ff58888611bb9565b61207b565b995061100960006103e86120cd565b50611052565b61104f6001600160701b0389166110268684611bb9565b8161102d57fe5b046001600160701b0389166110428685611bb9565b8161104957fe5b04612157565b98505b600089116110915760405162461bcd60e51b815260040180806020018281038252602881526020018061231a6028913960400191505060405180910390fd5b61109b8a8a6120cd565b6110a786868a8a611c6c565b81156110d1576008546110cd906001600160701b0380821691600160701b900416611bb9565b600b555b6040805185815260208101859052815133927f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f928290030190a250506001600c5550949695505050505050565b60016020526000908152604090205481565b600b5481565b60046020526000908152604090205481565b600080600c54600114611196576040805162461bcd60e51b8152602060048201526011602482015270155b9a5cddd85c158c8e881313d0d2d151607a1b604482015290519081900360640190fd5b6000600c819055806111a6610af9565b50600654600754604080516370a0823160e01b815230600482015290519496509294506001600160a01b039182169391169160009184916370a08231916024808301926020929190829003018186803b15801561120257600080fd5b505afa158015611216573d6000803e3d6000fd5b505050506040513d602081101561122c57600080fd5b5051604080516370a0823160e01b815230600482015290519192506000916001600160a01b038516916370a08231916024808301926020929190829003018186803b15801561127a57600080fd5b505afa15801561128e573d6000803e3d6000fd5b505050506040513d60208110156112a457600080fd5b5051306000908152600160205260408120549192506112c38888611f3b565b600054909150806112d48487611bb9565b816112db57fe5b049a50806112e98486611bb9565b816112f057fe5b04995060008b118015611303575060008a115b61133e5760405162461bcd60e51b81526004018080602001828103825260288152602001806122f26028913960400191505060405180910390fd5b611348308461216f565b611353878d8d611a1f565b61135e868d8c611a1f565b604080516370a0823160e01b815230600482015290516001600160a01b038916916370a08231916024808301926020929190829003018186803b1580156113a457600080fd5b505afa1580156113b8573d6000803e3d6000fd5b505050506040513d60208110156113ce57600080fd5b5051604080516370a0823160e01b815230600482015290519196506001600160a01b038816916370a0823191602480820192602092909190829003018186803b15801561141a57600080fd5b505afa15801561142e573d6000803e3d6000fd5b505050506040513d602081101561144457600080fd5b5051935061145485858b8b611c6c565b811561147e5760085461147a906001600160701b0380821691600160701b900416611bb9565b600b555b604080518c8152602081018c905281516001600160a01b038f169233927fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496929081900390910190a35050505050505050506001600c81905550915091565b604051806040016040528060038152602001620534c560ec1b81525081565b6000610b30338484611e8d565b6103e881565b600c54600114611559576040805162461bcd60e51b8152602060048201526011602482015270155b9a5cddd85c158c8e881313d0d2d151607a1b604482015290519081900360640190fd5b6000600c55600654600754600854604080516370a0823160e01b815230600482015290516001600160a01b03948516949093169261160292859287926115fd926001600160701b03169185916370a0823191602480820192602092909190829003018186803b1580156115cb57600080fd5b505afa1580156115df573d6000803e3d6000fd5b505050506040513d60208110156115f557600080fd5b505190611c1c565b611a1f565b61167681846115fd6008600e9054906101000a90046001600160701b03166001600160701b0316856001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156115cb57600080fd5b50506001600c5550565b6005546001600160a01b031681565b6007546001600160a01b031681565b428410156116e8576040805162461bcd60e51b8152602060048201526012602482015271155b9a5cddd85c158c8e881156141254915160721b604482015290519081900360640190fd5b6003546001600160a01b0380891660008181526004602090815260408083208054600180820190925582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98186015280840196909652958d166060860152608085018c905260a085019590955260c08085018b90528151808603909101815260e08501825280519083012061190160f01b6101008601526101028501969096526101228085019690965280518085039096018652610142840180825286519683019690962095839052610162840180825286905260ff89166101828501526101a284018890526101c28401879052519193926101e280820193601f1981019281900390910190855afa158015611803573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906118395750886001600160a01b0316816001600160a01b0316145b61188a576040805162461bcd60e51b815260206004820152601c60248201527f556e697377617056323a20494e56414c49445f5349474e415455524500000000604482015290519081900360640190fd5b611895898989611e2b565b505050505050505050565b600260209081526000928352604080842090915290825290205481565b600c54600114611908576040805162461bcd60e51b8152602060048201526011602482015270155b9a5cddd85c158c8e881313d0d2d151607a1b604482015290519081900360640190fd5b6000600c55600654604080516370a0823160e01b81523060048201529051611a18926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561195957600080fd5b505afa15801561196d573d6000803e3d6000fd5b505050506040513d602081101561198357600080fd5b5051600754604080516370a0823160e01b815230600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b1580156119d057600080fd5b505afa1580156119e4573d6000803e3d6000fd5b505050506040513d60208110156119fa57600080fd5b50516008546001600160701b0380821691600160701b900416611c6c565b6001600c55565b604080518082018252601981527f7472616e7366657228616464726573732c75696e74323536290000000000000060209182015281516001600160a01b0385811660248301526044808301869052845180840390910181526064909201845291810180516001600160e01b031663a9059cbb60e01b1781529251815160009460609489169392918291908083835b60208310611acc5780518252601f199092019160209182019101611aad565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611b2e576040519150601f19603f3d011682016040523d82523d6000602084013e611b33565b606091505b5091509150818015611b61575080511580611b615750808060200190516020811015611b5e57600080fd5b50515b611bb2576040805162461bcd60e51b815260206004820152601a60248201527f556e697377617056323a205452414e534645525f4641494c4544000000000000604482015290519081900360640190fd5b5050505050565b6000811580611bd457505080820282828281611bd157fe5b04145b610b34576040805162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6d756c2d6f766572666c6f7760601b604482015290519081900360640190fd5b80820382811115610b34576040805162461bcd60e51b815260206004820152601560248201527464732d6d6174682d7375622d756e646572666c6f7760581b604482015290519081900360640190fd5b6001600160701b038411801590611c8a57506001600160701b038311155b611cd1576040805162461bcd60e51b8152602060048201526013602482015272556e697377617056323a204f564552464c4f5760681b604482015290519081900360640190fd5b60085463ffffffff42811691600160e01b90048116820390811615801590611d0157506001600160701b03841615155b8015611d1557506001600160701b03831615155b15611d80578063ffffffff16611d3d85611d2e86612201565b6001600160e01b031690612213565b600980546001600160e01b03929092169290920201905563ffffffff8116611d6884611d2e87612201565b600a80546001600160e01b0392909216929092020190555b600880546dffffffffffffffffffffffffffff19166001600160701b03888116919091176dffffffffffffffffffffffffffff60701b1916600160701b8883168102919091176001600160e01b0316600160e01b63ffffffff871602179283905560408051848416815291909304909116602082015281517f1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1929181900390910190a1505050505050565b6001600160a01b03808416600081815260026020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b038316600090815260016020526040902054611eb09082611c1c565b6001600160a01b038085166000908152600160205260408082209390935590841681522054611edf9082612238565b6001600160a01b0380841660008181526001602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600080600560009054906101000a90046001600160a01b03166001600160a01b031663017e7e586040518163ffffffff1660e01b815260040160206040518083038186803b158015611f8c57600080fd5b505afa158015611fa0573d6000803e3d6000fd5b505050506040513d6020811015611fb657600080fd5b5051600b546001600160a01b038216158015945091925090612067578015612062576000611ff3610ff56001600160701b03888116908816611bb9565b905060006120008361207b565b90508082111561205f5760006120226120198484611c1c565b60005490611bb9565b9050600061203b83612035866005611bb9565b90612238565b9050600081838161204857fe5b049050801561205b5761205b87826120cd565b5050505b50505b612073565b8015612073576000600b555b505092915050565b600060038211156120be575080600160028204015b818110156120b8578091506002818285816120a757fe5b0401816120b057fe5b049050612090565b506120c8565b81156120c8575060015b919050565b6000546120da9082612238565b60009081556001600160a01b0383168152600160205260409020546120ff9082612238565b6001600160a01b03831660008181526001602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b60008183106121665781612168565b825b9392505050565b6001600160a01b0382166000908152600160205260409020546121929082611c1c565b6001600160a01b038316600090815260016020526040812091909155546121b99082611c1c565b60009081556040805183815290516001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef919081900360200190a35050565b6001600160701b0316600160701b0290565b60006001600160701b0382166001600160e01b0384168161223057fe5b049392505050565b80820182811015610b34576040805162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6164642d6f766572666c6f7760601b604482015290519081900360640190fdfe556e697377617056323a20494e53554646494349454e545f4f55545055545f414d4f554e54556e697377617056323a20494e53554646494349454e545f494e5055545f414d4f554e54556e697377617056323a20494e53554646494349454e545f4c4951554944495459556e697377617056323a20494e53554646494349454e545f4c49515549444954595f4255524e4544556e697377617056323a20494e53554646494349454e545f4c49515549444954595f4d494e544544a2646970667358221220713a8bf21df06433f34b5c9abf186abb737e72524583bdf420105a289791e24864736f6c634300060c0033a26469706673582212209c1e46967e61d91a65487ad45d080a227969fffa0564957df8e023b202f4d62a64736f6c634300060c0033" 219 | } 220 | --------------------------------------------------------------------------------