├── basev2 ├── interfaces │ ├── IJar.sol │ ├── IStrategy.sol │ └── IUniswap.sol ├── vaultBase.sol └── strategyBase.sol ├── kava_vault_addresses.json ├── movr_vault_addresses.json ├── ftm_vault_addresses.json ├── vaultaddresses ├── polygon_vault_addresses.json ├── transform.js ├── vaultBase.sol └── strategySingleAsset.sol /basev2/interfaces/IJar.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.12; 2 | 3 | import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.4/contracts/token/ERC20/IERC20.sol"; 4 | 5 | interface IJar is IERC20 { 6 | function token() external view returns (address); 7 | 8 | function getRatio() external view returns (uint256); 9 | 10 | function balance() external view returns (uint256); 11 | 12 | function depositAll() external; 13 | 14 | function deposit(uint256) external; 15 | 16 | function withdrawAll() external; 17 | 18 | function withdraw(uint256) external; 19 | 20 | function strategy() external view returns (address); 21 | 22 | function decimals() external view returns (uint8); 23 | } 24 | -------------------------------------------------------------------------------- /basev2/interfaces/IStrategy.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.12; 2 | 3 | interface IStrategy { 4 | function harvestedToken() external view returns (address); 5 | 6 | function rewards() external view returns (address); 7 | 8 | function emergencyStatus() external view returns (bool); 9 | 10 | function want() external view returns (address); 11 | 12 | function jarDeposit(uint256) external; 13 | 14 | function withdraw(uint256) external; 15 | 16 | function withdrawAll() external returns (uint256); 17 | 18 | function balanceOf() external view returns (uint256); 19 | 20 | function balanceOfPool() external view returns (uint256); 21 | 22 | function getHarvestable() external view returns (uint256); 23 | 24 | function pairName() external view returns (string memory); 25 | 26 | function harvest() external; 27 | 28 | function setJar(address _jar) external; 29 | } 30 | -------------------------------------------------------------------------------- /kava_vault_addresses.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "vault": "0x7e0aeCA18fe68B7e584984e2EcE7Acd8d5C4D044", 4 | "__comment": "Photonswap KPhoton-Kava LP" 5 | }, 6 | { 7 | "vault": "0xE60Ff9b586E645F80Cd761890F0C548B512A55b2", 8 | "__comment": "Photonswap KPhoton-USDC LP" 9 | }, 10 | { 11 | "vault": "0x2695A6Acc70802e758C4c1D547ed1604de9ffB28", 12 | "__comment": "Photonswap USDC-USDT LP" 13 | }, 14 | { 15 | "vault": "0x5263C50DFc9968aa0EC66407dAde988CDb46ADf6", 16 | "__comment": "Photonswap USDC-Dai LP" 17 | }, 18 | { 19 | "vault": "0xD62676C69a03B3e6F5c3D206Eca54892eefE21e6", 20 | "__comment": "Ruby Finance wKava" 21 | }, 22 | { 23 | "vault": "0x5Df309E6C22Ad6D78685c321Df5582B9C4D61492", 24 | "__comment": "Ruby Finance Ruby-Kava LP" 25 | }, 26 | { 27 | "vault": "0x2225BDc3b28eb3De0957Cd478EeDf92267896e56", 28 | "__comment": "Ruby Finance RShare-Kava LP" 29 | } 30 | ] 31 | -------------------------------------------------------------------------------- /basev2/interfaces/IUniswap.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.12; 2 | 3 | interface IUniswapRouterV2 { 4 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 5 | uint amountIn, 6 | uint amountOutMin, 7 | address[] calldata path, 8 | address to, 9 | uint deadline 10 | ) external; 11 | 12 | function swapExactTokensForTokens( 13 | uint256 amountIn, 14 | uint256 amountOutMin, 15 | address[] calldata path, 16 | address to, 17 | uint256 deadline 18 | ) external returns (uint256[] memory amounts); 19 | 20 | function addLiquidity( 21 | address tokenA, 22 | address tokenB, 23 | uint256 amountADesired, 24 | uint256 amountBDesired, 25 | uint256 amountAMin, 26 | uint256 amountBMin, 27 | address to, 28 | uint256 deadline 29 | ) 30 | external 31 | returns ( 32 | uint256 amountA, 33 | uint256 amountB, 34 | uint256 liquidity 35 | ); 36 | 37 | function addLiquidityETH( 38 | address token, 39 | uint256 amountTokenDesired, 40 | uint256 amountTokenMin, 41 | uint256 amountETHMin, 42 | address to, 43 | uint256 deadline 44 | ) 45 | external 46 | payable 47 | returns ( 48 | uint256 amountToken, 49 | uint256 amountETH, 50 | uint256 liquidity 51 | ); 52 | 53 | function removeLiquidity( 54 | address tokenA, 55 | address tokenB, 56 | uint256 liquidity, 57 | uint256 amountAMin, 58 | uint256 amountBMin, 59 | address to, 60 | uint256 deadline 61 | ) external returns (uint256 amountA, uint256 amountB); 62 | 63 | function getAmountsOut(uint256 amountIn, address[] calldata path) 64 | external 65 | view 66 | returns (uint256[] memory amounts); 67 | 68 | function getAmountsIn(uint256 amountOut, address[] calldata path) 69 | external 70 | view 71 | returns (uint256[] memory amounts); 72 | 73 | function swapETHForExactTokens( 74 | uint256 amountOut, 75 | address[] calldata path, 76 | address to, 77 | uint256 deadline 78 | ) external payable returns (uint256[] memory amounts); 79 | 80 | function swapExactETHForTokens( 81 | uint256 amountOutMin, 82 | address[] calldata path, 83 | address to, 84 | uint256 deadline 85 | ) external payable returns (uint256[] memory amounts); 86 | } 87 | -------------------------------------------------------------------------------- /movr_vault_addresses.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "vault": "0x50E618B129454373FF6F560c90cA334c3C17bc7f", 4 | "__comment": "Sushiswap BTC-ETH LP" 5 | }, 6 | { 7 | "vault": "0x1f7Fa5f767c62704cFdAa4277b378Dbc77DE7DB6", 8 | "__comment": "Sushiswap ETH-BNB LP" 9 | }, 10 | { 11 | "vault": "0x62cbB73a0AaA2009f325dc5ca940cB50bC28FFB8", 12 | "__comment": "Sushiswap USDC-USDT LP" 13 | }, 14 | { 15 | "vault": "0x80546BF73ed61B92aC2eE29f4aC9c016d74cC6D8", 16 | "__comment": "Sushiswap ETH-MOVR LP" 17 | }, 18 | { 19 | "vault": "0x7a7A3A42F0197D99469AFdC4209C2260ac006fB6", 20 | "__comment": "Sushiswap FRAX-USDC LP" 21 | }, 22 | { 23 | "vault": "0x3423892e9C717aeeC56aA4CeeBA213A35c10f3A2", 24 | "__comment": "Sushiswap MIM-MOVR LP" 25 | }, 26 | { 27 | "vault": "0x0a5E266afB071CB0F69310706154F2893a208D1c", 28 | "__comment": "SolarBeam Solar-Movr LP" 29 | }, 30 | { 31 | "vault": "0x4c42f8224E16b40d79BeB775bf1df1a63967FC7c", 32 | "__comment": "SolarBeam Solar-USDC LP" 33 | }, 34 | { 35 | "vault": "0xaE3BDcf55FE53408EC4ad07480368e04c795575d", 36 | "__comment": "SolarBeam Movr-USDC LP" 37 | }, 38 | { 39 | "vault": "0x005d1d02e396D4B47DD92e3c068a6Cec153238cd", 40 | "__comment": "SolarBeam USDC-Dai LP" 41 | }, 42 | { 43 | "vault": "0xB31E2E391251705b53983221AAB3fdB0c728C51f", 44 | "__comment": "SolarBeam USDC-ETH LP" 45 | }, 46 | { 47 | "vault": "0x02C4B3a6FF8b187fb381CD3461229e2c77E0B5f9", 48 | "__comment": "SolarBeam BTC-USDC LP" 49 | }, 50 | { 51 | "vault": "0xA5c44621FDDd448032d22987845c24Edf5c2953D", 52 | "__comment": "SolarBeam Matic-MOVR LP" 53 | }, 54 | { 55 | "vault": "0xa5133eE054a02fDEB7A03909B4bfd73b3C7e16A2", 56 | "__comment": "SolarBeam AVAX-MOVR LP" 57 | }, 58 | { 59 | "vault": "0xa70c8268152D2B06E2313de2273F82D9B031b35a", 60 | "__comment": "SolarBeam FTM-MOVR LP" 61 | }, 62 | { 63 | "vault": "0x39109Dd55Ed30fAd5aF63C8C79Bb5A8BB65e94C1", 64 | "__comment": "Huckleberry MOVR-FINN LP" 65 | }, 66 | { 67 | "vault": "0x98ec2A4afEe2578eF95421D6Ff699A247304D1F3", 68 | "__comment": "Huckleberry USDC-FINN LP" 69 | }, 70 | { 71 | "vault": "0xB1d3857e4435199cD6Bae09F6eCa346355BDbE12", 72 | "__comment": "Huckleberry DOT-FINN LP" 73 | }, 74 | { 75 | "vault": "0x33D33ac00877012943f850026E0aa2D6a0A3a629", 76 | "__comment": "Huckleberry XRP-FINN LP" 77 | }, 78 | { 79 | "vault": "0xfC4246D4B4973d3BF7C3A1e4C16df76fe3fD1dA0", 80 | "__comment": "Huckleberry AVAX-FINN LP" 81 | }, 82 | { 83 | "vault": "0xAAF6A5213AD7180559d626DE29d68decdDeb94FD", 84 | "__comment": "Huckleberry RKitty-FINN LP" 85 | }, 86 | { 87 | "vault": "0x790831a45Ef57B6260e6EdAb2AC81811b8f2Ec7d", 88 | "__comment": "Huckleberry FTM-FINN LP" 89 | }, 90 | { 91 | "vault": "0x0f0A5d5E4057393dC56d71D383D07f71c1961bF5", 92 | "__comment": "Huckleberry USDT-FINN LP" 93 | }, 94 | { 95 | "vault": "0x649680dbcB6486BdDf643C5Ce489F5E568d0C017", 96 | "__comment": "Huckleberry WAN-MOVR LP" 97 | }, 98 | { 99 | "vault": "0xb5f2f033113f8fa4f5Fe4BEd535e05ee308bcAbE", 100 | "__comment": "Huckleberry USDC.m-USDT.m LP" 101 | }, 102 | { 103 | "vault": "0xB816402B0EA623Fa669f59EE4F429BB9a919027e", 104 | "__comment": "Huckleberry USDT.m-MOVR LP" 105 | }, 106 | { 107 | "vault": "0xaBd70eaEB9C0bb58b9b83A102E309ac764fd8801", 108 | "__comment": "Huckleberry ETH.m-MOVR LP" 109 | }, 110 | { 111 | "vault": "0x6FC9F91C3db0190184849fF8d7C92E7d35158F2e", 112 | "__comment": "Huckleberry BTC.m-MOVR LP" 113 | } 114 | ] 115 | -------------------------------------------------------------------------------- /ftm_vault_addresses.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "vault": "0x68B9F58dfB5a7EFfD6ec9a6789E03BB9562aF4aD", 4 | "__comment": "Curve Dai-USDC-USDT LP" 5 | }, 6 | { 7 | "vault": "0x4Ef103DF324b20604e13170377233DDecD15074B", 8 | "__comment": "Curve USDC-Dai LP" 9 | }, 10 | { 11 | "vault": "0xEb4419dBbAFa8885d30994E47e922afbE7eecB4B", 12 | "__comment": "Curve Btc-renBTC LP" 13 | }, 14 | { 15 | "vault": "0x24700792EBCB57859833b8C27A114e569DBC3786", 16 | "__comment": "Curve Tricrypto LP" 17 | }, 18 | { 19 | "vault": "0x632918CE1c5D93E7CB7622e07e3934c24054a8dd", 20 | "__comment": "TombFinance TSHARE-FTM LP" 21 | }, 22 | { 23 | "vault": "0x234765DDD45c287d0565AAb4277f7ceE6Ed3BC4f", 24 | "__comment": "TombFinance TOMB-FTM LP" 25 | }, 26 | { 27 | "vault": "0x80C8513190D237455FEe3bFC4eeaaE6c15627606", 28 | "__comment": "Geist Geist-FTM LP" 29 | }, 30 | { 31 | "vault": "0xc8A4D5611F31f943eC22cd07C7078b7E4d4B9161", 32 | "__comment": "Beethoven-X Beets-USDC LP" 33 | }, 34 | { 35 | "vault": "0xC9f625e17650F69CA877f016aa2e9BfEC17D3Ed5", 36 | "__comment": "Beethoven-X Beets-wFTM LP" 37 | }, 38 | { 39 | "vault": "0xdFdd4e400B429979b774F8f0a1d106A3448350bC", 40 | "__comment": "Beethoven-X wFTM-BTC-ETH LP" 41 | }, 42 | { 43 | "vault": "0xf58d2F9A4c1F6b469Df1E77DAD99C0B99e82a722", 44 | "__comment": "Beethoven-X wFTM-Sonata" 45 | }, 46 | { 47 | "vault": "0x380DF95878feF749b19E468Ef4C1698a224a8990", 48 | "__comment": "Beethoven-X USDC-Eth LP" 49 | }, 50 | { 51 | "vault": "0x451918789b42814A314Ea2856d94E4ddB4d3430f", 52 | "__comment": "Beethoven-X BTC-USDC LP" 53 | }, 54 | { 55 | "vault": "0xb7F0b6d865B187D6E8d0FF734D4c6d616650C705", 56 | "__comment": "Beethoven-X BTC-Eth-USDC LP" 57 | }, 58 | { 59 | "vault": "0x184E361C92157bd44A28B6C4bC069588Ec0E97E2", 60 | "__comment": "Beethoven-X USDC-FTM LP" 61 | }, 62 | { 63 | "vault": "0x54d863a6dA9489d809581947C1305384e4D9F420", 64 | "__comment": "Beethoven-X FTM-Dai LP" 65 | }, 66 | { 67 | "vault": "0xE60Ff9b586E645F80Cd761890F0C548B512A55b2", 68 | "__comment": "Beethoven-X MIM-fUSDT-USDC LP" 69 | }, 70 | { 71 | "vault": "0x7D9F24523C73C46fB333777cF9688AF1AeA0Eb03", 72 | "__comment": "Beethoven-X DanceOfDegens LP" 73 | }, 74 | { 75 | "vault": "0x5751834D7e49863De62F545eb3283850D3ecf8Ec", 76 | "__comment": "Beethoven-X TheMagicTouch LP" 77 | }, 78 | { 79 | "vault": "0x7F5Fd897a936A9E4D40C2560c45f5600a43cb409", 80 | "__comment": "Beethoven-X Mai-USDC LP" 81 | }, 82 | { 83 | "vault": "0x9d0476F35f73d1D5bDB45CF64CFF2c32ec3Fa3a0", 84 | "__comment": "Beethoven-X Mai-Dai-USDC LP" 85 | }, 86 | { 87 | "vault": "0x12FEFE92fd9c6d3F9DcF8bE4978F84ac90048A9F", 88 | "__comment": "Beethoven-X FantomConservatory LP" 89 | }, 90 | { 91 | "vault": "0xe35369AEb6A09675DFb3c30A98ebFfA71EF439a4", 92 | "__comment": "Beethoven-X LateQuartet LP" 93 | }, 94 | { 95 | "vault": "0x55eE8a91b91B2a73075106FF5d6e9A2eBC6c2a58", 96 | "__comment": "Beethoven-X IceAndFire LP" 97 | }, 98 | { 99 | "vault": "0x4C59Fe438B54950Bd95d27A0677cb1c774650D55", 100 | "__comment": "Beethoven-X BaronVonBnb LP" 101 | }, 102 | { 103 | "vault": "0x211935dadeE885Eb6b686a7e27538Cc7DaFdC305", 104 | "__comment": "Beethoven-X TubularBells LP" 105 | }, 106 | { 107 | "vault": "0x6dF8d03066E321508f59A6eA6373C17e91371fA4", 108 | "__comment": "Beethoven-X USDC-Dai LP" 109 | }, 110 | { 111 | "vault": "0xfA31a189709262E70AC42CD71d3795a58473e321", 112 | "__comment": "SpookySwap FTM-BOO LP" 113 | }, 114 | { 115 | "vault": "0x6642617882Db7218770E9b13F57eE4c6207F175b", 116 | "__comment": "SpookySwap USDC-FTM LP" 117 | }, 118 | { 119 | "vault": "0x1F6c36C8a3a68D8a2B5C5Dee7f69dbB918995F30", 120 | "__comment": "SpookySwap FTM-WETH LP" 121 | }, 122 | { 123 | "vault": "0x0E441af528EE6e503FD8F48F46F9F24121b7A139", 124 | "__comment": "SpookySwap BTC-ETH LP" 125 | }, 126 | { 127 | "vault": "0x59413fFE8b41FE3b1f01ef7Da9D1D0929fB0F49c", 128 | "__comment": "SpookySwap FTM-BTC LP" 129 | }, 130 | { 131 | "vault": "0x75EA68202F413dc357180Ff72FE547Bf9442bFB5", 132 | "__comment": "SpookySwap FTM-DAI LP" 133 | }, 134 | { 135 | "vault": "0x0a5E266afB071CB0F69310706154F2893a208D1c", 136 | "__comment": "Abracadabra MIM-fUSDT-USDC LP" 137 | }, 138 | { 139 | "vault": "0x51DACd87f0CCb9B36B41EdAA2A0f0AbaeB360863", 140 | "__comment": "JetSwap fWINGS-FTM LP" 141 | }, 142 | { 143 | "vault": "0x2bCaE64b1D73C9C38CDb2714BeEe96dB3e7e8195", 144 | "__comment": "JetSwap fWINGS-USDC LP" 145 | }, 146 | { 147 | "vault": "0x355434F8aF4B918738450BBD919C993B9128aEac", 148 | "__comment": "JetSwap USDC-FTM LP" 149 | }, 150 | { 151 | "vault": "0x14DA37c0E647D85Ee0d255481CE6aB3dD54a87bc", 152 | "__comment": "JetSwap ETH-FTM LP" 153 | }, 154 | { 155 | "vault": "0x13c7210E630Bc3329F0476F762A9727105D671DF", 156 | "__comment": "JetSwap BTC-FTM LP" 157 | }, 158 | { 159 | "vault": "0x75836AD63aE0AAd9AF857400e9e8ea370A945d85", 160 | "__comment": "JetSwap BTC-ETH LP" 161 | }, 162 | { 163 | "vault": "0xa4648B8d95377904E16269cB694466E0F4237154", 164 | "__comment": "JetSwap ETH-USDC LP" 165 | }, 166 | { 167 | "vault": "0x2a6CBFC07d9b66c10733c3Cba3188B44af683CFF", 168 | "__comment": "JetSwap BTC-USDC LP" 169 | }, 170 | { 171 | "vault": "0x91DC6E84867B58F0945CeD3138c862a3A15A84a7", 172 | "__comment": "JetSwap fUSDT-USDC LP" 173 | }, 174 | { 175 | "vault": "0xD1FDFB2BE4fd5e7Ee5b9D6E91538b2cf073B8AA2", 176 | "__comment": "SpiritSwap USDC-FTM LP" 177 | }, 178 | { 179 | "vault": "0xc447E9a3fFbCa924Aa8CF9A2301975515DaE9661", 180 | "__comment": "SpiritSwap fUSDT-FTM LP" 181 | }, 182 | { 183 | "vault": "0xfF3349c817B795a0A44c74B823a765B31C226038", 184 | "__comment": "SpiritSwap MIM-FTM LP" 185 | }, 186 | { 187 | "vault": "0x02bc4F42b998FC23355c780A756446d9998d78dE", 188 | "__comment": "SpiritSwap LINK-FTM LP" 189 | }, 190 | { 191 | "vault": "0xB49fecd52B88EFA8248BF2408e4ff08EaFC85b91", 192 | "__comment": "SpiritSwap CRV-FTM LP" 193 | }, 194 | { 195 | "vault": "0xFc68488ca2DdEBBdcd980AafDde2E3374F5AD222", 196 | "__comment": "SpiritSwap ICE-FTM LP" 197 | }, 198 | { 199 | "vault": "0x5a94Fd3A5D58fbB97F817223aA2Ea6773fE7dA57", 200 | "__comment": "SpiritSwap SPELL-fUSDT LP" 201 | }, 202 | { 203 | "vault": "0x7641b2dF3d37fE5007EE09d7e21294c0E2c4c342", 204 | "__comment": "SpiritSwap MIM-wMEMO LP" 205 | }, 206 | { 207 | "vault": "0x9D26e1fb94Dc683F578678cfAC877Cd4ac9124E7", 208 | "__comment": "SpiritSwap Spell-sSpell LP" 209 | } 210 | ] 211 | -------------------------------------------------------------------------------- /basev2/vaultBase.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.12; 2 | 3 | import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.4/contracts/token/ERC20/ERC20.sol"; 4 | import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.4/contracts/token/ERC20/SafeERC20.sol"; 5 | import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.4/contracts/access/Ownable.sol"; 6 | import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.4/contracts/utils/ReentrancyGuard.sol"; 7 | import "./interfaces/IStrategy.sol"; 8 | 9 | 10 | /** 11 | // OpenZeppelin pausable: https://github.com/ConsenSysMesh/openzeppelin-solidity/blob/master/contracts/lifecycle/Pausable.sol 12 | * @title Pausable 13 | * @dev Base contract which allows children to implement an emergency stop mechanism. 14 | */ 15 | contract Pausable is Ownable { 16 | event Pause(); 17 | event Unpause(); 18 | 19 | bool public paused = false; 20 | 21 | 22 | /** 23 | * @dev Modifier to make a function callable only when the contract is not paused. 24 | */ 25 | modifier whenNotPaused() { 26 | require(!paused); 27 | _; 28 | } 29 | 30 | /** 31 | * @dev Modifier to make a function callable only when the contract is paused. 32 | */ 33 | modifier whenPaused() { 34 | require(paused); 35 | _; 36 | } 37 | 38 | /** 39 | * @dev called by the owner to pause, triggers stopped state 40 | */ 41 | function pause() onlyOwner whenNotPaused public { 42 | paused = true; 43 | emit Pause(); 44 | } 45 | 46 | /** 47 | * @dev called by the owner to unpause, returns to normal state 48 | */ 49 | function unpause() onlyOwner whenPaused public { 50 | paused = false; 51 | emit Unpause(); 52 | } 53 | } 54 | 55 | 56 | /* JarBase contract */ 57 | 58 | abstract contract JarBase is ERC20, Ownable, Pausable, ReentrancyGuard { 59 | using SafeERC20 for IERC20; 60 | using Address for address; 61 | using SafeMath for uint256; 62 | 63 | IERC20 public immutable token; 64 | address public immutable strategy; 65 | 66 | struct UserInfo { 67 | uint256 lastTimeStaked; // How many LP tokens the user has provided. 68 | uint256 lastAmountStaked; // Reward debt. See explanation below. 69 | } 70 | 71 | mapping (address => UserInfo) public userInfo; 72 | 73 | uint256 public constant keepMax = 10000; 74 | uint256 public constant maxDepositFeeMC = 1000; 75 | 76 | event Deposit(address indexed _from, uint256 _value); 77 | event Withdraw(address indexed _from, uint256 _value); 78 | 79 | constructor(IStrategy _strategy, string memory name, string memory symbol) 80 | public 81 | ERC20(name, symbol) 82 | { 83 | require(address(_strategy) != address(0)); 84 | _setupDecimals(ERC20(_strategy.want()).decimals()); 85 | token = IERC20(_strategy.want()); 86 | strategy = address(_strategy); 87 | } 88 | 89 | modifier onlyEOA() { 90 | require(msg.sender == tx.origin && !address(msg.sender).isContract(), "no contracts"); 91 | _; 92 | } 93 | 94 | function transfer(address recipient, uint256 amount) public override returns (bool) 95 | { 96 | require(recipient != address(this)); 97 | return super.transfer(recipient, amount); 98 | } 99 | 100 | function balance() public view returns (uint256) { 101 | return 102 | token.balanceOf(address(this)).add( 103 | IStrategy(strategy).balanceOf() 104 | ); 105 | } 106 | 107 | function depositAll() external { 108 | deposit(token.balanceOf(msg.sender)); 109 | } 110 | 111 | function deposit(uint256 _amount) public nonReentrant whenNotPaused onlyEOA { 112 | 113 | IStrategy(strategy).harvest(); 114 | 115 | // Calculate initial pool balance 116 | uint256 _pool = balance(); 117 | 118 | // Transfer token to strategy and calculate amount to stake 119 | uint256 _before = token.balanceOf(strategy); 120 | token.safeTransferFrom(msg.sender, strategy, _amount); 121 | uint256 _after = token.balanceOf(strategy); 122 | uint256 _toDeposit = _after.sub(_before); // Additional check for deflationary tokens or deposit fees 123 | 124 | // Stake and calculate pool balance after 125 | IStrategy(strategy).jarDeposit(_toDeposit); 126 | uint256 _afterPool = balance(); 127 | uint256 _newStaked = _afterPool.sub(_pool); 128 | 129 | // Require deposit fee to be within reasonable bounds 130 | uint256 maxDepositFee = _amount.mul(maxDepositFeeMC).div(keepMax); 131 | require(_newStaked.add(maxDepositFee) >= _amount, "!MC DEPOSIT FEE"); 132 | 133 | // Compute share 134 | uint256 shares = 0; 135 | if (totalSupply() == 0) { 136 | shares = _newStaked; 137 | } else { 138 | shares = (_newStaked.mul(totalSupply())).div(_pool); 139 | } 140 | 141 | // Send share of pool 142 | _mint(msg.sender, shares); 143 | 144 | // Save last time/amount staked 145 | UserInfo storage user = userInfo[msg.sender]; 146 | user.lastAmountStaked = balanceOf(msg.sender).mul(_afterPool).div(totalSupply()); 147 | user.lastTimeStaked = now; 148 | 149 | // Emit event 150 | emit Deposit(msg.sender, _amount); 151 | } 152 | 153 | // Withdraw all balanaces 154 | function withdrawAll() external { 155 | withdraw(balanceOf(msg.sender)); 156 | } 157 | 158 | // Withdraw some balances 159 | function withdraw(uint256 _shares) public nonReentrant { 160 | uint256 r = (balance().mul(_shares)).div(totalSupply()); 161 | _burn(msg.sender, _shares); 162 | 163 | // Check balance 164 | uint256 b = token.balanceOf(address(this)); 165 | if (b < r) { 166 | uint256 _withdraw = r.sub(b); 167 | IStrategy(strategy).withdraw(_withdraw); 168 | uint256 _after = token.balanceOf(address(this)); 169 | uint256 _diff = _after.sub(b); 170 | if (_diff < _withdraw) { 171 | r = _after; 172 | } 173 | } 174 | 175 | token.safeTransfer(msg.sender, r); 176 | 177 | // Emit event 178 | emit Withdraw(msg.sender, r); 179 | } 180 | 181 | // A view function that makes it easier for the UI to display LPs of users 182 | function getRatio() external view returns (uint256) { 183 | if (totalSupply() == 0) { 184 | return 1e18; 185 | } 186 | return balance().mul(1e18).div(totalSupply()); 187 | } 188 | 189 | 190 | } 191 | 192 | 193 | contract vaultBase is JarBase { 194 | 195 | constructor(IStrategy _strategy) 196 | public 197 | JarBase(_strategy, 198 | string(abi.encodePacked(_strategy.pairName(), " ","vault")), 199 | string(abi.encodePacked("v", _strategy.pairName())) 200 | ) 201 | { 202 | 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /vaultaddresses: -------------------------------------------------------------------------------- 1 | [ 2 | "0x992Ae1912CE6b608E0c0d2BF66259ab1aE62A657", 3 | "0xb6D7bA013e13C3f00a20826aF2008C83228eD50a", 4 | "0x84a9c05b9F52FfD041eA1cFD6f56031d50DECc5c", 5 | "0xECbCe31d1723611Db11358a186B9328ce65D78cc", 6 | "0x4a93D6b394Da4c1e6e436e9370E5DF08A45377a8", 7 | "0x34F0B8B2c3A82BCcb91dcA4Fc45EC8dC78132ccB", 8 | "0x8402c67fC92691c745E0Bbbe4989eB07Bc02c335", 9 | "0xB608A48aa322F2541bD65449148147c3935EBc5e", 10 | "0x69aAF33Cd4bd6Cbd3Ef275f8Ddc3342e0365F083", 11 | "0x81D61D56A19469259cDA912b5d1Eb0DCA6199A87", 12 | "0x36CB30b0223C16B7275A3C3641b7b5D5ad1433CB", 13 | "0x0051eCd6C71307313fd494e486E5d3bEfDa5CD04", 14 | "0xDc067a54161B9200d97CBEB84D983ca4Ee284d0A", 15 | "0x54A6ebb2f616e7a8C12f53D39Fc7AC1dD4f0C4F3", 16 | "0xCbfF2Efd73C3b3fd86130aE295d27017De16E025", 17 | "0xF0Ad1b426bb081D67533b76DC0efc8b0Fb08F826", 18 | "0xaB6707A9A19965594334Ec334cC82213D796f02B", 19 | "0x8B74b3F6ad25F8d55f272115AE7e83649Bcf1E50", 20 | "0xE8B31C01753AA167F99bCbbEC5127ee8169C1D71", 21 | "0xb17372A7BD7e76aa009Bd5062B42a5C0A88638b3", 22 | "0x5CEE9B233EACa8d93C2038D229EBb6670E8581BF", 23 | "0xd5E3Dc5e2de2fCa311150164258c093EF5EcAC3F", 24 | "0xd1C7962b4D007E10adb1bF977185dCA6f5A6fE9C", 25 | "0xAE2cb3830d7617f865b520bEB7d2fca3e37cFE51", 26 | "0x28c6c6e459E8e6AF7f8C9d61D7d4C3932854b8f3", 27 | "0x4792b5943a05fc6AF3B20B5F1D1d7dDe33C42980", 28 | "0x99dE9f6ACc587726FE72AC8F6E2b4a6563c98Af9", 29 | "0xBF773f00C3aE7B1eE9641c7e1cF14FdDCDC0CEBb", 30 | "0x967e9A7A23E68cc6A0e8b98db8C079f133580760", 31 | "0x9abF2f2acBce703Eaca4430F7E44Ab9098b60C48", 32 | "0x720726a3546B1f9CF145093bcdc293E149e2e07F", 33 | "0x57bc21ff1236A3fDE7164FCe75c97E3e0714CCB5", 34 | "0x0DCc3Cd939e347dAaaA5b5729E6A2DAf52E4F402", 35 | "0xEab5DAC8E6E3da7679b2a01FCD17DBE1Ed519904", 36 | "0x1ddE2a134E4dE3D0c85bb3f0816f343B9a861B64", 37 | "0x51AC169E6139E3bebaf8D51A8867b921a77E9d99", 38 | "0x5C744bA989Ef8f68c6EB97241cC9B5EA7AdF9904", 39 | "0xC2c5a92E4dA9052aF406c0b97f09378C51a7E767", 40 | "0x4aF74D22399DFcaD732A5504aa2E2c13b25303f4", 41 | "0x3c928f0eE37bafeB6e90D835e7000ef533A09472", 42 | "0xaE48aCc701151061A5bfff8e4c3f0DCfe4A957E9", 43 | "0x42064982010d0881c7A6BC89D83B32309bd17a99", 44 | "0xec05278322536650D3671D58672AC1B856cbc5f5", 45 | "0x15d5a8a94d4f65474fb150ee994119Ac561C9324", 46 | "0xF9cc76F275aCe60f11CBDd458214Bf86366e9930", 47 | "0xc74e6DcF602e81FC10dE4FE852Ab4243412E0Dd9", 48 | "0xA1e13449EA8218Ab2e3ea0CF841d39A61b2024D9", 49 | "0x2002ac0EE6Fb936d5F0d52ACebAB581a3dF5F971", 50 | "0x05e30F9b15a88f911c58D63EdAc8B60d24488AeB", 51 | "0x4B7E2DFDDFcA7aB50c4bEdc2721EceD34c8c79F6", 52 | "0x64ec0D31EA0345BCBf29855d7C0B74b5Dcc78fd9", 53 | "0x23f9c7097157c0f6Fdbf355D8fB8914f4711Ab05", 54 | "0x7a9be7CdF26C8311625ed97c174869fcA9b791eC", 55 | "0x00567b197A3506e8D05Dc8aA21E8Ce250dbcE13c", 56 | "0x92FB3E8323baDBEE16f4E69De52D3a0b5BA39C7C", 57 | "0xD33eDaB4e24D7471e8b772Fbc1f6b068d99FE391", 58 | "0x55A2FedB176C09488102596Db21937A753025466", 59 | "0xfC7B6d0f6157a1971679f5aF7F5B6374694E658f", 60 | "0x3De0305D703b5ce1A748D174e29BA38e7C834005", 61 | "0x79D2F222c67e954AcAc8eCF3166cefAEB6cb56D0", 62 | "0x2f026c3b0fdCcF941FB07A62F4803CAF36e45859", 63 | "0x0CB25E588E0dF55Fb6B4407884D6B3B553D16095", 64 | "0xD02064bEd4126ACCCe79431A52F206C558479648", 65 | "0xfee30B81bD194f23dc5AcC23769410Beab3adB21", 66 | "0xA838F1e986b27d7AC5a977c7d0eCbADFFCDC7Bb5", 67 | "0xa3F49c515b3c45294D3F9B5A4525AF6223EDf954", 68 | "0xa67153C4b30f24F60286C664547aeE010AE87F1D", 69 | "0x85eFa41967c508f6F2f5236B08E734cce88BC7e1", 70 | "0x1e187A8Fc90e5DCbbfd25B473e17955Efe6E15E5", 71 | "0x17754aCE28b367dc0ee5B9D00232B1Feb05664c5", 72 | "0x24771c6C514F0307b01dC14e361c311B8E9823b5", 73 | "0x74EeB0121f82784622Df86C9c2b1FEE61541B03b", 74 | "0xE48aA84AB5A0Ee50e08fc12dfaED0ada08a1aA5d", 75 | "0xa4FEb444c17FBe341e2481B89e1574DA1ab0A833", 76 | "0xa5B762Df7b6491f30A62681b2F988977a98A07Fe", 77 | "0x45a686CC6a9627a2fb2e4f44104c6EC09594bA93", 78 | "0xFc0Da0cBAab796e983b3c0ee42bE6edC498AEf61", 79 | "0x4ce450F7aa450ADd27E7F3631d1Ab1Cca56e1A3D", 80 | "0xB01705A4fe67D957E7e328834f09608359313065", 81 | "0x3528DB3895423c71d64D0F040D88B036B4579471", 82 | "0x9F807bf6FDfCa49adEA2a7a87cB86e9c3BacCC0a", 83 | "0xF31049674cb4d43edE717d430a5b16066ecD4EFA", 84 | "0x029f402412e0Ee600929Ae878473C4c9d2976E15", 85 | "0x8946C7a0b15a0d477A31F7cc06592cf356378D76", 86 | "0x8885A65E887E14Bd09F5112cA03D130076f65B6b", 87 | "0x0C776471CB3Ac5be3a0e7560C7B87977a5Ac0be2", 88 | "0xC9D6b9D95070f924E511415bb4a7640997704E4C", 89 | "0x8e66a05C09b31e12f65b71Eb36F46b7E249cEaa5", 90 | "0x2F47fBD707D9dFB3CAb292700b71A3681DEB0721", 91 | "0x9790a55E43a79f30e04f0B39FC766028950E793F", 92 | "0x88f87372bDe5E2242e1a7996B4472dE490AF8453", 93 | "0xba4A9A92fc9ae91Bb26f31D7Dc538e44Ab04f2a3", 94 | "0x7Bd9e5F441D2013c473c3e366F2883b9A6cf9091", 95 | "0x14d09C69163F94D7f5e674A004F224F24739A56C", 96 | "0xEB2852258F0E4117352bA3364E599dc980681c2e", 97 | "0xC918945e4785D7ffd3f801407368c3d5e32A7C18", 98 | "0x26e028B287486E0Daa6D4658cc70E7c3aDc75891", 99 | "0x43f28AAe9fcefA47D5d7835B0a9Eb86E36F035A7", 100 | "0x2A60105aB70Eb62A7EEaa04b2748a8054cA6D6aE", 101 | "0x8715Bb8f3157C7cA5bB379A107C9b810f11F7815", 102 | "0x00e80B9137560D0A0Abe5Ed39D39F5b0F5804237", 103 | "0x94d00dEe78f4b79CA8c07E0b2B00039b6B87c236", 104 | "0x33c7f2cD56506e3Eac79984E96453b517D532D1e", 105 | "0x7E90B622b8891e736247fFEE896dD2a1B3f9142e", 106 | "0x65378692264B09Ca93740F439dFA5A7978A821b1", 107 | "0x7B612e2A58F31Eb482812D1F3529e001655e6EB9", 108 | "0x79c3f7c36ACb46Ee566c2c33B9DdE4668eC069a6", 109 | "0x55D51F0C3215085e45BA7041d32Fc8d4890570fE", 110 | "0x95a56528Dcf6e8eC4c020Af18f869eA77b76E265", 111 | "0x5AA51B3890bAEdFB3BF570a6345D5F3B2A6ddfDf", 112 | "0x084A5e96F3EE81909bF8e4De5Ad3a823616Bd08f", 113 | "0xE5C7986950e10541CADC1646ff227aCA52F7995D", 114 | "0x64c20BB3D9aCD870f748fe73B6541D500643e490", 115 | "0xb99898440ff53A7f36422faee7030F4785452636", 116 | "0x82d007ffcd3DCCB60b461085Ecd11Fb5812A7335", 117 | "0x092b0a3e0d7b17E837a2ae8664885406D06bcB99", 118 | "0x885B1248D36fB83E824AD49eA637Ea7998C0Ca54", 119 | "0x2Cb2c97F28cC58de6bD3d379919dD66Ba1801c65", 120 | "0x9A7D67a685251567B0AEe4CA08402A1A9f8a1D05", 121 | "0xA0be41bF0454d1CDd4F19CDDC5A23A1D254722ed", 122 | "0xA6B3647DeCdefB4CE5D855250517f5EaE462F617", 123 | "0x66F483df4aE87991539B042E8320Ac21dD33A677", 124 | "0xaE3e4292705e5052aCA9054B4003421F717A521C", 125 | "0xB062BB2dC24FF6B764a9Cd32973674268bB8dfad", 126 | "0x453f0CdBE6cB2C56ac38A171Ff80d41981f9f149", 127 | "0xA7BEFC58c2e14e8f22E5566E49c05a7e7E6F054F", 128 | "0xfAa6Ca9A5FED9cAEF91711283d59F0EebE782a23", 129 | "0x5E0F3303218a3665a2707a1D01EDEe78Abe9F3D6", 130 | "0x4C389275c52b2A2b07E444cf0223744668A54b52", 131 | "0xBa1998aD991DDC36f9f927764d0950F10654cbE7", 132 | "0xAD367134f993D8C2d62A1255FE1252A18d5C78ba", 133 | "0x2E084932ECf2df9ad7841E7838Dd39f47Ea4e695", 134 | "0xbfE130aBd54F202dd7f8C3cdAe7C993fCd703f8a", 135 | "0x4e1578399F02F8f33c0911159dC61F5c9Adf1B25", 136 | "0x92F42e22D812C0C8ADFC30190faC42919032E19B", 137 | "0xbE3Eb5Ce0aB2223428995dDD799f551E200166B3", 138 | "0xE4a966c8225BA2A5dd7B4861AB5fe3570E002629", 139 | "0x0850B134Ba40943941a0e31F4850737Bb0700CDe", 140 | "0xE0011c255B8E7A5939e41913e3657D7852d50a9a", 141 | "0xd606Bd85424F372ec96DBDAcBB7ca7f9Bf04f270", 142 | "0xc0892B586636528a0ECd1dD16256867271C5C3b7", 143 | "0x1173c353e93342B337098b63B0B64226645Fb79d", 144 | "0x50B808875e9722E0bDADB7211f486D8E49a2ceB9", 145 | "0xFAf49e554778e9D11F8a646679fDBf406B871556", 146 | "0x883200d4E483d01eEef2ffE96d37f9Df1E85d954", 147 | "0x58051a556D3a2AA60c99F0758998998b884Bf216", 148 | "0x35F77cED3A5387Fe221Cd6C0cf0E02A93857861D", 149 | "0x1d7245824B0d7f7c08C0d8fdDEC66a2C49c20A95", 150 | "0xCA411AF0d316a05f33C9635f3e68276e4F575dc6", 151 | "0x106BAc65d64a68e6fa8fD8414D8ACb09dAe4ea1a", 152 | "0xb33576835cC51EF8D71ccB861775B2821470bb71", 153 | "0x3F5912c3312B73483Cd8015A7881Ef40118d50C6", 154 | "0xe5B7402d8Ccae02D3BaA65140a50B26f876cec8b", 155 | "0xb7D3e1C5cb26D088d619525c6fD5D8DDC1B543d1", 156 | "0xE28809B6070DB755b01303d03Dc0476F49A96B17", 157 | "0x3BF440465b8E5A36cac9e6B6F4300b461B42C9A6", 158 | "0x9ea363902D086A4707F71d7AF6Fb91DAf7aE4948", 159 | "0x5C3533B44d7c3e804C428A57C426577CA899A311", 160 | "0xeF721dc8AACFA0F2113DBfcB08a77207a220FEe9", 161 | "0x5781135c882d4Fc8c61D0C826123761F20F67153", 162 | "0xCc72AF943EF649B540021590fF349A454b5E2e9a", 163 | "0x52fd74517b9728E4a8c6A44a6D5efeECB49e2aC5", 164 | "0xf5bc9A2251A1Ae5AEeb0286CC9562608E8bDb824", 165 | "0x9A547d7c5359cd19C95A0c88C0967B715Cd19601", 166 | "0xf15b4FDc78a87786d3f3d775cB5E27847348490C", 167 | "0xb7b5641442C1762586AA03Fdc4Fa4200CB57D4e5", 168 | "0xCc5579577AD2F499F2d3583FCb4aFD765510A33B", 169 | "0x759DCd61C021eDC0365882048C726462fA05F642", 170 | "0xd6a9550Fe158b477bC12af882911CB5e89295D39", 171 | "0x53197CBe1cBeb417089cAAb3B5fB16391EDe0a69", 172 | "0x01E02c272f0436317B1d05C350ED9C5482777aAb", 173 | "0x0D3389DB05bC0d21961fEFd8b54B92558D798Fe2", 174 | "0xdc351171072F753409f52910449af613A2FA202a", 175 | "0xa8974E37d2B9dF1c9dDD49e7D6363d32D366D976", 176 | "0xc1f26fb014eF6EAa600ba95dAa18dDb0FeFaCC91", 177 | "0x41a3dDd6f2502689Bfd6170026ac45DC810E8037", 178 | "0xa32de2a04f68a17F6289105ce98baaA97f415309", 179 | "0x8488E2f70055fdc2aCDF511Be789AEb93ae0B1B3", 180 | "0x15113393DB8B1Cd9781E04499b942AE1A3412763", 181 | "0xEC56A5a3c43Ef9e60F7baE05254f5bE6eae4bdB5", 182 | "0xA6633cE2A7Bb69D3B1d34D56c95Aa0F59FFF6f57", 183 | "0xa807d2892698190207E6f66d35DFbF0a227f51f4", 184 | "0x1CFef93D79d0421cf5e21bbeAF8F8f389BA3A5B6", 185 | "0x96d1DB482032eE964D344Ca44B2AfE4B8f96f8d2", 186 | "0xa18A9C9527aCFCa8F697c8691687DA254F773f99", 187 | "0x89030969DB2B51897D7f4C789b7C9d3c2ef05083", 188 | "0x67cE36bf3106D782Ca06EEFa937d14f2D054ebe4", 189 | "0xb9F9E41ac77A6B6E90e7EC26D9CDcEdB194F508A", 190 | "0x9762Bb14a5E9a2Fa94eb5FB9D241FA3d4893e6A5", 191 | "0xFa10DbeFA09f369E191eD385FccC63c7De22bcd0", 192 | "0x93da5BAF95E313C99B76A98974D27d6eb32B2996", 193 | "0xE057c5b2e0eDbE5c336123409B0346d889286DdC", 194 | "0xae39a17C457d7fB75C0D5FAf96F685483aBD570b", 195 | "0x37E45856616Cf8CeE2E3a69C7C401b6163552afF", 196 | "0x1478883920113b91991a9520252347e3274a6396", 197 | "0x0eB72cd5f9911C307a0E3B07426a7FDeb4588600", 198 | "0xeeb87B59b162B54a7f61DD7C0E7157984A56f506", 199 | "0x424D5E4000a0795c4CAaa3ee252B1Ae13d4cA39B", 200 | "0xa937941C8CC9A21d0c6B866Fd2eEaED78B8C2834", 201 | "0x1B247E74d5c2D6CeF12C9BEc8115282CbC45c8B5", 202 | "0x36DFEAE548Cfc9A8335624Cffc3fCDF80a5141f2", 203 | "0x8b9C797DBcFAD409747962D1FE4718a9660dB94b", 204 | "0x846C27ec821F67A9177C56F0cA6FEc4cfc5e5C8E", 205 | "0x379566E654D071E917332F9aA7A10587D09059e9", 206 | "0xF457000D481Df3c486DFD38d8Fa0C4Fc949a6BbE", 207 | "0xA89414dD5E57b896a3b20137d36B46a3AF12066A", 208 | "0xeAdCb0469f05fa07d4f5178FC762C5C872b6D9c0", 209 | "0xa104c9Aad3EE07676D23159282124dCD3F542c62", 210 | "0x82e553b4B645A195BEA0E6C78c05483a07cf6116", 211 | "0x24Dbf973CC3fe6357cAB6394d94781784A55D930", 212 | "0x55C08f4F053170009010cF7435064d5e0E6905E3", 213 | "0x58201C1331Bf7f36ed326af0789A33851019875b", 214 | "0x2D03892d0fAE4479aE2B0d945f67675F006F7271", 215 | "0x54507Ee8E18FB6d7E4771A6619b04a84635bFf4B", 216 | "0x58FE96934a595Df1C03BddA09F0fdba38063770B", 217 | "0xB131089e899a6F2E7726b83b85C32bbE097b138b", 218 | "0x510D776fEA6469531f8be69e669e553C0De69621", 219 | "0x8a8c784DDE052dE731a4477Bb95B4F594f5B9Bc3", 220 | "0x6726775952DE79b66c2340fCB4DD1cb3D48944E5", 221 | "0x0e0BCba8269f5d2192Ab8ABED301Ee229DE0F244", 222 | "0xb9A4d32a547a4865E5247D611De7F3D7F3B2d378", 223 | "0x17051bB60771888Bc908B6946F4Fb7850042FE1d", 224 | "0x2f3E17b34A79F4990153EE5588aC04724E773C6E", 225 | "0x97B0262670F3F640A6Be287f403302E2285F5A87", 226 | "0xDF47221A2240754245dD3b88e01100C0d1d85Aa9", 227 | "0x7f9fc5bA0c2d213C9Eee7940fefA1a7a297B2320", 228 | "0x12977EdF05A6718036f4ecc9bE2D26366a97B96b", 229 | "0xe1A9ab14B4c0efa25a1EE6f1348ef4C34418c258", 230 | "0x05d83F3Ef95F921971763b035c00298BC42ff008", 231 | "0x2bb510a979fe3f277636A94B86FA304c6631581C", 232 | "0xEa2F645691d114f0A7Fa7a759032F8c6f90D58d5", 233 | "0xF0db902352dfe1EaF8deb2a2eb5c760568821f58", 234 | "0xbFad80456C71BE0fdE53ecd623605662cF808e53", 235 | "0x0Be469DE6635A71a07Df915D65D5f08Fb4ac007F", 236 | "0x4929f3D8934640Fd93a21E89Cd22ddb4b2aff8c1", 237 | "0xE80D7246EcD89Cb8707001c61f652B90eeA0dbc4", 238 | "0x72812112d635873F5fEF2b0bcAb22cC5BBA2E0dD", 239 | "0xaA5237Ff567987445e1AC35D5148c11Ef3703173", 240 | "0x9A48219D7b3106BaAD3F5D6Cf50d94F1Cf747C8D" 241 | ] 242 | -------------------------------------------------------------------------------- /basev2/strategyBase.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.12; 2 | 3 | import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.4/contracts/token/ERC20/ERC20.sol"; 4 | import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.4/contracts/token/ERC20/SafeERC20.sol"; 5 | import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.4/contracts/access/Ownable.sol"; 6 | import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.4/contracts/utils/ReentrancyGuard.sol"; 7 | import "./interfaces/IJar.sol"; 8 | import "./interfaces/IUniswap.sol"; 9 | 10 | 11 | abstract contract BaseStrategy is Ownable, ReentrancyGuard { 12 | using SafeERC20 for IERC20; 13 | using Address for address; 14 | using SafeMath for uint256; 15 | 16 | // Tokens 17 | address public immutable want; //The LP token, Harvest calls this "rewardToken" 18 | address public immutable harvestedToken; //The token we harvest 19 | 20 | // User accounts 21 | address public strategist; //The address the performance fee is sent to 22 | address public jar; 23 | 24 | // Events 25 | event SetStrategist(address indexed _newStrategist); 26 | 27 | constructor( 28 | address _want, 29 | address _strategist, 30 | address _harvestedToken 31 | ) public { 32 | require(_want != address(0)); 33 | require(_strategist != address(0)); 34 | 35 | want = _want; 36 | strategist = _strategist; 37 | harvestedToken = _harvestedToken; 38 | } 39 | 40 | // **** Views **** // 41 | 42 | function balanceOfWant() public view returns (uint256) { 43 | return IERC20(want).balanceOf(address(this)); 44 | } 45 | 46 | function balanceOfPool() public virtual view returns (uint256); 47 | 48 | function getHarvestable() external virtual view returns (uint256); 49 | 50 | function balanceOf() public view returns (uint256) { 51 | return balanceOfWant().add(balanceOfPool()); 52 | } 53 | 54 | function getName() external virtual pure returns (string memory); 55 | 56 | // **** Setters **** // 57 | 58 | function setJar(address _jar) external onlyOwner { 59 | require(jar == address(0), "jar already set"); 60 | jar = _jar; 61 | emit SetJar(_jar); 62 | } 63 | 64 | function setStrategist(address _strategist) external onlyOwner { 65 | require(_strategist != address(0)); 66 | strategist = _strategist; 67 | emit SetStrategist(_strategist); 68 | } 69 | 70 | // **** State mutations **** // 71 | function deposit(uint256 _amount) internal virtual; 72 | 73 | // Withdraw partial funds, normally used with a jar withdrawal 74 | function withdraw(uint256 _amount) external nonReentrant { 75 | require(msg.sender == jar, "!jar"); 76 | uint256 _balance = IERC20(want).balanceOf(address(this)); 77 | if (_balance < _amount) { 78 | _amount = _withdrawSome(_amount.sub(_balance)); 79 | _amount = _amount.add(_balance); 80 | } 81 | 82 | IERC20(want).safeTransfer(jar, _amount); 83 | } 84 | 85 | function _withdrawSome(uint256 _amount) internal virtual returns (uint256); 86 | 87 | function harvest() public virtual; 88 | 89 | // **** Internal functions **** 90 | function _swapUniswapWithPath( 91 | address[] memory path, 92 | uint256 _amount, 93 | address dexRouter 94 | ) internal { 95 | require(path[1] != address(0)); 96 | 97 | // Swap with uniswap 98 | IERC20(path[0]).safeApprove(dexRouter, 0); 99 | IERC20(path[0]).safeApprove(dexRouter, _amount); 100 | 101 | IUniswapRouterV2(dexRouter).swapExactTokensForTokens( 102 | _amount, 103 | 0, 104 | path, 105 | address(this), 106 | now 107 | ); 108 | } 109 | 110 | function _swapUniswapWithPathForFeeOnTransferTokens( 111 | address[] memory path, 112 | uint256 _amount, 113 | address dexRouter 114 | ) internal { 115 | require(path[1] != address(0)); 116 | 117 | // Swap with uniswap 118 | IERC20(path[0]).safeApprove(dexRouter, 0); 119 | IERC20(path[0]).safeApprove(dexRouter, _amount); 120 | 121 | IUniswapRouterV2(dexRouter).swapExactTokensForTokensSupportingFeeOnTransferTokens( 122 | _amount, 123 | 0, 124 | path, 125 | address(this), 126 | now 127 | ); 128 | } 129 | 130 | function _addLiquidityToDex( 131 | address token1, 132 | address token2, 133 | address dexRouter 134 | ) internal { 135 | uint256 _token1 = IERC20(token1).balanceOf(address(this)); 136 | uint256 _token2 = IERC20(token2).balanceOf(address(this)); 137 | if (_token1 > 0 && _token2 > 0) { 138 | IERC20(token1).safeApprove(dexRouter, 0); 139 | IERC20(token1).safeApprove(dexRouter, _token1); 140 | IERC20(token2).safeApprove(dexRouter, 0); 141 | IERC20(token2).safeApprove(dexRouter, _token2); 142 | 143 | IUniswapRouterV2(dexRouter).addLiquidity( 144 | token1, 145 | token2, 146 | _token1, 147 | _token2, 148 | 0, 149 | 0, 150 | address(this), 151 | now 152 | ); 153 | 154 | // Donates DUST 155 | uint256 _dust1 = IERC20(token1).balanceOf(address(this)); 156 | if (_dust1 > 0) { 157 | IERC20(token1).safeTransfer( 158 | strategist, 159 | _dust1 160 | ); 161 | } 162 | uint256 _dust2 = IERC20(token2).balanceOf(address(this)); 163 | if (_dust2 > 0) { 164 | IERC20(token2).safeTransfer( 165 | strategist, 166 | _dust2 167 | ); 168 | } 169 | } 170 | } 171 | 172 | // **** Events **** // 173 | event SetJar(address indexed jar); 174 | } 175 | 176 | // Masterchef interface - some function names may be different depending on the underlying farm 177 | interface IMasterChef { 178 | function deposit(uint256 _pid, uint256 _amount) external; 179 | function withdraw(uint256 _pid, uint256 _amount) external; 180 | function emergencyWithdraw(uint256 _pid) external; 181 | 182 | function userInfo(uint256 _pid, address _user) external view returns(uint256, uint256); 183 | function balanceOf(uint256 _pid, address _user) external view returns (uint256); 184 | function pending(uint256 _pid, address _user) external view returns (uint256); 185 | } 186 | 187 | // Base contract for MasterChef/SakeMaster/etc rewards contract interfaces 188 | 189 | abstract contract BaseStrategyMasterChef is BaseStrategy { 190 | 191 | address public immutable rewards; 192 | uint256 public immutable poolId; 193 | bool public emergencyStatus = false; 194 | 195 | // Events 196 | event SetFee(uint256 value); 197 | event SetMultiHarvest(address indexed _to); 198 | event SetHarvestCutoff(uint256 value); 199 | event Harvested(address indexed _from); 200 | event Salvage(address indexed token); 201 | event EmergencyWithdraw(); 202 | 203 | constructor( 204 | address _rewards, 205 | address _want, 206 | address _strategist, 207 | uint256 _poolId, 208 | address _harvestedToken 209 | ) 210 | public 211 | BaseStrategy(_want, _strategist, _harvestedToken) 212 | { 213 | poolId = _poolId; 214 | rewards = _rewards; 215 | } 216 | 217 | // **** Getters **** 218 | function balanceOfPool() public override view returns (uint256) { 219 | (uint256 amount, ) = IMasterChef(rewards).userInfo(poolId, address(this)); 220 | return amount; 221 | //return IMasterChef(rewards).balanceOf(poolId, address(this)); 222 | } 223 | 224 | function getHarvestable() external override view returns (uint256) { 225 | return IMasterChef(rewards).pending(poolId, address(this)); 226 | } 227 | 228 | // **** Setters **** 229 | 230 | function deposit(uint256 _amount) internal override { 231 | require(emergencyStatus == false, "emergency withdrawal in process"); 232 | if (_amount > 0) { 233 | IERC20(want).safeApprove(rewards, 0); 234 | IERC20(want).safeApprove(rewards, _amount); 235 | IMasterChef(rewards).deposit(poolId, _amount); 236 | } 237 | } 238 | 239 | function jarDeposit(uint256 _amount) external nonReentrant { 240 | require(msg.sender == jar, "!jar"); 241 | deposit(_amount); 242 | } 243 | 244 | function _withdrawSome(uint256 _amount) 245 | internal 246 | override 247 | returns (uint256) 248 | { 249 | uint256 _before = IERC20(want).balanceOf(address(this)); 250 | IMasterChef(rewards).withdraw(poolId, _amount); 251 | return IERC20(want).balanceOf(address(this)).sub(_before); 252 | } 253 | 254 | /* **** Other Mutative functions **** */ 255 | 256 | function _getReward() internal { 257 | IMasterChef(rewards).withdraw(poolId, 0); 258 | //Usually different for other pools based on IMasterChef 259 | //IMasterChef(rewards).claim(poolId); 260 | } 261 | 262 | // **** Admin functions **** 263 | 264 | function salvage(address token) external onlyOwner nonReentrant { 265 | require(token != want && token != harvestedToken, "cannot salvage"); 266 | 267 | uint256 _token = IERC20(token).balanceOf(address(this)); 268 | if (_token > 0) { 269 | IERC20(token).safeTransfer(msg.sender, _token); 270 | } 271 | 272 | emit Salvage(token); 273 | } 274 | 275 | function emergencyWithdraw() external onlyOwner nonReentrant { 276 | emergencyStatus = true; 277 | 278 | IMasterChef(rewards).emergencyWithdraw(poolId); 279 | 280 | uint256 _want = IERC20(want).balanceOf(address(this)); 281 | if (_want > 0) { 282 | IERC20(want).safeTransfer(jar, _want); 283 | } 284 | 285 | emit EmergencyWithdraw(); 286 | } 287 | } 288 | 289 | 290 | abstract contract StrategyFarmTwoAssets is BaseStrategyMasterChef { 291 | 292 | // Reward token address 293 | address public constant rewardTokenAddr = 0x580A84C73811E1839F75d86d75d88cCa0c241fF4; 294 | // One or more farm tokens 295 | address public constant farmToken0Addr = 0xa3Fa99A148fA48D14Ed51d610c367C61876997F1; 296 | address public constant farmToken1Addr = 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174; 297 | // Fee token 298 | address public constant feeTokenAddr = 0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270; 299 | // Routers 300 | address public constant feeTokenRouterAddr = 0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff; // Quickswap router 301 | address public constant farmTokenRouterAddr = 0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff; // Quickswap router 302 | address public constant swapRouter0Addr = 0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff; // Quickswap router 303 | address public constant swapRouter1Addr = 0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff; // Quickswap router 304 | 305 | address public multiHarvest = 0x0000000000000000000000000000000000000000; 306 | 307 | // Other constants 308 | uint256 public constant underlyingPoolId = 1; 309 | 310 | // The total fee in bps that KogeFarm will take from the reward token balance 311 | uint256 public kogefarmFeeAmountBps = 100; 312 | // The minimum amount (in bps) KogeFarm will harvest from the reward token 313 | uint256 public harvestCutoffBps = 10**12; 314 | // The reward --> fee token path 315 | address[] public rewardToFeeTokenPath; 316 | // Assuming one or more reward --> farm token paths 317 | address[] public rewardToFarmTokenPath0; 318 | address[] public rewardToFarmTokenPath1; 319 | 320 | constructor( 321 | address _rewards, 322 | address _want, 323 | address _strategist 324 | ) 325 | public 326 | BaseStrategyMasterChef( 327 | _rewards, 328 | _want, 329 | _strategist, 330 | underlyingPoolId, 331 | rewardTokenAddr 332 | ) 333 | { 334 | require(_want != feeTokenAddr, "Want token address should not be set to fee token address"); 335 | 336 | rewardToFeeTokenPath = new address[](2); 337 | rewardToFeeTokenPath[0] = rewardTokenAddr; 338 | rewardToFeeTokenPath[1] = feeTokenAddr; 339 | 340 | rewardToFarmTokenPath0 = new address[](2); 341 | rewardToFarmTokenPath0[0] = rewardTokenAddr; 342 | rewardToFarmTokenPath0[1] = farmToken0Addr; 343 | 344 | rewardToFarmTokenPath1 = new address[](3); 345 | rewardToFarmTokenPath1[0] = rewardTokenAddr; 346 | rewardToFarmTokenPath1[1] = farmToken0Addr; 347 | rewardToFarmTokenPath1[2] = farmToken1Addr; 348 | } 349 | 350 | // **** State Mutations **** 351 | 352 | function set_fee(uint256 NewFee) external onlyOwner() { 353 | require(NewFee <= 1000, "New fee must be less than 1000 bps"); 354 | kogefarmFeeAmountBps = NewFee; 355 | emit SetFee(NewFee); 356 | } 357 | function set_multiHarvest(address newHarvest) external onlyOwner() { 358 | multiHarvest = newHarvest; 359 | emit SetMultiHarvest(newHarvest); 360 | } 361 | 362 | function set_harvestCutoff(uint256 newCutoff) external onlyOwner() { 363 | harvestCutoffBps = newCutoff; 364 | emit SetHarvestCutoff(harvestCutoffBps); 365 | } 366 | 367 | function calculateSwapAmount(address _tokenToSwap, uint256 _bps) internal view returns (uint256) { 368 | uint256 _tokenAmount = IERC20(_tokenToSwap).balanceOf(address(this)); 369 | return _tokenAmount.mul(_bps).div(10000); 370 | } 371 | 372 | function collectFee(uint256 _rewardBalance) internal { 373 | // Figure out how much fee is owed 374 | uint256 _feeAmount = _rewardBalance.mul(kogefarmFeeAmountBps).div(10000); 375 | // Swap reward token for fee token using the fee token router 376 | if(rewardTokenAddr != feeTokenAddr) { 377 | _swapUniswapWithPathForFeeOnTransferTokens(rewardToFeeTokenPath, _feeAmount, feeTokenRouterAddr); 378 | // Figure out how much we now have as a fee token 379 | _feeAmount = IERC20(feeTokenAddr).balanceOf(address(this)); 380 | } 381 | // Send fee to strategist 382 | IERC20(feeTokenAddr).safeTransfer(strategist,_feeAmount); 383 | } 384 | 385 | //Harvest rewards and re-deposit into farm 386 | function harvest() public override nonReentrant { 387 | // prevent unauthorized smart contracts from calling harvest() 388 | require(msg.sender == tx.origin || msg.sender == owner() || msg.sender == strategist || msg.sender == multiHarvest || msg.sender == jar, "not authorized"); 389 | // prevent harvesting during emergency withdraw 390 | require(emergencyStatus == false, "emergency withdrawal in process"); 391 | 392 | // Collects reward tokens 393 | _getReward(); 394 | 395 | uint256 swapAmount; 396 | // Figure out how much reward we collected 397 | uint256 _rewardBalance = IERC20(rewardTokenAddr).balanceOf(address(this)); 398 | if (_rewardBalance > harvestCutoffBps){ 399 | // Collect fee if not at 0 400 | if (kogefarmFeeAmountBps > 0) { 401 | collectFee(_rewardBalance); 402 | } 403 | // Swap reward for farm tokens (want) 404 | // Calculate the amount to swap for the farm token. 405 | swapAmount = calculateSwapAmount(rewardTokenAddr,5000); 406 | // Swap the required amount of reward token using the designated swap path 407 | _swapUniswapWithPathForFeeOnTransferTokens(rewardToFarmTokenPath0, swapAmount, swapRouter0Addr); 408 | // Calculate the amount to swap for the farm token. 409 | swapAmount = calculateSwapAmount(rewardTokenAddr,10000); 410 | // Swap the required amount of reward token using the designated swap path 411 | _swapUniswapWithPathForFeeOnTransferTokens(rewardToFarmTokenPath1, swapAmount, swapRouter1Addr); 412 | // Add liquidity 413 | _addLiquidityToDex(farmToken0Addr,farmToken1Addr,farmTokenRouterAddr); 414 | // Stake the LP tokens 415 | uint256 _want = IERC20(want).balanceOf(address(this)); 416 | deposit(_want); 417 | } 418 | 419 | // Emit event 420 | emit Harvested(msg.sender); 421 | } 422 | 423 | } 424 | 425 | contract StrategyTwoAssets is StrategyFarmTwoAssets { 426 | // Token addresses 427 | address public FARM_MASTER_CHEF = 0x574Fe4E8120C4Da1741b5Fd45584de7A5b521F0F; 428 | address public LP_TOKEN = 0x160532D2536175d65C03B97b0630A9802c274daD; 429 | constructor() 430 | public 431 | StrategyFarmTwoAssets( 432 | FARM_MASTER_CHEF, 433 | LP_TOKEN, 434 | msg.sender 435 | ) 436 | {} 437 | // **** Views **** 438 | function getName() external override pure returns (string memory) { 439 | return "StrategyTwoAssets"; 440 | } 441 | function pairName() external pure returns (string memory) { 442 | return "FARMTOKEN1FARMTOKEN2"; 443 | } 444 | } 445 | -------------------------------------------------------------------------------- /polygon_vault_addresses.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "vault": "0x992Ae1912CE6b608E0c0d2BF66259ab1aE62A657", 4 | "__comment": "KogeFarm KogeCoin" 5 | }, 6 | { 7 | "vault": "0xb6D7bA013e13C3f00a20826aF2008C83228eD50a", 8 | "__comment": "KogeFarm DAO KogeCoin" 9 | }, 10 | { 11 | "vault": "0x84a9c05b9F52FfD041eA1cFD6f56031d50DECc5c", 12 | "__comment": "KogeFarm DAO KogeCoin-Matic" 13 | }, 14 | { 15 | "vault": "0xECbCe31d1723611Db11358a186B9328ce65D78cc", 16 | "__comment": "Curve DAI-USDC-USDT" 17 | }, 18 | { 19 | "vault": "0x4a93D6b394Da4c1e6e436e9370E5DF08A45377a8", 20 | "__comment": "Curve DAI-USDC-USDT" 21 | }, 22 | { 23 | "vault": "0x34F0B8B2c3A82BCcb91dcA4Fc45EC8dC78132ccB", 24 | "__comment": "Curve atricrypto3" 25 | }, 26 | { 27 | "vault": "0x8402c67fC92691c745E0Bbbe4989eB07Bc02c335", 28 | "__comment": "Curve atricrypto3" 29 | }, 30 | { 31 | "vault": "0xB608A48aa322F2541bD65449148147c3935EBc5e", 32 | "__comment": "Curve BTC-renBTC" 33 | }, 34 | { 35 | "vault": "0x69aAF33Cd4bd6Cbd3Ef275f8Ddc3342e0365F083", 36 | "__comment": "Curve BTC-renBTC" 37 | }, 38 | { 39 | "vault": "0x81D61D56A19469259cDA912b5d1Eb0DCA6199A87", 40 | "__comment": "QuickSwap TUSD-USDC" 41 | }, 42 | { 43 | "vault": "0x36CB30b0223C16B7275A3C3641b7b5D5ad1433CB", 44 | "__comment": "QuickSwap ETH-cxETH" 45 | }, 46 | { 47 | "vault": "0x0051eCd6C71307313fd494e486E5d3bEfDa5CD04", 48 | "__comment": "QuickSwap Matic-MaticX" 49 | }, 50 | { 51 | "vault": "0xDc067a54161B9200d97CBEB84D983ca4Ee284d0A", 52 | "__comment": "QuickSwap BTC-cxBTC" 53 | }, 54 | { 55 | "vault": "0x54A6ebb2f616e7a8C12f53D39Fc7AC1dD4f0C4F3", 56 | "__comment": "QuickSwap Matic-stMatic" 57 | }, 58 | { 59 | "vault": "0xCbfF2Efd73C3b3fd86130aE295d27017De16E025", 60 | "__comment": "QuickSwap USDC-Eth LP" 61 | }, 62 | { 63 | "vault": "0xF0Ad1b426bb081D67533b76DC0efc8b0Fb08F826", 64 | "__comment": "QuickSwap USDT-Eth LP" 65 | }, 66 | { 67 | "vault": "0xaB6707A9A19965594334Ec334cC82213D796f02B", 68 | "__comment": "QuickSwap Dai-Eth LP" 69 | }, 70 | { 71 | "vault": "0x8B74b3F6ad25F8d55f272115AE7e83649Bcf1E50", 72 | "__comment": "QuickSwap Quick(New)-Matic LP" 73 | }, 74 | { 75 | "vault": "0xE8B31C01753AA167F99bCbbEC5127ee8169C1D71", 76 | "__comment": "Stargate S*USDC" 77 | }, 78 | { 79 | "vault": "0xb17372A7BD7e76aa009Bd5062B42a5C0A88638b3", 80 | "__comment": "Stargate S*USDT" 81 | }, 82 | { 83 | "vault": "0x5CEE9B233EACa8d93C2038D229EBb6670E8581BF", 84 | "__comment": "QuickSwap Eth-Matic LP" 85 | }, 86 | { 87 | "vault": "0xd5E3Dc5e2de2fCa311150164258c093EF5EcAC3F", 88 | "__comment": "QuickSwap Usdc-Matic LP" 89 | }, 90 | { 91 | "vault": "0xd1C7962b4D007E10adb1bF977185dCA6f5A6fE9C", 92 | "__comment": "QuickSwap Quick-Matic LP" 93 | }, 94 | { 95 | "vault": "0xAE2cb3830d7617f865b520bEB7d2fca3e37cFE51", 96 | "__comment": "QuickSwap USDT-Matic LP" 97 | }, 98 | { 99 | "vault": "0x28c6c6e459E8e6AF7f8C9d61D7d4C3932854b8f3", 100 | "__comment": "Gains Network GNS-Dai" 101 | }, 102 | { 103 | "vault": "0x4792b5943a05fc6AF3B20B5F1D1d7dDe33C42980", 104 | "__comment": "Polysage SAGE-KOGE" 105 | }, 106 | { 107 | "vault": "0x99dE9f6ACc587726FE72AC8F6E2b4a6563c98Af9", 108 | "__comment": "Polysage SAGE-WMATIC" 109 | }, 110 | { 111 | "vault": "0xBF773f00C3aE7B1eE9641c7e1cF14FdDCDC0CEBb", 112 | "__comment": "Polysage SAGE-USDC" 113 | }, 114 | { 115 | "vault": "0x967e9A7A23E68cc6A0e8b98db8C079f133580760", 116 | "__comment": "PolyBeta Beta" 117 | }, 118 | { 119 | "vault": "0x9abF2f2acBce703Eaca4430F7E44Ab9098b60C48", 120 | "__comment": "PolyBeta Alpha" 121 | }, 122 | { 123 | "vault": "0x720726a3546B1f9CF145093bcdc293E149e2e07F", 124 | "__comment": "PolyBeta Spade" 125 | }, 126 | { 127 | "vault": "0x57bc21ff1236A3fDE7164FCe75c97E3e0714CCB5", 128 | "__comment": "PolyBeta Beta-USDC LP" 129 | }, 130 | { 131 | "vault": "0x0DCc3Cd939e347dAaaA5b5729E6A2DAf52E4F402", 132 | "__comment": "PolyBeta Beta-Matic LP" 133 | }, 134 | { 135 | "vault": "0xEab5DAC8E6E3da7679b2a01FCD17DBE1Ed519904", 136 | "__comment": "PolyBeta Beta-KogeCoin LP" 137 | }, 138 | { 139 | "vault": "0x1ddE2a134E4dE3D0c85bb3f0816f343B9a861B64", 140 | "__comment": "PolyBeta Beta-USDC LP" 141 | }, 142 | { 143 | "vault": "0x51AC169E6139E3bebaf8D51A8867b921a77E9d99", 144 | "__comment": "DFYN CRV-DFYN" 145 | }, 146 | { 147 | "vault": "0x5C744bA989Ef8f68c6EB97241cC9B5EA7AdF9904", 148 | "__comment": "DFYN CRV-DFYN" 149 | }, 150 | { 151 | "vault": "0xC2c5a92E4dA9052aF406c0b97f09378C51a7E767", 152 | "__comment": "QuickSwap MAI-USDT LP" 153 | }, 154 | { 155 | "vault": "0x4aF74D22399DFcaD732A5504aa2E2c13b25303f4", 156 | "__comment": "QuickSwap PolyDoge-Quick LP" 157 | }, 158 | { 159 | "vault": "0x3c928f0eE37bafeB6e90D835e7000ef533A09472", 160 | "__comment": "Qi Dao MAI(miMatic)-USDC" 161 | }, 162 | { 163 | "vault": "0xaE48aCc701151061A5bfff8e4c3f0DCfe4A957E9", 164 | "__comment": "Qi Dao MAI(miMatic)-Qi" 165 | }, 166 | { 167 | "vault": "0x42064982010d0881c7A6BC89D83B32309bd17a99", 168 | "__comment": "Qi Dao Qi-Matic" 169 | }, 170 | { 171 | "vault": "0xec05278322536650D3671D58672AC1B856cbc5f5", 172 | "__comment": "PolyDogeDao pdShare-Matic LP" 173 | }, 174 | { 175 | "vault": "0x15d5a8a94d4f65474fb150ee994119Ac561C9324", 176 | "__comment": "PolyDogeDao pdShare-ETH LP" 177 | }, 178 | { 179 | "vault": "0xF9cc76F275aCe60f11CBDd458214Bf86366e9930", 180 | "__comment": "PolyDogeDao PolyDoge" 181 | }, 182 | { 183 | "vault": "0xc74e6DcF602e81FC10dE4FE852Ab4243412E0Dd9", 184 | "__comment": "PolyPup Ball-USDC LP" 185 | }, 186 | { 187 | "vault": "0xA1e13449EA8218Ab2e3ea0CF841d39A61b2024D9", 188 | "__comment": "PolyPup Bone-USDC LP" 189 | }, 190 | { 191 | "vault": "0x2002ac0EE6Fb936d5F0d52ACebAB581a3dF5F971", 192 | "__comment": "Singular Sing-USDC LP" 193 | }, 194 | { 195 | "vault": "0x05e30F9b15a88f911c58D63EdAc8B60d24488AeB", 196 | "__comment": "Singular Sing-Matic LP" 197 | }, 198 | { 199 | "vault": "0x4B7E2DFDDFcA7aB50c4bEdc2721EceD34c8c79F6", 200 | "__comment": "PolyShield Shi3ld" 201 | }, 202 | { 203 | "vault": "0x64ec0D31EA0345BCBf29855d7C0B74b5Dcc78fd9", 204 | "__comment": "PolyShield Shi3ld-Matic" 205 | }, 206 | { 207 | "vault": "0x23f9c7097157c0f6Fdbf355D8fB8914f4711Ab05", 208 | "__comment": "PolyShield Shi3ld-USDC" 209 | }, 210 | { 211 | "vault": "0x7a9be7CdF26C8311625ed97c174869fcA9b791eC", 212 | "__comment": "PolyShield Shi3ld-KogeCoin LP" 213 | }, 214 | { 215 | "vault": "0x00567b197A3506e8D05Dc8aA21E8Ce250dbcE13c", 216 | "__comment": "PolyShield Shi3ld-Elk LP" 217 | }, 218 | { 219 | "vault": "0x92FB3E8323baDBEE16f4E69De52D3a0b5BA39C7C", 220 | "__comment": "Hermes Defi Iris" 221 | }, 222 | { 223 | "vault": "0xD33eDaB4e24D7471e8b772Fbc1f6b068d99FE391", 224 | "__comment": "Hermes Defi Iris-Matic" 225 | }, 226 | { 227 | "vault": "0x55A2FedB176C09488102596Db21937A753025466", 228 | "__comment": "Hermes Defi Iris-KogeCoin" 229 | }, 230 | { 231 | "vault": "0xfC7B6d0f6157a1971679f5aF7F5B6374694E658f", 232 | "__comment": "PolyAlpha Alpha" 233 | }, 234 | { 235 | "vault": "0x3De0305D703b5ce1A748D174e29BA38e7C834005", 236 | "__comment": "PolyAlpha Spade" 237 | }, 238 | { 239 | "vault": "0x79D2F222c67e954AcAc8eCF3166cefAEB6cb56D0", 240 | "__comment": "PolyAlpha Alpha-Matic LP" 241 | }, 242 | { 243 | "vault": "0x2f026c3b0fdCcF941FB07A62F4803CAF36e45859", 244 | "__comment": "PolyAlpha Alpha-USDC LP" 245 | }, 246 | { 247 | "vault": "0x0CB25E588E0dF55Fb6B4407884D6B3B553D16095", 248 | "__comment": "PolyAlpha Alpha-USDC LP" 249 | }, 250 | { 251 | "vault": "0xD02064bEd4126ACCCe79431A52F206C558479648", 252 | "__comment": "PolyAlpha Alpha-KogeCoin LP" 253 | }, 254 | { 255 | "vault": "0xfee30B81bD194f23dc5AcC23769410Beab3adB21", 256 | "__comment": "TamagoSwap TMGO-Matic LP" 257 | }, 258 | { 259 | "vault": "0xA838F1e986b27d7AC5a977c7d0eCbADFFCDC7Bb5", 260 | "__comment": "TamagoSwap TMGO-KogeCoin LP" 261 | }, 262 | { 263 | "vault": "0xa3F49c515b3c45294D3F9B5A4525AF6223EDf954", 264 | "__comment": "Gravity GFI" 265 | }, 266 | { 267 | "vault": "0xa67153C4b30f24F60286C664547aeE010AE87F1D", 268 | "__comment": "Gravity GFI" 269 | }, 270 | { 271 | "vault": "0x85eFa41967c508f6F2f5236B08E734cce88BC7e1", 272 | "__comment": "Gravity GFI-WETH LP" 273 | }, 274 | { 275 | "vault": "0x1e187A8Fc90e5DCbbfd25B473e17955Efe6E15E5", 276 | "__comment": "Gravity GFI-USDC LP" 277 | }, 278 | { 279 | "vault": "0x17754aCE28b367dc0ee5B9D00232B1Feb05664c5", 280 | "__comment": "Gravity GFI-Btc LP" 281 | }, 282 | { 283 | "vault": "0x24771c6C514F0307b01dC14e361c311B8E9823b5", 284 | "__comment": "Gravity USDC-Matic LP" 285 | }, 286 | { 287 | "vault": "0x74EeB0121f82784622Df86C9c2b1FEE61541B03b", 288 | "__comment": "Gravity AAVE-WETH LP" 289 | }, 290 | { 291 | "vault": "0xE48aA84AB5A0Ee50e08fc12dfaED0ada08a1aA5d", 292 | "__comment": "Gravity CRV-WETH LP" 293 | }, 294 | { 295 | "vault": "0xa4FEb444c17FBe341e2481B89e1574DA1ab0A833", 296 | "__comment": "Gravity USDC-ETH LP" 297 | }, 298 | { 299 | "vault": "0xa5B762Df7b6491f30A62681b2F988977a98A07Fe", 300 | "__comment": "Gravity Dai-ETH LP" 301 | }, 302 | { 303 | "vault": "0x45a686CC6a9627a2fb2e4f44104c6EC09594bA93", 304 | "__comment": "Gravity BTC-ETH LP" 305 | }, 306 | { 307 | "vault": "0xFc0Da0cBAab796e983b3c0ee42bE6edC498AEf61", 308 | "__comment": "Gravity ETH-Matic LP" 309 | }, 310 | { 311 | "vault": "0x4ce450F7aa450ADd27E7F3631d1Ab1Cca56e1A3D", 312 | "__comment": "Gravity USDC-USDT LP" 313 | }, 314 | { 315 | "vault": "0xB01705A4fe67D957E7e328834f09608359313065", 316 | "__comment": "Gravity USDC-Dai LP" 317 | }, 318 | { 319 | "vault": "0x3528DB3895423c71d64D0F040D88B036B4579471", 320 | "__comment": "Gravity UST-USDC LP" 321 | }, 322 | { 323 | "vault": "0x9F807bf6FDfCa49adEA2a7a87cB86e9c3BacCC0a", 324 | "__comment": "Gravity BTC-RenBTC LP" 325 | }, 326 | { 327 | "vault": "0xF31049674cb4d43edE717d430a5b16066ecD4EFA", 328 | "__comment": "Gravity Link" 329 | }, 330 | { 331 | "vault": "0x029f402412e0Ee600929Ae878473C4c9d2976E15", 332 | "__comment": "Gravity Sushi" 333 | }, 334 | { 335 | "vault": "0x8946C7a0b15a0d477A31F7cc06592cf356378D76", 336 | "__comment": "SushiSwap gOHM-ETH LP" 337 | }, 338 | { 339 | "vault": "0x8885A65E887E14Bd09F5112cA03D130076f65B6b", 340 | "__comment": "SushiSwap USDC-BCT LP" 341 | }, 342 | { 343 | "vault": "0x0C776471CB3Ac5be3a0e7560C7B87977a5Ac0be2", 344 | "__comment": "SushiSwap BTC-ETH LP" 345 | }, 346 | { 347 | "vault": "0xC9D6b9D95070f924E511415bb4a7640997704E4C", 348 | "__comment": "SushiSwap USDC-ETH LP" 349 | }, 350 | { 351 | "vault": "0x8e66a05C09b31e12f65b71Eb36F46b7E249cEaa5", 352 | "__comment": "SushiSwap ETH-Matic LP" 353 | }, 354 | { 355 | "vault": "0x2F47fBD707D9dFB3CAb292700b71A3681DEB0721", 356 | "__comment": "SushiSwap USDT-ETH LP" 357 | }, 358 | { 359 | "vault": "0x9790a55E43a79f30e04f0B39FC766028950E793F", 360 | "__comment": "SushiSwap USDC-USDT LP" 361 | }, 362 | { 363 | "vault": "0x88f87372bDe5E2242e1a7996B4472dE490AF8453", 364 | "__comment": "SushiSwap DAI-ETH LP" 365 | }, 366 | { 367 | "vault": "0xba4A9A92fc9ae91Bb26f31D7Dc538e44Ab04f2a3", 368 | "__comment": "SushiSwap USDC-DAI LP" 369 | }, 370 | { 371 | "vault": "0x7Bd9e5F441D2013c473c3e366F2883b9A6cf9091", 372 | "__comment": "SushiSwap MANA-ETH LP" 373 | }, 374 | { 375 | "vault": "0x14d09C69163F94D7f5e674A004F224F24739A56C", 376 | "__comment": "SushiSwap GRT-ETH LP" 377 | }, 378 | { 379 | "vault": "0xEB2852258F0E4117352bA3364E599dc980681c2e", 380 | "__comment": "SushiSwap AVAX-WETH LP" 381 | }, 382 | { 383 | "vault": "0xC918945e4785D7ffd3f801407368c3d5e32A7C18", 384 | "__comment": "SushiSwap AAVE-WETH LP" 385 | }, 386 | { 387 | "vault": "0x26e028B287486E0Daa6D4658cc70E7c3aDc75891", 388 | "__comment": "SushiSwap CRV-WETH LP" 389 | }, 390 | { 391 | "vault": "0x43f28AAe9fcefA47D5d7835B0a9Eb86E36F035A7", 392 | "__comment": "SushiSwap Link-WETH LP" 393 | }, 394 | { 395 | "vault": "0x2A60105aB70Eb62A7EEaa04b2748a8054cA6D6aE", 396 | "__comment": "ApeSwap Banana-Matic LP" 397 | }, 398 | { 399 | "vault": "0x8715Bb8f3157C7cA5bB379A107C9b810f11F7815", 400 | "__comment": "ApeSwap Eth-Matic LP" 401 | }, 402 | { 403 | "vault": "0x00e80B9137560D0A0Abe5Ed39D39F5b0F5804237", 404 | "__comment": "ApeSwap WMatic-Dai LP" 405 | }, 406 | { 407 | "vault": "0x94d00dEe78f4b79CA8c07E0b2B00039b6B87c236", 408 | "__comment": "ApeSwap WMatic-USDT LP" 409 | }, 410 | { 411 | "vault": "0x33c7f2cD56506e3Eac79984E96453b517D532D1e", 412 | "__comment": "ApeSwap WMatic-WBTC LP" 413 | }, 414 | { 415 | "vault": "0x7E90B622b8891e736247fFEE896dD2a1B3f9142e", 416 | "__comment": "ApeSwap USDC-Dai LP" 417 | }, 418 | { 419 | "vault": "0x65378692264B09Ca93740F439dFA5A7978A821b1", 420 | "__comment": "ApeSwap WMatic-Bnb LP" 421 | }, 422 | { 423 | "vault": "0x7B612e2A58F31Eb482812D1F3529e001655e6EB9", 424 | "__comment": "Iron DAI-USDC-USDT" 425 | }, 426 | { 427 | "vault": "0x79c3f7c36ACb46Ee566c2c33B9DdE4668eC069a6", 428 | "__comment": "Iron Iron-DAI-USDC-USDT" 429 | }, 430 | { 431 | "vault": "0x55D51F0C3215085e45BA7041d32Fc8d4890570fE", 432 | "__comment": "Iron Ice-USDC LP" 433 | }, 434 | { 435 | "vault": "0x95a56528Dcf6e8eC4c020Af18f869eA77b76E265", 436 | "__comment": "Iron Ice-WETH LP" 437 | }, 438 | { 439 | "vault": "0x5AA51B3890bAEdFB3BF570a6345D5F3B2A6ddfDf", 440 | "__comment": "PolyPup Collar-USDC LP" 441 | }, 442 | { 443 | "vault": "0x084A5e96F3EE81909bF8e4De5Ad3a823616Bd08f", 444 | "__comment": "PolyPup Collar-Matic LP" 445 | }, 446 | { 447 | "vault": "0xE5C7986950e10541CADC1646ff227aCA52F7995D", 448 | "__comment": "PolyPup Collar-USDC LP" 449 | }, 450 | { 451 | "vault": "0x64c20BB3D9aCD870f748fe73B6541D500643e490", 452 | "__comment": "PolyPup Collar-KogeCoin LP" 453 | }, 454 | { 455 | "vault": "0xb99898440ff53A7f36422faee7030F4785452636", 456 | "__comment": "PolyPup Collar" 457 | }, 458 | { 459 | "vault": "0x82d007ffcd3DCCB60b461085Ecd11Fb5812A7335", 460 | "__comment": "CafeSwap pBrew" 461 | }, 462 | { 463 | "vault": "0x092b0a3e0d7b17E837a2ae8664885406D06bcB99", 464 | "__comment": "CafeSwap pBrew-USDC LP" 465 | }, 466 | { 467 | "vault": "0x885B1248D36fB83E824AD49eA637Ea7998C0Ca54", 468 | "__comment": "CafeSwap pBrew-Matic LP" 469 | }, 470 | { 471 | "vault": "0x2Cb2c97F28cC58de6bD3d379919dD66Ba1801c65", 472 | "__comment": "CafeSwap pBrew-Paw LP" 473 | }, 474 | { 475 | "vault": "0x9A7D67a685251567B0AEe4CA08402A1A9f8a1D05", 476 | "__comment": "CafeSwap pBrew-ETH LP" 477 | }, 478 | { 479 | "vault": "0xA0be41bF0454d1CDd4F19CDDC5A23A1D254722ed", 480 | "__comment": "CafeSwap USDC-Matic LP" 481 | }, 482 | { 483 | "vault": "0xA6B3647DeCdefB4CE5D855250517f5EaE462F617", 484 | "__comment": "CafeSwap ETH-Matic LP" 485 | }, 486 | { 487 | "vault": "0x66F483df4aE87991539B042E8320Ac21dD33A677", 488 | "__comment": "CafeSwap USDC-Dai LP" 489 | }, 490 | { 491 | "vault": "0xaE3e4292705e5052aCA9054B4003421F717A521C", 492 | "__comment": "CafeSwap USDC-Eth LP" 493 | }, 494 | { 495 | "vault": "0xB062BB2dC24FF6B764a9Cd32973674268bB8dfad", 496 | "__comment": "CafeSwap Brew-USDC LP" 497 | }, 498 | { 499 | "vault": "0x453f0CdBE6cB2C56ac38A171Ff80d41981f9f149", 500 | "__comment": "CafeSwap Mocha-USDC LP" 501 | }, 502 | { 503 | "vault": "0xA7BEFC58c2e14e8f22E5566E49c05a7e7E6F054F", 504 | "__comment": "CafeSwap LINK-WETH LP" 505 | }, 506 | { 507 | "vault": "0xfAa6Ca9A5FED9cAEF91711283d59F0EebE782a23", 508 | "__comment": "CafeSwap AAVE-WETH LP" 509 | }, 510 | { 511 | "vault": "0x5E0F3303218a3665a2707a1D01EDEe78Abe9F3D6", 512 | "__comment": "CafeSwap BTC-ETH LP" 513 | }, 514 | { 515 | "vault": "0x4C389275c52b2A2b07E444cf0223744668A54b52", 516 | "__comment": "CafeSwap UST-USDC LP" 517 | }, 518 | { 519 | "vault": "0xBa1998aD991DDC36f9f927764d0950F10654cbE7", 520 | "__comment": "CafeSwap Btc-RenBtc LP" 521 | }, 522 | { 523 | "vault": "0xAD367134f993D8C2d62A1255FE1252A18d5C78ba", 524 | "__comment": "CafeSwap USDC-USDT LP" 525 | }, 526 | { 527 | "vault": "0x2E084932ECf2df9ad7841E7838Dd39f47Ea4e695", 528 | "__comment": "CafeSwap Eth-Quick LP" 529 | }, 530 | { 531 | "vault": "0xbfE130aBd54F202dd7f8C3cdAe7C993fCd703f8a", 532 | "__comment": "DinoSwap Dino" 533 | }, 534 | { 535 | "vault": "0x4e1578399F02F8f33c0911159dC61F5c9Adf1B25", 536 | "__comment": "DinoSwap Dino" 537 | }, 538 | { 539 | "vault": "0x92F42e22D812C0C8ADFC30190faC42919032E19B", 540 | "__comment": "DinoSwap Dino-USDC" 541 | }, 542 | { 543 | "vault": "0xbE3Eb5Ce0aB2223428995dDD799f551E200166B3", 544 | "__comment": "DinoSwap Dino-USDC" 545 | }, 546 | { 547 | "vault": "0xE4a966c8225BA2A5dd7B4861AB5fe3570E002629", 548 | "__comment": "DinoSwap Dino-Weth" 549 | }, 550 | { 551 | "vault": "0x0850B134Ba40943941a0e31F4850737Bb0700CDe", 552 | "__comment": "DinoSwap Dino-Weth" 553 | }, 554 | { 555 | "vault": "0xE0011c255B8E7A5939e41913e3657D7852d50a9a", 556 | "__comment": "DinoSwap DNXC-USDC LP" 557 | }, 558 | { 559 | "vault": "0xd606Bd85424F372ec96DBDAcBB7ca7f9Bf04f270", 560 | "__comment": "DinoSwap For-USDC LP" 561 | }, 562 | { 563 | "vault": "0xc0892B586636528a0ECd1dD16256867271C5C3b7", 564 | "__comment": "DinoSwap USDT-UST" 565 | }, 566 | { 567 | "vault": "0x1173c353e93342B337098b63B0B64226645Fb79d", 568 | "__comment": "DinoSwap Dfyn-WEth" 569 | }, 570 | { 571 | "vault": "0x50B808875e9722E0bDADB7211f486D8E49a2ceB9", 572 | "__comment": "DinoSwap XMark-USDC LP" 573 | }, 574 | { 575 | "vault": "0xFAf49e554778e9D11F8a646679fDBf406B871556", 576 | "__comment": "DinoSwap CGG-WMatic LP" 577 | }, 578 | { 579 | "vault": "0x883200d4E483d01eEef2ffE96d37f9Df1E85d954", 580 | "__comment": "DinoSwap Route-WETH LP" 581 | }, 582 | { 583 | "vault": "0x58051a556D3a2AA60c99F0758998998b884Bf216", 584 | "__comment": "DinoSwap EROWAN-ATOM" 585 | }, 586 | { 587 | "vault": "0x35F77cED3A5387Fe221Cd6C0cf0E02A93857861D", 588 | "__comment": "DinoSwap EROWAN-IRIS" 589 | }, 590 | { 591 | "vault": "0x1d7245824B0d7f7c08C0d8fdDEC66a2C49c20A95", 592 | "__comment": "DinoSwap EROWAN-QUICK" 593 | }, 594 | { 595 | "vault": "0xCA411AF0d316a05f33C9635f3e68276e4F575dc6", 596 | "__comment": "DinoSwap EROWAN-REGEN" 597 | }, 598 | { 599 | "vault": "0x106BAc65d64a68e6fa8fD8414D8ACb09dAe4ea1a", 600 | "__comment": "DinoSwap EROWAN-XPRT" 601 | }, 602 | { 603 | "vault": "0xb33576835cC51EF8D71ccB861775B2821470bb71", 604 | "__comment": "PolyQuity PUSD-USDC" 605 | }, 606 | { 607 | "vault": "0x3F5912c3312B73483Cd8015A7881Ef40118d50C6", 608 | "__comment": "PolyQuity PUSD-USDC" 609 | }, 610 | { 611 | "vault": "0xe5B7402d8Ccae02D3BaA65140a50B26f876cec8b", 612 | "__comment": "PolyQuity PYQ-USDC" 613 | }, 614 | { 615 | "vault": "0xb7D3e1C5cb26D088d619525c6fD5D8DDC1B543d1", 616 | "__comment": "QuickSwap KogeCoin-Matic" 617 | }, 618 | { 619 | "vault": "0xE28809B6070DB755b01303d03Dc0476F49A96B17", 620 | "__comment": "QuickSwap BTC-Eth LP" 621 | }, 622 | { 623 | "vault": "0x3BF440465b8E5A36cac9e6B6F4300b461B42C9A6", 624 | "__comment": "QuickSwap AVAX-Matic LP" 625 | }, 626 | { 627 | "vault": "0x9ea363902D086A4707F71d7AF6Fb91DAf7aE4948", 628 | "__comment": "QuickSwap Uni-ETH LP" 629 | }, 630 | { 631 | "vault": "0x5C3533B44d7c3e804C428A57C426577CA899A311", 632 | "__comment": "Swamp pSwamp" 633 | }, 634 | { 635 | "vault": "0xeF721dc8AACFA0F2113DBfcB08a77207a220FEe9", 636 | "__comment": "Swamp pSwamp-Matic LP" 637 | }, 638 | { 639 | "vault": "0x5781135c882d4Fc8c61D0C826123761F20F67153", 640 | "__comment": "Swamp pSwamp" 641 | }, 642 | { 643 | "vault": "0xCc72AF943EF649B540021590fF349A454b5E2e9a", 644 | "__comment": "Swamp pSwamp" 645 | }, 646 | { 647 | "vault": "0x52fd74517b9728E4a8c6A44a6D5efeECB49e2aC5", 648 | "__comment": "Swamp pSwamp-Matic LP" 649 | }, 650 | { 651 | "vault": "0xf5bc9A2251A1Ae5AEeb0286CC9562608E8bDb824", 652 | "__comment": "Swamp pSwamp-Matic LP" 653 | }, 654 | { 655 | "vault": "0x9A547d7c5359cd19C95A0c88C0967B715Cd19601", 656 | "__comment": "Swamp WEth-USDC" 657 | }, 658 | { 659 | "vault": "0xf15b4FDc78a87786d3f3d775cB5E27847348490C", 660 | "__comment": "Swamp Dino-USDC" 661 | }, 662 | { 663 | "vault": "0xb7b5641442C1762586AA03Fdc4Fa4200CB57D4e5", 664 | "__comment": "Swamp BTC-Eth" 665 | }, 666 | { 667 | "vault": "0xCc5579577AD2F499F2d3583FCb4aFD765510A33B", 668 | "__comment": "Swamp USDC-Dai" 669 | }, 670 | { 671 | "vault": "0x759DCd61C021eDC0365882048C726462fA05F642", 672 | "__comment": "PWAC Lithium" 673 | }, 674 | { 675 | "vault": "0xd6a9550Fe158b477bC12af882911CB5e89295D39", 676 | "__comment": "PWAC Lithium-USDC LP" 677 | }, 678 | { 679 | "vault": "0x53197CBe1cBeb417089cAAb3B5fB16391EDe0a69", 680 | "__comment": "PWAC Lithium-Matic LP" 681 | }, 682 | { 683 | "vault": "0x01E02c272f0436317B1d05C350ED9C5482777aAb", 684 | "__comment": "JetSwap pWings" 685 | }, 686 | { 687 | "vault": "0x0D3389DB05bC0d21961fEFd8b54B92558D798Fe2", 688 | "__comment": "JetSwap PWINGS-Matic LP" 689 | }, 690 | { 691 | "vault": "0xdc351171072F753409f52910449af613A2FA202a", 692 | "__comment": "JetSwap pForce-Matic LP" 693 | }, 694 | { 695 | "vault": "0xa8974E37d2B9dF1c9dDD49e7D6363d32D366D976", 696 | "__comment": "JetSwap USDC-Dai LP" 697 | }, 698 | { 699 | "vault": "0xc1f26fb014eF6EAa600ba95dAa18dDb0FeFaCC91", 700 | "__comment": "JetSwap USDC-ETH LP" 701 | }, 702 | { 703 | "vault": "0x41a3dDd6f2502689Bfd6170026ac45DC810E8037", 704 | "__comment": "PolyRoll Roll" 705 | }, 706 | { 707 | "vault": "0xa32de2a04f68a17F6289105ce98baaA97f415309", 708 | "__comment": "PolyRoll Roll" 709 | }, 710 | { 711 | "vault": "0x8488E2f70055fdc2aCDF511Be789AEb93ae0B1B3", 712 | "__comment": "PolyRoll Roll-Matic LP" 713 | }, 714 | { 715 | "vault": "0x15113393DB8B1Cd9781E04499b942AE1A3412763", 716 | "__comment": "PolyRoll Roll-Matic LP" 717 | }, 718 | { 719 | "vault": "0xEC56A5a3c43Ef9e60F7baE05254f5bE6eae4bdB5", 720 | "__comment": "SA myFriends" 721 | }, 722 | { 723 | "vault": "0xA6633cE2A7Bb69D3B1d34D56c95Aa0F59FFF6f57", 724 | "__comment": "SA Arcadium-USDC LP" 725 | }, 726 | { 727 | "vault": "0xa807d2892698190207E6f66d35DFbF0a227f51f4", 728 | "__comment": "SA Arcadium-Matic LP" 729 | }, 730 | { 731 | "vault": "0x1CFef93D79d0421cf5e21bbeAF8F8f389BA3A5B6", 732 | "__comment": "SA myFriends-USDC LP" 733 | }, 734 | { 735 | "vault": "0x96d1DB482032eE964D344Ca44B2AfE4B8f96f8d2", 736 | "__comment": "SA myFriends-Matic LP" 737 | }, 738 | { 739 | "vault": "0xa18A9C9527aCFCa8F697c8691687DA254F773f99", 740 | "__comment": "SA WMatic" 741 | }, 742 | { 743 | "vault": "0x89030969DB2B51897D7f4C789b7C9d3c2ef05083", 744 | "__comment": "SA USDC" 745 | }, 746 | { 747 | "vault": "0x67cE36bf3106D782Ca06EEFa937d14f2D054ebe4", 748 | "__comment": "SA Dai" 749 | }, 750 | { 751 | "vault": "0xb9F9E41ac77A6B6E90e7EC26D9CDcEdB194F508A", 752 | "__comment": "SA USDT" 753 | }, 754 | { 755 | "vault": "0x9762Bb14a5E9a2Fa94eb5FB9D241FA3d4893e6A5", 756 | "__comment": "PolyPup Ball" 757 | }, 758 | { 759 | "vault": "0xFa10DbeFA09f369E191eD385FccC63c7De22bcd0", 760 | "__comment": "PolyPup Ball-USDC LP" 761 | }, 762 | { 763 | "vault": "0x93da5BAF95E313C99B76A98974D27d6eb32B2996", 764 | "__comment": "PolyPup Ball-WMatic LP" 765 | }, 766 | { 767 | "vault": "0xE057c5b2e0eDbE5c336123409B0346d889286DdC", 768 | "__comment": "PolyPup Mai(miMatic)-USDC LP" 769 | }, 770 | { 771 | "vault": "0xae39a17C457d7fB75C0D5FAf96F685483aBD570b", 772 | "__comment": "PolyPup WMatic" 773 | }, 774 | { 775 | "vault": "0x37E45856616Cf8CeE2E3a69C7C401b6163552afF", 776 | "__comment": "PolyPup Eth" 777 | }, 778 | { 779 | "vault": "0x1478883920113b91991a9520252347e3274a6396", 780 | "__comment": "PolyPup Dai" 781 | }, 782 | { 783 | "vault": "0x0eB72cd5f9911C307a0E3B07426a7FDeb4588600", 784 | "__comment": "PolyPup USDC" 785 | }, 786 | { 787 | "vault": "0xeeb87B59b162B54a7f61DD7C0E7157984A56f506", 788 | "__comment": "PolyVertex Vert" 789 | }, 790 | { 791 | "vault": "0x424D5E4000a0795c4CAaa3ee252B1Ae13d4cA39B", 792 | "__comment": "PolyVertex Vert-USDC LP" 793 | }, 794 | { 795 | "vault": "0xa937941C8CC9A21d0c6B866Fd2eEaED78B8C2834", 796 | "__comment": "BoneSwap Bone(Swap)-WMatic LP" 797 | }, 798 | { 799 | "vault": "0x1B247E74d5c2D6CeF12C9BEc8115282CbC45c8B5", 800 | "__comment": "BoneSwap USDC" 801 | }, 802 | { 803 | "vault": "0x36DFEAE548Cfc9A8335624Cffc3fCDF80a5141f2", 804 | "__comment": "BoneSwap WMatic" 805 | }, 806 | { 807 | "vault": "0x8b9C797DBcFAD409747962D1FE4718a9660dB94b", 808 | "__comment": "PolyPup Bone-USDC LP" 809 | }, 810 | { 811 | "vault": "0x846C27ec821F67A9177C56F0cA6FEc4cfc5e5C8E", 812 | "__comment": "PolyPup Bone-WMatic LP" 813 | }, 814 | { 815 | "vault": "0x379566E654D071E917332F9aA7A10587D09059e9", 816 | "__comment": "PolyPup Pup-WMatic LP" 817 | }, 818 | { 819 | "vault": "0xF457000D481Df3c486DFD38d8Fa0C4Fc949a6BbE", 820 | "__comment": "PolyPup WMatic-USDC LP" 821 | }, 822 | { 823 | "vault": "0xA89414dD5E57b896a3b20137d36B46a3AF12066A", 824 | "__comment": "PolyPup Bone" 825 | }, 826 | { 827 | "vault": "0xeAdCb0469f05fa07d4f5178FC762C5C872b6D9c0", 828 | "__comment": "PolyPup Pup" 829 | }, 830 | { 831 | "vault": "0xa104c9Aad3EE07676D23159282124dCD3F542c62", 832 | "__comment": "PolyPup WMatic" 833 | }, 834 | { 835 | "vault": "0x82e553b4B645A195BEA0E6C78c05483a07cf6116", 836 | "__comment": "PolyPup ETH" 837 | }, 838 | { 839 | "vault": "0x24Dbf973CC3fe6357cAB6394d94781784A55D930", 840 | "__comment": "PolyPup Dai" 841 | }, 842 | { 843 | "vault": "0x55C08f4F053170009010cF7435064d5e0E6905E3", 844 | "__comment": "PolyCrystal CRYSTL" 845 | }, 846 | { 847 | "vault": "0x58201C1331Bf7f36ed326af0789A33851019875b", 848 | "__comment": "PolyCrystal CRYSTL-Matic LP" 849 | }, 850 | { 851 | "vault": "0x2D03892d0fAE4479aE2B0d945f67675F006F7271", 852 | "__comment": "PolyCrystal ETH-MATIC LP" 853 | }, 854 | { 855 | "vault": "0x54507Ee8E18FB6d7E4771A6619b04a84635bFf4B", 856 | "__comment": "PolyCrystal USDC-DAI LP" 857 | }, 858 | { 859 | "vault": "0x58FE96934a595Df1C03BddA09F0fdba38063770B", 860 | "__comment": "PolyCrystal Fish-Matic LP" 861 | }, 862 | { 863 | "vault": "0xB131089e899a6F2E7726b83b85C32bbE097b138b", 864 | "__comment": "PolyCrystal BANANA-ETH LP" 865 | }, 866 | { 867 | "vault": "0x510D776fEA6469531f8be69e669e553C0De69621", 868 | "__comment": "PolyCrystal POLYDOGE-MATIC LP" 869 | }, 870 | { 871 | "vault": "0x8a8c784DDE052dE731a4477Bb95B4F594f5B9Bc3", 872 | "__comment": "Augury Omen" 873 | }, 874 | { 875 | "vault": "0x6726775952DE79b66c2340fCB4DD1cb3D48944E5", 876 | "__comment": "Augury Omen-USDC LP" 877 | }, 878 | { 879 | "vault": "0x0e0BCba8269f5d2192Ab8ABED301Ee229DE0F244", 880 | "__comment": "Augury Omen-WMatic LP" 881 | }, 882 | { 883 | "vault": "0xb9A4d32a547a4865E5247D611De7F3D7F3B2d378", 884 | "__comment": "Yeld Yeld" 885 | }, 886 | { 887 | "vault": "0x17051bB60771888Bc908B6946F4Fb7850042FE1d", 888 | "__comment": "Yeld Yeld-Matic LP" 889 | }, 890 | { 891 | "vault": "0x2f3E17b34A79F4990153EE5588aC04724E773C6E", 892 | "__comment": "Yeld Yeld-Matic LP" 893 | }, 894 | { 895 | "vault": "0x97B0262670F3F640A6Be287f403302E2285F5A87", 896 | "__comment": "Yeld Yeld-Matic LP" 897 | }, 898 | { 899 | "vault": "0xDF47221A2240754245dD3b88e01100C0d1d85Aa9", 900 | "__comment": "Yeld Yeld-USDC LP" 901 | }, 902 | { 903 | "vault": "0x7f9fc5bA0c2d213C9Eee7940fefA1a7a297B2320", 904 | "__comment": "Wault WEXPoly" 905 | }, 906 | { 907 | "vault": "0x12977EdF05A6718036f4ecc9bE2D26366a97B96b", 908 | "__comment": "Wault WEXPoly-Matic LP" 909 | }, 910 | { 911 | "vault": "0xe1A9ab14B4c0efa25a1EE6f1348ef4C34418c258", 912 | "__comment": "Wault WEXPoly-USDC LP" 913 | }, 914 | { 915 | "vault": "0x05d83F3Ef95F921971763b035c00298BC42ff008", 916 | "__comment": "PolyCat Fish" 917 | }, 918 | { 919 | "vault": "0x2bb510a979fe3f277636A94B86FA304c6631581C", 920 | "__comment": "PolyCat Fish-Matic LP" 921 | }, 922 | { 923 | "vault": "0xEa2F645691d114f0A7Fa7a759032F8c6f90D58d5", 924 | "__comment": "PolyCat Fish-Matic LP" 925 | }, 926 | { 927 | "vault": "0xF0db902352dfe1EaF8deb2a2eb5c760568821f58", 928 | "__comment": "PirateDice Booty" 929 | }, 930 | { 931 | "vault": "0xbFad80456C71BE0fdE53ecd623605662cF808e53", 932 | "__comment": "PirateDice Booty-USDC LP" 933 | }, 934 | { 935 | "vault": "0x0Be469DE6635A71a07Df915D65D5f08Fb4ac007F", 936 | "__comment": "PirateDice Booty-Matic LP" 937 | }, 938 | { 939 | "vault": "0x4929f3D8934640Fd93a21E89Cd22ddb4b2aff8c1", 940 | "__comment": "PolyGaj Gaj-USDC LP" 941 | }, 942 | { 943 | "vault": "0xE80D7246EcD89Cb8707001c61f652B90eeA0dbc4", 944 | "__comment": "PolyGaj Gaj-MATIC LP" 945 | }, 946 | { 947 | "vault": "0x72812112d635873F5fEF2b0bcAb22cC5BBA2E0dD", 948 | "__comment": "Iron Titan" 949 | }, 950 | { 951 | "vault": "0xaA5237Ff567987445e1AC35D5148c11Ef3703173", 952 | "__comment": "Iron Titan-MATIC LP" 953 | }, 954 | { 955 | "vault": "0x9A48219D7b3106BaAD3F5D6Cf50d94F1Cf747C8D", 956 | "__comment": "Iron Titan-Iron LP" 957 | } 958 | ] 959 | -------------------------------------------------------------------------------- /transform.js: -------------------------------------------------------------------------------- 1 | // Just copy paste the vaults from our frontend vaults. 2 | 3 | // BE SURE TO REPLACE IT ONLY ON THE `transform.js` FILE. 4 | 5 | // Call it with `node transform.js` 6 | 7 | const fs = require('fs') 8 | 9 | const vaults = getVaults() 10 | 11 | // Modify the output filename and the jar addresse chainId as needed 12 | fs.writeFileSync( 13 | 'movr_vault_addresses.json', 14 | JSON.stringify( 15 | vaults.map((e) => ({ 16 | vault: e.jarAddresses['1285'], 17 | __comment: `${e.platform} ${e.lpSymbol}`, 18 | })), 19 | ), 20 | ) 21 | 22 | function getVaults() { 23 | return [ 24 | { 25 | pid: 45, 26 | lpSymbol: 'BTC-ETH LP', 27 | lpAddresses: { 28 | 80001: '', 29 | 1285: '0x85657487978d65BB7881e9dAD3aA119E6E6705cE', 30 | }, 31 | masterChefAddresses: { 32 | 80001: '', 33 | 1285: '0x3dB01570D97631f69bbb0ba39796865456Cf89A5', 34 | }, 35 | masterChefPid: 0, 36 | jarAddresses: { 37 | 80001: '', 38 | 1285: '0x50E618B129454373FF6F560c90cA334c3C17bc7f', 39 | }, 40 | 41 | 42 | 43 | 44 | rewardPerBlock1: 0.024 * 2, // Fix reward block time 45 | rewardPerBlock2: 0.00247 * 2, // Fix reward block time 46 | poolWeightDesignate: 1750 / 10000, 47 | minutesPerCompound: 60, 48 | kogefarmFee: 0.01, 49 | underlyingWebsite: 'https://app.sushi.com/farm', 50 | platform: 'Sushiswap', 51 | createdAt: "2021/11/16" 52 | }, 53 | { 54 | pid: 46, 55 | lpSymbol: 'ETH-BNB LP', 56 | lpAddresses: { 57 | 80001: '', 58 | 1285: '0x69B4FbD8c8Cf74720A62A5e92e2528c3f895cE10', 59 | }, 60 | masterChefAddresses: { 61 | 80001: '', 62 | 1285: '0x3dB01570D97631f69bbb0ba39796865456Cf89A5', 63 | }, 64 | masterChefPid: 1, 65 | jarAddresses: { 66 | 80001: '', 67 | 1285: '0x1f7Fa5f767c62704cFdAa4277b378Dbc77DE7DB6', 68 | }, 69 | 70 | 71 | 72 | 73 | rewardPerBlock1: 0.024 * 2, // Fix reward block time 74 | rewardPerBlock2: 0.00247 * 2, // Fix reward block time 75 | poolWeightDesignate: 1000 / 10000, 76 | minutesPerCompound: 60, 77 | kogefarmFee: 0.01, 78 | underlyingWebsite: 'https://app.sushi.com/farm', 79 | platform: 'Sushiswap', 80 | createdAt: "2021/11/16" 81 | }, 82 | { 83 | pid: 47, 84 | lpSymbol: 'USDT-ETH LP', 85 | lpAddresses: { 86 | 80001: '', 87 | 1285: '0xB0A594e76A876DE40a7fda9819E5c4Ec6d9Fd222', 88 | }, 89 | masterChefAddresses: { 90 | 80001: '', 91 | 1285: '0x3dB01570D97631f69bbb0ba39796865456Cf89A5', 92 | }, 93 | masterChefPid: 2, 94 | jarAddresses: { 95 | 80001: '', 96 | 1285: '0x38Da7A3a1EAE070Ade6768DCcAD7a9A9a7FFaf73', 97 | }, 98 | 99 | 100 | 101 | 102 | rewardPerBlock1: 0.024 * 2, // Fix reward block time 103 | rewardPerBlock2: 0.00247 * 2, // Fix reward block time 104 | poolWeightDesignate: 2000 / 10000, 105 | minutesPerCompound: 60, 106 | kogefarmFee: 0.01, 107 | underlyingWebsite: 'https://app.sushi.com/farm', 108 | platform: 'Sushiswap', 109 | createdAt: "2021/11/16" 110 | }, 111 | { 112 | pid: 48, 113 | lpSymbol: 'USDC-USDT LP', 114 | lpAddresses: { 115 | 80001: '', 116 | 1285: '0x930B0464411DE2296E3FD3eeE30ab989F635645E', 117 | }, 118 | masterChefAddresses: { 119 | 80001: '', 120 | 1285: '0x3dB01570D97631f69bbb0ba39796865456Cf89A5', 121 | }, 122 | masterChefPid: 3, 123 | jarAddresses: { 124 | 80001: '', 125 | 1285: '0x62cbB73a0AaA2009f325dc5ca940cB50bC28FFB8', 126 | }, 127 | 128 | 129 | 130 | 131 | rewardPerBlock1: 0.024 * 2, // Fix reward block time 132 | rewardPerBlock2: 0.00247 * 2, // Fix reward block time 133 | poolWeightDesignate: 750 / 10000, 134 | minutesPerCompound: 60, 135 | kogefarmFee: 0.01, 136 | underlyingWebsite: 'https://app.sushi.com/farm', 137 | platform: 'Sushiswap', 138 | createdAt: "2021/11/16" 139 | }, 140 | { 141 | pid: 49, 142 | lpSymbol: 'ETH-MOVR LP', 143 | lpAddresses: { 144 | 80001: '', 145 | 1285: '0xD4Ce5671b842573EDA99164971AFaA034245f4D8', 146 | }, 147 | masterChefAddresses: { 148 | 80001: '', 149 | 1285: '0x3dB01570D97631f69bbb0ba39796865456Cf89A5', 150 | }, 151 | masterChefPid: 4, 152 | jarAddresses: { 153 | 80001: '', 154 | 1285: '0x80546BF73ed61B92aC2eE29f4aC9c016d74cC6D8', 155 | }, 156 | 157 | 158 | 159 | 160 | rewardPerBlock1: 0.024 * 2, // Fix reward block time 161 | rewardPerBlock2: 0.00247 * 2, // Fix reward block time 162 | poolWeightDesignate: 3500 / 10000, 163 | minutesPerCompound: 60, 164 | kogefarmFee: 0.01, 165 | underlyingWebsite: 'https://app.sushi.com/farm', 166 | platform: 'Sushiswap', 167 | createdAt: "2021/11/16" 168 | 169 | }, 170 | { 171 | pid: 50, 172 | lpSymbol: 'FRAX-USDC LP', 173 | lpAddresses: { 174 | 80001: '', 175 | 1285: '0x310C4d18640aF4878567c4A31cB9cBde7Cd234A3', 176 | }, 177 | masterChefAddresses: { 178 | 80001: '', 179 | 1285: '0x3dB01570D97631f69bbb0ba39796865456Cf89A5', 180 | }, 181 | masterChefPid: 5, 182 | jarAddresses: { 183 | 80001: '', 184 | 1285: '0x7a7A3A42F0197D99469AFdC4209C2260ac006fB6', 185 | }, 186 | 187 | 188 | 189 | 190 | rewardPerBlock1: 0.024 * 2, // Fix reward block time 191 | rewardPerBlock2: 0.00247 * 2, // Fix reward block time 192 | poolWeightDesignate: 500 / 10000, 193 | minutesPerCompound: 60, 194 | kogefarmFee: 0.01, 195 | underlyingWebsite: 'https://app.sushi.com/farm', 196 | platform: 'Sushiswap', 197 | createdAt: "2021/11/16" 198 | }, 199 | { 200 | pid: 51, 201 | lpSymbol: 'MIM-MOVR LP', 202 | lpAddresses: { 203 | 80001: '', 204 | 1285: '0x6dC6D33331e9d5DeEf449C8CAb9e34D687BEA80E', 205 | }, 206 | masterChefAddresses: { 207 | 80001: '', 208 | 1285: '0x3dB01570D97631f69bbb0ba39796865456Cf89A5', 209 | }, 210 | masterChefPid: 6, 211 | jarAddresses: { 212 | 80001: '', 213 | 1285: '0x3423892e9C717aeeC56aA4CeeBA213A35c10f3A2', 214 | }, 215 | 216 | 217 | 218 | 219 | rewardPerBlock1: 0.024 * 2, // Fix reward block time 220 | rewardPerBlock2: 0.00247 * 2, // Fix reward block time 221 | poolWeightDesignate: 500 / 10000, 222 | minutesPerCompound: 60, 223 | kogefarmFee: 0.01, 224 | underlyingWebsite: 'https://app.sushi.com/farm', 225 | platform: 'Sushiswap', 226 | createdAt: "2021/11/16" 227 | }, 228 | { 229 | pid: 21, 230 | lpSymbol: 'Solar-Movr LP', 231 | lpAddresses: { 232 | 80001: '', 233 | 1285: '0x7eDA899b3522683636746a2f3a7814e6fFca75e1', 234 | }, 235 | masterChefAddresses: { 236 | 80001: '', 237 | 1285: '0xf03b75831397D4695a6b9dDdEEA0E578faa30907', 238 | }, 239 | masterChefPid: 0, 240 | jarAddresses: { 241 | 80001: '', 242 | 1285: '0x0a5E266afB071CB0F69310706154F2893a208D1c', 243 | }, 244 | 245 | 246 | 247 | rewardPerBlock: 3.1595159 * 2 / 14, // Fix reward block time 248 | poolWeightDesignate: 4876 / 10464, 249 | minutesPerCompound: 60, 250 | kogefarmFee: 0.01, 251 | underlyingWebsite: 'https://solarbeam.io/', 252 | platform: 'SolarBeam' 253 | }, 254 | 255 | { 256 | pid: 23, 257 | lpSymbol: 'Solar-USDC LP', 258 | lpAddresses: { 259 | 80001: '', 260 | 1285: '0xdb66BE1005f5Fe1d2f486E75cE3C50B52535F886', 261 | }, 262 | masterChefAddresses: { 263 | 80001: '', 264 | 1285: '0xf03b75831397D4695a6b9dDdEEA0E578faa30907', 265 | }, 266 | masterChefPid: 7, 267 | jarAddresses: { 268 | 80001: '', 269 | 1285: '0x4c42f8224E16b40d79BeB775bf1df1a63967FC7c', 270 | }, 271 | 272 | 273 | 274 | rewardPerBlock: 3.1595159 * 2 / 14, // Fix reward block time 275 | poolWeightDesignate: 1828 / 10464, 276 | minutesPerCompound: 60, 277 | kogefarmFee: 0.01, 278 | underlyingWebsite: 'https://solarbeam.io/', 279 | platform: 'SolarBeam' 280 | }, 281 | 282 | { 283 | pid: 22, 284 | lpSymbol: 'Movr-USDC LP', 285 | lpAddresses: { 286 | 80001: '', 287 | 1285: '0xe537f70a8b62204832B8Ba91940B77d3f79AEb81', 288 | }, 289 | masterChefAddresses: { 290 | 80001: '', 291 | 1285: '0xf03b75831397D4695a6b9dDdEEA0E578faa30907', 292 | }, 293 | masterChefPid: 6, 294 | jarAddresses: { 295 | 80001: '', 296 | 1285: '0xaE3BDcf55FE53408EC4ad07480368e04c795575d', 297 | }, 298 | 299 | 300 | 301 | rewardPerBlock: 3.1595159 * 2 / 14, // Fix reward block time 302 | poolWeightDesignate: 1828 / 10464, 303 | minutesPerCompound: 60, 304 | kogefarmFee: 0.01, 305 | underlyingWebsite: 'https://solarbeam.io/', 306 | platform: 'SolarBeam' 307 | }, 308 | 309 | { 310 | pid: 20, 311 | lpSymbol: 'USDC-Dai LP', 312 | lpAddresses: { 313 | 80001: '', 314 | 1285: '0xFE1b71BDAEE495dCA331D28F5779E87bd32FbE53', 315 | }, 316 | masterChefAddresses: { 317 | 80001: '', 318 | 1285: '0xf03b75831397D4695a6b9dDdEEA0E578faa30907', 319 | }, 320 | masterChefPid: 8, 321 | jarAddresses: { 322 | 80001: '', 323 | 1285: '0x005d1d02e396D4B47DD92e3c068a6Cec153238cd', 324 | }, 325 | 326 | 327 | 328 | rewardPerBlock: 3.1595159 * 2 / 14, // Fix reward block time 329 | poolWeightDesignate: 203 / 10464, 330 | minutesPerCompound: 60, 331 | kogefarmFee: 0.01, 332 | underlyingWebsite: 'https://solarbeam.io/', 333 | platform: 'SolarBeam' 334 | }, 335 | 336 | { 337 | pid: 24, 338 | lpSymbol: 'BUSD-USDC LP', 339 | lpAddresses: { 340 | 80001: '', 341 | 1285: '0x384704557F73fBFAE6e9297FD1E6075FC340dbe5', 342 | }, 343 | masterChefAddresses: { 344 | 80001: '', 345 | 1285: '0xf03b75831397D4695a6b9dDdEEA0E578faa30907', 346 | }, 347 | masterChefPid: 9, 348 | jarAddresses: { 349 | 80001: '', 350 | 1285: '0xFA45b55c3a2bA74B9De476FC01658F9352209390', 351 | }, 352 | 353 | 354 | 355 | rewardPerBlock: 3.1595159 * 2 / 14, // Fix reward block time 356 | poolWeightDesignate: 305 / 10464, 357 | minutesPerCompound: 60, 358 | kogefarmFee: 0.01, 359 | underlyingWebsite: 'https://solarbeam.io/', 360 | platform: 'SolarBeam' 361 | }, 362 | 363 | { 364 | pid: 25, 365 | lpSymbol: 'USDC-USDT LP', 366 | lpAddresses: { 367 | 80001: '', 368 | 1285: '0x2a44696DDc050f14429bd8a4A05c750C6582bF3b', 369 | }, 370 | masterChefAddresses: { 371 | 80001: '', 372 | 1285: '0xf03b75831397D4695a6b9dDdEEA0E578faa30907', 373 | }, 374 | masterChefPid: 13, 375 | jarAddresses: { 376 | 80001: '', 377 | 1285: '0x31645AEFBCF37127f511b7BD9A7bfdA7427AeF8e', 378 | }, 379 | 380 | 381 | 382 | rewardPerBlock: 3.1595159 * 2 / 14, // Fix reward block time 383 | poolWeightDesignate: 203 / 10464, 384 | minutesPerCompound: 60, 385 | kogefarmFee: 0.01, 386 | underlyingWebsite: 'https://solarbeam.io/', 387 | platform: 'SolarBeam' 388 | }, 389 | 390 | { 391 | pid: 26, 392 | lpSymbol: 'Mai-USDC LP', 393 | lpAddresses: { 394 | 80001: '', 395 | 1285: '0x55Ee073B38BF1069D5F1Ed0AA6858062bA42F5A9', 396 | }, 397 | masterChefAddresses: { 398 | 80001: '', 399 | 1285: '0xf03b75831397D4695a6b9dDdEEA0E578faa30907', 400 | }, 401 | masterChefPid: 17, 402 | jarAddresses: { 403 | 80001: '', 404 | 1285: '0xA1d30Bee6896e07B8713E73b56A6c35a559DEa50', 405 | }, 406 | 407 | 408 | 409 | rewardPerBlock: 3.1595159 * 2 / 14, // Fix reward block time 410 | poolWeightDesignate: 25 / 10464, 411 | minutesPerCompound: 60, 412 | kogefarmFee: 0.01, 413 | underlyingWebsite: 'https://solarbeam.io/', 414 | platform: 'SolarBeam' 415 | }, 416 | 417 | { 418 | pid: 33, 419 | lpSymbol: 'MIM-USDC LP', 420 | lpAddresses: { 421 | 80001: '', 422 | 1285: '0x9051fB701d6D880800e397e5B5d46FdDfAdc7056', 423 | }, 424 | masterChefAddresses: { 425 | 80001: '', 426 | 1285: '0xf03b75831397D4695a6b9dDdEEA0E578faa30907', 427 | }, 428 | masterChefPid: 19, 429 | jarAddresses: { 430 | 80001: '', 431 | 1285: '0xAc6DebA557fbeb17de8E0F88bFE92eAB54724018', 432 | }, 433 | 434 | 435 | 436 | rewardPerBlock: 3.1595159 * 2 / 14, // Fix reward block time 437 | poolWeightDesignate: 25 / 10464, 438 | minutesPerCompound: 60, 439 | kogefarmFee: 0.01, 440 | underlyingWebsite: 'https://solarbeam.io/', 441 | platform: 'SolarBeam' 442 | }, 443 | 444 | { 445 | pid: 27, 446 | lpSymbol: 'USDC-ETH LP', 447 | lpAddresses: { 448 | 80001: '', 449 | 1285: '0xA0D8DFB2CC9dFe6905eDd5B71c56BA92AD09A3dC', 450 | }, 451 | masterChefAddresses: { 452 | 80001: '', 453 | 1285: '0xf03b75831397D4695a6b9dDdEEA0E578faa30907', 454 | }, 455 | masterChefPid: 10, 456 | jarAddresses: { 457 | 80001: '', 458 | 1285: '0xB31E2E391251705b53983221AAB3fdB0c728C51f', 459 | }, 460 | 461 | 462 | 463 | rewardPerBlock: 3.1595159 * 2 / 14, // Fix reward block time 464 | poolWeightDesignate: 102 / 10464, 465 | minutesPerCompound: 60, 466 | kogefarmFee: 0.01, 467 | underlyingWebsite: 'https://solarbeam.io/', 468 | platform: 'SolarBeam' 469 | }, 470 | 471 | { 472 | pid: 28, 473 | lpSymbol: 'BNB-BUSD LP', 474 | lpAddresses: { 475 | 80001: '', 476 | 1285: '0xfb1d0D6141Fc3305C63f189E39Cc2f2F7E58f4c2', 477 | }, 478 | masterChefAddresses: { 479 | 80001: '', 480 | 1285: '0xf03b75831397D4695a6b9dDdEEA0E578faa30907', 481 | }, 482 | masterChefPid: 11, 483 | jarAddresses: { 484 | 80001: '', 485 | 1285: '0x6948E97d777Ea8EfD756dFa5E679C0D9be3A4E14', 486 | }, 487 | 488 | 489 | 490 | rewardPerBlock: 3.1595159 * 2 / 14, // Fix reward block time 491 | poolWeightDesignate: 102 / 10464, 492 | minutesPerCompound: 60, 493 | kogefarmFee: 0.01, 494 | underlyingWebsite: 'https://solarbeam.io/', 495 | platform: 'SolarBeam' 496 | }, 497 | 498 | { 499 | pid: 29, 500 | lpSymbol: 'BTC-USDC LP', 501 | lpAddresses: { 502 | 80001: '', 503 | 1285: '0x83d7a3fc841038E8c8F46e6192BBcCA8b19Ee4e7', 504 | }, 505 | masterChefAddresses: { 506 | 80001: '', 507 | 1285: '0xf03b75831397D4695a6b9dDdEEA0E578faa30907', 508 | }, 509 | masterChefPid: 12, 510 | jarAddresses: { 511 | 80001: '', 512 | 1285: '0x02C4B3a6FF8b187fb381CD3461229e2c77E0B5f9', 513 | }, 514 | 515 | 516 | 517 | rewardPerBlock: 3.1595159 * 2 / 14, // Fix reward block time 518 | poolWeightDesignate: 102 / 10464, 519 | minutesPerCompound: 60, 520 | kogefarmFee: 0.01, 521 | underlyingWebsite: 'https://solarbeam.io/', 522 | platform: 'SolarBeam' 523 | }, 524 | 525 | { 526 | pid: 30, 527 | lpSymbol: 'Matic-MOVR LP', 528 | lpAddresses: { 529 | 80001: '', 530 | 1285: '0x29633cc367AbD9b16d327Adaf6c3538b6e97f6C0', 531 | }, 532 | masterChefAddresses: { 533 | 80001: '', 534 | 1285: '0xf03b75831397D4695a6b9dDdEEA0E578faa30907', 535 | }, 536 | masterChefPid: 14, 537 | jarAddresses: { 538 | 80001: '', 539 | 1285: '0xA5c44621FDDd448032d22987845c24Edf5c2953D', 540 | }, 541 | 542 | 543 | 544 | rewardPerBlock: 3.1595159 * 2 / 14, // Fix reward block time 545 | poolWeightDesignate: 102 / 10464, 546 | minutesPerCompound: 60, 547 | kogefarmFee: 0.01, 548 | underlyingWebsite: 'https://solarbeam.io/', 549 | platform: 'SolarBeam' 550 | }, 551 | 552 | { 553 | pid: 31, 554 | lpSymbol: 'AVAX-MOVR LP', 555 | lpAddresses: { 556 | 80001: '', 557 | 1285: '0xb9a61ac826196AbC69A3C66ad77c563D6C5bdD7b', 558 | }, 559 | masterChefAddresses: { 560 | 80001: '', 561 | 1285: '0xf03b75831397D4695a6b9dDdEEA0E578faa30907', 562 | }, 563 | masterChefPid: 15, 564 | jarAddresses: { 565 | 80001: '', 566 | 1285: '0xa5133eE054a02fDEB7A03909B4bfd73b3C7e16A2', 567 | }, 568 | 569 | 570 | 571 | rewardPerBlock: 3.1595159 * 2 / 14, // Fix reward block time 572 | poolWeightDesignate: 203 / 10464, 573 | minutesPerCompound: 60, 574 | kogefarmFee: 0.01, 575 | underlyingWebsite: 'https://solarbeam.io/', 576 | platform: 'SolarBeam' 577 | }, 578 | 579 | { 580 | pid: 32, 581 | lpSymbol: 'FTM-MOVR LP', 582 | lpAddresses: { 583 | 80001: '', 584 | 1285: '0x1eebed8F28A6865a76D91189FD6FC45F4F774d67', 585 | }, 586 | masterChefAddresses: { 587 | 80001: '', 588 | 1285: '0xf03b75831397D4695a6b9dDdEEA0E578faa30907', 589 | }, 590 | masterChefPid: 18, 591 | jarAddresses: { 592 | 80001: '', 593 | 1285: '0xa70c8268152D2B06E2313de2273F82D9B031b35a', 594 | }, 595 | 596 | 597 | 598 | rewardPerBlock: 3.1595159 * 2 / 14, // Fix reward block time 599 | poolWeightDesignate: 102 / 10464, 600 | minutesPerCompound: 60, 601 | kogefarmFee: 0.01, 602 | underlyingWebsite: 'https://solarbeam.io/', 603 | platform: 'SolarBeam' 604 | }, 605 | { 606 | pid: 34, 607 | lpSymbol: 'MOVR-FINN LP', 608 | lpAddresses: { 609 | 80001: '', 610 | 1285: '0xbBe2f34367972Cb37ae8dea849aE168834440685', 611 | }, 612 | masterChefAddresses: { 613 | 80001: '', 614 | 1285: '0x1f4b7660b6AdC3943b5038e3426B33c1c0e343E6', 615 | }, 616 | masterChefPid: 4, 617 | jarAddresses: { 618 | 80001: '', 619 | 1285: '0x39109Dd55Ed30fAd5aF63C8C79Bb5A8BB65e94C1', 620 | }, 621 | 622 | 623 | 624 | rewardPerBlock: 7.6 * 2 / 12, // Fix reward block time 625 | poolWeightDesignate: 2500 / 10245, 626 | minutesPerCompound: 60, 627 | kogefarmFee: 0.01, 628 | underlyingWebsite: 'https://www.huckleberry.finance/', 629 | platform: 'Huckleberry', 630 | createdAt: "2021/10/21" 631 | }, 632 | 633 | { 634 | pid: 35, 635 | lpSymbol: 'USDC-FINN LP', 636 | lpAddresses: { 637 | 80001: '', 638 | 1285: '0xb04492345b0618acFf27AC27CeC4244fBdd30208', 639 | }, 640 | masterChefAddresses: { 641 | 80001: '', 642 | 1285: '0x1f4b7660b6AdC3943b5038e3426B33c1c0e343E6', 643 | }, 644 | masterChefPid: 8, 645 | jarAddresses: { 646 | 80001: '', 647 | 1285: '0x98ec2A4afEe2578eF95421D6Ff699A247304D1F3', 648 | }, 649 | 650 | 651 | 652 | rewardPerBlock: 7.6 * 2 / 12, // Fix reward block time 653 | poolWeightDesignate: 1000 / 10245, 654 | minutesPerCompound: 60, 655 | kogefarmFee: 0.01, 656 | underlyingWebsite: 'https://www.huckleberry.finance/', 657 | platform: 'Huckleberry', 658 | createdAt: "2021/10/21" 659 | }, 660 | 661 | { 662 | pid: 36, 663 | lpSymbol: 'DOT-FINN LP', 664 | lpAddresses: { 665 | 80001: '', 666 | 1285: '0xF09211fb5eD5019b072774cfD7Db0c9f4ccd5Be0', 667 | }, 668 | masterChefAddresses: { 669 | 80001: '', 670 | 1285: '0x1f4b7660b6AdC3943b5038e3426B33c1c0e343E6', 671 | }, 672 | masterChefPid: 7, 673 | jarAddresses: { 674 | 80001: '', 675 | 1285: '0xB1d3857e4435199cD6Bae09F6eCa346355BDbE12', 676 | }, 677 | 678 | 679 | 680 | rewardPerBlock: 7.6 * 2 / 12, // Fix reward block time 681 | poolWeightDesignate: 500 / 10245, 682 | minutesPerCompound: 60, 683 | kogefarmFee: 0.01, 684 | underlyingWebsite: 'https://www.huckleberry.finance/', 685 | platform: 'Huckleberry', 686 | createdAt: "2021/10/21" 687 | }, 688 | 689 | { 690 | pid: 37, 691 | lpSymbol: 'XRP-FINN LP', 692 | lpAddresses: { 693 | 80001: '', 694 | 1285: '0x7491D6e5aC2785Fc9c873922F9B424fCA7720519', 695 | }, 696 | masterChefAddresses: { 697 | 80001: '', 698 | 1285: '0x1f4b7660b6AdC3943b5038e3426B33c1c0e343E6', 699 | }, 700 | masterChefPid: 6, 701 | jarAddresses: { 702 | 80001: '', 703 | 1285: '0x33D33ac00877012943f850026E0aa2D6a0A3a629', 704 | }, 705 | 706 | 707 | 708 | rewardPerBlock: 7.6 * 2 / 12, // Fix reward block time 709 | poolWeightDesignate: 300 / 10245, 710 | minutesPerCompound: 60, 711 | kogefarmFee: 0.01, 712 | underlyingWebsite: 'https://www.huckleberry.finance/', 713 | platform: 'Huckleberry', 714 | createdAt: "2021/10/21" 715 | }, 716 | 717 | { 718 | pid: 38, 719 | lpSymbol: 'AVAX-FINN LP', 720 | lpAddresses: { 721 | 80001: '', 722 | 1285: '0x10300C5FD4Af0F81fC8DA3f48e44dbccd189f253', 723 | }, 724 | masterChefAddresses: { 725 | 80001: '', 726 | 1285: '0x1f4b7660b6AdC3943b5038e3426B33c1c0e343E6', 727 | }, 728 | masterChefPid: 9, 729 | jarAddresses: { 730 | 80001: '', 731 | 1285: '0xfC4246D4B4973d3BF7C3A1e4C16df76fe3fD1dA0', 732 | }, 733 | 734 | 735 | 736 | rewardPerBlock: 7.6 * 2 / 12, // Fix reward block time 737 | poolWeightDesignate: 300 / 10245, 738 | minutesPerCompound: 60, 739 | kogefarmFee: 0.01, 740 | underlyingWebsite: 'https://www.huckleberry.finance/', 741 | platform: 'Huckleberry', 742 | createdAt: "2021/10/29" 743 | }, 744 | { 745 | pid: 52, 746 | lpSymbol: 'RKitty-FINN LP', 747 | lpAddresses: { 748 | 80001: '', 749 | 1285: '0xDCd92eb568157D3c1a6b3AE53ADF18a230bc304A', 750 | }, 751 | masterChefAddresses: { 752 | 80001: '', 753 | 1285: '0x1f4b7660b6AdC3943b5038e3426B33c1c0e343E6', 754 | }, 755 | masterChefPid: 19, 756 | jarAddresses: { 757 | 80001: '', 758 | 1285: '0xAAF6A5213AD7180559d626DE29d68decdDeb94FD', 759 | }, 760 | 761 | 762 | 763 | rewardPerBlock: 7.6 * 2 / 12, // Fix reward block time 764 | poolWeightDesignate: 300 / 10245, 765 | minutesPerCompound: 60, 766 | kogefarmFee: 0.01, 767 | underlyingWebsite: 'https://www.huckleberry.finance/', 768 | platform: 'Huckleberry', 769 | createdAt: "2021/11/21" 770 | }, 771 | { 772 | pid: 53, 773 | lpSymbol: 'FTM-FINN LP', 774 | lpAddresses: { 775 | 80001: '', 776 | 1285: '0x135C0c09517AF7445a4B27976d3549B996483f4e', 777 | }, 778 | masterChefAddresses: { 779 | 80001: '', 780 | 1285: '0x1f4b7660b6AdC3943b5038e3426B33c1c0e343E6', 781 | }, 782 | masterChefPid: 18, 783 | jarAddresses: { 784 | 80001: '', 785 | 1285: '0x790831a45Ef57B6260e6EdAb2AC81811b8f2Ec7d', 786 | }, 787 | 788 | 789 | 790 | rewardPerBlock: 7.6 * 2 / 12, // Fix reward block time 791 | poolWeightDesignate: 300 / 10245, 792 | minutesPerCompound: 60, 793 | kogefarmFee: 0.01, 794 | underlyingWebsite: 'https://www.huckleberry.finance/', 795 | platform: 'Huckleberry', 796 | createdAt: "2021/11/21" 797 | }, 798 | { 799 | pid: 54, 800 | lpSymbol: 'USDT-FINN LP', 801 | lpAddresses: { 802 | 80001: '', 803 | 1285: '0xBE1C572E40150EaCf046ceFB4A4552FbB13E68f8', 804 | }, 805 | masterChefAddresses: { 806 | 80001: '', 807 | 1285: '0x1f4b7660b6AdC3943b5038e3426B33c1c0e343E6', 808 | }, 809 | masterChefPid: 10, 810 | jarAddresses: { 811 | 80001: '', 812 | 1285: '0x0f0A5d5E4057393dC56d71D383D07f71c1961bF5', 813 | }, 814 | 815 | 816 | 817 | rewardPerBlock: 7.6 * 2 / 12, // Fix reward block time 818 | poolWeightDesignate: 1000 / 10245, 819 | minutesPerCompound: 60, 820 | kogefarmFee: 0.01, 821 | underlyingWebsite: 'https://www.huckleberry.finance/', 822 | platform: 'Huckleberry', 823 | createdAt: "2021/11/21" 824 | }, 825 | { 826 | pid: 56, 827 | lpSymbol: 'TOM', 828 | lpAddresses: { 829 | 80001: '', 830 | 1285: '0x37619cC85325aFea778830e184CB60a3ABc9210B', 831 | }, 832 | masterChefAddresses: { 833 | 80001: '', 834 | 1285: '0x1f4b7660b6AdC3943b5038e3426B33c1c0e343E6', 835 | }, 836 | masterChefPid: 20, 837 | jarAddresses: { 838 | 80001: '', 839 | 1285: '0xFd5579b0Bfed054F9670c78eFeb6ccEb162A7f40', 840 | }, 841 | 842 | 843 | 844 | rewardPerBlock: 7.6 * 2 / 12, // Fix reward block time 845 | poolWeightDesignate: 1000 / 10245, 846 | minutesPerCompound: 60, 847 | kogefarmFee: 0.01, 848 | underlyingWebsite: 'https://www.huckleberry.finance/', 849 | platform: 'Huckleberry', 850 | createdAt: "2021/11/21" 851 | }, 852 | { 853 | pid: 55, 854 | lpSymbol: 'WAN-MOVR LP', 855 | lpAddresses: { 856 | 80001: '', 857 | 1285: '0x0Df4cD5fD2f69E54A3E6d13e5cad54f1eB995E8c', 858 | }, 859 | masterChefAddresses: { 860 | 80001: '', 861 | 1285: '0x1f4b7660b6AdC3943b5038e3426B33c1c0e343E6', 862 | }, 863 | masterChefPid: 1, 864 | jarAddresses: { 865 | 80001: '', 866 | 1285: '0x649680dbcB6486BdDf643C5Ce489F5E568d0C017', 867 | }, 868 | 869 | 870 | 871 | rewardPerBlock: 7.6 * 2 / 12, // Fix reward block time 872 | poolWeightDesignate: 500 / 10245, 873 | minutesPerCompound: 60, 874 | kogefarmFee: 0.01, 875 | underlyingWebsite: 'https://www.huckleberry.finance/', 876 | platform: 'Huckleberry', 877 | createdAt: "2021/11/21" 878 | }, 879 | { 880 | pid: 39, 881 | lpSymbol: 'USDC.m-USDT.m LP', 882 | lpAddresses: { 883 | 80001: '', 884 | 1285: '0xce634Ae7191aB885Fb4ce8d1ed58f80EA988D52a', 885 | }, 886 | masterChefAddresses: { 887 | 80001: '', 888 | 1285: '0x1f4b7660b6AdC3943b5038e3426B33c1c0e343E6', 889 | }, 890 | masterChefPid: 5, 891 | jarAddresses: { 892 | 80001: '', 893 | 1285: '0xb5f2f033113f8fa4f5Fe4BEd535e05ee308bcAbE', 894 | }, 895 | 896 | 897 | 898 | rewardPerBlock: 7.6 * 2 / 12, // Fix reward block time 899 | poolWeightDesignate: 150 / 10245, 900 | minutesPerCompound: 60, 901 | kogefarmFee: 0.01, 902 | underlyingWebsite: 'https://www.huckleberry.finance/', 903 | platform: 'Huckleberry', 904 | createdAt: "2021/10/29" 905 | }, 906 | { 907 | pid: 40, 908 | lpSymbol: 'USDT.m-MOVR LP', 909 | lpAddresses: { 910 | 80001: '', 911 | 1285: '0x037f019B6d98A61AF80c0da5ecFdc23612B0C134', 912 | }, 913 | masterChefAddresses: { 914 | 80001: '', 915 | 1285: '0x1f4b7660b6AdC3943b5038e3426B33c1c0e343E6', 916 | }, 917 | masterChefPid: 0, 918 | jarAddresses: { 919 | 80001: '', 920 | 1285: '0xB816402B0EA623Fa669f59EE4F429BB9a919027e', 921 | }, 922 | 923 | 924 | 925 | rewardPerBlock: 7.6 * 2 / 12, // Fix reward block time 926 | poolWeightDesignate: 500 / 10245, 927 | minutesPerCompound: 60, 928 | kogefarmFee: 0.01, 929 | underlyingWebsite: 'https://www.huckleberry.finance/', 930 | platform: 'Huckleberry', 931 | createdAt: "2021/10/29" 932 | }, 933 | { 934 | pid: 41, 935 | lpSymbol: 'ETH.m-MOVR LP', 936 | lpAddresses: { 937 | 80001: '', 938 | 1285: '0xBaf9eB00574C42Cf678778790b04705B435B65F8', 939 | }, 940 | masterChefAddresses: { 941 | 80001: '', 942 | 1285: '0x1f4b7660b6AdC3943b5038e3426B33c1c0e343E6', 943 | }, 944 | masterChefPid: 2, 945 | jarAddresses: { 946 | 80001: '', 947 | 1285: '0xaBd70eaEB9C0bb58b9b83A102E309ac764fd8801', 948 | }, 949 | 950 | 951 | 952 | rewardPerBlock: 7.6 * 2 / 12, // Fix reward block time 953 | poolWeightDesignate: 500 / 10245, 954 | minutesPerCompound: 60, 955 | kogefarmFee: 0.01, 956 | underlyingWebsite: 'https://www.huckleberry.finance/', 957 | platform: 'Huckleberry', 958 | createdAt: "2021/10/29" 959 | }, 960 | { 961 | pid: 42, 962 | lpSymbol: 'BTC.m-MOVR LP', 963 | lpAddresses: { 964 | 80001: '', 965 | 1285: '0x3fAF6e9Bf107199dB347B146F80A68CBD0B598B2', 966 | }, 967 | masterChefAddresses: { 968 | 80001: '', 969 | 1285: '0x1f4b7660b6AdC3943b5038e3426B33c1c0e343E6', 970 | }, 971 | masterChefPid: 3, 972 | jarAddresses: { 973 | 80001: '', 974 | 1285: '0x6FC9F91C3db0190184849fF8d7C92E7d35158F2e', 975 | }, 976 | 977 | 978 | 979 | rewardPerBlock: 7.6 * 2 / 12, // Fix reward block time 980 | poolWeightDesignate: 500 / 10245, 981 | minutesPerCompound: 60, 982 | kogefarmFee: 0.01, 983 | underlyingWebsite: 'https://www.huckleberry.finance/', 984 | platform: 'Huckleberry', 985 | createdAt: "2021/10/29" 986 | }, 987 | ] 988 | } 989 | -------------------------------------------------------------------------------- /vaultBase.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.12; 2 | // SPDX-License-Identifier: UNLICENSED 3 | 4 | interface IStrategy { 5 | function harvestedToken() external view returns (address); 6 | 7 | function rewards() external view returns (address); 8 | 9 | function emergencyStatus() external view returns (bool); 10 | 11 | function gauge() external view returns (address); 12 | 13 | function want() external view returns (address); 14 | 15 | function treasury() external view returns (address); 16 | 17 | function deposit() external; 18 | 19 | function depositLocked(uint256 _secs) external; 20 | 21 | function underlyingPoolId() external view returns(uint16); 22 | 23 | function withdrawForSwap(uint256) external returns (uint256); 24 | 25 | function withdraw(address) external; 26 | 27 | function withdraw(uint256) external; 28 | 29 | function withdrawLocked(bytes32 kek_id) external returns (uint256 balance); 30 | 31 | function skim() external; 32 | 33 | function migrate() external; 34 | 35 | function withdrawAll() external returns (uint256); 36 | 37 | function balanceOf() external view returns (uint256); 38 | 39 | function getHarvestable() external view returns (uint256); 40 | 41 | function pairName() external view returns (string memory); 42 | 43 | function harvest() external; 44 | 45 | function setJar(address _jar) external; 46 | 47 | function migrate(address newStakingContract) external; 48 | 49 | function getLastTimeMigrated() external view returns (uint256); 50 | 51 | function execute(address _target, bytes calldata _data) 52 | external 53 | payable 54 | returns (bytes memory response); 55 | 56 | function execute(bytes calldata _data) 57 | external 58 | payable 59 | returns (bytes memory response); 60 | } 61 | 62 | 63 | 64 | /* 65 | * @dev Provides information about the current execution context, including the 66 | * sender of the transaction and its data. While these are generally available 67 | * via msg.sender and msg.data, they should not be accessed in such a direct 68 | * manner, since when dealing with GSN meta-transactions the account sending and 69 | * paying for execution may not be the actual sender (as far as an application 70 | * is concerned). 71 | * 72 | * This contract is only required for intermediate, library-like contracts. 73 | */ 74 | abstract contract Context { 75 | function _msgSender() internal view virtual returns (address payable) { 76 | return msg.sender; 77 | } 78 | 79 | function _msgData() internal view virtual returns (bytes memory) { 80 | this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 81 | return msg.data; 82 | } 83 | } 84 | 85 | 86 | 87 | /** 88 | * @dev Interface of the ERC20 standard as defined in the EIP. 89 | */ 90 | interface IERC20 { 91 | /** 92 | * @dev Returns the amount of tokens in existence. 93 | */ 94 | function totalSupply() external view returns (uint256); 95 | 96 | /** 97 | * @dev Returns the amount of tokens owned by `account`. 98 | */ 99 | function balanceOf(address account) external view returns (uint256); 100 | 101 | /** 102 | * @dev Moves `amount` tokens from the caller's account to `recipient`. 103 | * 104 | * Returns a boolean value indicating whether the operation succeeded. 105 | * 106 | * Emits a {Transfer} event. 107 | */ 108 | function transfer(address recipient, uint256 amount) external returns (bool); 109 | 110 | /** 111 | * @dev Returns the remaining number of tokens that `spender` will be 112 | * allowed to spend on behalf of `owner` through {transferFrom}. This is 113 | * zero by default. 114 | * 115 | * This value changes when {approve} or {transferFrom} are called. 116 | */ 117 | function allowance(address owner, address spender) external view returns (uint256); 118 | 119 | /** 120 | * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 121 | * 122 | * Returns a boolean value indicating whether the operation succeeded. 123 | * 124 | * IMPORTANT: Beware that changing an allowance with this method brings the risk 125 | * that someone may use both the old and the new allowance by unfortunate 126 | * transaction ordering. One possible solution to mitigate this race 127 | * condition is to first reduce the spender's allowance to 0 and set the 128 | * desired value afterwards: 129 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 130 | * 131 | * Emits an {Approval} event. 132 | */ 133 | function approve(address spender, uint256 amount) external returns (bool); 134 | 135 | /** 136 | * @dev Moves `amount` tokens from `sender` to `recipient` using the 137 | * allowance mechanism. `amount` is then deducted from the caller's 138 | * allowance. 139 | * 140 | * Returns a boolean value indicating whether the operation succeeded. 141 | * 142 | * Emits a {Transfer} event. 143 | */ 144 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 145 | 146 | /** 147 | * @dev Emitted when `value` tokens are moved from one account (`from`) to 148 | * another (`to`). 149 | * 150 | * Note that `value` may be zero. 151 | */ 152 | event Transfer(address indexed from, address indexed to, uint256 value); 153 | 154 | /** 155 | * @dev Emitted when the allowance of a `spender` for an `owner` is set by 156 | * a call to {approve}. `value` is the new allowance. 157 | */ 158 | event Approval(address indexed owner, address indexed spender, uint256 value); 159 | } 160 | 161 | 162 | /** 163 | * @dev Wrappers over Solidity's arithmetic operations with added overflow 164 | * checks. 165 | * 166 | * Arithmetic operations in Solidity wrap on overflow. This can easily result 167 | * in bugs, because programmers usually assume that an overflow raises an 168 | * error, which is the standard behavior in high level programming languages. 169 | * `SafeMath` restores this intuition by reverting the transaction when an 170 | * operation overflows. 171 | * 172 | * Using this library instead of the unchecked operations eliminates an entire 173 | * class of bugs, so it's recommended to use it always. 174 | */ 175 | library SafeMath { 176 | /** 177 | * @dev Returns the addition of two unsigned integers, with an overflow flag. 178 | * 179 | * _Available since v3.4._ 180 | */ 181 | function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { 182 | uint256 c = a + b; 183 | if (c < a) return (false, 0); 184 | return (true, c); 185 | } 186 | 187 | /** 188 | * @dev Returns the substraction of two unsigned integers, with an overflow flag. 189 | * 190 | * _Available since v3.4._ 191 | */ 192 | function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { 193 | if (b > a) return (false, 0); 194 | return (true, a - b); 195 | } 196 | 197 | /** 198 | * @dev Returns the multiplication of two unsigned integers, with an overflow flag. 199 | * 200 | * _Available since v3.4._ 201 | */ 202 | function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { 203 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 204 | // benefit is lost if 'b' is also tested. 205 | // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 206 | if (a == 0) return (true, 0); 207 | uint256 c = a * b; 208 | if (c / a != b) return (false, 0); 209 | return (true, c); 210 | } 211 | 212 | /** 213 | * @dev Returns the division of two unsigned integers, with a division by zero flag. 214 | * 215 | * _Available since v3.4._ 216 | */ 217 | function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { 218 | if (b == 0) return (false, 0); 219 | return (true, a / b); 220 | } 221 | 222 | /** 223 | * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. 224 | * 225 | * _Available since v3.4._ 226 | */ 227 | function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { 228 | if (b == 0) return (false, 0); 229 | return (true, a % b); 230 | } 231 | 232 | /** 233 | * @dev Returns the addition of two unsigned integers, reverting on 234 | * overflow. 235 | * 236 | * Counterpart to Solidity's `+` operator. 237 | * 238 | * Requirements: 239 | * 240 | * - Addition cannot overflow. 241 | */ 242 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 243 | uint256 c = a + b; 244 | require(c >= a, "SafeMath: addition overflow"); 245 | return c; 246 | } 247 | 248 | /** 249 | * @dev Returns the subtraction of two unsigned integers, reverting on 250 | * overflow (when the result is negative). 251 | * 252 | * Counterpart to Solidity's `-` operator. 253 | * 254 | * Requirements: 255 | * 256 | * - Subtraction cannot overflow. 257 | */ 258 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 259 | require(b <= a, "SafeMath: subtraction overflow"); 260 | return a - b; 261 | } 262 | 263 | /** 264 | * @dev Returns the multiplication of two unsigned integers, reverting on 265 | * overflow. 266 | * 267 | * Counterpart to Solidity's `*` operator. 268 | * 269 | * Requirements: 270 | * 271 | * - Multiplication cannot overflow. 272 | */ 273 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 274 | if (a == 0) return 0; 275 | uint256 c = a * b; 276 | require(c / a == b, "SafeMath: multiplication overflow"); 277 | return c; 278 | } 279 | 280 | /** 281 | * @dev Returns the integer division of two unsigned integers, reverting on 282 | * division by zero. The result is rounded towards zero. 283 | * 284 | * Counterpart to Solidity's `/` operator. Note: this function uses a 285 | * `revert` opcode (which leaves remaining gas untouched) while Solidity 286 | * uses an invalid opcode to revert (consuming all remaining gas). 287 | * 288 | * Requirements: 289 | * 290 | * - The divisor cannot be zero. 291 | */ 292 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 293 | require(b > 0, "SafeMath: division by zero"); 294 | return a / b; 295 | } 296 | 297 | /** 298 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 299 | * reverting when dividing by zero. 300 | * 301 | * Counterpart to Solidity's `%` operator. This function uses a `revert` 302 | * opcode (which leaves remaining gas untouched) while Solidity uses an 303 | * invalid opcode to revert (consuming all remaining gas). 304 | * 305 | * Requirements: 306 | * 307 | * - The divisor cannot be zero. 308 | */ 309 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 310 | require(b > 0, "SafeMath: modulo by zero"); 311 | return a % b; 312 | } 313 | 314 | /** 315 | * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 316 | * overflow (when the result is negative). 317 | * 318 | * CAUTION: This function is deprecated because it requires allocating memory for the error 319 | * message unnecessarily. For custom revert reasons use {trySub}. 320 | * 321 | * Counterpart to Solidity's `-` operator. 322 | * 323 | * Requirements: 324 | * 325 | * - Subtraction cannot overflow. 326 | */ 327 | function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 328 | require(b <= a, errorMessage); 329 | return a - b; 330 | } 331 | 332 | /** 333 | * @dev Returns the integer division of two unsigned integers, reverting with custom message on 334 | * division by zero. The result is rounded towards zero. 335 | * 336 | * CAUTION: This function is deprecated because it requires allocating memory for the error 337 | * message unnecessarily. For custom revert reasons use {tryDiv}. 338 | * 339 | * Counterpart to Solidity's `/` operator. Note: this function uses a 340 | * `revert` opcode (which leaves remaining gas untouched) while Solidity 341 | * uses an invalid opcode to revert (consuming all remaining gas). 342 | * 343 | * Requirements: 344 | * 345 | * - The divisor cannot be zero. 346 | */ 347 | function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 348 | require(b > 0, errorMessage); 349 | return a / b; 350 | } 351 | 352 | /** 353 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 354 | * reverting with custom message when dividing by zero. 355 | * 356 | * CAUTION: This function is deprecated because it requires allocating memory for the error 357 | * message unnecessarily. For custom revert reasons use {tryMod}. 358 | * 359 | * Counterpart to Solidity's `%` operator. This function uses a `revert` 360 | * opcode (which leaves remaining gas untouched) while Solidity uses an 361 | * invalid opcode to revert (consuming all remaining gas). 362 | * 363 | * Requirements: 364 | * 365 | * - The divisor cannot be zero. 366 | */ 367 | function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 368 | require(b > 0, errorMessage); 369 | return a % b; 370 | } 371 | } 372 | 373 | 374 | 375 | 376 | /** 377 | * @dev Implementation of the {IERC20} interface. 378 | * 379 | * This implementation is agnostic to the way tokens are created. This means 380 | * that a supply mechanism has to be added in a derived contract using {_mint}. 381 | * For a generic mechanism see {ERC20PresetMinterPauser}. 382 | * 383 | * TIP: For a detailed writeup see our guide 384 | * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 385 | * to implement supply mechanisms]. 386 | * 387 | * We have followed general OpenZeppelin guidelines: functions revert instead 388 | * of returning `false` on failure. This behavior is nonetheless conventional 389 | * and does not conflict with the expectations of ERC20 applications. 390 | * 391 | * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 392 | * This allows applications to reconstruct the allowance for all accounts just 393 | * by listening to said events. Other implementations of the EIP may not emit 394 | * these events, as it isn't required by the specification. 395 | * 396 | * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 397 | * functions have been added to mitigate the well-known issues around setting 398 | * allowances. See {IERC20-approve}. 399 | */ 400 | 401 | contract ERC20 is Context, IERC20 { 402 | using SafeMath for uint256; 403 | 404 | mapping (address => uint256) private _balances; 405 | 406 | mapping (address => mapping (address => uint256)) private _allowances; 407 | 408 | uint256 private _totalSupply; 409 | 410 | string private _name; 411 | string private _symbol; 412 | uint8 private _decimals; 413 | 414 | /** 415 | * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 416 | * a default value of 18. 417 | * 418 | * To select a different value for {decimals}, use {_setupDecimals}. 419 | * 420 | * All three of these values are immutable: they can only be set once during 421 | * construction. 422 | */ 423 | constructor (string memory name_, string memory symbol_) public { 424 | _name = name_; 425 | _symbol = symbol_; 426 | _decimals = 18; 427 | } 428 | 429 | /** 430 | * @dev Returns the name of the token. 431 | */ 432 | function name() public view virtual returns (string memory) { 433 | return _name; 434 | } 435 | 436 | /** 437 | * @dev Returns the symbol of the token, usually a shorter version of the 438 | * name. 439 | */ 440 | function symbol() public view virtual returns (string memory) { 441 | return _symbol; 442 | } 443 | 444 | /** 445 | * @dev Returns the number of decimals used to get its user representation. 446 | * For example, if `decimals` equals `2`, a balance of `505` tokens should 447 | * be displayed to a user as `5,05` (`505 / 10 ** 2`). 448 | * 449 | * Tokens usually opt for a value of 18, imitating the relationship between 450 | * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 451 | * called. 452 | * 453 | * NOTE: This information is only used for _display_ purposes: it in 454 | * no way affects any of the arithmetic of the contract, including 455 | * {IERC20-balanceOf} and {IERC20-transfer}. 456 | */ 457 | function decimals() public view virtual returns (uint8) { 458 | return _decimals; 459 | } 460 | 461 | /** 462 | * @dev See {IERC20-totalSupply}. 463 | */ 464 | function totalSupply() public view virtual override returns (uint256) { 465 | return _totalSupply; 466 | } 467 | 468 | /** 469 | * @dev See {IERC20-balanceOf}. 470 | */ 471 | function balanceOf(address account) public view virtual override returns (uint256) { 472 | return _balances[account]; 473 | } 474 | 475 | /** 476 | * @dev See {IERC20-transfer}. 477 | * 478 | * Requirements: 479 | * 480 | * - `recipient` cannot be the zero address. 481 | * - the caller must have a balance of at least `amount`. 482 | */ 483 | function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 484 | _transfer(_msgSender(), recipient, amount); 485 | return true; 486 | } 487 | 488 | /** 489 | * @dev See {IERC20-allowance}. 490 | */ 491 | function allowance(address owner, address spender) public view virtual override returns (uint256) { 492 | return _allowances[owner][spender]; 493 | } 494 | 495 | /** 496 | * @dev See {IERC20-approve}. 497 | * 498 | * Requirements: 499 | * 500 | * - `spender` cannot be the zero address. 501 | */ 502 | function approve(address spender, uint256 amount) public virtual override returns (bool) { 503 | _approve(_msgSender(), spender, amount); 504 | return true; 505 | } 506 | 507 | /** 508 | * @dev See {IERC20-transferFrom}. 509 | * 510 | * Emits an {Approval} event indicating the updated allowance. This is not 511 | * required by the EIP. See the note at the beginning of {ERC20}. 512 | * 513 | * Requirements: 514 | * 515 | * - `sender` and `recipient` cannot be the zero address. 516 | * - `sender` must have a balance of at least `amount`. 517 | * - the caller must have allowance for ``sender``'s tokens of at least 518 | * `amount`. 519 | */ 520 | function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 521 | _transfer(sender, recipient, amount); 522 | _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 523 | return true; 524 | } 525 | 526 | /** 527 | * @dev Atomically increases the allowance granted to `spender` by the caller. 528 | * 529 | * This is an alternative to {approve} that can be used as a mitigation for 530 | * problems described in {IERC20-approve}. 531 | * 532 | * Emits an {Approval} event indicating the updated allowance. 533 | * 534 | * Requirements: 535 | * 536 | * - `spender` cannot be the zero address. 537 | */ 538 | function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 539 | _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 540 | return true; 541 | } 542 | 543 | /** 544 | * @dev Atomically decreases the allowance granted to `spender` by the caller. 545 | * 546 | * This is an alternative to {approve} that can be used as a mitigation for 547 | * problems described in {IERC20-approve}. 548 | * 549 | * Emits an {Approval} event indicating the updated allowance. 550 | * 551 | * Requirements: 552 | * 553 | * - `spender` cannot be the zero address. 554 | * - `spender` must have allowance for the caller of at least 555 | * `subtractedValue`. 556 | */ 557 | function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 558 | _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 559 | return true; 560 | } 561 | 562 | /** 563 | * @dev Moves tokens `amount` from `sender` to `recipient`. 564 | * 565 | * This is internal function is equivalent to {transfer}, and can be used to 566 | * e.g. implement automatic token fees, slashing mechanisms, etc. 567 | * 568 | * Emits a {Transfer} event. 569 | * 570 | * Requirements: 571 | * 572 | * - `sender` cannot be the zero address. 573 | * - `recipient` cannot be the zero address. 574 | * - `sender` must have a balance of at least `amount`. 575 | */ 576 | function _transfer(address sender, address recipient, uint256 amount) internal virtual { 577 | require(sender != address(0), "ERC20: transfer from the zero address"); 578 | require(recipient != address(0), "ERC20: transfer to the zero address"); 579 | 580 | _beforeTokenTransfer(sender, recipient, amount); 581 | 582 | _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 583 | _balances[recipient] = _balances[recipient].add(amount); 584 | emit Transfer(sender, recipient, amount); 585 | } 586 | 587 | /** @dev Creates `amount` tokens and assigns them to `account`, increasing 588 | * the total supply. 589 | * 590 | * Emits a {Transfer} event with `from` set to the zero address. 591 | * 592 | * Requirements: 593 | * 594 | * - `to` cannot be the zero address. 595 | */ 596 | function _mint(address account, uint256 amount) internal virtual { 597 | require(account != address(0), "ERC20: mint to the zero address"); 598 | 599 | _beforeTokenTransfer(address(0), account, amount); 600 | 601 | _totalSupply = _totalSupply.add(amount); 602 | _balances[account] = _balances[account].add(amount); 603 | emit Transfer(address(0), account, amount); 604 | } 605 | 606 | /** 607 | * @dev Destroys `amount` tokens from `account`, reducing the 608 | * total supply. 609 | * 610 | * Emits a {Transfer} event with `to` set to the zero address. 611 | * 612 | * Requirements: 613 | * 614 | * - `account` cannot be the zero address. 615 | * - `account` must have at least `amount` tokens. 616 | */ 617 | function _burn(address account, uint256 amount) internal virtual { 618 | require(account != address(0), "ERC20: burn from the zero address"); 619 | 620 | _beforeTokenTransfer(account, address(0), amount); 621 | 622 | _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 623 | _totalSupply = _totalSupply.sub(amount); 624 | emit Transfer(account, address(0), amount); 625 | } 626 | 627 | /** 628 | * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 629 | * 630 | * This internal function is equivalent to `approve`, and can be used to 631 | * e.g. set automatic allowances for certain subsystems, etc. 632 | * 633 | * Emits an {Approval} event. 634 | * 635 | * Requirements: 636 | * 637 | * - `owner` cannot be the zero address. 638 | * - `spender` cannot be the zero address. 639 | */ 640 | function _approve(address owner, address spender, uint256 amount) internal virtual { 641 | require(owner != address(0), "ERC20: approve from the zero address"); 642 | require(spender != address(0), "ERC20: approve to the zero address"); 643 | 644 | _allowances[owner][spender] = amount; 645 | emit Approval(owner, spender, amount); 646 | } 647 | 648 | /** 649 | * @dev Sets {decimals} to a value other than the default one of 18. 650 | * 651 | * WARNING: This function should only be called from the constructor. Most 652 | * applications that interact with token contracts will not expect 653 | * {decimals} to ever change, and may work incorrectly if it does. 654 | */ 655 | function _setupDecimals(uint8 decimals_) internal virtual { 656 | _decimals = decimals_; 657 | } 658 | 659 | /** 660 | * @dev Hook that is called before any transfer of tokens. This includes 661 | * minting and burning. 662 | * 663 | * Calling conditions: 664 | * 665 | * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 666 | * will be to transferred to `to`. 667 | * - when `from` is zero, `amount` tokens will be minted for `to`. 668 | * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 669 | * - `from` and `to` are never both zero. 670 | * 671 | * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 672 | */ 673 | function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 674 | } 675 | 676 | 677 | /** 678 | * @dev Collection of functions related to the address type 679 | */ 680 | library Address { 681 | /** 682 | * @dev Returns true if `account` is a contract. 683 | * 684 | * [IMPORTANT] 685 | * ==== 686 | * It is unsafe to assume that an address for which this function returns 687 | * false is an externally-owned account (EOA) and not a contract. 688 | * 689 | * Among others, `isContract` will return false for the following 690 | * types of addresses: 691 | * 692 | * - an externally-owned account 693 | * - a contract in construction 694 | * - an address where a contract will be created 695 | * - an address where a contract lived, but was destroyed 696 | * ==== 697 | */ 698 | function isContract(address account) internal view returns (bool) { 699 | // This method relies on extcodesize, which returns 0 for contracts in 700 | // construction, since the code is only stored at the end of the 701 | // constructor execution. 702 | 703 | uint256 size; 704 | // solhint-disable-next-line no-inline-assembly 705 | assembly { size := extcodesize(account) } 706 | return size > 0; 707 | } 708 | 709 | /** 710 | * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 711 | * `recipient`, forwarding all available gas and reverting on errors. 712 | * 713 | * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 714 | * of certain opcodes, possibly making contracts go over the 2300 gas limit 715 | * imposed by `transfer`, making them unable to receive funds via 716 | * `transfer`. {sendValue} removes this limitation. 717 | * 718 | * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 719 | * 720 | * IMPORTANT: because control is transferred to `recipient`, care must be 721 | * taken to not create reentrancy vulnerabilities. Consider using 722 | * {ReentrancyGuard} or the 723 | * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 724 | */ 725 | function sendValue(address payable recipient, uint256 amount) internal { 726 | require(address(this).balance >= amount, "Address: insufficient balance"); 727 | 728 | // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 729 | (bool success, ) = recipient.call{ value: amount }(""); 730 | require(success, "Address: unable to send value, recipient may have reverted"); 731 | } 732 | 733 | /** 734 | * @dev Performs a Solidity function call using a low level `call`. A 735 | * plain`call` is an unsafe replacement for a function call: use this 736 | * function instead. 737 | * 738 | * If `target` reverts with a revert reason, it is bubbled up by this 739 | * function (like regular Solidity function calls). 740 | * 741 | * Returns the raw returned data. To convert to the expected return value, 742 | * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 743 | * 744 | * Requirements: 745 | * 746 | * - `target` must be a contract. 747 | * - calling `target` with `data` must not revert. 748 | * 749 | * _Available since v3.1._ 750 | */ 751 | function functionCall(address target, bytes memory data) internal returns (bytes memory) { 752 | return functionCall(target, data, "Address: low-level call failed"); 753 | } 754 | 755 | /** 756 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 757 | * `errorMessage` as a fallback revert reason when `target` reverts. 758 | * 759 | * _Available since v3.1._ 760 | */ 761 | function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 762 | return functionCallWithValue(target, data, 0, errorMessage); 763 | } 764 | 765 | /** 766 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 767 | * but also transferring `value` wei to `target`. 768 | * 769 | * Requirements: 770 | * 771 | * - the calling contract must have an ETH balance of at least `value`. 772 | * - the called Solidity function must be `payable`. 773 | * 774 | * _Available since v3.1._ 775 | */ 776 | function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 777 | return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 778 | } 779 | 780 | /** 781 | * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 782 | * with `errorMessage` as a fallback revert reason when `target` reverts. 783 | * 784 | * _Available since v3.1._ 785 | */ 786 | function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 787 | require(address(this).balance >= value, "Address: insufficient balance for call"); 788 | require(isContract(target), "Address: call to non-contract"); 789 | 790 | // solhint-disable-next-line avoid-low-level-calls 791 | (bool success, bytes memory returndata) = target.call{ value: value }(data); 792 | return _verifyCallResult(success, returndata, errorMessage); 793 | } 794 | 795 | /** 796 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 797 | * but performing a static call. 798 | * 799 | * _Available since v3.3._ 800 | */ 801 | function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { 802 | return functionStaticCall(target, data, "Address: low-level static call failed"); 803 | } 804 | 805 | /** 806 | * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], 807 | * but performing a static call. 808 | * 809 | * _Available since v3.3._ 810 | */ 811 | function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { 812 | require(isContract(target), "Address: static call to non-contract"); 813 | 814 | // solhint-disable-next-line avoid-low-level-calls 815 | (bool success, bytes memory returndata) = target.staticcall(data); 816 | return _verifyCallResult(success, returndata, errorMessage); 817 | } 818 | 819 | /** 820 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 821 | * but performing a delegate call. 822 | * 823 | * _Available since v3.4._ 824 | */ 825 | function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { 826 | return functionDelegateCall(target, data, "Address: low-level delegate call failed"); 827 | } 828 | 829 | /** 830 | * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], 831 | * but performing a delegate call. 832 | * 833 | * _Available since v3.4._ 834 | */ 835 | function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 836 | require(isContract(target), "Address: delegate call to non-contract"); 837 | 838 | // solhint-disable-next-line avoid-low-level-calls 839 | (bool success, bytes memory returndata) = target.delegatecall(data); 840 | return _verifyCallResult(success, returndata, errorMessage); 841 | } 842 | 843 | function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { 844 | if (success) { 845 | return returndata; 846 | } else { 847 | // Look for revert reason and bubble it up if present 848 | if (returndata.length > 0) { 849 | // The easiest way to bubble the revert reason is using memory via assembly 850 | 851 | // solhint-disable-next-line no-inline-assembly 852 | assembly { 853 | let returndata_size := mload(returndata) 854 | revert(add(32, returndata), returndata_size) 855 | } 856 | } else { 857 | revert(errorMessage); 858 | } 859 | } 860 | } 861 | } 862 | 863 | 864 | 865 | /** 866 | * @title SafeERC20 867 | * @dev Wrappers around ERC20 operations that throw on failure (when the token 868 | * contract returns false). Tokens that return no value (and instead revert or 869 | * throw on failure) are also supported, non-reverting calls are assumed to be 870 | * successful. 871 | * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 872 | * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 873 | */ 874 | library SafeERC20 { 875 | using SafeMath for uint256; 876 | using Address for address; 877 | 878 | function safeTransfer(IERC20 token, address to, uint256 value) internal { 879 | _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 880 | } 881 | 882 | function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 883 | _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 884 | } 885 | 886 | /** 887 | * @dev Deprecated. This function has issues similar to the ones found in 888 | * {IERC20-approve}, and its usage is discouraged. 889 | * 890 | * Whenever possible, use {safeIncreaseAllowance} and 891 | * {safeDecreaseAllowance} instead. 892 | */ 893 | function safeApprove(IERC20 token, address spender, uint256 value) internal { 894 | // safeApprove should only be called when setting an initial allowance, 895 | // or when resetting it to zero. To increase and decrease it, use 896 | // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 897 | // solhint-disable-next-line max-line-length 898 | require((value == 0) || (token.allowance(address(this), spender) == 0), 899 | "SafeERC20: approve from non-zero to non-zero allowance" 900 | ); 901 | _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 902 | } 903 | 904 | function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 905 | uint256 newAllowance = token.allowance(address(this), spender).add(value); 906 | _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 907 | } 908 | 909 | function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 910 | uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 911 | _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 912 | } 913 | 914 | /** 915 | * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 916 | * on the return value: the return value is optional (but if data is returned, it must not be false). 917 | * @param token The token targeted by the call. 918 | * @param data The call data (encoded using abi.encode or one of its variants). 919 | */ 920 | function _callOptionalReturn(IERC20 token, bytes memory data) private { 921 | // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 922 | // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 923 | // the target address contains contract code and also asserts for success in the low-level call. 924 | 925 | bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); 926 | if (returndata.length > 0) { // Return data is optional 927 | // solhint-disable-next-line max-line-length 928 | require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 929 | } 930 | } 931 | } 932 | 933 | 934 | /* MasterChef contract */ 935 | contract MasterChef { 936 | using SafeMath for uint256; 937 | using SafeERC20 for IERC20; 938 | 939 | // Info of each pool. 940 | struct PoolInfo { 941 | IERC20 lpToken; // Address of LP token contract. 942 | uint256 allocPoint; // How many allocation points assigned to this pool. EGGs to distribute per block. 943 | uint256 lastRewardBlock; // Last block number that EGGs distribution occurs. 944 | uint256 accEggPerShare; // Accumulated EGGs per share, times 1e12. See below. 945 | uint16 depositFeeBP; // Make sure the underlying vault defines this is basis points in an immutable way 946 | } 947 | 948 | // Info of each pool. 949 | PoolInfo[] public poolInfo; 950 | 951 | // Withdrawal penalty 952 | uint256 public withdrawPenalty; // Make sure the underlying vault defines this is basis points in an immutable way 953 | 954 | } 955 | 956 | 957 | /** 958 | * @dev Contract module which provides a basic access control mechanism, where 959 | * there is an account (an owner) that can be granted exclusive access to 960 | * specific functions. 961 | * 962 | * By default, the owner account will be the one that deploys the contract. This 963 | * can later be changed with {transferOwnership}. 964 | * 965 | * This module is used through inheritance. It will make available the modifier 966 | * `onlyOwner`, which can be applied to your functions to restrict their use to 967 | * the owner. 968 | */ 969 | abstract contract Ownable is Context { 970 | address private _owner; 971 | 972 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 973 | 974 | /** 975 | * @dev Initializes the contract setting the deployer as the initial owner. 976 | */ 977 | constructor () internal { 978 | address msgSender = _msgSender(); 979 | _owner = msgSender; 980 | emit OwnershipTransferred(address(0), msgSender); 981 | } 982 | 983 | /** 984 | * @dev Returns the address of the current owner. 985 | */ 986 | function owner() public view virtual returns (address) { 987 | return _owner; 988 | } 989 | 990 | /** 991 | * @dev Throws if called by any account other than the owner. 992 | */ 993 | modifier onlyOwner() { 994 | require(owner() == _msgSender(), "Ownable: caller is not the owner"); 995 | _; 996 | } 997 | 998 | /** 999 | * @dev Leaves the contract without owner. It will not be possible to call 1000 | * `onlyOwner` functions anymore. Can only be called by the current owner. 1001 | * 1002 | * NOTE: Renouncing ownership will leave the contract without an owner, 1003 | * thereby removing any functionality that is only available to the owner. 1004 | */ 1005 | function renounceOwnership() public virtual onlyOwner { 1006 | emit OwnershipTransferred(_owner, address(0)); 1007 | _owner = address(0); 1008 | } 1009 | 1010 | /** 1011 | * @dev Transfers ownership of the contract to a new account (`newOwner`). 1012 | * Can only be called by the current owner. 1013 | */ 1014 | function transferOwnership(address newOwner) public virtual onlyOwner { 1015 | require(newOwner != address(0), "Ownable: new owner is the zero address"); 1016 | emit OwnershipTransferred(_owner, newOwner); 1017 | _owner = newOwner; 1018 | } 1019 | } 1020 | // Based on https://github.com/iearn-finance/vaults/blob/master/contracts/vaults/yVault.sol 1021 | 1022 | 1023 | 1024 | abstract contract JarBase is ERC20, Ownable { 1025 | using SafeERC20 for IERC20; 1026 | using Address for address; 1027 | using SafeMath for uint256; 1028 | 1029 | IERC20 public token; 1030 | address public strategy; 1031 | mapping (address => uint256) private lastTimeStaked; 1032 | mapping (address => uint256) private lastTimeRestaked; 1033 | uint256 public constant keepMax = 10000; 1034 | 1035 | constructor(IStrategy _strategy, string memory name, string memory symbol) 1036 | public 1037 | ERC20(name, symbol) 1038 | { 1039 | require(address(_strategy) != address(0)); 1040 | _setupDecimals(ERC20(_strategy.want()).decimals()); 1041 | token = IERC20(_strategy.want()); 1042 | strategy = address(_strategy); 1043 | } 1044 | 1045 | 1046 | function transfer(address recipient, uint256 amount) public override returns (bool) 1047 | { 1048 | require(recipient != address(this)); 1049 | return super.transfer(recipient, amount); 1050 | } 1051 | 1052 | function balance() public view returns (uint256) { 1053 | return 1054 | token.balanceOf(address(this)).add( 1055 | IStrategy(strategy).balanceOf() 1056 | ); 1057 | } 1058 | 1059 | function depositAll() external { 1060 | deposit(token.balanceOf(msg.sender)); 1061 | } 1062 | 1063 | function deposit(uint256 _amount) public { 1064 | require(msg.sender == tx.origin, "no contracts"); 1065 | lastTimeStaked[msg.sender] = now; 1066 | 1067 | uint256 _pool = balance(); 1068 | uint256 _before = token.balanceOf(address(this)); 1069 | token.safeTransferFrom(msg.sender, address(this), _amount); 1070 | uint256 _after = token.balanceOf(address(this)); 1071 | _amount = _after.sub(_before); // Additional check for deflationary tokens 1072 | uint256 shares = 0; 1073 | if (totalSupply() == 0) { 1074 | shares = _amount; 1075 | } else { 1076 | shares = (_amount.mul(totalSupply())).div(_pool); 1077 | } 1078 | 1079 | // If deposit penalty, grab it. Otherwise, just comment out this section. 1080 | //Grab deposit fee from underlying farm, if available. 1081 | address masterChefAddr = IStrategy(strategy).rewards(); 1082 | uint16 underlyingPoolId = IStrategy(strategy).underlyingPoolId(); 1083 | MasterChef underlyingMC = MasterChef(masterChefAddr); 1084 | // Read pool info on deposit fee 1085 | (, , , , uint256 depositFee) = underlyingMC.poolInfo(underlyingPoolId); 1086 | // Adjust for deposit fee 1087 | if(depositFee > 0) { 1088 | uint256 fee = shares.mul(depositFee).div(keepMax); 1089 | shares = shares.sub(fee); 1090 | } 1091 | // Send share of pool 1092 | _mint(msg.sender, shares); 1093 | earnAmount(_amount); 1094 | } 1095 | 1096 | //This does what earn() used to do, functionally the same for the end user since no LP tokens are stored in this contract during normal operation 1097 | function earnAmount(uint256 _amount) internal { 1098 | token.safeTransfer(strategy, _amount); 1099 | IStrategy(strategy).deposit(); 1100 | } 1101 | 1102 | function withdrawAll() external { 1103 | withdraw(balanceOf(msg.sender)); 1104 | } 1105 | 1106 | // No rebalance implementation for lower fees and faster swaps 1107 | function withdraw(uint256 _shares) public { 1108 | uint256 r = (balance().mul(_shares)).div(totalSupply()); 1109 | _burn(msg.sender, _shares); 1110 | 1111 | // Check balance 1112 | uint256 b = token.balanceOf(address(this)); 1113 | if (b < r) { 1114 | uint256 _withdraw = r.sub(b); 1115 | IStrategy(strategy).withdraw(_withdraw); 1116 | uint256 _after = token.balanceOf(address(this)); 1117 | uint256 _diff = _after.sub(b); 1118 | if (_diff < _withdraw) { 1119 | r = b.add(_diff); 1120 | } 1121 | } 1122 | 1123 | // If withdrawal penalty, subtract before transferring 1124 | // Otherwise, just comment out this section 1125 | address masterChefAddr = IStrategy(strategy).rewards(); 1126 | MasterChef underlyingMC = MasterChef(masterChefAddr); 1127 | // Read pool info on withdrawal fee 1128 | uint256 withdrawPenalty = underlyingMC.withdrawPenalty(); 1129 | bool emergencyStatus = IStrategy(strategy).emergencyStatus(); 1130 | if (withdrawPenalty>0 && emergencyStatus==false) { 1131 | uint256 WithdrawalFee = r.mul(withdrawPenalty).div(keepMax); 1132 | r = r.sub(WithdrawalFee); 1133 | } 1134 | 1135 | token.safeTransfer(msg.sender, r); 1136 | } 1137 | 1138 | function getRatio() public view returns (uint256) { 1139 | return balance().mul(1e18).div(totalSupply()); 1140 | } 1141 | 1142 | //Website UI will hide the restake button for a user if it's been less than 1 day since they last restaked 1143 | function getLastTimeRestaked(address _address) public view returns (uint256) { 1144 | return lastTimeRestaked[_address]; 1145 | } 1146 | 1147 | //Website UI will hide the restake button for a user if they staked after the migration 1148 | function getLastTimeStaked(address _address) public view returns (uint256) { 1149 | return lastTimeStaked[_address]; 1150 | } 1151 | } 1152 | 1153 | 1154 | contract vaultBase is JarBase { 1155 | 1156 | constructor(IStrategy _strategy) 1157 | public 1158 | JarBase(_strategy, 1159 | string(abi.encodePacked(_strategy.pairName(), "vault")), 1160 | string(abi.encodePacked("v", _strategy.pairName())) 1161 | ) 1162 | { 1163 | 1164 | } 1165 | } 1166 | -------------------------------------------------------------------------------- /strategySingleAsset.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.12; 2 | // SPDX-License-Identifier: UNLICENSED 3 | 4 | 5 | /* 6 | * @dev Provides information about the current execution context, including the 7 | * sender of the transaction and its data. While these are generally available 8 | * via msg.sender and msg.data, they should not be accessed in such a direct 9 | * manner, since when dealing with GSN meta-transactions the account sending and 10 | * paying for execution may not be the actual sender (as far as an application 11 | * is concerned). 12 | * 13 | * This contract is only required for intermediate, library-like contracts. 14 | */ 15 | abstract contract Context { 16 | function _msgSender() internal view virtual returns (address payable) { 17 | return msg.sender; 18 | } 19 | 20 | function _msgData() internal view virtual returns (bytes memory) { 21 | this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 22 | return msg.data; 23 | } 24 | } 25 | 26 | 27 | /** 28 | * @dev Interface of the ERC20 standard as defined in the EIP. 29 | */ 30 | interface IERC20 { 31 | /** 32 | * @dev Returns the amount of tokens in existence. 33 | */ 34 | function totalSupply() external view returns (uint256); 35 | 36 | /** 37 | * @dev Returns the amount of tokens owned by `account`. 38 | */ 39 | function balanceOf(address account) external view returns (uint256); 40 | 41 | /** 42 | * @dev Moves `amount` tokens from the caller's account to `recipient`. 43 | * 44 | * Returns a boolean value indicating whether the operation succeeded. 45 | * 46 | * Emits a {Transfer} event. 47 | */ 48 | function transfer(address recipient, uint256 amount) external returns (bool); 49 | 50 | /** 51 | * @dev Returns the remaining number of tokens that `spender` will be 52 | * allowed to spend on behalf of `owner` through {transferFrom}. This is 53 | * zero by default. 54 | * 55 | * This value changes when {approve} or {transferFrom} are called. 56 | */ 57 | function allowance(address owner, address spender) external view returns (uint256); 58 | 59 | /** 60 | * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 61 | * 62 | * Returns a boolean value indicating whether the operation succeeded. 63 | * 64 | * IMPORTANT: Beware that changing an allowance with this method brings the risk 65 | * that someone may use both the old and the new allowance by unfortunate 66 | * transaction ordering. One possible solution to mitigate this race 67 | * condition is to first reduce the spender's allowance to 0 and set the 68 | * desired value afterwards: 69 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 70 | * 71 | * Emits an {Approval} event. 72 | */ 73 | function approve(address spender, uint256 amount) external returns (bool); 74 | 75 | /** 76 | * @dev Moves `amount` tokens from `sender` to `recipient` using the 77 | * allowance mechanism. `amount` is then deducted from the caller's 78 | * allowance. 79 | * 80 | * Returns a boolean value indicating whether the operation succeeded. 81 | * 82 | * Emits a {Transfer} event. 83 | */ 84 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 85 | 86 | /** 87 | * @dev Emitted when `value` tokens are moved from one account (`from`) to 88 | * another (`to`). 89 | * 90 | * Note that `value` may be zero. 91 | */ 92 | event Transfer(address indexed from, address indexed to, uint256 value); 93 | 94 | /** 95 | * @dev Emitted when the allowance of a `spender` for an `owner` is set by 96 | * a call to {approve}. `value` is the new allowance. 97 | */ 98 | event Approval(address indexed owner, address indexed spender, uint256 value); 99 | } 100 | 101 | 102 | /** 103 | * @dev Wrappers over Solidity's arithmetic operations with added overflow 104 | * checks. 105 | * 106 | * Arithmetic operations in Solidity wrap on overflow. This can easily result 107 | * in bugs, because programmers usually assume that an overflow raises an 108 | * error, which is the standard behavior in high level programming languages. 109 | * `SafeMath` restores this intuition by reverting the transaction when an 110 | * operation overflows. 111 | * 112 | * Using this library instead of the unchecked operations eliminates an entire 113 | * class of bugs, so it's recommended to use it always. 114 | */ 115 | library SafeMath { 116 | /** 117 | * @dev Returns the addition of two unsigned integers, with an overflow flag. 118 | * 119 | * _Available since v3.4._ 120 | */ 121 | function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { 122 | uint256 c = a + b; 123 | if (c < a) return (false, 0); 124 | return (true, c); 125 | } 126 | 127 | /** 128 | * @dev Returns the substraction of two unsigned integers, with an overflow flag. 129 | * 130 | * _Available since v3.4._ 131 | */ 132 | function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { 133 | if (b > a) return (false, 0); 134 | return (true, a - b); 135 | } 136 | 137 | /** 138 | * @dev Returns the multiplication of two unsigned integers, with an overflow flag. 139 | * 140 | * _Available since v3.4._ 141 | */ 142 | function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { 143 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 144 | // benefit is lost if 'b' is also tested. 145 | // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 146 | if (a == 0) return (true, 0); 147 | uint256 c = a * b; 148 | if (c / a != b) return (false, 0); 149 | return (true, c); 150 | } 151 | 152 | /** 153 | * @dev Returns the division of two unsigned integers, with a division by zero flag. 154 | * 155 | * _Available since v3.4._ 156 | */ 157 | function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { 158 | if (b == 0) return (false, 0); 159 | return (true, a / b); 160 | } 161 | 162 | /** 163 | * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. 164 | * 165 | * _Available since v3.4._ 166 | */ 167 | function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { 168 | if (b == 0) return (false, 0); 169 | return (true, a % b); 170 | } 171 | 172 | /** 173 | * @dev Returns the addition of two unsigned integers, reverting on 174 | * overflow. 175 | * 176 | * Counterpart to Solidity's `+` operator. 177 | * 178 | * Requirements: 179 | * 180 | * - Addition cannot overflow. 181 | */ 182 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 183 | uint256 c = a + b; 184 | require(c >= a, "SafeMath: addition overflow"); 185 | return c; 186 | } 187 | 188 | /** 189 | * @dev Returns the subtraction of two unsigned integers, reverting on 190 | * overflow (when the result is negative). 191 | * 192 | * Counterpart to Solidity's `-` operator. 193 | * 194 | * Requirements: 195 | * 196 | * - Subtraction cannot overflow. 197 | */ 198 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 199 | require(b <= a, "SafeMath: subtraction overflow"); 200 | return a - b; 201 | } 202 | 203 | /** 204 | * @dev Returns the multiplication of two unsigned integers, reverting on 205 | * overflow. 206 | * 207 | * Counterpart to Solidity's `*` operator. 208 | * 209 | * Requirements: 210 | * 211 | * - Multiplication cannot overflow. 212 | */ 213 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 214 | if (a == 0) return 0; 215 | uint256 c = a * b; 216 | require(c / a == b, "SafeMath: multiplication overflow"); 217 | return c; 218 | } 219 | 220 | /** 221 | * @dev Returns the integer division of two unsigned integers, reverting on 222 | * division by zero. The result is rounded towards zero. 223 | * 224 | * Counterpart to Solidity's `/` operator. Note: this function uses a 225 | * `revert` opcode (which leaves remaining gas untouched) while Solidity 226 | * uses an invalid opcode to revert (consuming all remaining gas). 227 | * 228 | * Requirements: 229 | * 230 | * - The divisor cannot be zero. 231 | */ 232 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 233 | require(b > 0, "SafeMath: division by zero"); 234 | return a / b; 235 | } 236 | 237 | /** 238 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 239 | * reverting when dividing by zero. 240 | * 241 | * Counterpart to Solidity's `%` operator. This function uses a `revert` 242 | * opcode (which leaves remaining gas untouched) while Solidity uses an 243 | * invalid opcode to revert (consuming all remaining gas). 244 | * 245 | * Requirements: 246 | * 247 | * - The divisor cannot be zero. 248 | */ 249 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 250 | require(b > 0, "SafeMath: modulo by zero"); 251 | return a % b; 252 | } 253 | 254 | /** 255 | * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 256 | * overflow (when the result is negative). 257 | * 258 | * CAUTION: This function is deprecated because it requires allocating memory for the error 259 | * message unnecessarily. For custom revert reasons use {trySub}. 260 | * 261 | * Counterpart to Solidity's `-` operator. 262 | * 263 | * Requirements: 264 | * 265 | * - Subtraction cannot overflow. 266 | */ 267 | function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 268 | require(b <= a, errorMessage); 269 | return a - b; 270 | } 271 | 272 | /** 273 | * @dev Returns the integer division of two unsigned integers, reverting with custom message on 274 | * division by zero. The result is rounded towards zero. 275 | * 276 | * CAUTION: This function is deprecated because it requires allocating memory for the error 277 | * message unnecessarily. For custom revert reasons use {tryDiv}. 278 | * 279 | * Counterpart to Solidity's `/` operator. Note: this function uses a 280 | * `revert` opcode (which leaves remaining gas untouched) while Solidity 281 | * uses an invalid opcode to revert (consuming all remaining gas). 282 | * 283 | * Requirements: 284 | * 285 | * - The divisor cannot be zero. 286 | */ 287 | function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 288 | require(b > 0, errorMessage); 289 | return a / b; 290 | } 291 | 292 | /** 293 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 294 | * reverting with custom message when dividing by zero. 295 | * 296 | * CAUTION: This function is deprecated because it requires allocating memory for the error 297 | * message unnecessarily. For custom revert reasons use {tryMod}. 298 | * 299 | * Counterpart to Solidity's `%` operator. This function uses a `revert` 300 | * opcode (which leaves remaining gas untouched) while Solidity uses an 301 | * invalid opcode to revert (consuming all remaining gas). 302 | * 303 | * Requirements: 304 | * 305 | * - The divisor cannot be zero. 306 | */ 307 | function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 308 | require(b > 0, errorMessage); 309 | return a % b; 310 | } 311 | } 312 | 313 | 314 | 315 | /** 316 | * @dev Implementation of the {IERC20} interface. 317 | * 318 | * This implementation is agnostic to the way tokens are created. This means 319 | * that a supply mechanism has to be added in a derived contract using {_mint}. 320 | * For a generic mechanism see {ERC20PresetMinterPauser}. 321 | * 322 | * TIP: For a detailed writeup see our guide 323 | * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 324 | * to implement supply mechanisms]. 325 | * 326 | * We have followed general OpenZeppelin guidelines: functions revert instead 327 | * of returning `false` on failure. This behavior is nonetheless conventional 328 | * and does not conflict with the expectations of ERC20 applications. 329 | * 330 | * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 331 | * This allows applications to reconstruct the allowance for all accounts just 332 | * by listening to said events. Other implementations of the EIP may not emit 333 | * these events, as it isn't required by the specification. 334 | * 335 | * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 336 | * functions have been added to mitigate the well-known issues around setting 337 | * allowances. See {IERC20-approve}. 338 | */ 339 | contract ERC20 is Context, IERC20 { 340 | using SafeMath for uint256; 341 | 342 | mapping (address => uint256) private _balances; 343 | 344 | mapping (address => mapping (address => uint256)) private _allowances; 345 | 346 | uint256 private _totalSupply; 347 | 348 | string private _name; 349 | string private _symbol; 350 | uint8 private _decimals; 351 | 352 | /** 353 | * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 354 | * a default value of 18. 355 | * 356 | * To select a different value for {decimals}, use {_setupDecimals}. 357 | * 358 | * All three of these values are immutable: they can only be set once during 359 | * construction. 360 | */ 361 | constructor (string memory name_, string memory symbol_) public { 362 | _name = name_; 363 | _symbol = symbol_; 364 | _decimals = 18; 365 | } 366 | 367 | /** 368 | * @dev Returns the name of the token. 369 | */ 370 | function name() public view virtual returns (string memory) { 371 | return _name; 372 | } 373 | 374 | /** 375 | * @dev Returns the symbol of the token, usually a shorter version of the 376 | * name. 377 | */ 378 | function symbol() public view virtual returns (string memory) { 379 | return _symbol; 380 | } 381 | 382 | /** 383 | * @dev Returns the number of decimals used to get its user representation. 384 | * For example, if `decimals` equals `2`, a balance of `505` tokens should 385 | * be displayed to a user as `5,05` (`505 / 10 ** 2`). 386 | * 387 | * Tokens usually opt for a value of 18, imitating the relationship between 388 | * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 389 | * called. 390 | * 391 | * NOTE: This information is only used for _display_ purposes: it in 392 | * no way affects any of the arithmetic of the contract, including 393 | * {IERC20-balanceOf} and {IERC20-transfer}. 394 | */ 395 | function decimals() public view virtual returns (uint8) { 396 | return _decimals; 397 | } 398 | 399 | /** 400 | * @dev See {IERC20-totalSupply}. 401 | */ 402 | function totalSupply() public view virtual override returns (uint256) { 403 | return _totalSupply; 404 | } 405 | 406 | /** 407 | * @dev See {IERC20-balanceOf}. 408 | */ 409 | function balanceOf(address account) public view virtual override returns (uint256) { 410 | return _balances[account]; 411 | } 412 | 413 | /** 414 | * @dev See {IERC20-transfer}. 415 | * 416 | * Requirements: 417 | * 418 | * - `recipient` cannot be the zero address. 419 | * - the caller must have a balance of at least `amount`. 420 | */ 421 | function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 422 | _transfer(_msgSender(), recipient, amount); 423 | return true; 424 | } 425 | 426 | /** 427 | * @dev See {IERC20-allowance}. 428 | */ 429 | function allowance(address owner, address spender) public view virtual override returns (uint256) { 430 | return _allowances[owner][spender]; 431 | } 432 | 433 | /** 434 | * @dev See {IERC20-approve}. 435 | * 436 | * Requirements: 437 | * 438 | * - `spender` cannot be the zero address. 439 | */ 440 | function approve(address spender, uint256 amount) public virtual override returns (bool) { 441 | _approve(_msgSender(), spender, amount); 442 | return true; 443 | } 444 | 445 | /** 446 | * @dev See {IERC20-transferFrom}. 447 | * 448 | * Emits an {Approval} event indicating the updated allowance. This is not 449 | * required by the EIP. See the note at the beginning of {ERC20}. 450 | * 451 | * Requirements: 452 | * 453 | * - `sender` and `recipient` cannot be the zero address. 454 | * - `sender` must have a balance of at least `amount`. 455 | * - the caller must have allowance for ``sender``'s tokens of at least 456 | * `amount`. 457 | */ 458 | function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 459 | _transfer(sender, recipient, amount); 460 | _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 461 | return true; 462 | } 463 | 464 | /** 465 | * @dev Atomically increases the allowance granted to `spender` by the caller. 466 | * 467 | * This is an alternative to {approve} that can be used as a mitigation for 468 | * problems described in {IERC20-approve}. 469 | * 470 | * Emits an {Approval} event indicating the updated allowance. 471 | * 472 | * Requirements: 473 | * 474 | * - `spender` cannot be the zero address. 475 | */ 476 | function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 477 | _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 478 | return true; 479 | } 480 | 481 | /** 482 | * @dev Atomically decreases the allowance granted to `spender` by the caller. 483 | * 484 | * This is an alternative to {approve} that can be used as a mitigation for 485 | * problems described in {IERC20-approve}. 486 | * 487 | * Emits an {Approval} event indicating the updated allowance. 488 | * 489 | * Requirements: 490 | * 491 | * - `spender` cannot be the zero address. 492 | * - `spender` must have allowance for the caller of at least 493 | * `subtractedValue`. 494 | */ 495 | function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 496 | _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 497 | return true; 498 | } 499 | 500 | /** 501 | * @dev Moves tokens `amount` from `sender` to `recipient`. 502 | * 503 | * This is internal function is equivalent to {transfer}, and can be used to 504 | * e.g. implement automatic token fees, slashing mechanisms, etc. 505 | * 506 | * Emits a {Transfer} event. 507 | * 508 | * Requirements: 509 | * 510 | * - `sender` cannot be the zero address. 511 | * - `recipient` cannot be the zero address. 512 | * - `sender` must have a balance of at least `amount`. 513 | */ 514 | function _transfer(address sender, address recipient, uint256 amount) internal virtual { 515 | require(sender != address(0), "ERC20: transfer from the zero address"); 516 | require(recipient != address(0), "ERC20: transfer to the zero address"); 517 | 518 | _beforeTokenTransfer(sender, recipient, amount); 519 | 520 | _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 521 | _balances[recipient] = _balances[recipient].add(amount); 522 | emit Transfer(sender, recipient, amount); 523 | } 524 | 525 | /** @dev Creates `amount` tokens and assigns them to `account`, increasing 526 | * the total supply. 527 | * 528 | * Emits a {Transfer} event with `from` set to the zero address. 529 | * 530 | * Requirements: 531 | * 532 | * - `to` cannot be the zero address. 533 | */ 534 | function _mint(address account, uint256 amount) internal virtual { 535 | require(account != address(0), "ERC20: mint to the zero address"); 536 | 537 | _beforeTokenTransfer(address(0), account, amount); 538 | 539 | _totalSupply = _totalSupply.add(amount); 540 | _balances[account] = _balances[account].add(amount); 541 | emit Transfer(address(0), account, amount); 542 | } 543 | 544 | /** 545 | * @dev Destroys `amount` tokens from `account`, reducing the 546 | * total supply. 547 | * 548 | * Emits a {Transfer} event with `to` set to the zero address. 549 | * 550 | * Requirements: 551 | * 552 | * - `account` cannot be the zero address. 553 | * - `account` must have at least `amount` tokens. 554 | */ 555 | function _burn(address account, uint256 amount) internal virtual { 556 | require(account != address(0), "ERC20: burn from the zero address"); 557 | 558 | _beforeTokenTransfer(account, address(0), amount); 559 | 560 | _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 561 | _totalSupply = _totalSupply.sub(amount); 562 | emit Transfer(account, address(0), amount); 563 | } 564 | 565 | /** 566 | * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 567 | * 568 | * This internal function is equivalent to `approve`, and can be used to 569 | * e.g. set automatic allowances for certain subsystems, etc. 570 | * 571 | * Emits an {Approval} event. 572 | * 573 | * Requirements: 574 | * 575 | * - `owner` cannot be the zero address. 576 | * - `spender` cannot be the zero address. 577 | */ 578 | function _approve(address owner, address spender, uint256 amount) internal virtual { 579 | require(owner != address(0), "ERC20: approve from the zero address"); 580 | require(spender != address(0), "ERC20: approve to the zero address"); 581 | 582 | _allowances[owner][spender] = amount; 583 | emit Approval(owner, spender, amount); 584 | } 585 | 586 | /** 587 | * @dev Sets {decimals} to a value other than the default one of 18. 588 | * 589 | * WARNING: This function should only be called from the constructor. Most 590 | * applications that interact with token contracts will not expect 591 | * {decimals} to ever change, and may work incorrectly if it does. 592 | */ 593 | function _setupDecimals(uint8 decimals_) internal virtual { 594 | _decimals = decimals_; 595 | } 596 | 597 | /** 598 | * @dev Hook that is called before any transfer of tokens. This includes 599 | * minting and burning. 600 | * 601 | * Calling conditions: 602 | * 603 | * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 604 | * will be to transferred to `to`. 605 | * - when `from` is zero, `amount` tokens will be minted for `to`. 606 | * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 607 | * - `from` and `to` are never both zero. 608 | * 609 | * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 610 | */ 611 | function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 612 | } 613 | 614 | 615 | /** 616 | * @dev Collection of functions related to the address type 617 | */ 618 | library Address { 619 | /** 620 | * @dev Returns true if `account` is a contract. 621 | * 622 | * [IMPORTANT] 623 | * ==== 624 | * It is unsafe to assume that an address for which this function returns 625 | * false is an externally-owned account (EOA) and not a contract. 626 | * 627 | * Among others, `isContract` will return false for the following 628 | * types of addresses: 629 | * 630 | * - an externally-owned account 631 | * - a contract in construction 632 | * - an address where a contract will be created 633 | * - an address where a contract lived, but was destroyed 634 | * ==== 635 | */ 636 | function isContract(address account) internal view returns (bool) { 637 | // This method relies on extcodesize, which returns 0 for contracts in 638 | // construction, since the code is only stored at the end of the 639 | // constructor execution. 640 | 641 | uint256 size; 642 | // solhint-disable-next-line no-inline-assembly 643 | assembly { size := extcodesize(account) } 644 | return size > 0; 645 | } 646 | 647 | /** 648 | * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 649 | * `recipient`, forwarding all available gas and reverting on errors. 650 | * 651 | * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 652 | * of certain opcodes, possibly making contracts go over the 2300 gas limit 653 | * imposed by `transfer`, making them unable to receive funds via 654 | * `transfer`. {sendValue} removes this limitation. 655 | * 656 | * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 657 | * 658 | * IMPORTANT: because control is transferred to `recipient`, care must be 659 | * taken to not create reentrancy vulnerabilities. Consider using 660 | * {ReentrancyGuard} or the 661 | * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 662 | */ 663 | function sendValue(address payable recipient, uint256 amount) internal { 664 | require(address(this).balance >= amount, "Address: insufficient balance"); 665 | 666 | // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 667 | (bool success, ) = recipient.call{ value: amount }(""); 668 | require(success, "Address: unable to send value, recipient may have reverted"); 669 | } 670 | 671 | /** 672 | * @dev Performs a Solidity function call using a low level `call`. A 673 | * plain`call` is an unsafe replacement for a function call: use this 674 | * function instead. 675 | * 676 | * If `target` reverts with a revert reason, it is bubbled up by this 677 | * function (like regular Solidity function calls). 678 | * 679 | * Returns the raw returned data. To convert to the expected return value, 680 | * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 681 | * 682 | * Requirements: 683 | * 684 | * - `target` must be a contract. 685 | * - calling `target` with `data` must not revert. 686 | * 687 | * _Available since v3.1._ 688 | */ 689 | function functionCall(address target, bytes memory data) internal returns (bytes memory) { 690 | return functionCall(target, data, "Address: low-level call failed"); 691 | } 692 | 693 | /** 694 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 695 | * `errorMessage` as a fallback revert reason when `target` reverts. 696 | * 697 | * _Available since v3.1._ 698 | */ 699 | function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 700 | return functionCallWithValue(target, data, 0, errorMessage); 701 | } 702 | 703 | /** 704 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 705 | * but also transferring `value` wei to `target`. 706 | * 707 | * Requirements: 708 | * 709 | * - the calling contract must have an ETH balance of at least `value`. 710 | * - the called Solidity function must be `payable`. 711 | * 712 | * _Available since v3.1._ 713 | */ 714 | function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 715 | return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 716 | } 717 | 718 | /** 719 | * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 720 | * with `errorMessage` as a fallback revert reason when `target` reverts. 721 | * 722 | * _Available since v3.1._ 723 | */ 724 | function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 725 | require(address(this).balance >= value, "Address: insufficient balance for call"); 726 | require(isContract(target), "Address: call to non-contract"); 727 | 728 | // solhint-disable-next-line avoid-low-level-calls 729 | (bool success, bytes memory returndata) = target.call{ value: value }(data); 730 | return _verifyCallResult(success, returndata, errorMessage); 731 | } 732 | 733 | /** 734 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 735 | * but performing a static call. 736 | * 737 | * _Available since v3.3._ 738 | */ 739 | function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { 740 | return functionStaticCall(target, data, "Address: low-level static call failed"); 741 | } 742 | 743 | /** 744 | * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], 745 | * but performing a static call. 746 | * 747 | * _Available since v3.3._ 748 | */ 749 | function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { 750 | require(isContract(target), "Address: static call to non-contract"); 751 | 752 | // solhint-disable-next-line avoid-low-level-calls 753 | (bool success, bytes memory returndata) = target.staticcall(data); 754 | return _verifyCallResult(success, returndata, errorMessage); 755 | } 756 | 757 | /** 758 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 759 | * but performing a delegate call. 760 | * 761 | * _Available since v3.4._ 762 | */ 763 | function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { 764 | return functionDelegateCall(target, data, "Address: low-level delegate call failed"); 765 | } 766 | 767 | /** 768 | * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], 769 | * but performing a delegate call. 770 | * 771 | * _Available since v3.4._ 772 | */ 773 | function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 774 | require(isContract(target), "Address: delegate call to non-contract"); 775 | 776 | // solhint-disable-next-line avoid-low-level-calls 777 | (bool success, bytes memory returndata) = target.delegatecall(data); 778 | return _verifyCallResult(success, returndata, errorMessage); 779 | } 780 | 781 | function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { 782 | if (success) { 783 | return returndata; 784 | } else { 785 | // Look for revert reason and bubble it up if present 786 | if (returndata.length > 0) { 787 | // The easiest way to bubble the revert reason is using memory via assembly 788 | 789 | // solhint-disable-next-line no-inline-assembly 790 | assembly { 791 | let returndata_size := mload(returndata) 792 | revert(add(32, returndata), returndata_size) 793 | } 794 | } else { 795 | revert(errorMessage); 796 | } 797 | } 798 | } 799 | } 800 | 801 | 802 | 803 | /** 804 | * @title SafeERC20 805 | * @dev Wrappers around ERC20 operations that throw on failure (when the token 806 | * contract returns false). Tokens that return no value (and instead revert or 807 | * throw on failure) are also supported, non-reverting calls are assumed to be 808 | * successful. 809 | * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 810 | * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 811 | */ 812 | library SafeERC20 { 813 | using SafeMath for uint256; 814 | using Address for address; 815 | 816 | function safeTransfer(IERC20 token, address to, uint256 value) internal { 817 | _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 818 | } 819 | 820 | function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 821 | _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 822 | } 823 | 824 | /** 825 | * @dev Deprecated. This function has issues similar to the ones found in 826 | * {IERC20-approve}, and its usage is discouraged. 827 | * 828 | * Whenever possible, use {safeIncreaseAllowance} and 829 | * {safeDecreaseAllowance} instead. 830 | */ 831 | function safeApprove(IERC20 token, address spender, uint256 value) internal { 832 | // safeApprove should only be called when setting an initial allowance, 833 | // or when resetting it to zero. To increase and decrease it, use 834 | // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 835 | // solhint-disable-next-line max-line-length 836 | require((value == 0) || (token.allowance(address(this), spender) == 0), 837 | "SafeERC20: approve from non-zero to non-zero allowance" 838 | ); 839 | _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 840 | } 841 | 842 | function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 843 | uint256 newAllowance = token.allowance(address(this), spender).add(value); 844 | _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 845 | } 846 | 847 | function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 848 | uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 849 | _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 850 | } 851 | 852 | /** 853 | * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 854 | * on the return value: the return value is optional (but if data is returned, it must not be false). 855 | * @param token The token targeted by the call. 856 | * @param data The call data (encoded using abi.encode or one of its variants). 857 | */ 858 | function _callOptionalReturn(IERC20 token, bytes memory data) private { 859 | // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 860 | // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 861 | // the target address contains contract code and also asserts for success in the low-level call. 862 | 863 | bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); 864 | if (returndata.length > 0) { // Return data is optional 865 | // solhint-disable-next-line max-line-length 866 | require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 867 | } 868 | } 869 | } 870 | 871 | 872 | /** 873 | * @dev Contract module which provides a basic access control mechanism, where 874 | * there is an account (an owner) that can be granted exclusive access to 875 | * specific functions. 876 | * 877 | * By default, the owner account will be the one that deploys the contract. This 878 | * can later be changed with {transferOwnership}. 879 | * 880 | * This module is used through inheritance. It will make available the modifier 881 | * `onlyOwner`, which can be applied to your functions to restrict their use to 882 | * the owner. 883 | */ 884 | abstract contract Ownable is Context { 885 | address private _owner; 886 | 887 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 888 | 889 | /** 890 | * @dev Initializes the contract setting the deployer as the initial owner. 891 | */ 892 | constructor () internal { 893 | address msgSender = _msgSender(); 894 | _owner = msgSender; 895 | emit OwnershipTransferred(address(0), msgSender); 896 | } 897 | 898 | /** 899 | * @dev Returns the address of the current owner. 900 | */ 901 | function owner() public view virtual returns (address) { 902 | return _owner; 903 | } 904 | 905 | /** 906 | * @dev Throws if called by any account other than the owner. 907 | */ 908 | modifier onlyOwner() { 909 | require(owner() == _msgSender(), "Ownable: caller is not the owner"); 910 | _; 911 | } 912 | 913 | /** 914 | * @dev Leaves the contract without owner. It will not be possible to call 915 | * `onlyOwner` functions anymore. Can only be called by the current owner. 916 | * 917 | * NOTE: Renouncing ownership will leave the contract without an owner, 918 | * thereby removing any functionality that is only available to the owner. 919 | */ 920 | function renounceOwnership() public virtual onlyOwner { 921 | emit OwnershipTransferred(_owner, address(0)); 922 | _owner = address(0); 923 | } 924 | 925 | /** 926 | * @dev Transfers ownership of the contract to a new account (`newOwner`). 927 | * Can only be called by the current owner. 928 | */ 929 | function transferOwnership(address newOwner) public virtual onlyOwner { 930 | require(newOwner != address(0), "Ownable: new owner is the zero address"); 931 | emit OwnershipTransferred(_owner, newOwner); 932 | _owner = newOwner; 933 | } 934 | } 935 | 936 | 937 | interface IJar is IERC20 { 938 | function token() external view returns (address); 939 | 940 | //function claimInsurance() external; // NOTE: Only yDelegatedVault implements this 941 | 942 | function getRatio() external view returns (uint256); 943 | 944 | function balance() external view returns (uint256); 945 | 946 | function depositAll() external; 947 | 948 | function deposit(uint256) external; 949 | 950 | function depositFor(address user, uint256 amount) external; 951 | 952 | function withdrawAll() external; 953 | 954 | function withdraw(uint256) external; 955 | 956 | function earn() external; 957 | 958 | function strategy() external view returns (address); 959 | 960 | function decimals() external view returns (uint8); 961 | 962 | function getLastTimeRestaked(address _address) external view returns (uint256); 963 | 964 | function notifyReward(address _reward, uint256 _amount) external; 965 | 966 | function getPendingReward(address _user) external view returns (uint256); 967 | } 968 | 969 | interface IUniswapV2Pair { 970 | event Approval(address indexed owner, address indexed spender, uint value); 971 | event Transfer(address indexed from, address indexed to, uint value); 972 | 973 | function name() external pure returns (string memory); 974 | function symbol() external pure returns (string memory); 975 | function decimals() external pure returns (uint8); 976 | function totalSupply() external view returns (uint); 977 | function balanceOf(address owner) external view returns (uint); 978 | function allowance(address owner, address spender) external view returns (uint); 979 | 980 | function approve(address spender, uint value) external returns (bool); 981 | function transfer(address to, uint value) external returns (bool); 982 | function transferFrom(address from, address to, uint value) external returns (bool); 983 | 984 | function DOMAIN_SEPARATOR() external view returns (bytes32); 985 | function PERMIT_TYPEHASH() external pure returns (bytes32); 986 | function nonces(address owner) external view returns (uint); 987 | 988 | function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; 989 | 990 | event Mint(address indexed sender, uint amount0, uint amount1); 991 | event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); 992 | event Swap( 993 | address indexed sender, 994 | uint amount0In, 995 | uint amount1In, 996 | uint amount0Out, 997 | uint amount1Out, 998 | address indexed to 999 | ); 1000 | event Sync(uint112 reserve0, uint112 reserve1); 1001 | 1002 | function MINIMUM_LIQUIDITY() external pure returns (uint); 1003 | function factory() external view returns (address); 1004 | function token0() external view returns (address); 1005 | function token1() external view returns (address); 1006 | function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); 1007 | function price0CumulativeLast() external view returns (uint); 1008 | function price1CumulativeLast() external view returns (uint); 1009 | function kLast() external view returns (uint); 1010 | 1011 | function mint(address to) external returns (uint liquidity); 1012 | function burn(address to) external returns (uint amount0, uint amount1); 1013 | function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; 1014 | function skim(address to) external; 1015 | function sync() external; 1016 | 1017 | function initialize(address, address) external; 1018 | } 1019 | interface IUniswapRouterV2 { 1020 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 1021 | uint amountIn, 1022 | uint amountOutMin, 1023 | address[] calldata path, 1024 | address to, 1025 | uint deadline 1026 | ) external; 1027 | 1028 | function swapExactTokensForTokens( 1029 | uint256 amountIn, 1030 | uint256 amountOutMin, 1031 | address[] calldata path, 1032 | address to, 1033 | uint256 deadline 1034 | ) external returns (uint256[] memory amounts); 1035 | 1036 | function addLiquidity( 1037 | address tokenA, 1038 | address tokenB, 1039 | uint256 amountADesired, 1040 | uint256 amountBDesired, 1041 | uint256 amountAMin, 1042 | uint256 amountBMin, 1043 | address to, 1044 | uint256 deadline 1045 | ) 1046 | external 1047 | returns ( 1048 | uint256 amountA, 1049 | uint256 amountB, 1050 | uint256 liquidity 1051 | ); 1052 | 1053 | function addLiquidityETH( 1054 | address token, 1055 | uint256 amountTokenDesired, 1056 | uint256 amountTokenMin, 1057 | uint256 amountETHMin, 1058 | address to, 1059 | uint256 deadline 1060 | ) 1061 | external 1062 | payable 1063 | returns ( 1064 | uint256 amountToken, 1065 | uint256 amountETH, 1066 | uint256 liquidity 1067 | ); 1068 | 1069 | function removeLiquidity( 1070 | address tokenA, 1071 | address tokenB, 1072 | uint256 liquidity, 1073 | uint256 amountAMin, 1074 | uint256 amountBMin, 1075 | address to, 1076 | uint256 deadline 1077 | ) external returns (uint256 amountA, uint256 amountB); 1078 | 1079 | function getAmountsOut(uint256 amountIn, address[] calldata path) 1080 | external 1081 | view 1082 | returns (uint256[] memory amounts); 1083 | 1084 | function getAmountsIn(uint256 amountOut, address[] calldata path) 1085 | external 1086 | view 1087 | returns (uint256[] memory amounts); 1088 | 1089 | function swapETHForExactTokens( 1090 | uint256 amountOut, 1091 | address[] calldata path, 1092 | address to, 1093 | uint256 deadline 1094 | ) external payable returns (uint256[] memory amounts); 1095 | 1096 | function swapExactETHForTokens( 1097 | uint256 amountOutMin, 1098 | address[] calldata path, 1099 | address to, 1100 | uint256 deadline 1101 | ) external payable returns (uint256[] memory amounts); 1102 | } 1103 | 1104 | 1105 | abstract contract BaseStrategy is Ownable { 1106 | using SafeERC20 for IERC20; 1107 | using Address for address; 1108 | using SafeMath for uint256; 1109 | 1110 | // Tokens 1111 | address public want; //The LP token, Harvest calls this "rewardToken" 1112 | address public constant weth = 0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619; //weth for Matic 1113 | address public harvestedToken; //The token we harvest, will add support for multiple tokens in v2 1114 | 1115 | // User accounts 1116 | address public strategist; //The address the performance fee is sent to 1117 | address public jar; 1118 | 1119 | // Dex 1120 | address public constant currentRouter = 0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506; //SushiSwap router 1121 | 1122 | constructor( 1123 | address _want, 1124 | address _strategist, 1125 | address _harvestedToken 1126 | ) public { 1127 | require(_want != address(0)); 1128 | require(_strategist != address(0)); 1129 | 1130 | want = _want; 1131 | strategist = _strategist; 1132 | harvestedToken = _harvestedToken; 1133 | } 1134 | 1135 | // **** Modifiers **** // 1136 | 1137 | //Replaced with Ownable, which allows me to transfer ownership of the contract 1138 | /*modifier onlyStrategist { 1139 | require(msg.sender == strategist, "!strategist"); 1140 | _; 1141 | }*/ 1142 | 1143 | // **** Views **** // 1144 | 1145 | function balanceOfWant() public view returns (uint256) { 1146 | return IERC20(want).balanceOf(address(this)); 1147 | } 1148 | 1149 | function balanceOfPool() public virtual view returns (uint256); 1150 | 1151 | function getHarvestable() external virtual view returns (uint256); 1152 | 1153 | function balanceOf() public view returns (uint256) { 1154 | return balanceOfWant().add(balanceOfPool()); 1155 | } 1156 | 1157 | function getName() external virtual pure returns (string memory); 1158 | 1159 | // **** Setters **** // 1160 | 1161 | function setJar(address _jar) external onlyOwner { 1162 | require(jar == address(0), "jar already set"); 1163 | jar = _jar; 1164 | emit SetJar(_jar); 1165 | } 1166 | 1167 | function setStrategist(address _strategist) external onlyOwner { 1168 | strategist = _strategist; 1169 | } 1170 | 1171 | // **** State mutations **** // 1172 | function deposit() public virtual; 1173 | 1174 | // Withdraw partial funds, normally used with a jar withdrawal 1175 | function withdraw(uint256 _amount) external { 1176 | require(msg.sender == jar, "!jar"); 1177 | uint256 _balance = IERC20(want).balanceOf(address(this)); 1178 | if (_balance < _amount) { 1179 | _amount = _withdrawSome(_amount.sub(_balance)); 1180 | _amount = _amount.add(_balance); 1181 | } 1182 | 1183 | IERC20(want).safeTransfer(jar, _amount); 1184 | } 1185 | 1186 | function _withdrawAll() internal { 1187 | _withdrawSome(balanceOfPool()); 1188 | } 1189 | 1190 | function _withdrawSome(uint256 _amount) internal virtual returns (uint256); 1191 | 1192 | function harvest() public virtual; 1193 | 1194 | // **** Internal functions **** 1195 | function _swapUniswap( 1196 | address _from, 1197 | address _to, 1198 | uint256 _amount 1199 | ) internal { 1200 | require(_to != address(0)); 1201 | 1202 | // Swap with uniswap 1203 | IERC20(_from).safeApprove(currentRouter, 0); 1204 | IERC20(_from).safeApprove(currentRouter, _amount); 1205 | 1206 | address[] memory path; 1207 | 1208 | if (_from == weth || _to == weth) { 1209 | path = new address[](2); 1210 | path[0] = _from; 1211 | path[1] = _to; 1212 | } else { 1213 | path = new address[](3); 1214 | path[0] = _from; 1215 | path[1] = weth; 1216 | path[2] = _to; 1217 | } 1218 | 1219 | IUniswapRouterV2(currentRouter).swapExactTokensForTokens( 1220 | _amount, 1221 | 0, 1222 | path, 1223 | address(this), 1224 | now.add(60) 1225 | ); 1226 | } 1227 | 1228 | function _swapUniswapWithPath( 1229 | address[] memory path, 1230 | uint256 _amount 1231 | ) internal { 1232 | require(path[1] != address(0)); 1233 | 1234 | // Swap with uniswap 1235 | IERC20(path[0]).safeApprove(currentRouter, 0); 1236 | IERC20(path[0]).safeApprove(currentRouter, _amount); 1237 | 1238 | IUniswapRouterV2(currentRouter).swapExactTokensForTokens( 1239 | _amount, 1240 | 0, 1241 | path, 1242 | address(this), 1243 | now.add(60) 1244 | ); 1245 | } 1246 | 1247 | function _swapUniswapWithPathForFeeOnTransferTokens( 1248 | address[] memory path, 1249 | uint256 _amount 1250 | ) internal { 1251 | require(path[1] != address(0)); 1252 | 1253 | // Swap with uniswap 1254 | IERC20(path[0]).safeApprove(currentRouter, 0); 1255 | IERC20(path[0]).safeApprove(currentRouter, _amount); 1256 | 1257 | IUniswapRouterV2(currentRouter).swapExactTokensForTokensSupportingFeeOnTransferTokens( 1258 | _amount, 1259 | 0, 1260 | path, 1261 | address(this), 1262 | now.add(60) 1263 | ); 1264 | } 1265 | 1266 | function _distributePerformanceFeesAndDeposit() internal { 1267 | uint256 _want = IERC20(want).balanceOf(address(this)); 1268 | 1269 | if (_want > 0) { 1270 | deposit(); 1271 | } 1272 | } 1273 | 1274 | // **** Events **** // 1275 | event SetJar(address indexed jar); 1276 | } 1277 | interface IMasterChef { 1278 | function deposit(uint256 _pid, uint256 _amount) external; 1279 | function withdraw(uint256 _pid, uint256 _amount) external; 1280 | function emergencyWithdraw(uint256 _pid) external; 1281 | function exit(uint256 _pid) external; 1282 | 1283 | function userInfo(uint256 _pid, address _user) external view returns(uint256, uint256); 1284 | function balanceOf(uint256 _pid, address _user) external view returns (uint256); 1285 | function earned(uint256 _pid, address _user) external view returns (uint256); 1286 | function totalSupply(uint256 _pid) external view returns (uint256); 1287 | } 1288 | 1289 | // Base contract for MasterChef/SakeMaster/etc rewards contract interfaces 1290 | 1291 | abstract contract BaseStrategyMasterChef is BaseStrategy { 1292 | 1293 | address public rewards; 1294 | uint256 public poolId; 1295 | bool public emergencyStatus = false; 1296 | 1297 | constructor( 1298 | address _rewards, 1299 | address _want, 1300 | address _strategist, 1301 | uint256 _poolId, 1302 | address _harvestedToken 1303 | ) 1304 | public 1305 | BaseStrategy(_want, _strategist, _harvestedToken) 1306 | { 1307 | poolId = _poolId; 1308 | rewards = _rewards; 1309 | } 1310 | 1311 | // **** Getters **** 1312 | function balanceOfPool() public override view returns (uint256) { 1313 | (uint256 amount, ) = IMasterChef(rewards).userInfo(poolId, address(this)); 1314 | return amount; 1315 | //return IMasterChef(rewards).balanceOf(poolId, address(this)); 1316 | } 1317 | 1318 | function getHarvestable() external override view returns (uint256) { 1319 | return IMasterChef(rewards).earned(poolId, address(this)); 1320 | } 1321 | 1322 | // **** Setters **** 1323 | 1324 | function deposit() public override { 1325 | require(emergencyStatus == false, "emergency withdrawal in process"); 1326 | uint256 _want = IERC20(want).balanceOf(address(this)); 1327 | if (_want > 0) { 1328 | IERC20(want).safeApprove(rewards, 0); 1329 | IERC20(want).safeApprove(rewards, _want); 1330 | IMasterChef(rewards).deposit(poolId, _want); 1331 | } 1332 | } 1333 | 1334 | function _withdrawSome(uint256 _amount) 1335 | internal 1336 | override 1337 | returns (uint256) 1338 | { 1339 | IMasterChef(rewards).withdraw(poolId, _amount); 1340 | return _amount; 1341 | } 1342 | 1343 | /* **** Other Mutative functions **** */ 1344 | 1345 | function _getReward() internal { 1346 | IMasterChef(rewards).withdraw(poolId, 0); 1347 | //Usually different for other pools based on IMasterChef 1348 | //IMasterChef(rewards).claim(poolId); 1349 | } 1350 | 1351 | // **** Admin functions **** 1352 | 1353 | function salvage(address token) public onlyOwner { 1354 | require(token != want && token != harvestedToken, "cannot salvage"); 1355 | 1356 | uint256 _token = IERC20(token).balanceOf(address(this)); 1357 | if (_token > 0) { 1358 | IERC20(token).safeTransfer(msg.sender, _token); 1359 | } 1360 | } 1361 | 1362 | function emergencyWithdraw() public onlyOwner { 1363 | IMasterChef(rewards).emergencyWithdraw(poolId); 1364 | 1365 | uint256 _want = IERC20(want).balanceOf(address(this)); 1366 | if (_want > 0) { 1367 | IERC20(want).safeTransfer(jar, _want); 1368 | } 1369 | 1370 | emergencyStatus = true; 1371 | } 1372 | } 1373 | 1374 | 1375 | abstract contract StrategyFarmSingle is BaseStrategyMasterChef { 1376 | 1377 | // Addresses for the harvested and reward tokens 1378 | address public constant rewardToken = 0xF4B0903774532AEe5ee567C02aaB681a81539e92; 1379 | address public multiHarvest = 0x0000000000000000000000000000000000000000; 1380 | 1381 | // Set swap path depending on what other liquidity pools the farm offers 1382 | // Not relevant for Gaj but might be relevant for other implementations 1383 | address public constant usdc = rewardToken; 1384 | address public constant iron = 0xD86b5923F3AD7b585eD81B448170ae026c65ae9a; 1385 | address public constant titan = 0xaAa5B9e6c589642f98a1cDA99B9D024B8407285A; 1386 | 1387 | address[] public usdc_titan_path; 1388 | 1389 | // Other constants 1390 | uint16 public constant underlyingPoolId = 2; 1391 | 1392 | uint256 public keepFXS = 0; 1393 | uint256 public harvestCutoff = 10; 1394 | 1395 | uint256 public constant keepFXSmax = 10000; 1396 | 1397 | // Uniswap swap paths 1398 | constructor( 1399 | address _rewards, 1400 | address _want, 1401 | address _strategist 1402 | ) 1403 | public 1404 | BaseStrategyMasterChef( 1405 | _rewards, 1406 | _want, 1407 | _strategist, 1408 | underlyingPoolId, 1409 | rewardToken 1410 | ) 1411 | { 1412 | usdc_titan_path = new address[](3); 1413 | usdc_titan_path[0] = usdc; 1414 | usdc_titan_path[1] = iron; 1415 | usdc_titan_path[2] = titan; 1416 | } 1417 | 1418 | // **** State Mutations **** 1419 | 1420 | function set_fee(uint256 NewFee) external onlyOwner() { 1421 | require(NewFee <= 1000, "Cannot be more than 1000 bps"); 1422 | keepFXS = NewFee; 1423 | } 1424 | 1425 | function set_multiHarvest(address newHarvest) external onlyOwner() { 1426 | multiHarvest = newHarvest; 1427 | } 1428 | 1429 | function set_harvestCutoff(uint256 newCutoff) external onlyOwner() { 1430 | require(newCutoff <= 10**18, "New cutoff must be less than 1 gaj"); 1431 | harvestCutoff = newCutoff; 1432 | } 1433 | 1434 | // Check if there is no re-entrancy condition from the underlying farms' MC. If there is one, separate out the _getReward() part from the rest. 1435 | function harvest() public override { 1436 | //prevent unauthorized smart contracts from calling harvest() 1437 | require(msg.sender == tx.origin || msg.sender == owner() || msg.sender == strategist || msg.sender == multiHarvest, "not authorized"); 1438 | 1439 | // Get Reward 1440 | _getReward(); 1441 | 1442 | //Swap Reward for Want 1443 | uint256 _harvestBalance = IERC20(rewardToken).balanceOf(address(this)); 1444 | if (_harvestBalance > harvestCutoff){ 1445 | if (rewardToken != want) { 1446 | _swapUniswapWithPath(usdc_titan_path, _harvestBalance); 1447 | } 1448 | 1449 | //Send performance fee to strategist 1450 | uint256 _want = IERC20(want).balanceOf(address(this)); 1451 | if (_want > 0) { 1452 | uint256 performanceFee = _want.mul(keepFXS).div(keepFXSmax); 1453 | if (performanceFee>0) { 1454 | IERC20(want).safeTransfer( 1455 | strategist, 1456 | performanceFee 1457 | ); 1458 | } 1459 | } 1460 | } 1461 | // Stake the LP tokens 1462 | _distributePerformanceFeesAndDeposit(); 1463 | } 1464 | } 1465 | 1466 | contract StrategySingle is StrategyFarmSingle { 1467 | // Token addresses 1468 | address public Gaj_MASTER_CHEF = 0xb03f95E649724dF6bA575C2c6eF062766a7fDb51; 1469 | address public Want_Token = 0xF4B0903774532AEe5ee567C02aaB681a81539e92; 1470 | 1471 | constructor() 1472 | public 1473 | StrategyFarmSingle( 1474 | Gaj_MASTER_CHEF, 1475 | Want_Token, 1476 | msg.sender 1477 | ) 1478 | {} 1479 | 1480 | // **** Views **** 1481 | 1482 | function getName() external override pure returns (string memory) { 1483 | return "StrategyGajGaj"; 1484 | } 1485 | 1486 | function pairName() external pure returns (string memory) { 1487 | return "GajGaj"; 1488 | } 1489 | } 1490 | --------------------------------------------------------------------------------