├── .gitignore ├── LICENSE ├── README.md ├── abi └── governance-vault │ └── ValueGovernanceVault.json ├── contracts ├── compositevaults │ ├── CompositeVaultBank.sol │ ├── CompositeVaultMaster.sol │ ├── ICompositeVault.sol │ ├── IController.sol │ ├── ILpPairConverter.sol │ ├── ILpPairStrategy.sol │ ├── IVaultMaster.sol │ ├── controllers │ │ └── CompositeVaultController.sol │ ├── converters │ │ ├── BalancerBptPoolConverter.sol │ │ ├── BaseConverter.sol │ │ ├── ConverterHelper.sol │ │ ├── IDecimals.sol │ │ └── SushiswapLpPairConverter.sol │ ├── mock │ │ ├── AttackingContract.sol │ │ ├── MockConverter.sol │ │ ├── MockERC20.sol │ │ ├── MockLpPairConverter.sol │ │ ├── MockOneSplitAudit.sol │ │ ├── MockSushiMasterChef.sol │ │ ├── MockUniswapRouter.sol │ │ ├── MockUniswapV2Pair.sol │ │ └── TToken.sol │ ├── strategies │ │ ├── StrategyBalancerEthUsdc.sol │ │ ├── StrategyBase.sol │ │ └── StrategySushiEthUsdc.sol │ └── vaults │ │ ├── CompositeVaultBase.sol │ │ ├── CompositeVaultBptEthUsdc.sol │ │ └── CompositeVaultSlpEthUsdc.sol ├── governance-vault │ ├── IController.sol │ ├── NoMintRewardPool.sol │ ├── ValueGovernanceVault.sol │ ├── YFVController.sol │ ├── YFVGovernanceVault.sol │ ├── YFVStrategy.sol │ └── mock │ │ └── UniswapRouterMock.sol ├── interfaces │ ├── Aave.sol │ ├── Balancer.sol │ ├── Converter.sol │ ├── Curve.sol │ ├── DForce.sol │ ├── Gauge.sol │ ├── IUniswapV2Factory.sol │ ├── IUniswapV2Pair.sol │ ├── IUniswapV2Router.sol │ ├── MStable.sol │ ├── OneSplitAudit.sol │ ├── PickleJar.sol │ ├── PickleMasterChef.sol │ ├── SushiMasterChef.sol │ ├── ValueMinorPool.sol │ └── Yfii.sol ├── libraries │ └── Math.sol ├── multivaults │ ├── IMultiVaultController.sol │ ├── IMultiVaultConverter.sol │ ├── IMultiVaultStrategy.sol │ ├── IShareConverter.sol │ ├── IValueMultiVault.sol │ ├── IValueVaultMaster.sol │ ├── ValueMultiVaultBank.sol │ ├── ValueMultiVaultMaster.sol │ ├── controllers │ │ └── MultiStablesVaultController.sol │ ├── converters │ │ ├── ShareConverter.sol │ │ ├── StableSwap3PoolConverter.sol │ │ ├── StableSwapBusdConverter.sol │ │ └── StableSwapCompoundConverter.sol │ ├── mock │ │ ├── MockCERC20.sol │ │ ├── MockConverter.sol │ │ ├── MockCurveGauge.sol │ │ ├── MockCurveMinter.sol │ │ ├── MockERC20.sol │ │ ├── MockPickleJar.sol │ │ ├── MockPickleMasterChef.sol │ │ ├── MockStableSwap3Pool.sol │ │ ├── MockUniswapRouter.sol │ │ ├── MockWrapYERC20.sol │ │ └── TToken.sol │ ├── pool-interfaces │ │ ├── IDepositBUSD.sol │ │ ├── IDepositCompound.sol │ │ ├── IDepositHUSD.sol │ │ ├── IDepositSUSD.sol │ │ ├── IStableSwap3Pool.sol │ │ ├── IStableSwapBUSD.sol │ │ ├── IStableSwapCompound.sol │ │ ├── IStableSwapHUSD.sol │ │ └── IStableSwapSUSD.sol │ ├── proxy │ │ ├── AdminUpgradeabilityProxy.sol │ │ ├── Proxy.sol │ │ ├── ProxyAdmin.sol │ │ └── UpgradeabilityProxy.sol │ ├── strategies │ │ ├── StrategyCurveBCrv.sol │ │ └── StrategyPickle3Crv.sol │ └── vaults │ │ └── MultiStablesVault.sol └── vaults │ ├── ValueVaultBank.sol │ ├── ValueVaultMaster.sol │ ├── misc │ ├── ValueLiquidityToken.sol │ ├── ValueMinorPool.sol │ ├── ValueVaultProfitSharer.sol │ ├── ValueVaultProfitSharerV2.sol │ └── YFV_Referral.sol │ ├── mock │ ├── MockERC20.sol │ ├── MockFarmingPool.sol │ ├── MockGovVault.sol │ ├── MockSodaPool.sol │ ├── MockSodaVault.sol │ ├── MockSushiPool.sol │ └── MockUniswapRouter.sol │ ├── v1 │ ├── ValueVault.sol │ ├── strategies │ │ ├── IStrategy.sol │ │ └── WETHSodaPoolStrategy.sol │ └── vaults │ │ └── WETHVault.sol │ └── v2 │ ├── ValueVaultV2.sol │ ├── strategies │ ├── IStrategyV2.sol │ ├── Univ2ETHUSDCMultiPoolStrategy.sol │ ├── Univ2ETHWBTCMultiPoolStrategy.sol │ └── WETHMultiPoolStrategy.sol │ └── vaults │ ├── UNIv2ETHUSDCVault.sol │ └── UNIv2ETHWBTCVault.sol ├── package.json └── test ├── MultiStrategies.test.js ├── ValueVaultV1.WETHMultiPool.test.js ├── ValueVaultV2.test.js ├── compositevaults ├── 000_bank.single_vault_no_controller.test.ts ├── 001_vault.strategy_slp.test.ts ├── 002_vault.strategy_bpt.test.ts └── 003_two_vaults.test.ts ├── governance-vault ├── gov_vault.test.js └── gov_vault_lock_and_boost.test.js └── multivaults ├── 001_bank.test.ts ├── 002_vault.single_strategy.test.ts └── 003_vault.two_strategies.test.ts /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 yfv-finance 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Value logo 3 |

4 | 5 |

Value Vaults

6 | 7 | ## Value Vaults 8 | https://valuedefi.io/value-vaults 9 | 10 | Value Vaults is the core feature of YFValue in order to achieve long-term profitability of the token. 11 | 12 | ## Value Governance Vault (v2) 13 | https://valuedefi.io/stake 14 | 15 | The contract is deployed [here](https://etherscan.io/address/0x78d46e6b5c022ffbd1a558c65407ad28ad98e51b#code) 16 | 17 | - VALUE can be staked 18 | - Profit from farming strategies will be auto-compounded 19 | - Locking VALUE in the vault for an extra period of time will boost VALUE yield 20 | - Governance Vault v2 will support multiple strategy farming as well, our state-of-the-art farming innovation -------------------------------------------------------------------------------- /contracts/compositevaults/CompositeVaultMaster.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IERC20 { 6 | function transfer(address recipient, uint256 amount) external returns (bool); 7 | } 8 | 9 | contract CompositeVaultMaster { 10 | address public governance; 11 | 12 | address public valueToken = address(0x49E833337ECe7aFE375e44F4E3e8481029218E5c); 13 | 14 | address public govVault = address(0xceC03a960Ea678A2B6EA350fe0DbD1807B22D875); // 14.0% profit from Value Vaults 15 | address public insuranceFund = 0xb7b2Ea8A1198368f950834875047aA7294A2bDAa; // set to Governance Multisig at start 16 | address public performanceReward = 0x7Be4D5A99c903C437EC77A20CB6d0688cBB73c7f; // set to deploy wallet at start 17 | 18 | uint256 public govVaultProfitShareFee = 1400; // 14.0% | VIP-7 (https://yfv.finance/vip-vote/vip_7) 19 | uint256 public gasFee = 50; // 0.5% at start and can be set by governance decision 20 | uint256 public insuranceFee = 0; // 6% | VIP-10 (to compensate who lost during the exploit on Nov 14 2020) 21 | uint256 public withdrawalProtectionFee = 0; // % of withdrawal go back to vault (for auto-compounding) to protect withdrawals 22 | 23 | mapping(address => address) public bank; 24 | mapping(address => bool) public isVault; 25 | mapping(address => bool) public isController; 26 | mapping(address => bool) public isStrategy; 27 | 28 | mapping(address => uint) public slippage; // over 10000 29 | 30 | constructor(address _valueToken) public { 31 | if (_valueToken != address(0)) valueToken = _valueToken; 32 | governance = msg.sender; 33 | } 34 | 35 | function setGovernance(address _governance) external { 36 | require(msg.sender == governance, "!governance"); 37 | governance = _governance; 38 | } 39 | 40 | function setBank(address _vault, address _bank) external { 41 | require(msg.sender == governance, "!governance"); 42 | bank[_vault] = _bank; 43 | } 44 | 45 | function addVault(address _vault) external { 46 | require(msg.sender == governance, "!governance"); 47 | isVault[_vault] = true; 48 | } 49 | 50 | function removeVault(address _vault) external { 51 | require(msg.sender == governance, "!governance"); 52 | isVault[_vault] = false; 53 | } 54 | 55 | function addController(address _controller) external { 56 | require(msg.sender == governance, "!governance"); 57 | isController[_controller] = true; 58 | } 59 | 60 | function removeController(address _controller) external { 61 | require(msg.sender == governance, "!governance"); 62 | isController[_controller] = true; 63 | } 64 | 65 | function addStrategy(address _strategy) external { 66 | require(msg.sender == governance, "!governance"); 67 | isStrategy[_strategy] = true; 68 | } 69 | 70 | function removeStrategy(address _strategy) external { 71 | require(msg.sender == governance, "!governance"); 72 | isStrategy[_strategy] = false; 73 | } 74 | 75 | function setGovVault(address _govVault) public { 76 | require(msg.sender == governance, "!governance"); 77 | govVault = _govVault; 78 | } 79 | 80 | function setInsuranceFund(address _insuranceFund) public { 81 | require(msg.sender == governance, "!governance"); 82 | insuranceFund = _insuranceFund; 83 | } 84 | 85 | function setPerformanceReward(address _performanceReward) public { 86 | require(msg.sender == governance, "!governance"); 87 | performanceReward = _performanceReward; 88 | } 89 | 90 | function setGovVaultProfitShareFee(uint256 _govVaultProfitShareFee) public { 91 | require(msg.sender == governance, "!governance"); 92 | require(_govVaultProfitShareFee <= 3000, "_govVaultProfitShareFee over 30%"); 93 | govVaultProfitShareFee = _govVaultProfitShareFee; 94 | } 95 | 96 | function setGasFee(uint256 _gasFee) public { 97 | require(msg.sender == governance, "!governance"); 98 | require(_gasFee <= 500, "_gasFee over 5%"); 99 | gasFee = _gasFee; 100 | } 101 | 102 | function setInsuranceFee(uint256 _insuranceFee) public { 103 | require(msg.sender == governance, "!governance"); 104 | require(_insuranceFee <= 2000, "_insuranceFee over 20%"); 105 | insuranceFee = _insuranceFee; 106 | } 107 | 108 | function setWithdrawalProtectionFee(uint256 _withdrawalProtectionFee) public { 109 | require(msg.sender == governance, "!governance"); 110 | require(_withdrawalProtectionFee <= 100, "_withdrawalProtectionFee over 1%"); 111 | withdrawalProtectionFee = _withdrawalProtectionFee; 112 | } 113 | 114 | function setSlippage(address _token, uint _slippage) external { 115 | require(msg.sender == governance, "!governance"); 116 | require(_slippage <= 1000, ">10%"); 117 | slippage[_token] = _slippage; 118 | } 119 | 120 | function convertSlippage(address _input, address _output) view external returns (uint) { 121 | uint _is = slippage[_input]; 122 | uint _os = slippage[_output]; 123 | return (_is > _os) ? _is : _os; 124 | } 125 | 126 | /** 127 | * This function allows governance to take unsupported tokens out of the contract. This is in an effort to make someone whole, should they seriously mess up. 128 | * There is no guarantee governance will vote to return these. It also allows for removal of airdropped tokens. 129 | */ 130 | function governanceRecoverUnsupported(IERC20 _token, uint256 amount, address to) external { 131 | require(msg.sender == governance, "!governance"); 132 | _token.transfer(to, amount); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /contracts/compositevaults/ICompositeVault.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface ICompositeVault { 6 | function cap() external view returns (uint); 7 | function getConverter() external view returns (address); 8 | function getVaultMaster() external view returns (address); 9 | function balance() external view returns (uint); 10 | function tvl() external view returns (uint); // total dollar value 11 | function token() external view returns (address); 12 | function available() external view returns (uint); 13 | function accept(address _input) external view returns (bool); 14 | 15 | function earn() external; 16 | function harvest(address reserve, uint amount) external; 17 | function addNewCompound(uint, uint) external; 18 | 19 | function withdraw_fee(uint _shares) external view returns (uint); 20 | function calc_token_amount_deposit(address _input, uint _amount) external view returns (uint); 21 | function calc_add_liquidity(uint _amount0, uint _amount1) external view returns (uint); 22 | function calc_token_amount_withdraw(uint _shares, address _output) external view returns (uint); 23 | function calc_remove_liquidity(uint _shares) external view returns (uint _amount0, uint _amount1); 24 | 25 | function getPricePerFullShare() external view returns (uint); 26 | function get_virtual_price() external view returns (uint); // average dollar value of vault share token 27 | 28 | function deposit(address _input, uint _amount, uint _min_mint_amount) external returns (uint); 29 | function depositFor(address _account, address _to, address _input, uint _amount, uint _min_mint_amount) external returns (uint _mint_amount); 30 | function addLiquidity(uint _amount0, uint _amount1, uint _min_mint_amount) external returns (uint); 31 | function addLiquidityFor(address _account, address _to, uint _amount0, uint _amount1, uint _min_mint_amount) external returns (uint _mint_amount); 32 | function withdraw(uint _shares, address _output, uint _min_output_amount) external returns (uint); 33 | function withdrawFor(address _account, uint _shares, address _output, uint _min_output_amount) external returns (uint _output_amount); 34 | 35 | function harvestStrategy(address _strategy) external; 36 | function harvestAllStrategies() external; 37 | } 38 | -------------------------------------------------------------------------------- /contracts/compositevaults/IController.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IController { 6 | function vault() external view returns (address); 7 | 8 | function strategyLength() external view returns (uint); 9 | function strategyBalance() external view returns (uint); 10 | 11 | function getStrategyCount() external view returns(uint); 12 | function strategies(uint _stratId) external view returns (address _strategy, uint _quota, uint _percent); 13 | function getBestStrategy() external view returns (address _strategy); 14 | 15 | function want() external view returns (address); 16 | 17 | function balanceOf() external view returns (uint); 18 | function withdraw_fee(uint _amount) external view returns (uint); // eg. 3CRV => pJar: 0.5% (50/10000) 19 | function investDisabled() external view returns (bool); 20 | 21 | function withdraw(uint) external returns (uint _withdrawFee); 22 | function earn(address _token, uint _amount) external; 23 | 24 | function harvestStrategy(address _strategy) external; 25 | function harvestAllStrategies() external; 26 | } 27 | -------------------------------------------------------------------------------- /contracts/compositevaults/ILpPairConverter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface ILpPairConverter { 6 | function lpPair() external view returns (address); 7 | function token0() external view returns (address); 8 | function token1() external view returns (address); 9 | 10 | function accept(address _input) external view returns (bool); 11 | function get_virtual_price() external view returns (uint); 12 | 13 | function convert_rate(address _input, address _output, uint _inputAmount) external view returns (uint _outputAmount); 14 | function calc_add_liquidity(uint _amount0, uint _amount1) external view returns (uint); 15 | function calc_remove_liquidity(uint _shares) external view returns (uint _amount0, uint _amount1); 16 | 17 | function convert(address _input, address _output, address _to) external returns (uint _outputAmount); 18 | function add_liquidity(address _to) external returns (uint _outputAmount); 19 | function remove_liquidity(address _to) external returns (uint _amount0, uint _amount1); 20 | } 21 | -------------------------------------------------------------------------------- /contracts/compositevaults/ILpPairStrategy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface ILpPairStrategy { 6 | function lpPair() external view returns (address); 7 | function token0() external view returns (address); 8 | function token1() external view returns (address); 9 | function deposit() external; 10 | function withdraw(address _asset) external; 11 | function withdraw(uint _amount) external returns (uint); 12 | function withdrawToController(uint _amount) external; 13 | function skim() external; 14 | function harvest(address _mergedStrategy) external; 15 | function withdrawAll() external returns (uint); 16 | function balanceOf() external view returns (uint); 17 | function withdrawFee(uint) external view returns (uint); // pJar: 0.5% (50/10000) 18 | } 19 | -------------------------------------------------------------------------------- /contracts/compositevaults/IVaultMaster.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IVaultMaster { 6 | function bank(address) view external returns (address); 7 | function isVault(address) view external returns (bool); 8 | function isController(address) view external returns (bool); 9 | function isStrategy(address) view external returns (bool); 10 | 11 | function slippage(address) view external returns (uint); 12 | function convertSlippage(address _input, address _output) view external returns (uint); 13 | 14 | function valueToken() view external returns (address); 15 | function govVault() view external returns (address); 16 | function insuranceFund() view external returns (address); 17 | function performanceReward() view external returns (address); 18 | 19 | function govVaultProfitShareFee() view external returns (uint); 20 | function gasFee() view external returns (uint); 21 | function insuranceFee() view external returns (uint); 22 | 23 | function withdrawalProtectionFee() view external returns (uint); 24 | } 25 | -------------------------------------------------------------------------------- /contracts/compositevaults/converters/BalancerBptPoolConverter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 7 | 8 | import "../../interfaces/IUniswapV2Router.sol"; 9 | import "../../interfaces/IUniswapV2Pair.sol"; 10 | import "../../libraries/Math.sol"; 11 | import "../../interfaces/Balancer.sol"; 12 | import "../../interfaces/OneSplitAudit.sol"; 13 | 14 | import "../ILpPairConverter.sol"; 15 | import "../IVaultMaster.sol"; 16 | 17 | import "./ConverterHelper.sol"; 18 | import "./IDecimals.sol"; 19 | import "./BaseConverter.sol"; 20 | 21 | contract BalancerBptPoolConverter is BaseConverter { 22 | constructor ( 23 | IUniswapV2Router _uniswapRouter, 24 | IUniswapV2Router _sushiswapRouter, 25 | address _lpUni, address _lpSlp, address _lpBpt, 26 | OneSplitAudit _oneSplitAudit, 27 | IERC20 _usdc 28 | ) public BaseConverter(_uniswapRouter, _sushiswapRouter, _lpUni, _lpSlp, _lpBpt, _oneSplitAudit, _usdc) { 29 | } 30 | 31 | function getName() public override pure returns (string memory) { 32 | return "BalancerBptPoolConverter:[To_be_replaced_by_pair_name]"; 33 | } 34 | 35 | function lpPair() external override view returns (address) { 36 | return lpBpt; 37 | } 38 | 39 | function token0() public override view returns (address) { 40 | return IUniswapV2Pair(lpSlp).token0(); 41 | } 42 | 43 | function token1() public override view returns (address) { 44 | return IUniswapV2Pair(lpSlp).token1(); 45 | } 46 | 47 | function accept(address _input) external override view returns (bool) { 48 | return (_input == lpUni) || (_input == lpSlp) || (_input == lpBpt); 49 | } 50 | 51 | function get_virtual_price() external override view returns (uint) { 52 | if (preset_virtual_price > 0) return preset_virtual_price; 53 | Balancer _bPool = Balancer(lpBpt); 54 | uint _totalSupply = _bPool.totalSupply(); 55 | IDecimals _token0 = IDecimals(token0()); 56 | uint _reserve0 = _bPool.getBalance(address(_token0)); 57 | uint _amount = uint(10) ** _token0.decimals(); 58 | // 0.1% pool 59 | if (_amount > _reserve0.div(1000)) { 60 | _amount = _reserve0.div(1000); 61 | } 62 | uint _returnAmount; 63 | (_returnAmount,) = oneSplitAudit.getExpectedReturn(address(_token0), address(tokenUSDC), _amount, 1, 0); 64 | // precision 1e18 65 | uint _tmp = _returnAmount.mul(_reserve0).div(_amount).mul(10 ** 30).div(_totalSupply); 66 | return _tmp.mul(_bPool.getTotalDenormalizedWeight()).div(_bPool.getDenormalizedWeight(address(_token0))); 67 | } 68 | 69 | function convert_rate(address _input, address _output, uint _inputAmount) external override view returns (uint _outputAmount) { 70 | if (_input == _output) return 1; 71 | if (_inputAmount == 0) return 0; 72 | if ((_input == lpUni || _input == lpSlp) && _output == lpBpt) {// convert SLP,UNI -> BPT 73 | return ConverterHelper.convertRateUniLpToBpt(_input, _output, _inputAmount); 74 | } 75 | if (_input == lpBpt && (_output == lpSlp || _output == lpUni)) {// convert BPT -> SLP,UNI 76 | return ConverterHelper.convertRateBptToUniLp(_input, _output, _inputAmount); 77 | } 78 | revert("Not supported"); 79 | } 80 | 81 | function calc_add_liquidity(uint _amount0, uint _amount1) external override view returns (uint) { 82 | return ConverterHelper.calculateAddUniLpLiquidity(IUniswapV2Pair(lpSlp), _amount0, _amount1); 83 | } 84 | 85 | function calc_remove_liquidity(uint _shares) external override view returns (uint _amount0, uint _amount1) { 86 | return ConverterHelper.calculateRemoveUniLpLiquidity(IUniswapV2Pair(lpSlp), _shares); 87 | } 88 | 89 | function convert(address _input, address _output, address _to) external lock override returns (uint _outputAmount) { 90 | require(_input != _output, "same asset"); 91 | if (_input == lpUni && _output == lpBpt) {// convert UniLp -> BPT 92 | return ConverterHelper.convertUniLpToBpt(_input, _output, uniswapRouter, _to); 93 | } 94 | if (_input == lpSlp && _output == lpBpt) {// convert SLP -> BPT 95 | return ConverterHelper.convertUniLpToBpt(_input, _output, sushiswapRouter, _to); 96 | } 97 | if (_input == lpBpt && _output == lpSlp) {// convert BPT -> SLP 98 | return ConverterHelper.convertBPTToUniLp(_input, _output, sushiswapRouter, _to); 99 | } 100 | if (_input == lpBpt && _output == lpUni) {// convert BPT -> UniLp 101 | return ConverterHelper.convertBPTToUniLp(_input, _output, uniswapRouter, _to); 102 | } 103 | revert("Not supported"); 104 | } 105 | 106 | function add_liquidity(address _to) external lock virtual override returns (uint _outputAmount) { 107 | Balancer _balPool = Balancer(lpBpt); 108 | address _token0 = token0(); 109 | address _token1 = token1(); 110 | uint _amount0 = IERC20(_token0).balanceOf(address(this)); 111 | uint _amount1 = IERC20(_token1).balanceOf(address(this)); 112 | uint _poolAmountOut = ConverterHelper.calculateAddBptLiquidity(_balPool, _token0, _token1, _amount0, _amount1); 113 | return ConverterHelper.addBalancerLiquidity(_balPool, _poolAmountOut, _to); 114 | } 115 | 116 | function remove_liquidity(address _to) external lock override returns (uint _amount0, uint _amount1) { 117 | ConverterHelper.removeBptLiquidity(Balancer(lpBpt)); 118 | _amount0 = ConverterHelper.skim(token0(), _to); 119 | _amount1 = ConverterHelper.skim(token1(), _to); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /contracts/compositevaults/converters/BaseConverter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 7 | 8 | import "../../interfaces/IUniswapV2Router.sol"; 9 | import "../../interfaces/IUniswapV2Pair.sol"; 10 | import "../../libraries/Math.sol"; 11 | import "../../interfaces/Balancer.sol"; 12 | import "../../interfaces/OneSplitAudit.sol"; 13 | 14 | import "../ILpPairConverter.sol"; 15 | import "./ConverterHelper.sol"; 16 | import "./IDecimals.sol"; 17 | 18 | abstract contract BaseConverter is ILpPairConverter { 19 | using SafeMath for uint; 20 | using SafeERC20 for IERC20; 21 | 22 | address public governance; 23 | 24 | IUniswapV2Router public uniswapRouter = IUniswapV2Router(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D); 25 | IUniswapV2Router public sushiswapRouter = IUniswapV2Router(0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F); 26 | 27 | address public lpUni; 28 | address public lpSlp; 29 | address public lpBpt; 30 | 31 | // To calculate virtual_price (dollar value) 32 | OneSplitAudit public oneSplitAudit = OneSplitAudit(0xC586BeF4a0992C495Cf22e1aeEE4E446CECDee0E); 33 | IERC20 public tokenUSDC = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48); 34 | 35 | uint private unlocked = 1; 36 | uint public preset_virtual_price = 0; 37 | 38 | modifier lock() { 39 | require(unlocked == 1, 'Converter: LOCKED'); 40 | unlocked = 0; 41 | _; 42 | unlocked = 1; 43 | } 44 | 45 | constructor ( 46 | IUniswapV2Router _uniswapRouter, 47 | IUniswapV2Router _sushiswapRouter, 48 | address _lpUni, address _lpSlp, address _lpBpt, 49 | OneSplitAudit _oneSplitAudit, 50 | IERC20 _usdc 51 | ) public { 52 | if (address(_uniswapRouter) != address(0)) uniswapRouter = _uniswapRouter; 53 | if (address(_sushiswapRouter) != address(0)) sushiswapRouter = _sushiswapRouter; 54 | 55 | lpUni = _lpUni; 56 | lpSlp = _lpSlp; 57 | lpBpt = _lpBpt; 58 | 59 | address token0_ = IUniswapV2Pair(lpUni).token0(); 60 | address token1_ = IUniswapV2Pair(lpUni).token1(); 61 | 62 | IERC20(lpUni).safeApprove(address(uniswapRouter), type(uint256).max); 63 | IERC20(token0_).safeApprove(address(uniswapRouter), type(uint256).max); 64 | IERC20(token1_).safeApprove(address(uniswapRouter), type(uint256).max); 65 | 66 | IERC20(lpSlp).safeApprove(address(sushiswapRouter), type(uint256).max); 67 | IERC20(token0_).safeApprove(address(sushiswapRouter), type(uint256).max); 68 | IERC20(token1_).safeApprove(address(sushiswapRouter), type(uint256).max); 69 | 70 | IERC20(token0_).safeApprove(address(lpBpt), type(uint256).max); 71 | IERC20(token1_).safeApprove(address(lpBpt), type(uint256).max); 72 | 73 | if (address(_oneSplitAudit) != address(0)) oneSplitAudit = _oneSplitAudit; 74 | if (address(_usdc) != address(0)) tokenUSDC = _usdc; 75 | 76 | governance = msg.sender; 77 | } 78 | 79 | function getName() public virtual pure returns (string memory); 80 | 81 | function setGovernance(address _governance) public { 82 | require(msg.sender == governance, "!governance"); 83 | governance = _governance; 84 | } 85 | 86 | function approveForSpender(IERC20 _token, address _spender, uint _amount) external { 87 | require(msg.sender == governance, "!governance"); 88 | _token.safeApprove(_spender, _amount); 89 | } 90 | 91 | function set_preset_virtual_price(uint _preset_virtual_price) public { 92 | require(msg.sender == governance, "!governance"); 93 | preset_virtual_price = _preset_virtual_price; 94 | } 95 | 96 | /** 97 | * This function allows governance to take unsupported tokens out of the contract. This is in an effort to make someone whole, should they seriously mess up. 98 | * There is no guarantee governance will vote to return these. It also allows for removal of airdropped tokens. 99 | */ 100 | function governanceRecoverUnsupported(IERC20 _token, uint256 amount, address to) external { 101 | require(msg.sender == governance, "!governance"); 102 | _token.transfer(to, amount); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /contracts/compositevaults/converters/IDecimals.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity =0.6.12; 4 | interface IDecimals { 5 | function decimals() external view returns (uint8); 6 | } -------------------------------------------------------------------------------- /contracts/compositevaults/converters/SushiswapLpPairConverter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 7 | 8 | import "../../interfaces/IUniswapV2Router.sol"; 9 | import "../../interfaces/IUniswapV2Pair.sol"; 10 | import "../../libraries/Math.sol"; 11 | import "../../interfaces/Balancer.sol"; 12 | import "../../interfaces/OneSplitAudit.sol"; 13 | 14 | import "../ILpPairConverter.sol"; 15 | import "../IVaultMaster.sol"; 16 | import "./ConverterHelper.sol"; 17 | import "./IDecimals.sol"; 18 | import "./BaseConverter.sol"; 19 | 20 | contract SushiswapLpPairConverter is BaseConverter { 21 | constructor ( 22 | IUniswapV2Router _uniswapRouter, 23 | IUniswapV2Router _sushiswapRouter, 24 | address _lpUni, address _lpSlp, address _lpBpt, 25 | OneSplitAudit _oneSplitAudit, 26 | IERC20 _usdc 27 | ) public BaseConverter(_uniswapRouter, _sushiswapRouter, _lpUni, _lpSlp, _lpBpt, _oneSplitAudit, _usdc) { 28 | } 29 | 30 | function getName() public override pure returns (string memory) { 31 | return "SushiswapLpPairConverter:[To_be_replaced_by_pair_name]"; 32 | } 33 | 34 | function lpPair() external override view returns (address) { 35 | return lpSlp; 36 | } 37 | 38 | function token0() public override view returns (address) { 39 | return IUniswapV2Pair(lpSlp).token0(); 40 | } 41 | 42 | function token1() public override view returns (address) { 43 | return IUniswapV2Pair(lpSlp).token1(); 44 | } 45 | 46 | function accept(address _input) external override view returns (bool) { 47 | return (_input == lpUni) || (_input == lpSlp) || (_input == lpBpt); 48 | } 49 | 50 | function get_virtual_price() external override view returns (uint) { 51 | if (preset_virtual_price > 0) return preset_virtual_price; 52 | IUniswapV2Pair _pair = IUniswapV2Pair(lpSlp); 53 | uint _totalSupply = _pair.totalSupply(); 54 | IDecimals _token0 = IDecimals(_pair.token0()); 55 | uint _reserve0 = 0; 56 | (_reserve0,,) = _pair.getReserves(); 57 | uint _amount = uint(10) ** _token0.decimals(); 58 | // 0.1% pool 59 | if (_amount > _reserve0.div(1000)) { 60 | _amount = _reserve0.div(1000); 61 | } 62 | uint _returnAmount; 63 | (_returnAmount,) = oneSplitAudit.getExpectedReturn(address(_token0), address(tokenUSDC), _amount, 1, 0); 64 | // precision 1e18 65 | return _returnAmount.mul(2).mul(_reserve0).div(_amount).mul(10 ** 30).div(_totalSupply); 66 | } 67 | 68 | function convert_rate(address _input, address _output, uint _inputAmount) external override view returns (uint _outputAmount) { 69 | if (_input == _output) return 1; 70 | if (_inputAmount == 0) return 0; 71 | if ((_input == lpSlp && _output == lpUni) || (_input == lpUni && _output == lpSlp)) {// convert UNI <-> SLP 72 | return ConverterHelper.convertRateUniToUniInternal(_input, _output, _inputAmount); 73 | } 74 | if (_input == lpSlp && _output == lpBpt) {// convert SLP -> BPT 75 | return ConverterHelper.convertRateUniLpToBpt(_input, _output, _inputAmount); 76 | } 77 | if (_input == lpBpt && _output == lpSlp) {// convert BPT -> SLP 78 | return ConverterHelper.convertRateBptToUniLp(_input, _output, _inputAmount); 79 | } 80 | revert("Not supported"); 81 | } 82 | 83 | function calc_add_liquidity(uint _amount0, uint _amount1) external override view returns (uint) { 84 | return ConverterHelper.calculateAddUniLpLiquidity(IUniswapV2Pair(lpSlp), _amount0, _amount1); 85 | } 86 | 87 | function calc_remove_liquidity(uint _shares) external override view returns (uint _amount0, uint _amount1) { 88 | return ConverterHelper.calculateRemoveUniLpLiquidity(IUniswapV2Pair(lpSlp), _shares); 89 | } 90 | 91 | function convert(address _input, address _output, address _to) external lock override returns (uint _outputAmount) { 92 | require(_input != _output, "same asset"); 93 | if (_input == lpUni && _output == lpSlp) {// convert UNI -> SLP 94 | return ConverterHelper.convertUniToUniLp(_input, _output, uniswapRouter, sushiswapRouter, _to); 95 | } 96 | if (_input == lpSlp && _output == lpUni) {// convert SLP -> SLP 97 | return ConverterHelper.convertUniToUniLp(_input, _output, sushiswapRouter, uniswapRouter, _to); 98 | } 99 | if (_input == lpSlp && _output == lpBpt) {// convert SLP -> BPT 100 | return ConverterHelper.convertUniLpToBpt(_input, _output, sushiswapRouter, _to); 101 | } 102 | if (_input == lpBpt && _output == lpSlp) {// convert BPT -> SLP 103 | return ConverterHelper.convertBPTToUniLp(_input, _output, sushiswapRouter, _to); 104 | } 105 | revert("Not supported"); 106 | } 107 | 108 | function add_liquidity(address _to) external lock override returns (uint _outputAmount) { 109 | return ConverterHelper.addUniLpLiquidity(sushiswapRouter, IUniswapV2Pair(lpSlp), _to); 110 | } 111 | 112 | function remove_liquidity(address _to) external lock override returns (uint _amount0, uint _amount1) { 113 | return ConverterHelper.removeUniLpLiquidity(sushiswapRouter, IUniswapV2Pair(lpSlp), _to); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /contracts/compositevaults/mock/AttackingContract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.2; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 7 | import "../ILpPairConverter.sol"; 8 | import "../ICompositeVault.sol"; 9 | import "../ILpPairConverter.sol"; 10 | 11 | interface Bank { 12 | function deposit(address _vault, address _input, uint _amount, uint _min_mint_amount, bool _isStake, uint8 _flag) external; 13 | function addLiquidity(address _vault, uint _amount0, uint _amount1, uint _min_mint_amount, bool _isStake, uint8 _flag) external; 14 | } 15 | 16 | interface Vault { 17 | function depositFor(address _account, address _to, address _input, uint _amount, uint _min_mint_amount) external; 18 | function addLiquidityFor(address _account, address _to, uint _amount0, uint _amount1, uint _min_mint_amount) external; 19 | } 20 | 21 | contract AttackingContract { 22 | using SafeERC20 for IERC20; 23 | 24 | function deposit(address _bank, address _vault, address _input, uint _amount, uint _min_mint_amount, bool _isStake) external { 25 | IERC20(_input).safeIncreaseAllowance(_bank, _amount); 26 | 27 | Bank(_bank).deposit(_vault, _input, _amount, _min_mint_amount, _isStake, uint8(0)); 28 | } 29 | 30 | function addLiquidity(address _bank, address _vault, uint _amount0, uint _amount1, uint _min_mint_amount, bool _isStake) external { 31 | 32 | ILpPairConverter _cnvrt = ILpPairConverter(ICompositeVault(_vault).getConverter()); 33 | address _token0 = _cnvrt.token0(); 34 | address _token1 = _cnvrt.token1(); 35 | 36 | IERC20(_token0).safeIncreaseAllowance(_bank, _amount0); 37 | IERC20(_token1).safeIncreaseAllowance(_bank, _amount1); 38 | 39 | Bank(_bank).addLiquidity(_vault, _amount0, _amount1, _min_mint_amount, _isStake, uint8(0)); 40 | } 41 | 42 | function depositFor(address _vault, address _account, address _to, address _input, uint _amount, uint _min_mint_amount) external { 43 | Vault(_vault).depositFor(_account, _to, _input, _amount, _min_mint_amount); 44 | } 45 | 46 | function addLiquidityFor(address _vault, address _account, address _to, uint _amount0, uint _amount1, uint _min_mint_amount) external { 47 | Vault(_vault).addLiquidityFor(_account, _to, _amount0, _amount1, _min_mint_amount); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /contracts/compositevaults/mock/MockConverter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.2; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | import "@openzeppelin/contracts/math/SafeMath.sol"; 7 | import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 8 | 9 | import "../../interfaces/Converter.sol"; 10 | 11 | contract MockConverter is Converter { 12 | using SafeERC20 for IERC20; 13 | using SafeMath for uint256; 14 | 15 | IERC20 want; 16 | 17 | constructor(IERC20 _want) public { 18 | want = _want; 19 | } 20 | 21 | function convert(address _token) external override returns (uint _wantAmount) { 22 | uint _tokenAmount = IERC20(_token).balanceOf(address(this)); 23 | _wantAmount = _tokenAmount.div(2); // always convert to 50% amount of input 24 | want.safeTransfer(msg.sender, _wantAmount); 25 | IERC20(_token).safeTransfer(address(0x000000000000000000000000000000000000dEaD), _tokenAmount); // clear the _token balance (send to BurnAddress) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /contracts/compositevaults/mock/MockERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 6 | 7 | contract MockERC20 is ERC20 { 8 | address public governance; 9 | mapping(address => bool) public minters; 10 | 11 | constructor( 12 | string memory name, 13 | string memory symbol, 14 | uint256 supply 15 | ) public ERC20(name, symbol) { 16 | governance = msg.sender; 17 | _mint(msg.sender, supply); 18 | addMinter(msg.sender); 19 | } 20 | 21 | function mint(address account, uint256 amount) public { 22 | require(minters[msg.sender], "!minter"); 23 | _mint(account, amount); 24 | } 25 | 26 | function burn(uint256 amount) public { 27 | _burn(msg.sender, amount); 28 | } 29 | 30 | function setGovernance(address _governance) public { 31 | require(msg.sender == governance, "!governance"); 32 | governance = _governance; 33 | } 34 | 35 | function addMinter(address _minter) public { 36 | require(msg.sender == governance, "!governance"); 37 | minters[_minter] = true; 38 | } 39 | 40 | function removeMinter(address _minter) public { 41 | require(msg.sender == governance, "!governance"); 42 | minters[_minter] = false; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /contracts/compositevaults/mock/MockLpPairConverter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 7 | 8 | contract MockLpPairConverter { 9 | using SafeMath for uint; 10 | using SafeERC20 for IERC20; 11 | 12 | address public lpPair; 13 | address public token0; 14 | address public token1; 15 | 16 | constructor (address _lpPair, address _token0, address _token1) public { 17 | lpPair = _lpPair; 18 | token0 = _token0; 19 | token1 = _token1; 20 | } 21 | 22 | function getName() public pure returns (string memory) { 23 | return "MockLpPairConverter"; 24 | } 25 | 26 | function accept(address) external pure returns (bool) { 27 | return true; 28 | } 29 | 30 | function convert_rate(address _input, address, uint) external view returns (uint _outputAmount) { 31 | uint _tokenAmount = IERC20(_input).balanceOf(address(this)); 32 | _outputAmount = _tokenAmount.div(5); 33 | } 34 | 35 | function convert(address _input, address _output, address _to) external returns (uint _outputAmount) { 36 | uint _tokenAmount = IERC20(_input).balanceOf(address(this)); 37 | _outputAmount = _tokenAmount.div(5); // always convert to 20% amount of input 38 | IERC20(_output).safeTransfer(_to, _outputAmount); 39 | } 40 | 41 | function add_liquidity(address _to) external returns (uint _outputAmount) { 42 | _outputAmount = IERC20(token0).balanceOf(address(this)).div(5); // aways convert to 20% amount of input 43 | IERC20(lpPair).safeTransfer(_to, _outputAmount); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /contracts/compositevaults/mock/MockOneSplitAudit.sol: -------------------------------------------------------------------------------- 1 | import "../../interfaces/OneSplitAudit.sol"; 2 | 3 | contract MockOneSplitAudit is OneSplitAudit { 4 | function swap( 5 | address fromToken, 6 | address destToken, 7 | uint256 amount, 8 | uint256 minReturn, 9 | uint256[] calldata distribution, 10 | uint256 flags 11 | ) 12 | external 13 | override 14 | payable 15 | returns (uint256 returnAmount) { 16 | return 0; 17 | } 18 | 19 | function getExpectedReturn( 20 | address fromToken, 21 | address destToken, 22 | uint256 amount, 23 | uint256 parts, 24 | uint256 flags // See constants in IOneSplit.sol 25 | ) 26 | external 27 | override 28 | view 29 | returns ( 30 | uint256 returnAmount, 31 | uint256[] memory distribution 32 | ) { 33 | returnAmount = amount; 34 | } 35 | } -------------------------------------------------------------------------------- /contracts/compositevaults/mock/MockSushiMasterChef.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IERC20 { 6 | function totalSupply() external view returns (uint); 7 | function balanceOf(address account) external view returns (uint); 8 | function transfer(address recipient, uint amount) external returns (bool); 9 | function allowance(address owner, address spender) external view returns (uint); 10 | function approve(address spender, uint amount) external returns (bool); 11 | function transferFrom(address sender, address recipient, uint amount) external returns (bool); 12 | 13 | event Transfer(address indexed from, address indexed to, uint value); 14 | event Approval(address indexed owner, address indexed spender, uint value); 15 | } 16 | 17 | contract MockSushiMasterChef { 18 | IERC20 public sushiToken; 19 | IERC20 public lpToken; 20 | 21 | struct UserInfo { 22 | uint amount; // How many LP tokens the user has provided. 23 | uint rewardDebt; // Reward debt. See explanation below. 24 | } 25 | 26 | mapping(uint => mapping(address => UserInfo)) public userInfo; 27 | 28 | constructor(IERC20 _sushiToken, IERC20 _lpToken) public { 29 | sushiToken = _sushiToken; 30 | lpToken = _lpToken; 31 | } 32 | 33 | function deposit(uint _pid, uint _amount) external { 34 | lpToken.transferFrom(msg.sender, address(this), _amount); 35 | UserInfo storage user = userInfo[_pid][msg.sender]; 36 | sushiToken.transfer(msg.sender, user.amount / 10); // always get 10% of deposited amount 37 | user.amount = user.amount + _amount; 38 | } 39 | 40 | function withdraw(uint _pid, uint _amount) external { 41 | lpToken.transfer(msg.sender, _amount); 42 | UserInfo storage user = userInfo[_pid][msg.sender]; 43 | sushiToken.transfer(msg.sender, user.amount / 10); // always get 10% of deposited amount 44 | user.amount = user.amount - _amount; 45 | } 46 | 47 | function pendingSushi(uint, address) external view returns (uint) { 48 | return sushiToken.balanceOf(address(this)) / 10; 49 | } 50 | 51 | function emergencyWithdraw(uint _pid) external { 52 | UserInfo storage user = userInfo[_pid][msg.sender]; 53 | lpToken.transfer(msg.sender, user.amount); 54 | user.amount = 0; 55 | user.rewardDebt = 0; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /contracts/compositevaults/mock/MockUniswapRouter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | import "@openzeppelin/contracts/math/SafeMath.sol"; 7 | import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 8 | 9 | interface IUniswapRouter { 10 | function swapExactTokensForTokens( 11 | uint256 amountIn, 12 | uint256 amountOutMin, 13 | address[] calldata path, 14 | address to, 15 | uint256 deadline 16 | ) external returns (uint256[] memory amounts); 17 | 18 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 19 | uint256 amountIn, 20 | uint256 amountOutMin, 21 | address[] calldata path, 22 | address to, 23 | uint256 deadline 24 | ) external returns (uint256[] memory amounts); 25 | 26 | function addLiquidity( 27 | address tokenA, 28 | address tokenB, 29 | uint amountADesired, 30 | uint amountBDesired, 31 | uint amountAMin, 32 | uint amountBMin, 33 | address to, 34 | uint deadline 35 | ) external returns (uint amountA, uint amountB, uint liquidity); 36 | } 37 | 38 | contract MockUniswapRouter is IUniswapRouter { 39 | using SafeERC20 for IERC20; 40 | using SafeMath for uint256; 41 | 42 | IERC20 univ2LpToken; 43 | mapping(address => mapping(address => uint)) swapRate; 44 | 45 | constructor(IERC20 _univ2LpToken) public { 46 | univ2LpToken = _univ2LpToken; 47 | } 48 | 49 | function swapExactTokensForTokens( 50 | uint256 amountIn, 51 | uint256 amountOutMin, 52 | address[] calldata path, 53 | address to, 54 | uint256 deadline 55 | ) public override returns (uint256[] memory amounts) { 56 | return _swap(amountIn, amountOutMin, path, to, deadline); 57 | } 58 | 59 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 60 | uint256 amountIn, 61 | uint256 amountOutMin, 62 | address[] calldata path, 63 | address to, 64 | uint256 deadline 65 | ) external override returns (uint256[] memory amounts) { 66 | return _swap(amountIn, amountOutMin, path, to, deadline); 67 | } 68 | 69 | function setRate(address _input, address _output, uint rate) public { 70 | swapRate[_input][_output] = rate; 71 | } 72 | 73 | function getRate(address _input, address _output) public view returns (uint _rate) { 74 | _rate = swapRate[_input][_output]; 75 | if (_rate == 0) _rate = 1e18; 76 | } 77 | 78 | function _swap( 79 | uint256 amountIn, 80 | uint256, 81 | address[] calldata path, 82 | address to, 83 | uint256 84 | ) internal returns (uint256[] memory amounts) { 85 | uint256 rate = getRate(path[0], path[path.length - 1]); 86 | uint256 amountOut = amountIn.mul(rate).div(1e18); 87 | IERC20 inputToken = IERC20(path[0]); 88 | IERC20 outputToken = IERC20(path[path.length - 1]); 89 | inputToken.safeTransferFrom(msg.sender, address(this), amountIn); 90 | outputToken.safeTransfer(to, amountOut); 91 | amounts = new uint256[](2); 92 | amounts[0] = amountIn; 93 | amounts[1] = amountOut; 94 | } 95 | 96 | function addLiquidity( 97 | address tokenA, 98 | address tokenB, 99 | uint amountADesired, 100 | uint amountBDesired, 101 | uint, 102 | uint, 103 | address to, 104 | uint 105 | ) external override returns (uint amountA, uint amountB, uint liquidity) { 106 | amountA = (amountADesired < amountBDesired) ? amountADesired : amountBDesired; 107 | amountB = amountA; 108 | liquidity = amountA; 109 | IERC20(tokenA).safeTransferFrom(msg.sender, address(this), amountA); 110 | IERC20(tokenB).safeTransferFrom(msg.sender, address(this), amountB); 111 | univ2LpToken.safeTransfer(to, liquidity); // 1A + 1B -> 1LP 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /contracts/compositevaults/mock/MockUniswapV2Pair.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | 7 | contract MockUniswapV2Pair { 8 | string private _name; 9 | string private _symbol; 10 | uint8 private _decimals = 18; 11 | 12 | uint internal _totalSupply; 13 | 14 | address public token0; 15 | address public token1; 16 | 17 | mapping(address => uint) private _balance; 18 | mapping(address => mapping(address => uint)) private _allowance; 19 | 20 | event Approval(address indexed src, address indexed dst, uint amt); 21 | event Transfer(address indexed src, address indexed dst, uint amt); 22 | 23 | // Math 24 | function add(uint a, uint b) internal pure returns (uint c) { 25 | require((c = a + b) >= a); 26 | } 27 | 28 | function sub(uint a, uint b) internal pure returns (uint c) { 29 | require((c = a - b) <= a); 30 | } 31 | 32 | constructor(string memory name, string memory symbol, address _token0, address _token1) public { 33 | _name = name; 34 | _symbol = symbol; 35 | token0 = _token0; 36 | token1 = _token1; 37 | } 38 | 39 | function name() public view returns (string memory) { 40 | return _name; 41 | } 42 | 43 | function symbol() public view returns (string memory) { 44 | return _symbol; 45 | } 46 | 47 | function decimals() public view returns (uint8) { 48 | return _decimals; 49 | } 50 | 51 | function _move(address src, address dst, uint amt) internal { 52 | require(_balance[src] >= amt, "ERR_INSUFFICIENT"); 53 | _balance[src] = sub(_balance[src], amt); 54 | _balance[dst] = add(_balance[dst], amt); 55 | emit Transfer(src, dst, amt); 56 | } 57 | 58 | function _push(address to, uint amt) internal { 59 | _move(address(this), to, amt); 60 | } 61 | 62 | function _pull(address from, uint amt) internal { 63 | _move(from, address(this), amt); 64 | } 65 | 66 | function _mint(address dst, uint amt) internal { 67 | _balance[dst] = add(_balance[dst], amt); 68 | _totalSupply = add(_totalSupply, amt); 69 | emit Transfer(address(0), dst, amt); 70 | } 71 | 72 | function allowance(address src, address dst) external view returns (uint) { 73 | return _allowance[src][dst]; 74 | } 75 | 76 | function balanceOf(address whom) external view returns (uint) { 77 | return _balance[whom]; 78 | } 79 | 80 | function totalSupply() public view returns (uint) { 81 | return _totalSupply; 82 | } 83 | 84 | function approve(address dst, uint amt) external returns (bool) { 85 | _allowance[msg.sender][dst] = amt; 86 | emit Approval(msg.sender, dst, amt); 87 | return true; 88 | } 89 | 90 | function faucet(uint256 amt) public returns (bool) { 91 | _mint(msg.sender, amt); 92 | return true; 93 | } 94 | 95 | function mintTo(address dst, uint amt) public returns (bool) { 96 | _mint(dst, amt); 97 | return true; 98 | } 99 | 100 | function burn(uint amt) public returns (bool) { 101 | _burn(msg.sender, amt); 102 | return true; 103 | } 104 | 105 | function _burn(address dst, uint amt) internal returns (bool) { 106 | require(_balance[dst] >= amt, "ERR_INSUFFICIENT"); 107 | _balance[dst] = sub(_balance[dst], amt); 108 | _totalSupply = sub(_totalSupply, amt); 109 | emit Transfer(dst, address(0), amt); 110 | return true; 111 | } 112 | 113 | function transfer(address dst, uint amt) external returns (bool) { 114 | _move(msg.sender, dst, amt); 115 | return true; 116 | } 117 | 118 | function transferFrom(address src, address dst, uint amt) external returns (bool) { 119 | require(msg.sender == src || amt <= _allowance[src][msg.sender], "ERR_BAD_CALLER"); 120 | _move(src, dst, amt); 121 | if (msg.sender != src && _allowance[src][msg.sender] != uint256(- 1)) { 122 | _allowance[src][msg.sender] = sub(_allowance[src][msg.sender], amt); 123 | emit Approval(msg.sender, dst, _allowance[src][msg.sender]); 124 | } 125 | return true; 126 | } 127 | 128 | function getBalance(address _token) external view returns (uint) { 129 | return IERC20(_token).balanceOf(address(this)); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /contracts/compositevaults/mock/TToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.12; 2 | 3 | contract TToken { 4 | 5 | string private _name; 6 | string private _symbol; 7 | uint8 private _decimals; 8 | 9 | uint internal _totalSupply; 10 | 11 | mapping(address => uint) private _balance; 12 | mapping(address => mapping(address => uint)) private _allowance; 13 | 14 | event Approval(address indexed src, address indexed dst, uint amt); 15 | event Transfer(address indexed src, address indexed dst, uint amt); 16 | 17 | // Math 18 | function add(uint a, uint b) internal pure returns (uint c) { 19 | require((c = a + b) >= a); 20 | } 21 | 22 | function sub(uint a, uint b) internal pure returns (uint c) { 23 | require((c = a - b) <= a); 24 | } 25 | 26 | constructor( 27 | string memory name, 28 | string memory symbol, 29 | uint8 decimals 30 | ) public { 31 | _name = name; 32 | _symbol = symbol; 33 | _decimals = decimals; 34 | } 35 | 36 | 37 | function name() public view returns (string memory) { 38 | return _name; 39 | } 40 | 41 | function symbol() public view returns (string memory) { 42 | return _symbol; 43 | } 44 | 45 | function decimals() public view returns (uint8) { 46 | return _decimals; 47 | } 48 | 49 | function _move(address src, address dst, uint amt) internal { 50 | require(_balance[src] >= amt, "ERR_INSUFFICIENT"); 51 | _balance[src] = sub(_balance[src], amt); 52 | _balance[dst] = add(_balance[dst], amt); 53 | emit Transfer(src, dst, amt); 54 | } 55 | 56 | function _push(address to, uint amt) internal { 57 | _move(address(this), to, amt); 58 | } 59 | 60 | function _pull(address from, uint amt) internal { 61 | _move(from, address(this), amt); 62 | } 63 | 64 | function _mint(address dst, uint amt) internal { 65 | _balance[dst] = add(_balance[dst], amt); 66 | _totalSupply = add(_totalSupply, amt); 67 | emit Transfer(address(0), dst, amt); 68 | } 69 | 70 | function allowance(address src, address dst) external view returns (uint) { 71 | return _allowance[src][dst]; 72 | } 73 | 74 | function balanceOf(address whom) external view returns (uint) { 75 | return _balance[whom]; 76 | } 77 | 78 | function totalSupply() public view returns (uint) { 79 | return _totalSupply; 80 | } 81 | 82 | function approve(address dst, uint amt) external returns (bool) { 83 | _allowance[msg.sender][dst] = amt; 84 | emit Approval(msg.sender, dst, amt); 85 | return true; 86 | } 87 | 88 | function faucet(uint256 amt) public returns (bool) { 89 | _mint(msg.sender, amt); 90 | return true; 91 | } 92 | 93 | function mintTo(address dst, uint amt) public returns (bool) { 94 | _mint(dst, amt); 95 | return true; 96 | } 97 | 98 | function burn(uint amt) public returns (bool) { 99 | _burn(msg.sender, amt); 100 | return true; 101 | } 102 | 103 | function _burn(address dst, uint amt) internal returns (bool) { 104 | require(_balance[dst] >= amt, "ERR_INSUFFICIENT"); 105 | _balance[dst] = sub(_balance[dst], amt); 106 | _totalSupply = sub(_totalSupply, amt); 107 | emit Transfer(dst, address(0), amt); 108 | return true; 109 | } 110 | 111 | function transfer(address dst, uint amt) external returns (bool) { 112 | _move(msg.sender, dst, amt); 113 | return true; 114 | } 115 | 116 | function transferFrom(address src, address dst, uint amt) external returns (bool) { 117 | require(msg.sender == src || amt <= _allowance[src][msg.sender], "ERR_BAD_CALLER"); 118 | _move(src, dst, amt); 119 | if (msg.sender != src && _allowance[src][msg.sender] != uint256(- 1)) { 120 | _allowance[src][msg.sender] = sub(_allowance[src][msg.sender], amt); 121 | emit Approval(msg.sender, dst, _allowance[src][msg.sender]); 122 | } 123 | return true; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /contracts/compositevaults/strategies/StrategyBalancerEthUsdc.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | import "@openzeppelin/contracts/math/SafeMath.sol"; 7 | import "@openzeppelin/contracts/utils/Address.sol"; 8 | import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 9 | 10 | import "../../interfaces/SushiMasterChef.sol"; 11 | 12 | import "./StrategyBase.sol"; 13 | 14 | /* 15 | 16 | A strategy must implement the following calls; 17 | 18 | - deposit() 19 | - withdraw(address) must exclude any tokens used in the yield - Controller role - withdraw should return to Controller 20 | - withdraw(uint) - Controller | Vault role - withdraw should always return to vault 21 | - withdrawAll() - Controller | Vault role - withdraw should always return to vault 22 | - balanceOf() 23 | 24 | Where possible, strategies must remain as immutable as possible, instead of updating variables, we update the contract by linking it in the controller 25 | 26 | */ 27 | 28 | contract StrategyBalancerEthUsdc is StrategyBase { 29 | uint public blocksToReleaseCompound = 7 * 6500; // 7 days to release all the new compounding amount 30 | 31 | // lpPair = 0x8a649274E4d777FFC6851F13d23A86BBFA2f2Fbf (BPT ETH-USDC 50/50) 32 | // token0 = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 (USDC) 33 | // token1 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 (WETH) 34 | // farmingToken = 0xba100000625a3754423978a60c9317c58a424e3D (BAL) 35 | constructor(address _converter, address _farmingToken, address _weth, address _controller) public 36 | StrategyBase(_converter, _farmingToken, _weth, _controller) { 37 | } 38 | 39 | function getName() public override pure returns (string memory) { 40 | return "StrategyBalancerEthUsdc"; 41 | } 42 | 43 | function deposit() public override { 44 | // do nothing 45 | } 46 | 47 | function _withdrawSome(uint) internal override returns (uint) { 48 | return 0; 49 | } 50 | 51 | function _withdrawAll() internal override { 52 | // do nothing 53 | } 54 | 55 | function claimReward() public override { 56 | // do nothing 57 | } 58 | 59 | function _buyWantAndReinvest() internal override { 60 | uint256 _wethBal = IERC20(weth).balanceOf(address(this)); 61 | uint256 _wethToBuyToken0 = _wethBal.mul(495).div(1000); // we have Token1 (WETH) already, so use 49.5% balance to buy Token0 (USDC) 62 | _swapTokens(weth, token0, _wethToBuyToken0); 63 | uint _before = IERC20(lpPair).balanceOf(address(this)); 64 | _addLiquidity(); 65 | uint _after = IERC20(lpPair).balanceOf(address(this)); 66 | if (_after > 0) { 67 | if (_after > _before) { 68 | uint _compound = _after.sub(_before); 69 | vault.addNewCompound(_compound, blocksToReleaseCompound); 70 | } 71 | } 72 | } 73 | 74 | function balanceOfPool() public override view returns (uint) { 75 | return 0; 76 | } 77 | 78 | function claimable_tokens() external override view returns (uint) { 79 | return 0; 80 | } 81 | 82 | function setBlocksToReleaseCompound(uint _blocks) external onlyStrategist { 83 | blocksToReleaseCompound = _blocks; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /contracts/compositevaults/strategies/StrategySushiEthUsdc.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | import "@openzeppelin/contracts/math/SafeMath.sol"; 7 | import "@openzeppelin/contracts/utils/Address.sol"; 8 | import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 9 | 10 | import "../../interfaces/SushiMasterChef.sol"; 11 | 12 | import "./StrategyBase.sol"; 13 | 14 | /* 15 | 16 | A strategy must implement the following calls; 17 | 18 | - deposit() 19 | - withdraw(address) must exclude any tokens used in the yield - Controller role - withdraw should return to Controller 20 | - withdraw(uint) - Controller | Vault role - withdraw should always return to vault 21 | - withdrawAll() - Controller | Vault role - withdraw should always return to vault 22 | - balanceOf() 23 | 24 | Where possible, strategies must remain as immutable as possible, instead of updating variables, we update the contract by linking it in the controller 25 | 26 | */ 27 | 28 | contract StrategySushiEthUsdc is StrategyBase { 29 | uint public poolId = 1; 30 | 31 | uint public blocksToReleaseCompound = 1 * 6500; // 2 days to release all the new compounding amount 32 | 33 | address public farmingPool; 34 | 35 | // lpPair = 0x397FF1542f962076d0BFE58eA045FfA2d347ACa0 (SLP ETH-USDC) 36 | // token0 = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 (USDC) 37 | // token1 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 (WETH) 38 | // farmingToken = 0x6B3595068778DD592e39A122f4f5a5cF09C90fE2 (SUSHI) 39 | // farmingPool = 0xc2EdaD668740f1aA35E4D8f227fB8E17dcA888Cd (Sushiswap's MasterChef) 40 | constructor(address _converter, address _farmingToken, address _farmingPool, address _weth, address _controller) public 41 | StrategyBase(_converter, _farmingToken, _weth, _controller) { 42 | farmingPool = _farmingPool; 43 | IERC20(lpPair).safeApprove(address(farmingPool), type(uint256).max); 44 | } 45 | 46 | function getName() public override pure returns (string memory) { 47 | return "StrategySushiEthUsdc"; 48 | } 49 | 50 | function deposit() public override { 51 | uint _lpPairBal = IERC20(lpPair).balanceOf(address(this)); 52 | if (_lpPairBal > 0) { 53 | SushiMasterChef(farmingPool).deposit(poolId, _lpPairBal); 54 | } 55 | } 56 | 57 | function _withdrawSome(uint _amount) internal override returns (uint) { 58 | (uint _stakedAmount,) = SushiMasterChef(farmingPool).userInfo(poolId, address(this)); 59 | if (_amount > _stakedAmount) { 60 | _amount = _stakedAmount; 61 | } 62 | uint _before = IERC20(lpPair).balanceOf(address(this)); 63 | SushiMasterChef(farmingPool).withdraw(poolId, _amount); 64 | uint _after = IERC20(lpPair).balanceOf(address(this)); 65 | _amount = _after.sub(_before); 66 | 67 | return _amount; 68 | } 69 | 70 | function _withdrawAll() internal override { 71 | (uint _stakedAmount,) = SushiMasterChef(farmingPool).userInfo(poolId, address(this)); 72 | SushiMasterChef(farmingPool).withdraw(poolId, _stakedAmount); 73 | } 74 | 75 | function claimReward() public override { 76 | SushiMasterChef(farmingPool).withdraw(poolId, 0); 77 | } 78 | 79 | function _buyWantAndReinvest() internal override { 80 | uint256 _wethBal = IERC20(weth).balanceOf(address(this)); 81 | uint256 _wethToBuyToken0 = _wethBal.mul(495).div(1000); // we have Token1 (WETH) already, so use 49.5% balance to buy Token0 (USDC) 82 | _swapTokens(weth, token0, _wethToBuyToken0); 83 | uint _before = IERC20(lpPair).balanceOf(address(this)); 84 | _addLiquidity(); 85 | uint _after = IERC20(lpPair).balanceOf(address(this)); 86 | if (_after > 0) { 87 | if (_after > _before) { 88 | uint _compound = _after.sub(_before); 89 | vault.addNewCompound(_compound, blocksToReleaseCompound); 90 | } 91 | deposit(); 92 | } 93 | } 94 | 95 | function balanceOfPool() public override view returns (uint) { 96 | (uint amount,) = SushiMasterChef(farmingPool).userInfo(poolId, address(this)); 97 | return amount; 98 | } 99 | 100 | function claimable_tokens() external override view returns (uint) { 101 | return SushiMasterChef(farmingPool).pendingSushi(poolId, address(this)); 102 | } 103 | 104 | function setBlocksToReleaseCompound(uint _blocks) external onlyStrategist { 105 | blocksToReleaseCompound = _blocks; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /contracts/compositevaults/vaults/CompositeVaultBptEthUsdc.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "./CompositeVaultBase.sol"; 6 | 7 | contract CompositeVaultBptEthUsdc is CompositeVaultBase { 8 | function _getName() internal override view returns (string memory) { 9 | return "CompositeVault:BptEthUsdc"; 10 | } 11 | 12 | function _getSymbol() internal override view returns (string memory) { 13 | return "cvETH-USDC:BPT"; 14 | } 15 | 16 | event ExecuteTransaction(address indexed target, uint value, string signature, bytes data); 17 | 18 | /** 19 | * @dev This is from Timelock contract, the governance should be a Timelock contract before calling this emergency function 20 | * Periodically we will need this to claim BAL (for idle fund stay in Vault and not transferred to Strategy 21 | */ 22 | function executeTransaction(address target, uint value, string memory signature, bytes memory data) public returns (bytes memory) { 23 | require(msg.sender == governance, "!governance"); 24 | 25 | bytes memory callData; 26 | 27 | if (bytes(signature).length == 0) { 28 | callData = data; 29 | } else { 30 | callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data); 31 | } 32 | 33 | // solium-disable-next-line security/no-call-value 34 | (bool success, bytes memory returnData) = target.call{value : value}(callData); 35 | require(success, string(abi.encodePacked(_getName(), "::executeTransaction: Transaction execution reverted."))); 36 | 37 | emit ExecuteTransaction(target, value, signature, data); 38 | 39 | return returnData; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /contracts/compositevaults/vaults/CompositeVaultSlpEthUsdc.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "./CompositeVaultBase.sol"; 6 | 7 | contract CompositeVaultSlpEthUsdc is CompositeVaultBase { 8 | function _getName() internal override view returns (string memory) { 9 | return "CompositeVault:SlpEthUsdc"; 10 | } 11 | 12 | function _getSymbol() internal override view returns (string memory) { 13 | return "cvETH-USDC:SLP"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /contracts/governance-vault/IController.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IController { 6 | function vaults(address) external view returns (address); 7 | function rewards() external view returns (address); 8 | function want(address) external view returns (address); 9 | function balanceOf(address) external view returns (uint); 10 | function withdraw(address, uint) external; 11 | function maxAcceptAmount(address) external view returns (uint256); 12 | function earn(address, uint) external; 13 | 14 | function getStrategyCount(address _vault) external view returns(uint256); 15 | function depositAvailable(address _vault) external view returns(bool); 16 | function harvestAllStrategies(address _vault) external; 17 | function harvestStrategy(address _vault, address _strategy) external; 18 | } 19 | -------------------------------------------------------------------------------- /contracts/governance-vault/mock/UniswapRouterMock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | interface IERC20 { 4 | function totalSupply() external view returns (uint256); 5 | function balanceOf(address account) external view returns (uint256); 6 | function transfer(address recipient, uint256 amount) external returns (bool); 7 | function allowance(address owner, address spender) external view returns (uint256); 8 | function decimals() external view returns (uint256); 9 | function name() external view returns (string memory); 10 | function approve(address spender, uint256 amount) external returns (bool); 11 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 12 | function burn(uint amount) external; 13 | 14 | event Transfer(address indexed from, address indexed to, uint256 value); 15 | event Approval(address indexed owner, address indexed spender, uint256 value); 16 | } 17 | 18 | library SafeMath { 19 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 20 | uint256 c = a + b; 21 | require(c >= a, "SafeMath: addition overflow"); 22 | 23 | return c; 24 | } 25 | 26 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 27 | return sub(a, b, "SafeMath: subtraction overflow"); 28 | } 29 | 30 | function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 31 | require(b <= a, errorMessage); 32 | uint256 c = a - b; 33 | 34 | return c; 35 | } 36 | 37 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 38 | if (a == 0) { 39 | return 0; 40 | } 41 | 42 | uint256 c = a * b; 43 | require(c / a == b, "SafeMath: multiplication overflow"); 44 | 45 | return c; 46 | } 47 | 48 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 49 | return div(a, b, "SafeMath: division by zero"); 50 | } 51 | 52 | function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 53 | // Solidity only automatically asserts when dividing by 0 54 | require(b > 0, errorMessage); 55 | uint256 c = a / b; 56 | 57 | return c; 58 | } 59 | 60 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 61 | return mod(a, b, "SafeMath: modulo by zero"); 62 | } 63 | 64 | function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 65 | require(b != 0, errorMessage); 66 | return a % b; 67 | } 68 | } 69 | 70 | library Address { 71 | function isContract(address account) internal view returns (bool) { 72 | bytes32 codehash; 73 | bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; 74 | // solhint-disable-next-line no-inline-assembly 75 | assembly {codehash := extcodehash(account)} 76 | return (codehash != 0x0 && codehash != accountHash); 77 | } 78 | 79 | function toPayable(address account) internal pure returns (address payable) { 80 | return address(uint160(account)); 81 | } 82 | 83 | function sendValue(address payable recipient, uint256 amount) internal { 84 | require(address(this).balance >= amount, "Address: insufficient balance"); 85 | 86 | // solhint-disable-next-line avoid-call-value 87 | (bool success,) = recipient.call.value(amount)(""); 88 | require(success, "Address: unable to send value, recipient may have reverted"); 89 | } 90 | } 91 | 92 | library SafeERC20 { 93 | using SafeMath for uint256; 94 | using Address for address; 95 | 96 | function safeTransfer(IERC20 token, address to, uint256 value) internal { 97 | callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 98 | } 99 | 100 | function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 101 | callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 102 | } 103 | 104 | function safeApprove(IERC20 token, address spender, uint256 value) internal { 105 | require((value == 0) || (token.allowance(address(this), spender) == 0), 106 | "SafeERC20: approve from non-zero to non-zero allowance" 107 | ); 108 | callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 109 | } 110 | 111 | function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 112 | uint256 newAllowance = token.allowance(address(this), spender).add(value); 113 | callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 114 | } 115 | 116 | function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 117 | uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 118 | callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 119 | } 120 | 121 | function callOptionalReturn(IERC20 token, bytes memory data) private { 122 | require(address(token).isContract(), "SafeERC20: call to non-contract"); 123 | 124 | // solhint-disable-next-line avoid-low-level-calls 125 | (bool success, bytes memory returndata) = address(token).call(data); 126 | require(success, "SafeERC20: low-level call failed"); 127 | 128 | if (returndata.length > 0) {// Return data is optional 129 | // solhint-disable-next-line max-line-length 130 | require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 131 | } 132 | } 133 | } 134 | 135 | interface IUniswapRouter { 136 | function swapExactTokensForTokens( 137 | uint256 amountIn, 138 | uint256 amountOutMin, 139 | address[] calldata path, 140 | address to, 141 | uint256 deadline 142 | ) external returns (uint256[] memory amounts); 143 | } 144 | 145 | contract UniswapRouterMock is IUniswapRouter { 146 | using SafeERC20 for IERC20; 147 | using Address for address; 148 | using SafeMath for uint256; 149 | 150 | function swapExactTokensForTokens( 151 | uint256 amountIn, 152 | uint256, 153 | address[] calldata path, 154 | address to, 155 | uint256 156 | ) external returns (uint256[] memory) { 157 | uint256 amountOut = amountIn.div(10); // assume 1 FARM -> 10 YFV 158 | IERC20 inputToken = IERC20(path[0]); 159 | IERC20 outputToken = IERC20(path[path.length - 1]); 160 | inputToken.safeTransferFrom(msg.sender, address(this), amountIn); 161 | outputToken.safeTransfer(to, amountOut); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /contracts/interfaces/Aave.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.6.2; 3 | 4 | interface Aave { 5 | function borrow(address _reserve, uint _amount, uint _interestRateModel, uint16 _referralCode) external; 6 | function setUserUseReserveAsCollateral(address _reserve, bool _useAsCollateral) external; 7 | function repay(address _reserve, uint _amount, address payable _onBehalfOf) external payable; 8 | function getUserAccountData(address _user) 9 | external 10 | view 11 | returns ( 12 | uint totalLiquidityETH, 13 | uint totalCollateralETH, 14 | uint totalBorrowsETH, 15 | uint totalFeesETH, 16 | uint availableBorrowsETH, 17 | uint currentLiquidationThreshold, 18 | uint ltv, 19 | uint healthFactor 20 | ); 21 | function getUserReserveData(address _reserve, address _user) 22 | external 23 | view 24 | returns ( 25 | uint currentATokenBalance, 26 | uint currentBorrowBalance, 27 | uint principalBorrowBalance, 28 | uint borrowRateMode, 29 | uint borrowRate, 30 | uint liquidityRate, 31 | uint originationFee, 32 | uint variableBorrowIndex, 33 | uint lastUpdateTimestamp, 34 | bool usageAsCollateralEnabled 35 | ); 36 | } 37 | 38 | interface LendingPoolAddressesProvider { 39 | function getLendingPool() external view returns (address); 40 | function getLendingPoolCore() external view returns (address); 41 | function getPriceOracle() external view returns (address); 42 | } 43 | 44 | interface AaveToken { 45 | function underlyingAssetAddress() external view returns (address); 46 | } 47 | 48 | interface Oracle { 49 | function getAssetPrice(address reserve) external view returns (uint); 50 | function latestAnswer() external view returns (uint); 51 | } 52 | -------------------------------------------------------------------------------- /contracts/interfaces/Balancer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.6.2; 3 | 4 | interface Balancer { 5 | function balanceOf(address account) external view returns (uint256); 6 | function transfer(address recipient, uint256 amount) external returns (bool); 7 | function joinPool(uint poolAmountOut, uint[] calldata maxAmountsIn) external; 8 | function exitPool(uint poolAmountIn, uint[] calldata minAmountsOut) external; 9 | function swapExactAmountIn( 10 | address tokenIn, 11 | uint tokenAmountIn, 12 | address tokenOut, 13 | uint minAmountOut, 14 | uint maxPrice 15 | ) external returns (uint tokenAmountOut, uint spotPriceAfter); 16 | function swapExactAmountOut( 17 | address tokenIn, 18 | uint maxAmountIn, 19 | address tokenOut, 20 | uint tokenAmountOut, 21 | uint maxPrice 22 | ) external returns (uint tokenAmountIn, uint spotPriceAfter); 23 | function joinswapExternAmountIn(address tokenIn, uint tokenAmountIn, uint minPoolAmountOut) external returns (uint poolAmountOut); 24 | function exitswapPoolAmountIn(address tokenOut, uint poolAmountIn, uint minAmountOut) external returns (uint tokenAmountOut); 25 | function getBalance(address token) external view returns (uint); 26 | function totalSupply() external view returns (uint256); 27 | function getTotalDenormalizedWeight() external view returns (uint); 28 | function getNormalizedWeight(address token) external view returns (uint); 29 | function getDenormalizedWeight(address token) external view returns (uint); 30 | } 31 | -------------------------------------------------------------------------------- /contracts/interfaces/Converter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.6.2; 3 | 4 | interface Converter { 5 | function convert(address) external returns (uint); 6 | } 7 | -------------------------------------------------------------------------------- /contracts/interfaces/Curve.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.6.2; 3 | 4 | interface ICurveFi { 5 | function get_virtual_price() external view returns (uint); 6 | function add_liquidity( 7 | uint256[4] calldata amounts, 8 | uint256 min_mint_amount 9 | ) external; 10 | function remove_liquidity_imbalance( 11 | uint256[4] calldata amounts, 12 | uint256 max_burn_amount 13 | ) external; 14 | function remove_liquidity( 15 | uint256 _amount, 16 | uint256[4] calldata amounts 17 | ) external; 18 | function exchange( 19 | int128 from, int128 to, uint256 _from_amount, uint256 _min_to_amount 20 | ) external; 21 | } 22 | -------------------------------------------------------------------------------- /contracts/interfaces/DForce.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.6.2; 3 | 4 | interface dRewards { 5 | function withdraw(uint) external; 6 | function getReward() external; 7 | function stake(uint) external; 8 | function balanceOf(address) external view returns (uint); 9 | function exit() external; 10 | } 11 | 12 | interface dERC20 { 13 | function mint(address, uint256) external; 14 | function redeem(address, uint) external; 15 | function getTokenBalance(address) external view returns (uint); 16 | function getExchangeRate() external view returns (uint); 17 | } 18 | -------------------------------------------------------------------------------- /contracts/interfaces/Gauge.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.6.2; 3 | 4 | interface Gauge { 5 | function deposit(uint) external; 6 | function balanceOf(address) external view returns (uint); 7 | function withdraw(uint) external; 8 | function claimable_tokens(address) external view returns (uint); 9 | } 10 | 11 | interface Mintr { 12 | function mint(address) external; 13 | } 14 | -------------------------------------------------------------------------------- /contracts/interfaces/IUniswapV2Factory.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | interface IUniswapV2Factory { 4 | event PairCreated(address indexed token0, address indexed token1, address pair, uint); 5 | 6 | function feeTo() external view returns (address); 7 | function feeToSetter() external view returns (address); 8 | 9 | function getPair(address tokenA, address tokenB) external view returns (address pair); 10 | function allPairs(uint) external view returns (address pair); 11 | function allPairsLength() external view returns (uint); 12 | 13 | function createPair(address tokenA, address tokenB) external returns (address pair); 14 | 15 | function setFeeTo(address) external; 16 | function setFeeToSetter(address) external; 17 | } 18 | -------------------------------------------------------------------------------- /contracts/interfaces/IUniswapV2Pair.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | interface IUniswapV2Pair { 4 | event Approval(address indexed owner, address indexed spender, uint value); 5 | event Transfer(address indexed from, address indexed to, uint value); 6 | 7 | function name() external pure returns (string memory); 8 | function symbol() external pure returns (string memory); 9 | function decimals() external pure returns (uint8); 10 | function totalSupply() external view returns (uint); 11 | function balanceOf(address owner) external view returns (uint); 12 | function allowance(address owner, address spender) external view returns (uint); 13 | 14 | function approve(address spender, uint value) external returns (bool); 15 | function transfer(address to, uint value) external returns (bool); 16 | function transferFrom(address from, address to, uint value) external returns (bool); 17 | 18 | function DOMAIN_SEPARATOR() external view returns (bytes32); 19 | function PERMIT_TYPEHASH() external pure returns (bytes32); 20 | function nonces(address owner) external view returns (uint); 21 | 22 | function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; 23 | 24 | event Mint(address indexed sender, uint amount0, uint amount1); 25 | event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); 26 | event Swap( 27 | address indexed sender, 28 | uint amount0In, 29 | uint amount1In, 30 | uint amount0Out, 31 | uint amount1Out, 32 | address indexed to 33 | ); 34 | event Sync(uint112 reserve0, uint112 reserve1); 35 | 36 | function MINIMUM_LIQUIDITY() external pure returns (uint); 37 | function factory() external view returns (address); 38 | function token0() external view returns (address); 39 | function token1() external view returns (address); 40 | function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); 41 | function price0CumulativeLast() external view returns (uint); 42 | function price1CumulativeLast() external view returns (uint); 43 | function kLast() external view returns (uint); 44 | 45 | function mint(address to) external returns (uint liquidity); 46 | function burn(address to) external returns (uint amount0, uint amount1); 47 | function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; 48 | function skim(address to) external; 49 | function sync() external; 50 | 51 | function initialize(address, address) external; 52 | } 53 | -------------------------------------------------------------------------------- /contracts/interfaces/IUniswapV2Router.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.6.2; 3 | 4 | interface IUniswapV2Router { 5 | function factory() external pure returns (address); 6 | 7 | function WETH() external pure returns (address); 8 | 9 | function addLiquidity( 10 | address tokenA, 11 | address tokenB, 12 | uint amountADesired, 13 | uint amountBDesired, 14 | uint amountAMin, 15 | uint amountBMin, 16 | address to, 17 | uint deadline 18 | ) external returns (uint amountA, uint amountB, uint liquidity); 19 | 20 | function addLiquidityETH( 21 | address token, 22 | uint amountTokenDesired, 23 | uint amountTokenMin, 24 | uint amountETHMin, 25 | address to, 26 | uint deadline 27 | ) external payable returns (uint amountToken, uint amountETH, uint liquidity); 28 | 29 | function removeLiquidity( 30 | address tokenA, 31 | address tokenB, 32 | uint liquidity, 33 | uint amountAMin, 34 | uint amountBMin, 35 | address to, 36 | uint deadline 37 | ) external returns (uint amountA, uint amountB); 38 | 39 | function removeLiquidityETH( 40 | address token, 41 | uint liquidity, 42 | uint amountTokenMin, 43 | uint amountETHMin, 44 | address to, 45 | uint deadline 46 | ) external returns (uint amountToken, uint amountETH); 47 | 48 | function removeLiquidityWithPermit( 49 | address tokenA, 50 | address tokenB, 51 | uint liquidity, 52 | uint amountAMin, 53 | uint amountBMin, 54 | address to, 55 | uint deadline, 56 | bool approveMax, uint8 v, bytes32 r, bytes32 s 57 | ) external returns (uint amountA, uint amountB); 58 | 59 | function removeLiquidityETHWithPermit( 60 | address token, 61 | uint liquidity, 62 | uint amountTokenMin, 63 | uint amountETHMin, 64 | address to, 65 | uint deadline, 66 | bool approveMax, uint8 v, bytes32 r, bytes32 s 67 | ) external returns (uint amountToken, uint amountETH); 68 | 69 | function swapExactTokensForTokens( 70 | uint amountIn, 71 | uint amountOutMin, 72 | address[] calldata path, 73 | address to, 74 | uint deadline 75 | ) external returns (uint[] memory amounts); 76 | 77 | function swapTokensForExactTokens( 78 | uint amountOut, 79 | uint amountInMax, 80 | address[] calldata path, 81 | address to, 82 | uint deadline 83 | ) external returns (uint[] memory amounts); 84 | 85 | function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) 86 | external 87 | payable 88 | returns (uint[] memory amounts); 89 | 90 | function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) 91 | external 92 | returns (uint[] memory amounts); 93 | 94 | function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) 95 | external 96 | returns (uint[] memory amounts); 97 | 98 | function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) external payable 99 | returns (uint[] memory amounts); 100 | 101 | function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); 102 | 103 | function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); 104 | 105 | function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); 106 | 107 | function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); 108 | 109 | function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); 110 | 111 | function removeLiquidityETHSupportingFeeOnTransferTokens( 112 | address token, 113 | uint liquidity, 114 | uint amountTokenMin, 115 | uint amountETHMin, 116 | address to, 117 | uint deadline 118 | ) external returns (uint amountETH); 119 | 120 | function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( 121 | address token, 122 | uint liquidity, 123 | uint amountTokenMin, 124 | uint amountETHMin, 125 | address to, 126 | uint deadline, 127 | bool approveMax, uint8 v, bytes32 r, bytes32 s 128 | ) external returns (uint amountETH); 129 | 130 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 131 | uint amountIn, 132 | uint amountOutMin, 133 | address[] calldata path, 134 | address to, 135 | uint deadline 136 | ) external; 137 | 138 | function swapExactETHForTokensSupportingFeeOnTransferTokens( 139 | uint amountOutMin, 140 | address[] calldata path, 141 | address to, 142 | uint deadline 143 | ) external payable; 144 | 145 | function swapExactTokensForETHSupportingFeeOnTransferTokens( 146 | uint amountIn, 147 | uint amountOutMin, 148 | address[] calldata path, 149 | address to, 150 | uint deadline 151 | ) external; 152 | } 153 | -------------------------------------------------------------------------------- /contracts/interfaces/MStable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.6.2; 3 | 4 | interface MStable { 5 | function mint(address, uint) external; 6 | function redeem(address, uint) external; 7 | } 8 | 9 | interface mSavings { 10 | function depositSavings(uint) external; 11 | function creditBalances(address) external view returns (uint); 12 | function redeem(uint) external; 13 | function exchangeRate() external view returns (uint); 14 | } 15 | -------------------------------------------------------------------------------- /contracts/interfaces/OneSplitAudit.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.6.2; 3 | 4 | interface OneSplitAudit { 5 | function swap( 6 | address fromToken, 7 | address destToken, 8 | uint256 amount, 9 | uint256 minReturn, 10 | uint256[] calldata distribution, 11 | uint256 flags 12 | ) 13 | external 14 | payable 15 | returns(uint256 returnAmount); 16 | 17 | function getExpectedReturn( 18 | address fromToken, 19 | address destToken, 20 | uint256 amount, 21 | uint256 parts, 22 | uint256 flags // See constants in IOneSplit.sol 23 | ) 24 | external 25 | view 26 | returns( 27 | uint256 returnAmount, 28 | uint256[] memory distribution 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /contracts/interfaces/PickleJar.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.2; 4 | 5 | interface PickleJar { 6 | function balanceOf(address account) external view returns (uint); 7 | function balance() external view returns (uint); 8 | function available() external view returns (uint); 9 | function depositAll() external; 10 | function deposit(uint _amount) external; 11 | function withdrawAll() external; 12 | function withdraw(uint _shares) external; 13 | function getRatio() external view returns (uint); 14 | } 15 | -------------------------------------------------------------------------------- /contracts/interfaces/PickleMasterChef.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.2; 4 | 5 | interface PickleMasterChef { 6 | function deposit(uint _poolId, uint _amount) external; 7 | function withdraw(uint _poolId, uint _amount) external; 8 | function pendingPickle(uint _pid, address _user) external view returns (uint); 9 | function userInfo(uint _pid, address _user) external view returns (uint amount, uint rewardDebt); 10 | function emergencyWithdraw(uint _pid) external; 11 | } 12 | -------------------------------------------------------------------------------- /contracts/interfaces/SushiMasterChef.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface SushiMasterChef { 6 | function deposit(uint _poolId, uint _amount) external; 7 | function withdraw(uint _poolId, uint _amount) external; 8 | function pendingSushi(uint _pid, address _user) external view returns (uint); 9 | function userInfo(uint _pid, address _user) external view returns (uint amount, uint rewardDebt); 10 | function emergencyWithdraw(uint _pid) external; 11 | } 12 | -------------------------------------------------------------------------------- /contracts/interfaces/ValueMinorPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface ValueMinorPool { 6 | function depositOnBehalf(address farmer, uint256 _pid, uint256 _amount, address _referrer) external; 7 | function withdrawOnBehalf(address farmer, uint256 _pid, uint256 _amount) external; 8 | function pendingValue(uint256 _pid, address _user) public view returns (uint256); 9 | function userInfo(uint _pid, address _user) external view returns (uint amount, uint rewardDebt, uint accumulatedStakingPower); 10 | function emergencyWithdraw(uint _pid) external; 11 | } 12 | -------------------------------------------------------------------------------- /contracts/interfaces/Yfii.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.6.2; 3 | 4 | interface Yfii { 5 | function withdraw(uint) external; 6 | function getReward() external; 7 | function stake(uint) external; 8 | function balanceOf(address) external view returns (uint); 9 | function exit() external; 10 | } 11 | -------------------------------------------------------------------------------- /contracts/libraries/Math.sol: -------------------------------------------------------------------------------- 1 | pragma solidity =0.6.12; 2 | 3 | // a library for performing various math operations 4 | 5 | library Math { 6 | function min(uint x, uint y) internal pure returns (uint z) { 7 | z = x < y ? x : y; 8 | } 9 | 10 | // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) 11 | function sqrt(uint y) internal pure returns (uint z) { 12 | if (y > 3) { 13 | z = y; 14 | uint x = y / 2 + 1; 15 | while (x < z) { 16 | z = x; 17 | x = (y / x + x) / 2; 18 | } 19 | } else if (y != 0) { 20 | z = 1; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /contracts/multivaults/IMultiVaultController.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IMultiVaultController { 6 | function vault() external view returns (address); 7 | 8 | function wantQuota(address _want) external view returns (uint); 9 | function wantStrategyLength(address _want) external view returns (uint); 10 | function wantStrategyBalance(address _want) external view returns (uint); 11 | 12 | function getStrategyCount() external view returns(uint); 13 | function strategies(address _want, uint _stratId) external view returns (address _strategy, uint _quota, uint _percent); 14 | function getBestStrategy(address _want) external view returns (address _strategy); 15 | 16 | function basedWant() external view returns (address); 17 | function want() external view returns (address); 18 | function wantLength() external view returns (uint); 19 | 20 | function balanceOf(address _want, bool _sell) external view returns (uint); 21 | function withdraw_fee(address _want, uint _amount) external view returns (uint); // eg. 3CRV => pJar: 0.5% (50/10000) 22 | function investDisabled(address _want) external view returns (bool); 23 | 24 | function withdraw(address _want, uint) external returns (uint _withdrawFee); 25 | function earn(address _token, uint _amount) external; 26 | 27 | function harvestStrategy(address _strategy) external; 28 | function harvestWant(address _want) external; 29 | function harvestAllStrategies() external; 30 | } 31 | -------------------------------------------------------------------------------- /contracts/multivaults/IMultiVaultConverter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IMultiVaultConverter { 6 | function token() external returns (address); 7 | function get_virtual_price() external view returns (uint); 8 | 9 | function convert_rate(address _input, address _output, uint _inputAmount) external view returns (uint _outputAmount); 10 | function calc_token_amount_deposit(uint[] calldata _amounts) external view returns (uint _shareAmount); 11 | function calc_token_amount_withdraw(uint _shares, address _output) external view returns (uint _outputAmount); 12 | 13 | function convert(address _input, address _output, uint _inputAmount) external returns (uint _outputAmount); 14 | function convertAll(uint[] calldata _amounts) external returns (uint _outputAmount); 15 | } 16 | -------------------------------------------------------------------------------- /contracts/multivaults/IMultiVaultStrategy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IMultiVaultStrategy { 6 | function want() external view returns (address); 7 | function deposit() external; 8 | function withdraw(address _asset) external; 9 | function withdraw(uint _amount) external returns (uint); 10 | function withdrawToController(uint _amount) external; 11 | function skim() external; 12 | function harvest(address _mergedStrategy) external; 13 | function withdrawAll() external returns (uint); 14 | function balanceOf() external view returns (uint); 15 | function withdrawFee(uint) external view returns (uint); // pJar: 0.5% (50/10000) 16 | } 17 | -------------------------------------------------------------------------------- /contracts/multivaults/IShareConverter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IShareConverter { 6 | function convert_shares_rate(address _input, address _output, uint _inputAmount) external view returns (uint _outputAmount); 7 | 8 | function convert_shares(address _input, address _output, uint _inputAmount) external returns (uint _outputAmount); 9 | } 10 | -------------------------------------------------------------------------------- /contracts/multivaults/IValueMultiVault.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IValueMultiVault { 6 | function cap() external view returns (uint); 7 | function getConverter(address _want) external view returns (address); 8 | function getVaultMaster() external view returns (address); 9 | function balance() external view returns (uint); 10 | function token() external view returns (address); 11 | function available(address _want) external view returns (uint); 12 | function accept(address _input) external view returns (bool); 13 | 14 | function claimInsurance() external; 15 | function earn(address _want) external; 16 | function harvest(address reserve, uint amount) external; 17 | 18 | function withdraw_fee(uint _shares) external view returns (uint); 19 | function calc_token_amount_deposit(uint[] calldata _amounts) external view returns (uint); 20 | function calc_token_amount_withdraw(uint _shares, address _output) external view returns (uint); 21 | function convert_rate(address _input, uint _amount) external view returns (uint); 22 | function getPricePerFullShare() external view returns (uint); 23 | function get_virtual_price() external view returns (uint); // average dollar value of vault share token 24 | 25 | function deposit(address _input, uint _amount, uint _min_mint_amount) external returns (uint _mint_amount); 26 | function depositFor(address _account, address _to, address _input, uint _amount, uint _min_mint_amount) external returns (uint _mint_amount); 27 | function depositAll(uint[] calldata _amounts, uint _min_mint_amount) external returns (uint _mint_amount); 28 | function depositAllFor(address _account, address _to, uint[] calldata _amounts, uint _min_mint_amount) external returns (uint _mint_amount); 29 | function withdraw(uint _shares, address _output, uint _min_output_amount) external returns (uint); 30 | function withdrawFor(address _account, uint _shares, address _output, uint _min_output_amount) external returns (uint _output_amount); 31 | 32 | function harvestStrategy(address _strategy) external; 33 | function harvestWant(address _want) external; 34 | function harvestAllStrategies() external; 35 | } 36 | -------------------------------------------------------------------------------- /contracts/multivaults/IValueVaultMaster.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IValueVaultMaster { 6 | function bank(address) view external returns (address); 7 | function isVault(address) view external returns (bool); 8 | function isController(address) view external returns (bool); 9 | function isStrategy(address) view external returns (bool); 10 | 11 | function slippage(address) view external returns (uint); 12 | function convertSlippage(address _input, address _output) view external returns (uint); 13 | 14 | function valueToken() view external returns (address); 15 | function govVault() view external returns (address); 16 | function insuranceFund() view external returns (address); 17 | function performanceReward() view external returns (address); 18 | 19 | function govVaultProfitShareFee() view external returns (uint); 20 | function gasFee() view external returns (uint); 21 | function insuranceFee() view external returns (uint); 22 | function withdrawalProtectionFee() view external returns (uint); 23 | } 24 | -------------------------------------------------------------------------------- /contracts/multivaults/ValueMultiVaultMaster.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IERC20 { 6 | function transfer(address recipient, uint256 amount) external returns (bool); 7 | } 8 | 9 | contract ValueMultiVaultMaster { 10 | address public governance; 11 | 12 | address public valueToken = address(0x49E833337ECe7aFE375e44F4E3e8481029218E5c); 13 | 14 | address public govVault = address(0xceC03a960Ea678A2B6EA350fe0DbD1807B22D875); // 14.0% profit from Value Vaults 15 | address public insuranceFund = 0xb7b2Ea8A1198368f950834875047aA7294A2bDAa; // set to Governance Multisig at start 16 | address public performanceReward = 0x7Be4D5A99c903C437EC77A20CB6d0688cBB73c7f; // set to deploy wallet at start 17 | 18 | uint256 public govVaultProfitShareFee = 1400; // 14.0% | VIP-7 (https://yfv.finance/vip-vote/vip_7) 19 | uint256 public gasFee = 100; // 1.0% at start and can be set by governance decision 20 | uint256 public insuranceFee = 0; // % of deposits go into an insurance fund (or auto-compounding if called by controller) in-case of negative profits to protect withdrawals 21 | uint256 public withdrawalProtectionFee = 10; // % of withdrawal go back to vault (for auto-compounding) to protect withdrawals 22 | 23 | mapping(address => address) public bank; 24 | mapping(address => bool) public isVault; 25 | mapping(address => bool) public isController; 26 | mapping(address => bool) public isStrategy; 27 | 28 | mapping(address => uint) public slippage; // over 10000 29 | 30 | constructor(address _valueToken) public { 31 | valueToken = _valueToken; 32 | governance = msg.sender; 33 | } 34 | 35 | function setGovernance(address _governance) external { 36 | require(msg.sender == governance, "!governance"); 37 | governance = _governance; 38 | } 39 | 40 | function setBank(address _vault, address _bank) external { 41 | require(msg.sender == governance, "!governance"); 42 | bank[_vault] = _bank; 43 | } 44 | 45 | function addVault(address _vault) external { 46 | require(msg.sender == governance, "!governance"); 47 | isVault[_vault] = true; 48 | } 49 | 50 | function removeVault(address _vault) external { 51 | require(msg.sender == governance, "!governance"); 52 | isVault[_vault] = false; 53 | } 54 | 55 | function addController(address _controller) external { 56 | require(msg.sender == governance, "!governance"); 57 | isController[_controller] = true; 58 | } 59 | 60 | function removeController(address _controller) external { 61 | require(msg.sender == governance, "!governance"); 62 | isController[_controller] = true; 63 | } 64 | 65 | function addStrategy(address _strategy) external { 66 | require(msg.sender == governance, "!governance"); 67 | isStrategy[_strategy] = true; 68 | } 69 | 70 | function removeStrategy(address _strategy) external { 71 | require(msg.sender == governance, "!governance"); 72 | isStrategy[_strategy] = false; 73 | } 74 | 75 | function setGovVault(address _govVault) public { 76 | require(msg.sender == governance, "!governance"); 77 | govVault = _govVault; 78 | } 79 | 80 | function setInsuranceFund(address _insuranceFund) public { 81 | require(msg.sender == governance, "!governance"); 82 | insuranceFund = _insuranceFund; 83 | } 84 | 85 | function setPerformanceReward(address _performanceReward) public{ 86 | require(msg.sender == governance, "!governance"); 87 | performanceReward = _performanceReward; 88 | } 89 | 90 | function setGovVaultProfitShareFee(uint256 _govVaultProfitShareFee) public { 91 | require(msg.sender == governance, "!governance"); 92 | govVaultProfitShareFee = _govVaultProfitShareFee; 93 | } 94 | 95 | function setGasFee(uint256 _gasFee) public { 96 | require(msg.sender == governance, "!governance"); 97 | gasFee = _gasFee; 98 | } 99 | 100 | function setInsuranceFee(uint256 _insuranceFee) public { 101 | require(msg.sender == governance, "!governance"); 102 | require(_insuranceFee <= 100, "_insuranceFee over 1%"); 103 | insuranceFee = _insuranceFee; 104 | } 105 | 106 | function setWithdrawalProtectionFee(uint256 _withdrawalProtectionFee) public { 107 | require(msg.sender == governance, "!governance"); 108 | require(_withdrawalProtectionFee <= 100, "_withdrawalProtectionFee over 1%"); 109 | withdrawalProtectionFee = _withdrawalProtectionFee; 110 | } 111 | 112 | function setSlippage(address _token, uint _slippage) external { 113 | require(msg.sender == governance, "!governance"); 114 | require(_slippage <= 1000, ">10%"); 115 | slippage[_token] = _slippage; 116 | } 117 | 118 | function convertSlippage(address _input, address _output) view external returns (uint) { 119 | uint _is = slippage[_input]; 120 | uint _os = slippage[_output]; 121 | return (_is > _os) ? _is : _os; 122 | } 123 | 124 | /** 125 | * This function allows governance to take unsupported tokens out of the contract. 126 | * This is in an effort to make someone whole, should they seriously mess up. 127 | * There is no guarantee governance will vote to return these. 128 | * It also allows for removal of airdropped tokens. 129 | */ 130 | function governanceRecoverUnsupported(IERC20 _token, uint256 amount, address to) external { 131 | require(msg.sender == governance, "!governance"); 132 | _token.transfer(to, amount); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /contracts/multivaults/mock/MockCERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 6 | import "@openzeppelin/contracts/math/SafeMath.sol"; 7 | import "./TToken.sol"; 8 | interface IDecimals { 9 | function decimals() external view returns (uint8); 10 | } 11 | 12 | contract MockWrapCERC20 is TToken { 13 | using SafeMath for uint256; 14 | address public underlyingToken; 15 | uint256 public underlyingDecimals; 16 | constructor( 17 | string memory name, 18 | string memory symbol, 19 | address _underlyingToken 20 | ) public TToken(name, symbol, 8) { 21 | underlyingToken = _underlyingToken; 22 | underlyingDecimals = IDecimals(_underlyingToken).decimals(); 23 | } 24 | 25 | function exchangeRateCurrent() external pure returns (uint) { 26 | return 10 ** 18; 27 | } 28 | 29 | function exchangeRateStored() external pure returns (uint) { 30 | return 10 ** 18; 31 | } 32 | 33 | function supplyRatePerBlock() external pure returns (uint) { 34 | return 1; 35 | } 36 | function accrualBlockNumber() external pure returns (uint) { 37 | return 1; 38 | } 39 | function mint(uint256 _amount) public returns (uint) { 40 | IERC20(underlyingToken).transferFrom(msg.sender, address(this), _amount); 41 | _mint(msg.sender, _amount);//.mul(10 ** 8).div( 10 ** underlyingDecimals)); 42 | return 0; 43 | } 44 | 45 | function redeem(uint256 _amount) public returns (uint) { 46 | IERC20(underlyingToken).transfer(msg.sender, _amount); 47 | _burn(msg.sender, _amount); 48 | return 0; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /contracts/multivaults/mock/MockConverter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.2; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | import "@openzeppelin/contracts/math/SafeMath.sol"; 7 | import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 8 | 9 | import "../../interfaces/Converter.sol"; 10 | 11 | contract MockConverter is Converter { 12 | using SafeERC20 for IERC20; 13 | using SafeMath for uint256; 14 | 15 | IERC20 want; 16 | 17 | constructor(IERC20 _want) public { 18 | want = _want; 19 | } 20 | 21 | function convert(address _token) external override returns (uint _wantAmount) { 22 | uint _tokenAmount = IERC20(_token).balanceOf(address(this)); 23 | _wantAmount = _tokenAmount.div(2); // always convert to 50% amount of input 24 | want.safeTransfer(msg.sender, _wantAmount); 25 | IERC20(_token).safeTransfer(address(0x000000000000000000000000000000000000dEaD), _tokenAmount); // clear the _token balance (send to BurnAddress) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /contracts/multivaults/mock/MockCurveGauge.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.2; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | import "@openzeppelin/contracts/math/SafeMath.sol"; 7 | import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 8 | 9 | import "../../interfaces/Gauge.sol"; 10 | 11 | contract MockCurveGauge is Gauge { 12 | using SafeERC20 for IERC20; 13 | using SafeMath for uint256; 14 | 15 | IERC20 want; 16 | 17 | mapping(address => uint) public amounts; 18 | 19 | constructor(IERC20 _want) public { 20 | want = _want; 21 | } 22 | 23 | function deposit(uint _amount) external override { 24 | want.safeTransferFrom(msg.sender, address(this), _amount); 25 | amounts[msg.sender] = amounts[msg.sender].add(_amount); 26 | } 27 | 28 | function balanceOf(address _account) external override view returns (uint) { 29 | return amounts[_account]; 30 | } 31 | 32 | function withdraw(uint _amount) external override { 33 | want.safeTransfer(msg.sender, _amount); 34 | amounts[msg.sender] = amounts[msg.sender].sub(_amount); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /contracts/multivaults/mock/MockCurveMinter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.2; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | import "@openzeppelin/contracts/math/SafeMath.sol"; 7 | import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 8 | 9 | import "../../interfaces/Gauge.sol"; 10 | 11 | contract MockCurveMinter is Mintr { 12 | using SafeERC20 for IERC20; 13 | using SafeMath for uint256; 14 | 15 | IERC20 crv; 16 | 17 | constructor(IERC20 _crv) public { 18 | crv = _crv; 19 | } 20 | 21 | function mint(address) external override { 22 | uint _bal = crv.balanceOf(address(this)); 23 | crv.safeTransfer(msg.sender, _bal.div(10)); // always mint 10% amount of balance 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /contracts/multivaults/mock/MockERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 6 | 7 | contract MockERC20 is ERC20 { 8 | address public governance; 9 | mapping(address => bool) public minters; 10 | 11 | constructor( 12 | string memory name, 13 | string memory symbol, 14 | uint256 supply 15 | ) public ERC20(name, symbol) { 16 | governance = msg.sender; 17 | _mint(msg.sender, supply); 18 | addMinter(msg.sender); 19 | } 20 | 21 | function mint(address account, uint256 amount) public { 22 | require(minters[msg.sender], "!minter"); 23 | _mint(account, amount); 24 | } 25 | 26 | function burn(uint256 amount) public { 27 | _burn(msg.sender, amount); 28 | } 29 | 30 | function setGovernance(address _governance) public { 31 | require(msg.sender == governance, "!governance"); 32 | governance = _governance; 33 | } 34 | 35 | function addMinter(address _minter) public { 36 | require(msg.sender == governance, "!governance"); 37 | minters[_minter] = true; 38 | } 39 | 40 | function removeMinter(address _minter) public { 41 | require(msg.sender == governance, "!governance"); 42 | minters[_minter] = false; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /contracts/multivaults/mock/MockPickleJar.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "../../interfaces/PickleJar.sol"; 6 | import "./MockERC20.sol"; 7 | 8 | contract MockPickleJar is MockERC20 { 9 | IERC20 public t3crv; 10 | IERC20 public lpToken; 11 | 12 | constructor(IERC20 _t3crv) public MockERC20("pickling Curve.fi DAI/USDC/USDT", "p3Crv", 18) { 13 | t3crv = _t3crv; 14 | } 15 | 16 | function balance() public view returns (uint) { 17 | return t3crv.balanceOf(address(this)); 18 | } 19 | 20 | function available() external view returns (uint) { 21 | return balance() * 9500 / 10000; 22 | } 23 | 24 | function depositAll() external { 25 | deposit(t3crv.balanceOf(msg.sender)); 26 | } 27 | 28 | function deposit(uint _amount) public { 29 | t3crv.transferFrom(msg.sender, address(this), _amount); 30 | uint256 shares = _amount * 1000000000000000000 / getRatio(); 31 | _mint(msg.sender, shares); 32 | } 33 | 34 | function withdrawAll() external { 35 | withdraw(balanceOf(msg.sender)); 36 | } 37 | 38 | function withdraw(uint _shares) public { 39 | uint256 r = _shares * getRatio() / 1000000000000000000; 40 | _burn(msg.sender, _shares); 41 | t3crv.transfer(msg.sender, r); 42 | } 43 | 44 | function getRatio() public pure returns (uint) { 45 | return 1010000000000000000; // +1% 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /contracts/multivaults/mock/MockPickleMasterChef.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IERC20 { 6 | function totalSupply() external view returns (uint); 7 | function balanceOf(address account) external view returns (uint); 8 | function transfer(address recipient, uint amount) external returns (bool); 9 | function allowance(address owner, address spender) external view returns (uint); 10 | function approve(address spender, uint amount) external returns (bool); 11 | function transferFrom(address sender, address recipient, uint amount) external returns (bool); 12 | 13 | event Transfer(address indexed from, address indexed to, uint value); 14 | event Approval(address indexed owner, address indexed spender, uint value); 15 | } 16 | 17 | contract MockPickleMasterChef { 18 | IERC20 public pickleToken; 19 | IERC20 public lpToken; 20 | 21 | struct UserInfo { 22 | uint amount; // How many LP tokens the user has provided. 23 | uint rewardDebt; // Reward debt. See explanation below. 24 | } 25 | 26 | mapping(uint => mapping(address => UserInfo)) public userInfo; 27 | 28 | constructor(IERC20 _pickleToken, IERC20 _lpToken) public { 29 | pickleToken = _pickleToken; 30 | lpToken = _lpToken; 31 | } 32 | 33 | function deposit(uint _pid, uint _amount) external { 34 | lpToken.transferFrom(msg.sender, address(this), _amount); 35 | UserInfo storage user = userInfo[_pid][msg.sender]; 36 | pickleToken.transfer(msg.sender, user.amount / 10); // always get 10% of deposited amount 37 | user.amount = user.amount + _amount; 38 | } 39 | 40 | function withdraw(uint _pid, uint _amount) external { 41 | lpToken.transfer(msg.sender, _amount); 42 | UserInfo storage user = userInfo[_pid][msg.sender]; 43 | pickleToken.transfer(msg.sender, user.amount / 10); // always get 10% of deposited amount 44 | user.amount = user.amount - _amount; 45 | } 46 | 47 | function pendingPickle(uint, address) external view returns (uint) { 48 | return pickleToken.balanceOf(address(this)) / 10; 49 | } 50 | 51 | function emergencyWithdraw(uint _pid) external { 52 | UserInfo storage user = userInfo[_pid][msg.sender]; 53 | lpToken.transfer(msg.sender, user.amount); 54 | user.amount = 0; 55 | user.rewardDebt = 0; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /contracts/multivaults/mock/MockStableSwap3Pool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | import "@openzeppelin/contracts/math/SafeMath.sol"; 7 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 8 | import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 9 | 10 | import "../pool-interfaces/IStableSwap3Pool.sol"; 11 | 12 | contract MockStableSwap3Pool is IStableSwap3Pool { 13 | using SafeMath for uint; 14 | using SafeERC20 for IERC20; 15 | 16 | // DAI, USDC, USDT 17 | uint[3] public RATE = [10020, 9995, 9990]; 18 | uint[3] public PRECISION_MUL = [1, 1000000000000, 1000000000000]; 19 | 20 | IERC20[3] public inputTokens; // DAI, USDC, USDT 21 | IERC20 public token3CRV; // 3Crv 22 | 23 | constructor (IERC20 _tokenDAI, IERC20 _tokenUSDC, IERC20 _tokenUSDT, IERC20 _token3CRV) public { 24 | inputTokens[0] = _tokenDAI; 25 | inputTokens[1] = _tokenUSDC; 26 | inputTokens[2] = _tokenUSDT; 27 | token3CRV = _token3CRV; 28 | } 29 | 30 | function get_virtual_price() external override view returns (uint) { 31 | return RATE[0].add(RATE[1]).add(RATE[2]).mul(1e18).div(30000); 32 | } 33 | 34 | function get_dy(int128 i, int128 j, uint dx) public override view returns (uint) { 35 | return dx.mul(RATE[uint8(i)]).mul(PRECISION_MUL[uint8(i)]).div(RATE[uint8(j)]).div(PRECISION_MUL[uint8(j)]); 36 | } 37 | 38 | function balances(uint _index) external override view returns (uint) { 39 | return inputTokens[_index].balanceOf(address(this)); 40 | } 41 | 42 | function add_liquidity(uint[3] calldata amounts, uint min_mint_amount) external override { 43 | uint _shareAmount = 0; 44 | for (uint8 i = 0; i < 3; ++i) { 45 | _shareAmount = _shareAmount.add(amounts[i].mul(RATE[i]).mul(PRECISION_MUL[i]).div(10000)); 46 | } 47 | require(_shareAmount >= min_mint_amount, "below min_mint_amount"); 48 | token3CRV.safeTransfer(msg.sender, _shareAmount); 49 | } 50 | 51 | function remove_liquidity_one_coin(uint _token_amount, int128 i, uint min_amount) external override { 52 | uint _outputAmount = calc_withdraw_one_coin(_token_amount, i); 53 | require(_outputAmount >= min_amount, "below min_amount"); 54 | token3CRV.safeTransferFrom(msg.sender, address(this), _token_amount); 55 | inputTokens[uint8(i)].safeTransfer(msg.sender, _outputAmount); 56 | } 57 | 58 | function exchange(int128 i, int128 j, uint dx, uint min_dy) external override { 59 | uint dy = get_dy(i, j, dx); 60 | require(dy >= min_dy, "below min_dy"); 61 | inputTokens[uint8(i)].safeTransferFrom(msg.sender, address(this), dx); 62 | inputTokens[uint8(j)].safeTransfer(msg.sender, dy); 63 | } 64 | 65 | function calc_token_amount(uint[3] calldata amounts, bool) public override view returns (uint) { 66 | uint _shareAmount = 0; 67 | for (uint8 i = 0; i < 3; ++i) { 68 | _shareAmount = _shareAmount.add(amounts[i].mul(RATE[i]).mul(PRECISION_MUL[i]).div(10000)); 69 | } 70 | return _shareAmount; 71 | } 72 | 73 | function calc_withdraw_one_coin(uint _token_amount, int128 i) public override view returns (uint) { 74 | return _token_amount.mul(10000).div(RATE[uint8(i)]).div(PRECISION_MUL[uint8(i)]); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /contracts/multivaults/mock/MockUniswapRouter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | import "@openzeppelin/contracts/math/SafeMath.sol"; 7 | import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 8 | 9 | interface IUniswapRouter { 10 | function swapExactTokensForTokens( 11 | uint256 amountIn, 12 | uint256 amountOutMin, 13 | address[] calldata path, 14 | address to, 15 | uint256 deadline 16 | ) external returns (uint256[] memory amounts); 17 | 18 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 19 | uint256 amountIn, 20 | uint256 amountOutMin, 21 | address[] calldata path, 22 | address to, 23 | uint256 deadline 24 | ) external returns (uint256[] memory amounts); 25 | 26 | function addLiquidity( 27 | address tokenA, 28 | address tokenB, 29 | uint amountADesired, 30 | uint amountBDesired, 31 | uint amountAMin, 32 | uint amountBMin, 33 | address to, 34 | uint deadline 35 | ) external returns (uint amountA, uint amountB, uint liquidity); 36 | } 37 | 38 | contract MockUniswapRouter is IUniswapRouter { 39 | using SafeERC20 for IERC20; 40 | using SafeMath for uint256; 41 | 42 | IERC20 univ2LpToken; 43 | 44 | constructor(IERC20 _univ2LpToken) public { 45 | univ2LpToken = _univ2LpToken; 46 | } 47 | 48 | function swapExactTokensForTokens( 49 | uint256 amountIn, 50 | uint256 amountOutMin, 51 | address[] calldata path, 52 | address to, 53 | uint256 deadline 54 | ) public override returns (uint256[] memory amounts) { 55 | return _swap(amountIn, amountOutMin, path, to, deadline); 56 | } 57 | 58 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 59 | uint256 amountIn, 60 | uint256 amountOutMin, 61 | address[] calldata path, 62 | address to, 63 | uint256 deadline 64 | ) external override returns (uint256[] memory amounts) { 65 | return _swap(amountIn, amountOutMin, path, to, deadline); 66 | } 67 | 68 | function _swap( 69 | uint256 amountIn, 70 | uint256, 71 | address[] calldata path, 72 | address to, 73 | uint256 74 | ) internal returns (uint256[] memory amounts) { 75 | uint256 amountOut = amountIn.div(2); // always convert to 50% amount of input 76 | IERC20 inputToken = IERC20(path[0]); 77 | IERC20 outputToken = IERC20(path[path.length - 1]); 78 | inputToken.safeTransferFrom(msg.sender, address(this), amountIn); 79 | outputToken.safeTransfer(to, amountOut); 80 | amounts = new uint256[](2); 81 | amounts[0] = amountIn; 82 | amounts[1] = amountOut; 83 | } 84 | 85 | function addLiquidity( 86 | address tokenA, 87 | address tokenB, 88 | uint amountADesired, 89 | uint amountBDesired, 90 | uint, 91 | uint, 92 | address to, 93 | uint 94 | ) external override returns (uint amountA, uint amountB, uint liquidity) { 95 | amountA = (amountADesired < amountBDesired) ? amountADesired : amountBDesired; 96 | amountB = amountA; 97 | liquidity = amountA; 98 | IERC20(tokenA).safeTransferFrom(msg.sender, address(this), amountA); 99 | IERC20(tokenB).safeTransferFrom(msg.sender, address(this), amountB); 100 | univ2LpToken.safeTransfer(to, liquidity); // 1A + 1B -> 1LP 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /contracts/multivaults/mock/MockWrapYERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 6 | import "./TToken.sol"; 7 | import "hardhat/console.sol"; 8 | 9 | interface IDecimals { 10 | function decimals() external view returns (uint8); 11 | } 12 | 13 | contract MockWrapYERC20 is TToken { 14 | address public underlyingToken; 15 | uint8 private _decimals; 16 | 17 | constructor( 18 | string memory name, 19 | string memory symbol, 20 | address _underlyingToken 21 | ) public TToken(name, symbol, IDecimals(_underlyingToken).decimals()) { 22 | underlyingToken = _underlyingToken; 23 | } 24 | function getPricePerFullShare() external pure returns (uint) { 25 | return 10 ** 18; 26 | } 27 | 28 | function deposit(uint256 _amount) public { 29 | IERC20(underlyingToken).transferFrom(msg.sender, address(this), _amount); 30 | _mint(msg.sender, _amount); 31 | } 32 | 33 | function withdraw(uint256 _amount) public { 34 | IERC20(underlyingToken).transfer(msg.sender, _amount); 35 | _burn(msg.sender, _amount); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /contracts/multivaults/mock/TToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.12; 2 | 3 | contract TToken { 4 | 5 | string private _name; 6 | string private _symbol; 7 | uint8 private _decimals; 8 | 9 | uint internal _totalSupply; 10 | 11 | mapping(address => uint) private _balance; 12 | mapping(address => mapping(address => uint)) private _allowance; 13 | 14 | event Approval(address indexed src, address indexed dst, uint amt); 15 | event Transfer(address indexed src, address indexed dst, uint amt); 16 | 17 | // Math 18 | function add(uint a, uint b) internal pure returns (uint c) { 19 | require((c = a + b) >= a); 20 | } 21 | 22 | function sub(uint a, uint b) internal pure returns (uint c) { 23 | require((c = a - b) <= a); 24 | } 25 | 26 | constructor( 27 | string memory name, 28 | string memory symbol, 29 | uint8 decimals 30 | ) public { 31 | _name = name; 32 | _symbol = symbol; 33 | _decimals = decimals; 34 | } 35 | 36 | 37 | function name() public view returns (string memory) { 38 | return _name; 39 | } 40 | 41 | function symbol() public view returns (string memory) { 42 | return _symbol; 43 | } 44 | 45 | function decimals() public view returns (uint8) { 46 | return _decimals; 47 | } 48 | 49 | function _move(address src, address dst, uint amt) internal { 50 | require(_balance[src] >= amt, "ERR_INSUFFICIENT"); 51 | _balance[src] = sub(_balance[src], amt); 52 | _balance[dst] = add(_balance[dst], amt); 53 | emit Transfer(src, dst, amt); 54 | } 55 | 56 | function _push(address to, uint amt) internal { 57 | _move(address(this), to, amt); 58 | } 59 | 60 | function _pull(address from, uint amt) internal { 61 | _move(from, address(this), amt); 62 | } 63 | 64 | function _mint(address dst, uint amt) internal { 65 | _balance[dst] = add(_balance[dst], amt); 66 | _totalSupply = add(_totalSupply, amt); 67 | emit Transfer(address(0), dst, amt); 68 | } 69 | 70 | function allowance(address src, address dst) external view returns (uint) { 71 | return _allowance[src][dst]; 72 | } 73 | 74 | function balanceOf(address whom) external view returns (uint) { 75 | return _balance[whom]; 76 | } 77 | 78 | function totalSupply() public view returns (uint) { 79 | return _totalSupply; 80 | } 81 | 82 | function approve(address dst, uint amt) external returns (bool) { 83 | _allowance[msg.sender][dst] = amt; 84 | emit Approval(msg.sender, dst, amt); 85 | return true; 86 | } 87 | 88 | function faucet(uint256 amt) public returns (bool) { 89 | _mint(msg.sender, amt); 90 | return true; 91 | } 92 | 93 | function mintTo(address dst, uint amt) public returns (bool) { 94 | _mint(dst, amt); 95 | return true; 96 | } 97 | 98 | function burn(uint amt) public returns (bool) { 99 | _burn(msg.sender, amt); 100 | return true; 101 | } 102 | 103 | function _burn(address dst, uint amt) internal returns (bool) { 104 | require(_balance[dst] >= amt, "ERR_INSUFFICIENT"); 105 | _balance[dst] = sub(_balance[dst], amt); 106 | _totalSupply = sub(_totalSupply, amt); 107 | emit Transfer(dst, address(0), amt); 108 | return true; 109 | } 110 | 111 | function transfer(address dst, uint amt) external returns (bool) { 112 | _move(msg.sender, dst, amt); 113 | return true; 114 | } 115 | 116 | function transferFrom(address src, address dst, uint amt) external returns (bool) { 117 | require(msg.sender == src || amt <= _allowance[src][msg.sender], "ERR_BAD_CALLER"); 118 | _move(src, dst, amt); 119 | if (msg.sender != src && _allowance[src][msg.sender] != uint256(- 1)) { 120 | _allowance[src][msg.sender] = sub(_allowance[src][msg.sender], amt); 121 | emit Approval(msg.sender, dst, _allowance[src][msg.sender]); 122 | } 123 | return true; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /contracts/multivaults/pool-interfaces/IDepositBUSD.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IDepositBUSD { 6 | function calc_withdraw_one_coin(uint _token_amount, int128 i) external view returns (uint); 7 | function add_liquidity(uint[4] calldata amounts, uint min_mint_amount) external; 8 | function remove_liquidity_one_coin(uint _token_amount, int128 i, uint min_amount) external; 9 | } 10 | -------------------------------------------------------------------------------- /contracts/multivaults/pool-interfaces/IDepositCompound.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IDepositCompound { 6 | function calc_withdraw_one_coin(uint _token_amount, int128 i) external view returns (uint); 7 | function add_liquidity(uint[2] calldata amounts, uint min_mint_amount) external; 8 | function remove_liquidity_one_coin(uint _token_amount, int128 i, uint min_amount) external; 9 | } 10 | -------------------------------------------------------------------------------- /contracts/multivaults/pool-interfaces/IDepositHUSD.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IDepositHUSD { 6 | function calc_withdraw_one_coin(uint _token_amount, int128 i) external view returns (uint); 7 | function calc_token_amount(uint[4] calldata amounts, bool deposit) external view returns (uint); 8 | function add_liquidity(uint[4] calldata amounts, uint min_mint_amount) external returns (uint); 9 | function remove_liquidity_one_coin(uint _token_amount, int128 i, uint min_amount) external returns (uint); 10 | } 11 | -------------------------------------------------------------------------------- /contracts/multivaults/pool-interfaces/IDepositSUSD.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IDepositSUSD { 6 | function calc_withdraw_one_coin(uint _token_amount, int128 i) external view returns (uint); 7 | function add_liquidity(uint[4] calldata amounts, uint min_mint_amount) external; 8 | function remove_liquidity_one_coin(uint _token_amount, int128 i, uint min_amount) external; 9 | } 10 | -------------------------------------------------------------------------------- /contracts/multivaults/pool-interfaces/IStableSwap3Pool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | // 0: DAI, 1: USDC, 2: USDT 6 | interface IStableSwap3Pool { 7 | function get_virtual_price() external view returns (uint); 8 | function balances(uint) external view returns (uint); 9 | function calc_token_amount(uint[3] calldata amounts, bool deposit) external view returns (uint); 10 | function calc_withdraw_one_coin(uint _token_amount, int128 i) external view returns (uint); 11 | function get_dy(int128 i, int128 j, uint dx) external view returns (uint); 12 | function add_liquidity(uint[3] calldata amounts, uint min_mint_amount) external; 13 | function remove_liquidity_one_coin(uint _token_amount, int128 i, uint min_amount) external; 14 | function exchange(int128 i, int128 j, uint dx, uint min_dy) external; 15 | } 16 | -------------------------------------------------------------------------------- /contracts/multivaults/pool-interfaces/IStableSwapBUSD.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | // 0: DAI, 1: USDC, 2: USDT, 3: BUSD 6 | interface IStableSwapBUSD { 7 | function get_virtual_price() external view returns (uint); 8 | function calc_token_amount(uint[4] calldata amounts, bool deposit) external view returns (uint); 9 | function get_dy_underlying(int128 i, int128 j, uint dx) external view returns (uint dy); 10 | function get_dx_underlying(int128 i, int128 j, uint dy) external view returns (uint dx); 11 | function exchange_underlying(int128 i, int128 j, uint dx, uint min_dy) external; 12 | } 13 | -------------------------------------------------------------------------------- /contracts/multivaults/pool-interfaces/IStableSwapCompound.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | // 0: DAI, 1: USDC 6 | interface IStableSwapCompound { 7 | function get_virtual_price() external view returns (uint); 8 | function calc_token_amount(uint[2] calldata amounts, bool deposit) external view returns (uint); 9 | function get_dy_underlying(int128 i, int128 j, uint dx) external view returns (uint dy); 10 | function get_dx_underlying(int128 i, int128 j, uint dy) external view returns (uint dx); 11 | function exchange_underlying(int128 i, int128 j, uint dx, uint min_dy) external; 12 | } 13 | -------------------------------------------------------------------------------- /contracts/multivaults/pool-interfaces/IStableSwapHUSD.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | // 0: hUSD, 1: 3Crv 6 | interface IStableSwapHUSD { 7 | function get_virtual_price() external view returns (uint); 8 | function calc_token_amount(uint[2] calldata amounts, bool deposit) external view returns (uint); 9 | function get_dy(int128 i, int128 j, uint dx) external view returns (uint dy); 10 | function get_dy_underlying(int128 i, int128 j, uint dx) external view returns (uint dy); 11 | function get_dx_underlying(int128 i, int128 j, uint dy) external view returns (uint dx); 12 | function exchange_underlying(int128 i, int128 j, uint dx, uint min_dy) external; 13 | function exchange(int128 i, int128 j, uint dx, uint min_dy) external; 14 | function calc_withdraw_one_coin(uint amount, int128 i) external view returns (uint); 15 | function remove_liquidity_one_coin(uint amount, int128 i, uint minAmount) external returns (uint); 16 | function add_liquidity(uint[2] calldata amounts, uint min_mint_amount) external returns (uint); 17 | } 18 | -------------------------------------------------------------------------------- /contracts/multivaults/pool-interfaces/IStableSwapSUSD.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | // 0: DAI, 1: USDC, 2: USDT, 3: sUSD 6 | interface IStableSwapSUSD { 7 | function get_virtual_price() external view returns (uint); 8 | function calc_token_amount(uint[4] calldata amounts, bool deposit) external view returns (uint); 9 | function get_dy_underlying(int128 i, int128 j, uint dx) external view returns (uint dy); 10 | function get_dx_underlying(int128 i, int128 j, uint dy) external view returns (uint dx); 11 | function exchange_underlying(int128 i, int128 j, uint dx, uint min_dy) external; 12 | } 13 | -------------------------------------------------------------------------------- /contracts/multivaults/proxy/AdminUpgradeabilityProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.12; 4 | 5 | import './UpgradeabilityProxy.sol'; 6 | 7 | /** 8 | * @title AdminUpgradeabilityProxy 9 | * @dev This contract combines an upgradeability proxy with an authorization 10 | * mechanism for administrative tasks. 11 | * All external functions in this contract must be guarded by the 12 | * `ifAdmin` modifier. See ethereum/solidity#3864 for a Solidity 13 | * feature proposal that would enable this to be done automatically. 14 | */ 15 | contract AdminUpgradeabilityProxy is UpgradeabilityProxy { 16 | /** 17 | * Contract constructor. 18 | * @param _logic address of the initial implementation. 19 | * @param _admin Address of the proxy administrator. 20 | * @param _data Data to send as msg.data to the implementation to initialize the proxied contract. 21 | * It should include the signature and the parameters of the function to be called, as described in 22 | * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. 23 | * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped. 24 | */ 25 | constructor(address _logic, address _admin, bytes memory _data) UpgradeabilityProxy(_logic, _data) public payable { 26 | assert(ADMIN_SLOT == bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)); 27 | _setAdmin(_admin); 28 | } 29 | 30 | /** 31 | * @dev Emitted when the administration has been transferred. 32 | * @param previousAdmin Address of the previous admin. 33 | * @param newAdmin Address of the new admin. 34 | */ 35 | event AdminChanged(address previousAdmin, address newAdmin); 36 | 37 | /** 38 | * @dev Storage slot with the admin of the contract. 39 | * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is 40 | * validated in the constructor. 41 | */ 42 | 43 | bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; 44 | 45 | /** 46 | * @dev Modifier to check whether the `msg.sender` is the admin. 47 | * If it is, it will run the function. Otherwise, it will delegate the call 48 | * to the implementation. 49 | */ 50 | modifier ifAdmin() { 51 | if (msg.sender == _admin()) { 52 | _; 53 | } else { 54 | _fallback(); 55 | } 56 | } 57 | 58 | /** 59 | * @return The address of the proxy admin. 60 | */ 61 | function admin() external ifAdmin returns (address) { 62 | return _admin(); 63 | } 64 | 65 | /** 66 | * @return The address of the implementation. 67 | */ 68 | function implementation() external ifAdmin returns (address) { 69 | return _implementation(); 70 | } 71 | 72 | /** 73 | * @dev Changes the admin of the proxy. 74 | * Only the current admin can call this function. 75 | * @param newAdmin Address to transfer proxy administration to. 76 | */ 77 | function changeAdmin(address newAdmin) external ifAdmin { 78 | require(newAdmin != address(0), "Cannot change the admin of a proxy to the zero address"); 79 | emit AdminChanged(_admin(), newAdmin); 80 | _setAdmin(newAdmin); 81 | } 82 | 83 | /** 84 | * @dev Upgrade the backing implementation of the proxy. 85 | * Only the admin can call this function. 86 | * @param newImplementation Address of the new implementation. 87 | */ 88 | function upgradeTo(address newImplementation) external ifAdmin { 89 | _upgradeTo(newImplementation); 90 | } 91 | 92 | /** 93 | * @dev Upgrade the backing implementation of the proxy and call a function 94 | * on the new implementation. 95 | * This is useful to initialize the proxied contract. 96 | * @param newImplementation Address of the new implementation. 97 | * @param data Data to send as msg.data in the low level call. 98 | * It should include the signature and the parameters of the function to be called, as described in 99 | * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. 100 | */ 101 | function upgradeToAndCall(address newImplementation, bytes calldata data) payable external ifAdmin { 102 | _upgradeTo(newImplementation); 103 | (bool success,) = newImplementation.delegatecall(data); 104 | require(success); 105 | } 106 | 107 | /** 108 | * @return adm The admin slot. 109 | */ 110 | function _admin() internal view returns (address adm) { 111 | bytes32 slot = ADMIN_SLOT; 112 | assembly { 113 | adm := sload(slot) 114 | } 115 | } 116 | 117 | /** 118 | * @dev Sets the address of the proxy admin. 119 | * @param newAdmin Address of the new proxy admin. 120 | */ 121 | function _setAdmin(address newAdmin) internal { 122 | bytes32 slot = ADMIN_SLOT; 123 | 124 | assembly { 125 | sstore(slot, newAdmin) 126 | } 127 | } 128 | 129 | /** 130 | * @dev Only fall back when the sender is not the admin. 131 | */ 132 | function _willFallback() internal override virtual { 133 | require(msg.sender != _admin(), "Cannot call fallback function from the proxy admin"); 134 | super._willFallback(); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /contracts/multivaults/proxy/Proxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.12; 4 | 5 | /** 6 | * @title Proxy 7 | * @dev Implements delegation of calls to other contracts, with proper 8 | * forwarding of return values and bubbling of failures. 9 | * It defines a fallback function that delegates all calls to the address 10 | * returned by the abstract _implementation() internal function. 11 | */ 12 | abstract contract Proxy { 13 | /** 14 | * @dev Fallback function. 15 | * Implemented entirely in `_fallback`. 16 | */ 17 | fallback () payable external { 18 | _fallback(); 19 | } 20 | 21 | /** 22 | * @dev Receive function. 23 | * Implemented entirely in `_fallback`. 24 | */ 25 | receive () payable external { 26 | _fallback(); 27 | } 28 | 29 | /** 30 | * @return The Address of the implementation. 31 | */ 32 | function _implementation() internal virtual view returns (address); 33 | 34 | /** 35 | * @dev Delegates execution to an implementation contract. 36 | * This is a low level function that doesn't return to its internal call site. 37 | * It will return to the external caller whatever the implementation returns. 38 | * @param implementation Address to delegate. 39 | */ 40 | function _delegate(address implementation) internal { 41 | assembly { 42 | // Copy msg.data. We take full control of memory in this inline assembly 43 | // block because it will not return to Solidity code. We overwrite the 44 | // Solidity scratch pad at memory position 0. 45 | calldatacopy(0, 0, calldatasize()) 46 | 47 | // Call the implementation. 48 | // out and outsize are 0 because we don't know the size yet. 49 | let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) 50 | 51 | // Copy the returned data. 52 | returndatacopy(0, 0, returndatasize()) 53 | 54 | switch result 55 | // delegatecall returns 0 on error. 56 | case 0 { revert(0, returndatasize()) } 57 | default { return(0, returndatasize()) } 58 | } 59 | } 60 | 61 | /** 62 | * @dev Function that is run as the first thing in the fallback function. 63 | * Can be redefined in derived contracts to add functionality. 64 | * Redefinitions must call super._willFallback(). 65 | */ 66 | function _willFallback() internal virtual { 67 | } 68 | 69 | /** 70 | * @dev fallback implementation. 71 | * Extracted to enable manual triggering. 72 | */ 73 | function _fallback() internal { 74 | _willFallback(); 75 | _delegate(_implementation()); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /contracts/multivaults/proxy/ProxyAdmin.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.12; 4 | 5 | import "@openzeppelin/contracts/access/Ownable.sol"; 6 | import "./AdminUpgradeabilityProxy.sol"; 7 | 8 | /** 9 | * @title ProxyAdmin 10 | * @dev This contract is the admin of a proxy, and is in charge 11 | * of upgrading it as well as transferring it to another admin. 12 | */ 13 | contract ProxyAdmin is Ownable { 14 | 15 | /** 16 | * @dev Returns the current implementation of a proxy. 17 | * This is needed because only the proxy admin can query it. 18 | * @return The address of the current implementation of the proxy. 19 | */ 20 | function getProxyImplementation(AdminUpgradeabilityProxy proxy) public view returns (address) { 21 | // We need to manually run the static call since the getter cannot be flagged as view 22 | // bytes4(keccak256("implementation()")) == 0x5c60da1b 23 | (bool success, bytes memory returndata) = address(proxy).staticcall(hex"5c60da1b"); 24 | require(success); 25 | return abi.decode(returndata, (address)); 26 | } 27 | 28 | /** 29 | * @dev Returns the admin of a proxy. Only the admin can query it. 30 | * @return The address of the current admin of the proxy. 31 | */ 32 | function getProxyAdmin(AdminUpgradeabilityProxy proxy) public view returns (address) { 33 | // We need to manually run the static call since the getter cannot be flagged as view 34 | // bytes4(keccak256("admin()")) == 0xf851a440 35 | (bool success, bytes memory returndata) = address(proxy).staticcall(hex"f851a440"); 36 | require(success); 37 | return abi.decode(returndata, (address)); 38 | } 39 | 40 | /** 41 | * @dev Changes the admin of a proxy. 42 | * @param proxy Proxy to change admin. 43 | * @param newAdmin Address to transfer proxy administration to. 44 | */ 45 | function changeProxyAdmin(AdminUpgradeabilityProxy proxy, address newAdmin) public onlyOwner { 46 | proxy.changeAdmin(newAdmin); 47 | } 48 | 49 | /** 50 | * @dev Upgrades a proxy to the newest implementation of a contract. 51 | * @param proxy Proxy to be upgraded. 52 | * @param implementation the address of the Implementation. 53 | */ 54 | function upgrade(AdminUpgradeabilityProxy proxy, address implementation) public onlyOwner { 55 | proxy.upgradeTo(implementation); 56 | } 57 | 58 | /** 59 | * @dev Upgrades a proxy to the newest implementation of a contract and forwards a function call to it. 60 | * This is useful to initialize the proxied contract. 61 | * @param proxy Proxy to be upgraded. 62 | * @param implementation Address of the Implementation. 63 | * @param data Data to send as msg.data in the low level call. 64 | * It should include the signature and the parameters of the function to be called, as described in 65 | * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. 66 | */ 67 | function upgradeAndCall(AdminUpgradeabilityProxy proxy, address implementation, bytes memory data) payable public onlyOwner { 68 | proxy.upgradeToAndCall{value: msg.value}(implementation, data); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /contracts/multivaults/proxy/UpgradeabilityProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.12; 4 | 5 | import './Proxy.sol'; 6 | import '@openzeppelin/contracts/utils/Address.sol'; 7 | 8 | /** 9 | * @title UpgradeabilityProxy 10 | * @dev This contract implements a proxy that allows to change the 11 | * implementation address to which it will delegate. 12 | * Such a change is called an implementation upgrade. 13 | */ 14 | contract UpgradeabilityProxy is Proxy { 15 | /** 16 | * @dev Contract constructor. 17 | * @param _logic Address of the initial implementation. 18 | * @param _data Data to send as msg.data to the implementation to initialize the proxied contract. 19 | * It should include the signature and the parameters of the function to be called, as described in 20 | * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. 21 | * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped. 22 | */ 23 | constructor(address _logic, bytes memory _data) public payable { 24 | assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)); 25 | _setImplementation(_logic); 26 | if(_data.length > 0) { 27 | (bool success,) = _logic.delegatecall(_data); 28 | require(success); 29 | } 30 | } 31 | 32 | /** 33 | * @dev Emitted when the implementation is upgraded. 34 | * @param implementation Address of the new implementation. 35 | */ 36 | event Upgraded(address indexed implementation); 37 | 38 | /** 39 | * @dev Storage slot with the address of the current implementation. 40 | * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is 41 | * validated in the constructor. 42 | */ 43 | bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; 44 | 45 | /** 46 | * @dev Returns the current implementation. 47 | * @return impl Address of the current implementation 48 | */ 49 | function _implementation() internal override view returns (address impl) { 50 | bytes32 slot = IMPLEMENTATION_SLOT; 51 | assembly { 52 | impl := sload(slot) 53 | } 54 | } 55 | 56 | /** 57 | * @dev Upgrades the proxy to a new implementation. 58 | * @param newImplementation Address of the new implementation. 59 | */ 60 | function _upgradeTo(address newImplementation) internal { 61 | _setImplementation(newImplementation); 62 | emit Upgraded(newImplementation); 63 | } 64 | 65 | /** 66 | * @dev Sets the implementation address of the proxy. 67 | * @param newImplementation Address of the new implementation. 68 | */ 69 | function _setImplementation(address newImplementation) internal { 70 | require(Address.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address"); 71 | 72 | bytes32 slot = IMPLEMENTATION_SLOT; 73 | 74 | assembly { 75 | sstore(slot, newImplementation) 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /contracts/vaults/ValueVaultMaster.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | /* 6 | * Here we have a list of constants. In order to get access to an address 7 | * managed by ValueVaultMaster, the calling contract should copy and define 8 | * some of these constants and use them as keys. 9 | * Keys themselves are immutable. Addresses can be immutable or mutable. 10 | * 11 | * Vault addresses are immutable once set, and the list may grow: 12 | * K_VAULT_WETH = 0; 13 | * K_VAULT_ETH_USDC_UNI_V2_LP = 1; 14 | * K_VAULT_ETH_WBTC_UNI_V2_LP = 2; 15 | * 16 | * Strategy addresses are mutable: 17 | * K_STRATEGY_WETH_SODA_POOL = 0; 18 | * K_STRATEGY_WETH_MULTI_POOL = 1; 19 | * K_STRATEGY_ETHUSDC_MULTIPOOL = 100; 20 | * K_STRATEGY_ETHWBTC_MULTIPOOL = 200; 21 | */ 22 | 23 | /* 24 | * ValueVaultMaster manages all the vaults and strategies of our Value Vaults system. 25 | */ 26 | contract ValueVaultMaster { 27 | address public governance; 28 | 29 | address public bank; 30 | address public minorPool; 31 | address public profitSharer; 32 | 33 | address public govToken; // VALUE 34 | address public yfv; // When harvesting, convert some parts to YFV for govVault 35 | address public usdc; // we only used USDC to estimate APY 36 | 37 | address public govVault; // YFV -> VALUE, vUSD, vETH and 6.7% profit from Value Vaults 38 | address public insuranceFund = 0xb7b2Ea8A1198368f950834875047aA7294A2bDAa; // set to Governance Multisig at start 39 | address public performanceReward = 0x7Be4D5A99c903C437EC77A20CB6d0688cBB73c7f; // set to deploy wallet at start 40 | 41 | uint256 public constant FEE_DENOMINATOR = 10000; 42 | uint256 public govVaultProfitShareFee = 670; // 6.7% | VIP-1 (https://yfv.finance/vip-vote/vip_1) 43 | uint256 public gasFee = 50; // 0.5% at start and can be set by governance decision 44 | 45 | uint256 public minStakeTimeToClaimVaultReward = 24 hours; 46 | 47 | mapping(address => bool) public isVault; 48 | mapping(uint256 => address) public vaultByKey; 49 | 50 | mapping(address => bool) public isStrategy; 51 | mapping(uint256 => address) public strategyByKey; 52 | mapping(address => uint256) public strategyQuota; 53 | 54 | constructor(address _govToken, address _yfv, address _usdc) public { 55 | govToken = _govToken; 56 | yfv = _yfv; 57 | usdc = _usdc; 58 | governance = tx.origin; 59 | } 60 | 61 | function setGovernance(address _governance) external { 62 | require(msg.sender == governance, "!governance"); 63 | governance = _governance; 64 | } 65 | 66 | // Immutable once set. 67 | function setBank(address _bank) external { 68 | require(msg.sender == governance, "!governance"); 69 | require(bank == address(0)); 70 | bank = _bank; 71 | } 72 | 73 | // Mutable in case we want to upgrade the pool. 74 | function setMinorPool(address _minorPool) external { 75 | require(msg.sender == governance, "!governance"); 76 | minorPool = _minorPool; 77 | } 78 | 79 | // Mutable in case we want to upgrade this module. 80 | function setProfitSharer(address _profitSharer) external { 81 | require(msg.sender == governance, "!governance"); 82 | profitSharer = _profitSharer; 83 | } 84 | 85 | // Mutable, in case governance want to upgrade VALUE to new version 86 | function setGovToken(address _govToken) external { 87 | require(msg.sender == governance, "!governance"); 88 | govToken = _govToken; 89 | } 90 | 91 | // Immutable once added, and you can always add more. 92 | function addVault(uint256 _key, address _vault) external { 93 | require(msg.sender == governance, "!governance"); 94 | require(vaultByKey[_key] == address(0), "vault: key is taken"); 95 | 96 | isVault[_vault] = true; 97 | vaultByKey[_key] = _vault; 98 | } 99 | 100 | // Mutable and removable. 101 | function addStrategy(uint256 _key, address _strategy) external { 102 | require(msg.sender == governance, "!governance"); 103 | isStrategy[_strategy] = true; 104 | strategyByKey[_key] = _strategy; 105 | } 106 | 107 | // Set 0 to disable quota (no limit) 108 | function setStrategyQuota(address _strategy, uint256 _quota) external { 109 | require(msg.sender == governance, "!governance"); 110 | strategyQuota[_strategy] = _quota; 111 | } 112 | 113 | function removeStrategy(uint256 _key) external { 114 | require(msg.sender == governance, "!governance"); 115 | isStrategy[strategyByKey[_key]] = false; 116 | delete strategyByKey[_key]; 117 | } 118 | 119 | function setGovVault(address _govVault) public { 120 | require(msg.sender == governance, "!governance"); 121 | govVault = _govVault; 122 | } 123 | 124 | function setInsuranceFund(address _insuranceFund) public { 125 | require(msg.sender == governance, "!governance"); 126 | require(_insuranceFund <= 2000, "cannot be over 20%"); 127 | insuranceFund = _insuranceFund; 128 | } 129 | 130 | function setPerformanceReward(address _performanceReward) public{ 131 | require(msg.sender == governance, "!governance"); 132 | require(_performanceReward <= 2000, "cannot be over 20%"); 133 | performanceReward = _performanceReward; 134 | } 135 | 136 | function setGovVaultProfitShareFee(uint256 _govVaultProfitShareFee) public { 137 | require(msg.sender == governance, "!governance"); 138 | require(_govVaultProfitShareFee <= 3000, "cannot be over 30%"); 139 | govVaultProfitShareFee = _govVaultProfitShareFee; 140 | } 141 | 142 | function setGasFee(uint256 _gasFee) public { 143 | require(msg.sender == governance, "!governance"); 144 | require(_gasFee <= 1000, "cannot be over 10%"); 145 | gasFee = _gasFee; 146 | } 147 | 148 | function setMinStakeTimeToClaimVaultReward(uint256 _minStakeTimeToClaimVaultReward) public { 149 | require(msg.sender == governance, "!governance"); 150 | minStakeTimeToClaimVaultReward = _minStakeTimeToClaimVaultReward; 151 | } 152 | 153 | /** 154 | * This function allows governance to take unsupported tokens out of the contract. 155 | * This is in an effort to make someone whole, should they seriously mess up. 156 | * There is no guarantee governance will vote to return these. 157 | * It also allows for removal of airdropped tokens. 158 | */ 159 | function governanceRecoverUnsupported(IERC20x _token, uint256 amount, address to) external { 160 | require(msg.sender == governance, "!governance"); 161 | _token.transfer(to, amount); 162 | } 163 | } 164 | 165 | interface IERC20x { 166 | function transfer(address recipient, uint256 amount) external returns (bool); 167 | } 168 | -------------------------------------------------------------------------------- /contracts/vaults/misc/ValueVaultProfitSharer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "./ValueLiquidityToken.sol"; 6 | 7 | interface IERC20Burnable { 8 | function totalSupply() external view returns (uint256); 9 | function balanceOf(address account) external view returns (uint256); 10 | function transfer(address recipient, uint256 amount) external returns (bool); 11 | function burn(uint amount) external; 12 | function allowance(address owner, address spender) external view returns (uint256); 13 | function approve(address spender, uint256 amount) external returns (bool); 14 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 15 | 16 | event Transfer(address indexed from, address indexed to, uint256 value); 17 | event Approval(address indexed owner, address indexed spender, uint256 value); 18 | } 19 | 20 | interface IGovVault { 21 | function make_profit(uint256 amount) external; 22 | function addValueReward(uint256 _amount) external; 23 | } 24 | 25 | contract ValueVaultProfitSharer { 26 | using SafeMath for uint256; 27 | 28 | address public governance; 29 | 30 | ValueLiquidityToken public valueToken; 31 | IERC20Burnable public yfvToken; 32 | 33 | address public govVault; // YFV -> VALUE, vUSD, vETH and 6.7% profit from Value Vaults 34 | address public insuranceFund = 0xb7b2Ea8A1198368f950834875047aA7294A2bDAa; // set to Governance Multisig at start 35 | address public performanceReward = 0x7Be4D5A99c903C437EC77A20CB6d0688cBB73c7f; // set to deploy wallet at start 36 | 37 | uint256 public constant FEE_DENOMINATOR = 10000; 38 | uint256 public insuranceFee = 0; // 0% at start and can be set by governance decision 39 | uint256 public performanceFee = 0; // 0% at start and can be set by governance decision 40 | uint256 public burnFee = 0; // 0% at start and can be set by governance decision 41 | 42 | constructor(ValueLiquidityToken _valueToken, IERC20Burnable _yfvToken) public { 43 | valueToken = _valueToken; 44 | yfvToken = _yfvToken; 45 | yfvToken.approve(address(valueToken), type(uint256).max); 46 | governance = tx.origin; 47 | } 48 | 49 | function setGovernance(address _governance) external { 50 | require(msg.sender == governance, "!governance"); 51 | governance = _governance; 52 | } 53 | 54 | function setGovVault(address _govVault) public { 55 | require(msg.sender == governance, "!governance"); 56 | govVault = _govVault; 57 | } 58 | 59 | function setInsuranceFund(address _insuranceFund) public { 60 | require(msg.sender == governance, "!governance"); 61 | insuranceFund = _insuranceFund; 62 | } 63 | 64 | function setPerformanceReward(address _performanceReward) public{ 65 | require(msg.sender == governance, "!governance"); 66 | performanceReward = _performanceReward; 67 | } 68 | 69 | function setInsuranceFee(uint256 _insuranceFee) public { 70 | require(msg.sender == governance, "!governance"); 71 | insuranceFee = _insuranceFee; 72 | } 73 | 74 | function setPerformanceFee(uint256 _performanceFee) public { 75 | require(msg.sender == governance, "!governance"); 76 | performanceFee = _performanceFee; 77 | } 78 | 79 | function setBurnFee(uint256 _burnFee) public { 80 | require(msg.sender == governance, "!governance"); 81 | burnFee = _burnFee; 82 | } 83 | 84 | function shareProfit() public returns (uint256 profit) { 85 | if (govVault != address(0)) { 86 | profit = yfvToken.balanceOf(address(this)); 87 | if (profit > 0) { 88 | if (performanceReward != address(0) && performanceFee > 0) { 89 | uint256 _performanceFee = profit.mul(performanceFee).div(FEE_DENOMINATOR); 90 | yfvToken.transfer(performanceReward, _performanceFee); 91 | } 92 | if (insuranceFund != address(0) && insuranceFee > 0) { 93 | uint256 _insuranceFee = profit.mul(insuranceFee).div(FEE_DENOMINATOR); 94 | yfvToken.transfer(insuranceFund, _insuranceFee); 95 | } 96 | if (burnFee > 0) { 97 | uint256 _burnFee = profit.mul(burnFee).div(FEE_DENOMINATOR); 98 | yfvToken.burn(_burnFee); 99 | } 100 | uint256 balanceLeft = yfvToken.balanceOf(address(this)); 101 | valueToken.deposit(balanceLeft); 102 | valueToken.approve(govVault, 0); 103 | valueToken.approve(govVault, balanceLeft); 104 | IGovVault(govVault).make_profit(balanceLeft); 105 | } 106 | } 107 | } 108 | 109 | /** 110 | * This function allows governance to take unsupported tokens out of the contract. 111 | * This is in an effort to make someone whole, should they seriously mess up. 112 | * There is no guarantee governance will vote to return these. 113 | * It also allows for removal of airdropped tokens. 114 | */ 115 | function governanceRecoverUnsupported(IERC20 _token, uint256 amount, address to) external { 116 | require(msg.sender == governance, "!governance"); 117 | _token.transfer(to, amount); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /contracts/vaults/misc/ValueVaultProfitSharerV2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/math/SafeMath.sol"; 6 | 7 | interface ITokenInterface { 8 | function totalSupply() external view returns (uint256); 9 | function balanceOf(address account) external view returns (uint256); 10 | function transfer(address recipient, uint256 amount) external returns (bool); 11 | function burn(uint amount) external; 12 | function allowance(address owner, address spender) external view returns (uint256); 13 | function approve(address spender, uint256 amount) external returns (bool); 14 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 15 | 16 | /** VALUE, YFV, vUSD, vETH has minters **/ 17 | function minters(address account) external view returns (bool); 18 | function mint(address _to, uint _amount) external; 19 | 20 | /** YFV <-> VALUE **/ 21 | function deposit(uint _amount) external; 22 | function withdraw(uint _amount) external; 23 | function cap() external returns (uint); 24 | function yfvLockedBalance() external returns (uint); 25 | 26 | event Transfer(address indexed from, address indexed to, uint256 value); 27 | event Approval(address indexed owner, address indexed spender, uint256 value); 28 | } 29 | 30 | contract ValueVaultProfitSharerV2 { 31 | using SafeMath for uint256; 32 | 33 | address public governance; 34 | 35 | ITokenInterface public valueToken; 36 | ITokenInterface public yfvToken; 37 | 38 | address public govVault = 0xceC03a960Ea678A2B6EA350fe0DbD1807B22D875; // VALUE -> VALUE and 6.7% profit from Value Vaults 39 | address public insuranceFund = 0xb7b2Ea8A1198368f950834875047aA7294A2bDAa; // set to Governance Multisig at start 40 | address public performanceReward = 0x7Be4D5A99c903C437EC77A20CB6d0688cBB73c7f; // set to deploy wallet at start 41 | 42 | uint256 public constant FEE_DENOMINATOR = 10000; 43 | uint256 public insuranceFee = 0; // 0% at start and can be set by governance decision 44 | uint256 public performanceFee = 0; // 0% at start and can be set by governance decision 45 | uint256 public burnFee = 0; // 0% at start and can be set by governance decision 46 | 47 | uint256 public distributeCap = 100 ether; // Maximum of Value to distribute each time 48 | uint256 public distributeCooldownPeriod = 0; // Cool-down period for each time distribution 49 | uint256 public distributeLasttime = 0; 50 | 51 | constructor(ITokenInterface _valueToken, ITokenInterface _yfvToken) public { 52 | valueToken = _valueToken; 53 | yfvToken = _yfvToken; 54 | yfvToken.approve(address(valueToken), type(uint256).max); 55 | governance = tx.origin; 56 | } 57 | 58 | function setGovernance(address _governance) external { 59 | require(msg.sender == governance, "!governance"); 60 | governance = _governance; 61 | } 62 | 63 | function setGovVault(address _govVault) public { 64 | require(msg.sender == governance, "!governance"); 65 | govVault = _govVault; 66 | } 67 | 68 | function setInsuranceFund(address _insuranceFund) public { 69 | require(msg.sender == governance, "!governance"); 70 | insuranceFund = _insuranceFund; 71 | } 72 | 73 | function setPerformanceReward(address _performanceReward) public { 74 | require(msg.sender == governance, "!governance"); 75 | performanceReward = _performanceReward; 76 | } 77 | 78 | function setInsuranceFee(uint256 _insuranceFee) public { 79 | require(msg.sender == governance, "!governance"); 80 | insuranceFee = _insuranceFee; 81 | } 82 | 83 | function setPerformanceFee(uint256 _performanceFee) public { 84 | require(msg.sender == governance, "!governance"); 85 | performanceFee = _performanceFee; 86 | } 87 | 88 | function setBurnFee(uint256 _burnFee) public { 89 | require(msg.sender == governance, "!governance"); 90 | burnFee = _burnFee; 91 | } 92 | 93 | function setDistributeCap(uint256 _distributeCap) public { 94 | require(msg.sender == governance, "!governance"); 95 | distributeCap = _distributeCap; 96 | } 97 | 98 | function setDistributeCooldownPeriod(uint256 _distributeCooldownPeriod) public { 99 | require(msg.sender == governance, "!governance"); 100 | distributeCooldownPeriod = _distributeCooldownPeriod; 101 | } 102 | 103 | function shareProfit() public returns (uint256 profit) { 104 | if (distributeCap > 0 && govVault != address(0) && distributeLasttime.add(distributeCooldownPeriod) <= block.timestamp) { 105 | profit = yfvToken.balanceOf(address(this)); 106 | if (profit > 0) { 107 | valueToken.deposit(profit); 108 | } 109 | profit = valueToken.balanceOf(address(this)); 110 | if (profit > 0) { 111 | if (performanceFee > 0 && performanceReward != address(0)) { 112 | valueToken.transfer(performanceReward, profit.mul(performanceFee).div(FEE_DENOMINATOR)); 113 | } 114 | if (insuranceFee > 0 && insuranceFund != address(0)) { 115 | valueToken.transfer(insuranceFund, profit.mul(insuranceFee).div(FEE_DENOMINATOR)); 116 | } 117 | if (burnFee > 0) { 118 | valueToken.burn(profit.mul(burnFee).div(FEE_DENOMINATOR)); 119 | } 120 | uint256 _valueBal = valueToken.balanceOf(address(this)); 121 | valueToken.transfer(govVault, (_valueBal <= distributeCap) ? _valueBal : distributeCap); 122 | distributeLasttime = block.timestamp; 123 | } 124 | } 125 | } 126 | 127 | /** 128 | * This function allows governance to take unsupported tokens out of the contract. 129 | * This is in an effort to make someone whole, should they seriously mess up. 130 | * There is no guarantee governance will vote to return these. 131 | * It also allows for removal of airdropped tokens. 132 | */ 133 | function governanceRecoverUnsupported(ITokenInterface _token, uint256 amount, address to) external { 134 | require(msg.sender == governance, "!governance"); 135 | _token.transfer(to, amount); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /contracts/vaults/misc/YFV_Referral.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | contract YFVReferral { 6 | mapping(address => address) public referrers; // account_address -> referrer_address 7 | mapping(address => uint256) public referredCount; // referrer_address -> num_of_referred 8 | 9 | event Referral(address indexed referrer, address indexed farmer); 10 | 11 | // Standard contract ownership transfer. 12 | address public owner; 13 | address private nextOwner; 14 | 15 | mapping(address => bool) public isAdmin; 16 | 17 | constructor () public { 18 | owner = msg.sender; 19 | } 20 | 21 | // Standard modifier on methods invokable only by contract owner. 22 | modifier onlyOwner { 23 | require(msg.sender == owner, "OnlyOwner methods called by non-owner."); 24 | _; 25 | } 26 | 27 | modifier onlyAdmin { 28 | require(isAdmin[msg.sender], "OnlyAdmin methods called by non-admin."); 29 | _; 30 | } 31 | 32 | // Standard contract ownership transfer implementation, 33 | function approveNextOwner(address _nextOwner) external onlyOwner { 34 | require(_nextOwner != owner, "Cannot approve current owner."); 35 | nextOwner = _nextOwner; 36 | } 37 | 38 | function acceptNextOwner() external { 39 | require(msg.sender == nextOwner, "Can only accept preapproved new owner."); 40 | owner = nextOwner; 41 | } 42 | 43 | function setReferrer(address farmer, address referrer) public onlyAdmin { 44 | if (referrers[farmer] == address(0) && referrer != address(0)) { 45 | referrers[farmer] = referrer; 46 | referredCount[referrer] += 1; 47 | emit Referral(referrer, farmer); 48 | } 49 | } 50 | 51 | function getReferrer(address farmer) public view returns (address) { 52 | return referrers[farmer]; 53 | } 54 | 55 | // Set admin status. 56 | function setAdminStatus(address _admin, bool _status) external onlyOwner { 57 | isAdmin[_admin] = _status; 58 | } 59 | 60 | event EmergencyERC20Drain(address token, address owner, uint256 amount); 61 | 62 | // owner can drain tokens that are sent here by mistake 63 | function emergencyERC20Drain(ERC20 token, uint amount) external onlyOwner { 64 | emit EmergencyERC20Drain(address(token), owner, amount); 65 | token.transfer(owner, amount); 66 | } 67 | } 68 | 69 | /** 70 | * @title ERC20 interface 71 | * @dev see https://github.com/ethereum/EIPs/issues/20 72 | */ 73 | abstract contract ERC20 { 74 | function totalSupply() public virtual view returns (uint256); 75 | 76 | function balanceOf(address _who) public virtual view returns (uint256); 77 | 78 | function transfer(address _to, uint256 _value) public virtual returns (bool); 79 | 80 | function allowance(address _owner, address _spender) public virtual view returns (uint256); 81 | 82 | function transferFrom(address _from, address _to, uint256 _value) public virtual returns (bool); 83 | 84 | function approve(address _spender, uint256 _value) public virtual returns (bool); 85 | 86 | event Transfer(address indexed from, address indexed to, uint256 value); 87 | event Approval(address indexed owner, address indexed spender, uint256 value); 88 | } 89 | -------------------------------------------------------------------------------- /contracts/vaults/mock/MockERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 6 | 7 | contract MockERC20 is ERC20 { 8 | address public governance; 9 | mapping(address => bool) public minters; 10 | 11 | constructor( 12 | string memory name, 13 | string memory symbol, 14 | uint256 supply 15 | ) public ERC20(name, symbol) { 16 | governance = msg.sender; 17 | _mint(msg.sender, supply); 18 | } 19 | 20 | function mint(address account, uint256 amount) public { 21 | require(minters[msg.sender], "!minter"); 22 | _mint(account, amount); 23 | } 24 | 25 | function burn(uint256 amount) public { 26 | _burn(msg.sender, amount); 27 | } 28 | 29 | function setGovernance(address _governance) public { 30 | require(msg.sender == governance, "!governance"); 31 | governance = _governance; 32 | } 33 | 34 | function addMinter(address _minter) public { 35 | require(msg.sender == governance, "!governance"); 36 | minters[_minter] = true; 37 | } 38 | 39 | function removeMinter(address _minter) public { 40 | require(msg.sender == governance, "!governance"); 41 | minters[_minter] = false; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /contracts/vaults/mock/MockFarmingPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | import "@openzeppelin/contracts/math/SafeMath.sol"; 7 | import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 8 | 9 | interface IStandardFarmingPool { 10 | function withdraw(uint256) external; 11 | function getReward() external; 12 | function stake(uint256) external; 13 | function balanceOf(address) external view returns (uint256); 14 | function exit() external; 15 | function earned(address) external view returns (uint256); 16 | } 17 | 18 | contract MockFarmingPool is IStandardFarmingPool { 19 | using SafeMath for uint256; 20 | using SafeERC20 for IERC20; 21 | 22 | IERC20 public lpToken; 23 | IERC20 public rewardToken; 24 | 25 | uint256 private _totalSupply; 26 | mapping(address => uint256) private _balances; 27 | 28 | uint256 rewardRate; // over 1000 29 | 30 | constructor( 31 | address _lpToken, 32 | address _rewardToken, 33 | uint256 _rewardRate) public 34 | { 35 | lpToken = IERC20(_lpToken); 36 | rewardToken = IERC20(_rewardToken); 37 | rewardRate = _rewardRate; 38 | } 39 | 40 | function totalSupply() public view returns (uint256) { 41 | return _totalSupply; 42 | } 43 | 44 | function balanceOf(address account) public override view returns (uint256) { 45 | return _balances[account]; 46 | } 47 | 48 | function earned(address account) public override view returns (uint256) { 49 | return balanceOf(account).mul(rewardRate).div(1000); 50 | } 51 | 52 | function stake(uint256 amount) public override { 53 | _totalSupply = _totalSupply.add(amount); 54 | _balances[msg.sender] = _balances[msg.sender].add(amount); 55 | lpToken.safeTransferFrom(msg.sender, address(this), amount); 56 | } 57 | 58 | function withdraw(uint256 amount) public override { 59 | _totalSupply = _totalSupply.sub(amount); 60 | _balances[msg.sender] = _balances[msg.sender].sub(amount); 61 | lpToken.safeTransfer(msg.sender, amount); 62 | } 63 | 64 | function exit() external override { 65 | withdraw(balanceOf(msg.sender)); 66 | getReward(); 67 | } 68 | 69 | function getReward() public override { 70 | uint256 reward = earned(msg.sender); 71 | if (reward > 0) { 72 | if (reward > rewardToken.balanceOf(address(this))) { 73 | reward = rewardToken.balanceOf(address(this)); 74 | } 75 | rewardToken.safeTransfer(msg.sender, reward); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /contracts/vaults/mock/MockGovVault.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IERC20 { 6 | function totalSupply() external view returns (uint256); 7 | function balanceOf(address account) external view returns (uint256); 8 | function transfer(address recipient, uint256 amount) external returns (bool); 9 | function allowance(address owner, address spender) external view returns (uint256); 10 | function approve(address spender, uint256 amount) external returns (bool); 11 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 12 | 13 | event Transfer(address indexed from, address indexed to, uint256 value); 14 | event Approval(address indexed owner, address indexed spender, uint256 value); 15 | } 16 | 17 | contract MockGovVault { 18 | IERC20 public valueToken; 19 | 20 | constructor(IERC20 _valueToken) public { 21 | valueToken = _valueToken; 22 | } 23 | 24 | function addValueReward(uint256 _amount) external { 25 | valueToken.transferFrom(msg.sender, address(this), _amount); 26 | } 27 | 28 | function make_profit(uint256 _amount) external { 29 | valueToken.transferFrom(msg.sender, address(this), _amount); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /contracts/vaults/mock/MockSodaPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IERC20 { 6 | function totalSupply() external view returns (uint256); 7 | function balanceOf(address account) external view returns (uint256); 8 | function transfer(address recipient, uint256 amount) external returns (bool); 9 | function allowance(address owner, address spender) external view returns (uint256); 10 | function approve(address spender, uint256 amount) external returns (bool); 11 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 12 | 13 | event Transfer(address indexed from, address indexed to, uint256 value); 14 | event Approval(address indexed owner, address indexed spender, uint256 value); 15 | } 16 | 17 | interface ISodaPool { 18 | // Deposit LP tokens to SodaPool for SODA allocation 19 | function deposit(uint256 _poolId, uint256 _amount) external; 20 | 21 | // Claim SODA (and potentially other tokens depends on strategy). 22 | function claim(uint256 _poolId) external; 23 | 24 | // Withdraw LP tokens from SodaPool 25 | function withdraw(uint256 _poolId, uint256 _amount) external; 26 | } 27 | 28 | contract MockSodaPool is ISodaPool { 29 | IERC20 public sodaToken; 30 | IERC20 public lpToken; 31 | 32 | constructor(IERC20 _sodaToken, IERC20 _lpToken) public { 33 | sodaToken = _sodaToken; 34 | lpToken = _lpToken; 35 | } 36 | 37 | function deposit(uint256, uint256 _amount) public override { 38 | lpToken.transferFrom(msg.sender, address(this), _amount); 39 | } 40 | 41 | // mock: send rewards is anything this contract has 42 | function claim(uint256) public override { 43 | sodaToken.transfer(msg.sender, sodaToken.balanceOf(address(this))); 44 | } 45 | 46 | function withdraw(uint256, uint256 _amount) public override { 47 | lpToken.transfer(msg.sender, _amount); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /contracts/vaults/mock/MockSodaVault.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 6 | 7 | contract MockSodaVault is ERC20("Mock SodaVaultWETH", "msvWETH") { 8 | IERC20 public sodaToken; 9 | address public pool; 10 | 11 | constructor(IERC20 _sodaToken, address _pool) public { 12 | sodaToken = _sodaToken; 13 | pool = _pool; 14 | } 15 | 16 | function getPendingReward(address, uint256) public view returns (uint256) { 17 | return sodaToken.balanceOf(pool); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/vaults/mock/MockSushiPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IERC20 { 6 | function totalSupply() external view returns (uint256); 7 | function balanceOf(address account) external view returns (uint256); 8 | function transfer(address recipient, uint256 amount) external returns (bool); 9 | function allowance(address owner, address spender) external view returns (uint256); 10 | function approve(address spender, uint256 amount) external returns (bool); 11 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 12 | 13 | event Transfer(address indexed from, address indexed to, uint256 value); 14 | event Approval(address indexed owner, address indexed spender, uint256 value); 15 | } 16 | 17 | interface ISushiPool { 18 | function deposit(uint256 _poolId, uint256 _amount) external; 19 | function withdraw(uint256 _poolId, uint256 _amount) external; 20 | } 21 | 22 | contract MockSushiPool is ISushiPool { 23 | IERC20 public sushiToken; 24 | IERC20 public lpToken; 25 | 26 | constructor(IERC20 _sushiToken, IERC20 _lpToken) public { 27 | sushiToken = _sushiToken; 28 | lpToken = _lpToken; 29 | } 30 | 31 | function deposit(uint256, uint256 _amount) public override { 32 | lpToken.transferFrom(msg.sender, address(this), _amount); 33 | if (_amount == 0) { 34 | // claim 35 | sushiToken.transfer(msg.sender, sushiToken.balanceOf(address(this)) / 10); 36 | } 37 | } 38 | 39 | function withdraw(uint256, uint256 _amount) public override { 40 | lpToken.transfer(msg.sender, _amount); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /contracts/vaults/mock/MockUniswapRouter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | import "@openzeppelin/contracts/math/SafeMath.sol"; 7 | import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 8 | 9 | interface IUniswapRouter { 10 | function swapExactTokensForTokens( 11 | uint256 amountIn, 12 | uint256 amountOutMin, 13 | address[] calldata path, 14 | address to, 15 | uint256 deadline 16 | ) external returns (uint256[] memory amounts); 17 | 18 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 19 | uint256 amountIn, 20 | uint256 amountOutMin, 21 | address[] calldata path, 22 | address to, 23 | uint256 deadline 24 | ) external returns (uint256[] memory amounts); 25 | 26 | function addLiquidity( 27 | address tokenA, 28 | address tokenB, 29 | uint amountADesired, 30 | uint amountBDesired, 31 | uint amountAMin, 32 | uint amountBMin, 33 | address to, 34 | uint deadline 35 | ) external returns (uint amountA, uint amountB, uint liquidity); 36 | } 37 | 38 | contract MockUniswapRouter is IUniswapRouter { 39 | using SafeERC20 for IERC20; 40 | using SafeMath for uint256; 41 | 42 | IERC20 univ2LpToken; 43 | 44 | constructor(IERC20 _univ2LpToken) public { 45 | univ2LpToken = _univ2LpToken; 46 | } 47 | 48 | function swapExactTokensForTokens( 49 | uint256 amountIn, 50 | uint256 amountOutMin, 51 | address[] calldata path, 52 | address to, 53 | uint256 deadline 54 | ) public override returns (uint256[] memory amounts) { 55 | return _swap(amountIn, amountOutMin, path, to, deadline); 56 | } 57 | 58 | // address public msg_sender; 59 | // address public contract_address; 60 | 61 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 62 | uint256 amountIn, 63 | uint256 amountOutMin, 64 | address[] calldata path, 65 | address to, 66 | uint256 deadline 67 | ) external override returns (uint256[] memory amounts) { 68 | // msg_sender = msg.sender; 69 | // contract_address = address(this); 70 | return _swap(amountIn, amountOutMin, path, to, deadline); 71 | } 72 | 73 | function _swap( 74 | uint256 amountIn, 75 | uint256, 76 | address[] calldata path, 77 | address to, 78 | uint256 79 | ) internal returns (uint256[] memory amounts) { 80 | uint256 amountOut = amountIn.mul(1); // assume 1 INPUT -> 1 OUTPUT 81 | IERC20 inputToken = IERC20(path[0]); 82 | IERC20 outputToken = IERC20(path[path.length - 1]); 83 | inputToken.safeTransferFrom(msg.sender, address(this), amountIn); 84 | outputToken.safeTransfer(to, amountOut); 85 | amounts = new uint256[](2); 86 | amounts[0] = amountIn; 87 | amounts[1] = amountOut; 88 | } 89 | 90 | function addLiquidity( 91 | address tokenA, 92 | address tokenB, 93 | uint amountADesired, 94 | uint amountBDesired, 95 | uint, 96 | uint, 97 | address to, 98 | uint 99 | ) external override returns (uint amountA, uint amountB, uint liquidity) { 100 | amountA = (amountADesired < amountBDesired) ? amountADesired : amountBDesired; 101 | amountB = amountA; 102 | liquidity = amountA; 103 | IERC20(tokenA).safeTransferFrom(msg.sender, address(this), amountA); 104 | IERC20(tokenB).safeTransferFrom(msg.sender, address(this), amountB); 105 | univ2LpToken.safeTransfer(to, liquidity); // 1A + 1B -> 1LP 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /contracts/vaults/v1/ValueVault.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/math/SafeMath.sol"; 6 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 7 | import "./strategies/IStrategy.sol"; 8 | import "../ValueVaultMaster.sol"; 9 | 10 | contract ValueVault is ERC20 { 11 | using SafeMath for uint256; 12 | 13 | address public governance; 14 | 15 | mapping (address => uint256) public lockedAmount; 16 | 17 | IStrategy[] public strategies; 18 | 19 | uint256[] public strategyPreferredOrders; 20 | 21 | ValueVaultMaster public valueVaultMaster; 22 | 23 | constructor (ValueVaultMaster _valueVaultMaster, string memory _name, string memory _symbol) ERC20(_name, _symbol) public { 24 | valueVaultMaster = _valueVaultMaster; 25 | governance = tx.origin; 26 | } 27 | 28 | function setGovernance(address _governance) external { 29 | require(msg.sender == governance, "!governance"); 30 | governance = _governance; 31 | } 32 | 33 | function setStrategies(IStrategy[] memory _strategies) public { 34 | require(msg.sender == governance, "!governance"); 35 | delete strategies; 36 | for (uint256 i = 0; i < _strategies.length; ++i) { 37 | strategies.push(_strategies[i]); 38 | } 39 | } 40 | 41 | function setStrategyPreferredOrders(uint256[] memory _strategyPreferredOrders) public { 42 | require(msg.sender == governance, "!governance"); 43 | delete strategyPreferredOrders; 44 | for (uint256 i = 0; i < _strategyPreferredOrders.length; ++i) { 45 | strategyPreferredOrders.push(_strategyPreferredOrders[i]); 46 | } 47 | } 48 | 49 | function getStrategyCount() public view returns(uint count) { 50 | return strategies.length; 51 | } 52 | 53 | function depositAvailable() public view returns(bool) { 54 | if (strategies.length == 0) return false; 55 | for (uint256 i = 0; i < strategies.length; ++i) { 56 | IStrategy strategy = strategies[i]; 57 | uint256 quota = valueVaultMaster.strategyQuota(address(strategy)); 58 | if (quota == 0 || strategy.balanceOf(address(this)) < quota) { 59 | return true; 60 | } 61 | } 62 | return false; 63 | } 64 | 65 | /// @notice Creates `_amount` token to `_to`. Must only be called by ValueVaultBank. 66 | function mintByBank(IERC20 _token, address _to, uint256 _amount) public { 67 | require(_msgSender() == valueVaultMaster.bank(), "not bank"); 68 | 69 | _deposit(_token, _amount); 70 | if (_amount > 0) { 71 | _mint(_to, _amount); 72 | } 73 | } 74 | 75 | // Must only be called by ValueVaultBank. 76 | function burnByBank(IERC20 _token, address _account, uint256 _amount) public { 77 | require(_msgSender() == valueVaultMaster.bank(), "not bank"); 78 | 79 | uint256 balance = balanceOf(_account); 80 | require(lockedAmount[_account] + _amount <= balance, "Vault: burn too much"); 81 | 82 | _withdraw(_token, _amount); 83 | _burn(_account, _amount); 84 | } 85 | 86 | // Any user can transfer to another user. 87 | function transfer(address _to, uint256 _amount) public override returns (bool) { 88 | uint256 balance = balanceOf(_msgSender()); 89 | require(lockedAmount[_msgSender()] + _amount <= balance, "transfer: <= balance"); 90 | 91 | _transfer(_msgSender(), _to, _amount); 92 | 93 | return true; 94 | } 95 | 96 | function _deposit(IERC20 _token, uint256 _amount) internal { 97 | require(strategies.length > 0, "no strategies"); 98 | if (strategyPreferredOrders.length == 0 || strategyPreferredOrders.length != strategies.length) { 99 | for (uint256 i = 0; i < strategies.length; ++i) { 100 | IStrategy strategy = strategies[i]; 101 | uint256 quota = valueVaultMaster.strategyQuota(address(strategy)); 102 | if (quota == 0 || strategy.balanceOf(address(this)) < quota) { 103 | _token.transfer(address(strategy), _amount); 104 | strategy.deposit(address(this), _amount); 105 | return; 106 | } 107 | } 108 | } else { 109 | for (uint256 i = 0; i < strategies.length; ++i) { 110 | IStrategy strategy = strategies[strategyPreferredOrders[i]]; 111 | uint256 quota = valueVaultMaster.strategyQuota(address(strategy)); 112 | if (quota == 0 || strategy.balanceOf(address(this)) < quota) { 113 | _token.transfer(address(strategy), _amount); 114 | strategy.deposit(address(this), _amount); 115 | return; 116 | } 117 | } 118 | } 119 | revert("Exceeded quota"); 120 | } 121 | 122 | function _withdraw(IERC20 _token, uint256 _amount) internal { 123 | require(strategies.length > 0, "no strategies"); 124 | if (strategyPreferredOrders.length == 0 || strategyPreferredOrders.length != strategies.length) { 125 | for (uint256 i = strategies.length; i >= 1; --i) { 126 | IStrategy strategy = strategies[i - 1]; 127 | uint256 bal = strategy.balanceOf(address(this)); 128 | if (bal > 0) { 129 | strategy.withdraw(address(this), (bal > _amount) ? _amount : bal); 130 | _token.transferFrom(address(strategy), valueVaultMaster.bank(), _token.balanceOf(address(strategy))); 131 | if (_token.balanceOf(valueVaultMaster.bank()) >= _amount) break; 132 | } 133 | } 134 | } else { 135 | for (uint256 i = strategies.length; i >= 1; --i) { 136 | IStrategy strategy = strategies[strategyPreferredOrders[i - 1]]; 137 | uint256 bal = strategy.balanceOf(address(this)); 138 | if (bal > 0) { 139 | strategy.withdraw(address(this), (bal > _amount) ? _amount : bal); 140 | _token.transferFrom(address(strategy), valueVaultMaster.bank(), _token.balanceOf(address(strategy))); 141 | if (_token.balanceOf(valueVaultMaster.bank()) >= _amount) break; 142 | } 143 | } 144 | } 145 | } 146 | 147 | function harvestAllStrategies(uint256 _bankPoolId) external { 148 | require(_msgSender() == valueVaultMaster.bank(), "not bank"); 149 | for (uint256 i = 0; i < strategies.length; ++i) { 150 | strategies[i].harvest(_bankPoolId); 151 | } 152 | } 153 | 154 | function harvestStrategy(IStrategy _strategy, uint256 _bankPoolId) external { 155 | require(_msgSender() == valueVaultMaster.bank(), "not bank"); 156 | _strategy.harvest(_bankPoolId); 157 | } 158 | 159 | function withdrawStrategy(IStrategy _strategy, uint256 amount) external { 160 | require(msg.sender == governance, "!governance"); 161 | _strategy.withdraw(address(this), amount); 162 | } 163 | 164 | function claimStrategy(IStrategy _strategy) external { 165 | require(msg.sender == governance, "!governance"); 166 | _strategy.claim(address(this)); 167 | } 168 | 169 | /** 170 | * This function allows governance to take unsupported tokens out of the contract. 171 | * This is in an effort to make someone whole, should they seriously mess up. 172 | * There is no guarantee governance will vote to return these. 173 | * It also allows for removal of airdropped tokens. 174 | */ 175 | function governanceRecoverUnsupported(IERC20 _token, uint256 amount, address to) external { 176 | require(msg.sender == governance, "!governance"); 177 | _token.transfer(to, amount); 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /contracts/vaults/v1/strategies/IStrategy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | 7 | interface IStrategy { 8 | function approve(IERC20 _token) external; 9 | 10 | function approveForSpender(IERC20 _token, address spender) external; 11 | 12 | // Deposit tokens to a farm to yield more tokens. 13 | function deposit(address _vault, uint256 _amount) external; 14 | 15 | // Claim farming tokens 16 | function claim(address _vault) external; 17 | 18 | // The vault request to harvest the profit 19 | function harvest(uint256 _bankPoolId) external; 20 | 21 | // Withdraw the principal from a farm. 22 | function withdraw(address _vault, uint256 _amount) external; 23 | 24 | // Target farming token of this strategy. 25 | function getTargetToken(address _vault) external view returns(address); 26 | 27 | function balanceOf(address _vault) external view returns (uint256); 28 | 29 | function pendingReward(address _vault) external view returns (uint256); 30 | 31 | function expectedAPY(address _vault) external view returns (uint256); 32 | 33 | function governanceRescueToken(IERC20 _token) external returns (uint256); 34 | } 35 | -------------------------------------------------------------------------------- /contracts/vaults/v1/vaults/WETHVault.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "../ValueVault.sol"; 6 | 7 | contract WETHVault is ValueVault { 8 | constructor ( 9 | ValueVaultMaster _master, 10 | IStrategy _wethStrategy 11 | ) ValueVault(_master, "Value Vaults: WETH", "vWETH") public { 12 | IStrategy[] memory strategies = new IStrategy[](1); 13 | strategies[0] = _wethStrategy; 14 | setStrategies(strategies); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /contracts/vaults/v2/ValueVaultV2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/math/SafeMath.sol"; 6 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 7 | import "./strategies/IStrategyV2.sol"; 8 | import "../ValueVaultMaster.sol"; 9 | 10 | interface IValueVault { 11 | function getStrategyCount() external view returns(uint256); 12 | function depositAvailable() external view returns(bool); 13 | function mintByBank(IERC20 _token, address _to, uint256 _amount) external; 14 | function burnByBank(IERC20 _token, address _account, uint256 _amount) external; 15 | function harvestAllStrategies(uint256 _bankPoolId) external; 16 | function harvestStrategy(address _strategy, uint256 _bankPoolId) external; 17 | } 18 | 19 | contract ValueVaultV2 is IValueVault, ERC20 { 20 | using SafeMath for uint256; 21 | 22 | address public governance; 23 | 24 | IStrategyV2 public strategy; 25 | 26 | uint256[] public poolStrategyIds; // sorted by preference 27 | 28 | ValueVaultMaster public valueVaultMaster; 29 | 30 | constructor (ValueVaultMaster _valueVaultMaster, string memory _name, string memory _symbol) ERC20(_name, _symbol) public { 31 | valueVaultMaster = _valueVaultMaster; 32 | governance = tx.origin; 33 | } 34 | 35 | function setGovernance(address _governance) external { 36 | require(msg.sender == governance, "!governance"); 37 | governance = _governance; 38 | } 39 | 40 | function setStrategy(IStrategyV2 _strategy) public { 41 | require(msg.sender == governance, "!governance"); 42 | strategy = _strategy; 43 | } 44 | 45 | function setPoolStrategyIds(uint256[] memory _poolStrategyIds) public { 46 | require(msg.sender == governance, "!governance"); 47 | delete poolStrategyIds; 48 | for (uint256 i = 0; i < _poolStrategyIds.length; ++i) { 49 | poolStrategyIds.push(_poolStrategyIds[i]); 50 | } 51 | } 52 | 53 | function getStrategyCount() public override view returns(uint count) { 54 | return poolStrategyIds.length; 55 | } 56 | 57 | function depositAvailable() public override view returns(bool) { 58 | if (poolStrategyIds.length == 0) return false; 59 | for (uint256 i = 0; i < poolStrategyIds.length; ++i) { 60 | uint256 _pid = poolStrategyIds[i]; 61 | uint256 _quota = strategy.poolQuota(_pid); 62 | if (_quota == 0 || strategy.balanceOf(_pid) < _quota) { 63 | return true; 64 | } 65 | } 66 | return false; 67 | } 68 | 69 | /// @notice Creates `_amount` token to `_to`. Must only be called by ValueVaultBank. 70 | function mintByBank(IERC20 _token, address _to, uint256 _amount) public override { 71 | require(_msgSender() == valueVaultMaster.bank(), "not bank"); 72 | 73 | _deposit(_token, _amount); 74 | if (_amount > 0) { 75 | _mint(_to, _amount); 76 | } 77 | } 78 | 79 | // Must only be called by ValueVaultBank. 80 | function burnByBank(IERC20 _token, address _account, uint256 _amount) public override { 81 | require(_msgSender() == valueVaultMaster.bank(), "not bank"); 82 | 83 | uint256 balance = balanceOf(_account); 84 | require(lockedAmount[_account] + _amount <= balance, "Vault: burn too much"); 85 | 86 | _withdraw(_token, _amount); 87 | _burn(_account, _amount); 88 | } 89 | 90 | // Any user can transfer to another user. 91 | function transfer(address _to, uint256 _amount) public override returns (bool) { 92 | uint256 balance = balanceOf(_msgSender()); 93 | require(lockedAmount[_msgSender()] + _amount <= balance, "transfer: <= balance"); 94 | 95 | _transfer(_msgSender(), _to, _amount); 96 | 97 | return true; 98 | } 99 | 100 | function _deposit(IERC20 _token, uint256 _amount) internal { 101 | require(poolStrategyIds.length > 0, "no strategies"); 102 | for (uint256 i = 0; i < poolStrategyIds.length; ++i) { 103 | uint256 _pid = poolStrategyIds[i]; 104 | uint256 _quota = strategy.poolQuota(_pid); 105 | if (_quota == 0 || strategy.balanceOf(_pid) < _quota) { 106 | _token.transfer(address(strategy), _amount); 107 | strategy.deposit(_pid, _amount); 108 | return; 109 | } 110 | } 111 | revert("Exceeded quota"); 112 | } 113 | 114 | function _withdraw(IERC20 _token, uint256 _amount) internal { 115 | require(poolStrategyIds.length > 0, "no strategies"); 116 | for (uint256 i = poolStrategyIds.length; i >= 1; --i) { 117 | uint256 _pid = poolStrategyIds[i - 1]; 118 | uint256 bal = strategy.balanceOf(_pid); 119 | if (bal > 0) { 120 | strategy.withdraw(_pid, (bal > _amount) ? _amount : bal); 121 | _token.transferFrom(address(strategy), valueVaultMaster.bank(), _token.balanceOf(address(strategy))); 122 | if (_token.balanceOf(valueVaultMaster.bank()) >= _amount) break; 123 | } 124 | } 125 | } 126 | 127 | function harvestAllStrategies(uint256 _bankPoolId) external override { 128 | require(_msgSender() == valueVaultMaster.bank(), "not bank"); 129 | for (uint256 i = 0; i < poolStrategyIds.length; ++i) { 130 | strategy.harvest(_bankPoolId, poolStrategyIds[i]); 131 | } 132 | } 133 | 134 | function harvestStrategy(address _strategy, uint256 _bankPoolId) external override { 135 | require(_msgSender() == valueVaultMaster.bank(), "not bank"); 136 | IStrategyV2(_strategy).harvest(_bankPoolId, poolStrategyIds[0]); // always harvest the first pool 137 | } 138 | 139 | function harvestStrategy(uint256 _bankPoolId, uint256 _poolStrategyId) external { 140 | require(msg.sender == governance, "!governance"); 141 | strategy.harvest(_bankPoolId, _poolStrategyId); 142 | } 143 | 144 | function withdrawStrategy(IStrategyV2 _strategy, uint256 _poolStrategyId, uint256 _amount) external { 145 | require(msg.sender == governance, "!governance"); 146 | _strategy.withdraw(_poolStrategyId, _amount); 147 | } 148 | 149 | function claimStrategy(IStrategyV2 _strategy, uint256 _poolStrategyId) external { 150 | require(msg.sender == governance, "!governance"); 151 | _strategy.claim(_poolStrategyId); 152 | } 153 | 154 | function forwardBetweenStrategies(IStrategyV2 _source, IStrategyV2 _dest, uint256 _amount) external { 155 | require(msg.sender == governance, "!governance"); 156 | _source.forwardToAnotherStrategy(address(_dest), _amount); 157 | } 158 | 159 | /** 160 | * This function allows governance to take unsupported tokens out of the contract. 161 | * This is in an effort to make someone whole, should they seriously mess up. 162 | * There is no guarantee governance will vote to return these. 163 | * It also allows for removal of airdropped tokens. 164 | */ 165 | function governanceRecoverUnsupported(IERC20 _token, uint256 _amount, address _to) external { 166 | require(msg.sender == governance, "!governance"); 167 | _token.transfer(_to, _amount); 168 | } 169 | 170 | event ExecuteTransaction(address indexed target, uint value, string signature, bytes data); 171 | 172 | function executeTransaction(address target, uint value, string memory signature, bytes memory data) public returns (bytes memory) { 173 | require(msg.sender == governance, "!governance"); 174 | 175 | bytes memory callData; 176 | 177 | if (bytes(signature).length == 0) { 178 | callData = data; 179 | } else { 180 | callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data); 181 | } 182 | 183 | // solium-disable-next-line security/no-call-value 184 | (bool success, bytes memory returnData) = target.call{value: value}(callData); 185 | require(success, "Univ2ETHUSDCMultiPoolStrategy::executeTransaction: Transaction execution reverted."); 186 | 187 | emit ExecuteTransaction(target, value, signature, data); 188 | 189 | return returnData; 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /contracts/vaults/v2/strategies/IStrategyV2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | 7 | interface IStrategyV2 { 8 | function approve(IERC20 _token) external; 9 | 10 | function approveForSpender(IERC20 _token, address spender) external; 11 | 12 | // Deposit tokens to a farm to yield more tokens. 13 | function deposit(uint256 _poolId, uint256 _amount) external; 14 | 15 | // Claim farming tokens 16 | function claim(uint256 _poolId) external; 17 | 18 | // The vault request to harvest the profit 19 | function harvest(uint256 _bankPoolId, uint256 _poolId) external; 20 | 21 | // Withdraw the principal from a farm. 22 | function withdraw(uint256 _poolId, uint256 _amount) external; 23 | 24 | // Set 0 to disable quota (no limit) 25 | function poolQuota(uint256 _poolId) external view returns (uint256); 26 | 27 | // Use when we want to switch between strategies 28 | function forwardToAnotherStrategy(address _dest, uint256 _amount) external returns (uint256); 29 | 30 | // Source LP token of this strategy 31 | function getLpToken() external view returns(address); 32 | 33 | // Target farming token of this strategy by vault 34 | function getTargetToken(uint256 _poolId) external view returns(address); 35 | 36 | function balanceOf(uint256 _poolId) external view returns (uint256); 37 | 38 | function pendingReward(uint256 _poolId) external view returns (uint256); 39 | 40 | // Helper function, Should never use it on-chain. 41 | // Return 1e18x of APY. _lpPairUsdcPrice = current lpPair price (1-wei in USDC-wei) multiple by 1e18 42 | function expectedAPY(uint256 _poolId, uint256 _lpPairUsdcPrice) external view returns (uint256); 43 | 44 | function governanceRescueToken(IERC20 _token) external returns (uint256); 45 | } 46 | -------------------------------------------------------------------------------- /contracts/vaults/v2/vaults/UNIv2ETHUSDCVault.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "../ValueVaultV2.sol"; 6 | 7 | contract UNIv2ETHUSDCVault is ValueVaultV2 { 8 | constructor ( 9 | ValueVaultMaster _master, 10 | IStrategyV2 _univ2ethusdcStrategy 11 | ) ValueVaultV2(_master, "Value Vaults: UNIv2ETHUSDC", "vUNIv2ETHUSDC") public { 12 | setStrategy(_univ2ethusdcStrategy); 13 | uint256[] memory _poolStrategyIds = new uint256[](1); 14 | _poolStrategyIds[0] = 0; 15 | setPoolStrategyIds(_poolStrategyIds); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /contracts/vaults/v2/vaults/UNIv2ETHWBTCVault.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "../ValueVaultV2.sol"; 6 | 7 | contract UNIv2ETHWBTCVault is ValueVaultV2 { 8 | constructor ( 9 | ValueVaultMaster _master, 10 | IStrategyV2 _univ2ethwbtcStrategy 11 | ) ValueVaultV2(_master, "Value Vaults: UNIv2ETHWBTC", "vUNIv2ETHWBTC") public { 12 | setStrategy(_univ2ethwbtcStrategy); 13 | uint256[] memory _poolStrategyIds = new uint256[](1); 14 | _poolStrategyIds[0] = 0; 15 | setPoolStrategyIds(_poolStrategyIds); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "value-vaults", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "description": "Value Vaults Contracts and ABI", 7 | "scripts": { 8 | "build": "hardhat typechain", 9 | "deploy": "hardhat deploy", 10 | "deploy-kovan": "hardhat deploy --network kovan", 11 | "kovan-addresses": "hardhat --network kovan run scripts/addresses.ts", 12 | "compile": "hardhat compile", 13 | "test": "hardhat test", 14 | "test:verbose": "VERBOSE=true hardhat test", 15 | "coverage": "npm run build && npx buidler coverage --temp artifacts --network coverage", 16 | "truffle-test": "truffle test", 17 | "truffle-test:verbose": "VERBOSE=true truffle test", 18 | "lint": "eslint .", 19 | "lint:contracts": "solhint contracts/*.sol", 20 | "flat:contracts": "sol-merger \"./contracts/*.sol\" ./build", 21 | "flat:contracts-vaults": "sol-merger \"./contracts/vaults/*.sol\" ./build/vaults", 22 | "flat:contracts-vaults-misc": "sol-merger \"./contracts/vaults/misc/*.sol\" ./build/vaults/misc", 23 | "flat:contracts-vaults-mock": "sol-merger \"./contracts/vaults/mock/*.sol\" ./build/vaults/mock", 24 | "flat:contracts-vaults-strategies": "sol-merger \"./contracts/vaults/v2/strategies/*.sol\" ./build/vaults/v2/strategies" 25 | }, 26 | "repository": { 27 | "type": "git", 28 | "url": "git+https://github.com/valuedefi/vaults.git" 29 | }, 30 | "bugs": { 31 | "url": "https://github.com/valuedefi/vaults/issues" 32 | }, 33 | "homepage": "https://github.com/valuedefi/vaults#readme", 34 | "devDependencies": { 35 | "hardhat": "^2.0.3", 36 | "ethers": "^5.0.19", 37 | "typechain": "^3.0.0", 38 | "hardhat-typechain": "^0.3.3", 39 | "@typechain/ethers-v5": "^2.0.0", 40 | "hardhat-deploy": "^0.7.0-beta.28", 41 | "hardhat-deploy-ethers": "^0.3.0-beta.5", 42 | "@nomiclabs/hardhat-vyper": "^2.0.0", 43 | "@nomiclabs/hardhat-truffle5": "^2.0.0", 44 | "@nomiclabs/hardhat-web3": "^2.0.0", 45 | "@openzeppelin/test-helpers": "^0.5.9", 46 | "@ethereum-waffle/chai": "^3.0.2", 47 | "bignumber.js": "^9.0.1", 48 | "solidity-coverage": "^0.7.11", 49 | "ts-node": "^9.0.0", 50 | "typescript": "^4.0.3", 51 | "@types/chai": "^4.2.14", 52 | "@types/mocha": "^8.0.3", 53 | "@types/node": "^14.14.2", 54 | "@openzeppelin/contracts": "^3.2.0", 55 | "dotenv": "^8.2.0" 56 | }, 57 | "dependencies": { 58 | "@openzeppelin/contracts-ethereum-package": "^3.0.0" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /test/governance-vault/gov_vault.test.js: -------------------------------------------------------------------------------- 1 | const {expectRevert, time} = require('@openzeppelin/test-helpers'); 2 | 3 | const ValueLiquidityToken = artifacts.require('ValueLiquidityToken'); 4 | const ValueGovernanceVault = artifacts.require('ValueGovernanceVault'); 5 | const YFVReferral = artifacts.require('YFVReferral'); 6 | const MockERC20 = artifacts.require('MockERC20'); 7 | 8 | const ADDRESS_ZERO = '0x0000000000000000000000000000000000000000'; 9 | 10 | contract('ValueGovernanceVault.test', ([alice, bob, carol, insuranceFund, minter]) => { 11 | beforeEach(async () => { 12 | this.vUSD = await MockERC20.new('Value USD', 'vUSD', 9, 10000000, {from: alice}); 13 | this.vETH = await MockERC20.new('Value ETH', 'vETH', 9, 10000000, {from: alice}); 14 | this.yfv = await MockERC20.new('YFValue', 'YFV', 18, 40000000, {from: alice}); 15 | this.value = await ValueLiquidityToken.new(this.yfv.address, 2370000, {from: alice}); 16 | await this.yfv.approve(this.value.address, '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', {from: alice}); 17 | await this.value.deposit(20000000, {from: alice}); 18 | }); 19 | 20 | it('should work', async () => { 21 | this.govVault = await ValueGovernanceVault.new(this.yfv.address, this.value.address, this.vUSD.address, this.vETH.address, 0, 500, 0); 22 | await this.value.addMinter(this.govVault.address, {from: alice}); 23 | await this.vUSD.addMinter(this.govVault.address, {from: alice}); 24 | await this.vETH.addMinter(this.govVault.address, {from: alice}); 25 | await this.yfv.transfer(bob, '1000'); 26 | await this.value.transfer(carol, '1000'); 27 | await this.yfv.approve(this.govVault.address, '1000', {from: bob}); 28 | await this.value.approve(this.govVault.address, '1000', {from: bob}); 29 | await this.value.approve(this.govVault.address, '2000', {from: carol}); 30 | await this.govVault.depositYFV(100, ADDRESS_ZERO, 0x0, {from: bob}); 31 | await this.govVault.deposit(1000, ADDRESS_ZERO, 0x0, {from: carol}); 32 | assert.equal(String(await this.govVault.totalSupply()), '1100'); 33 | assert.equal(String(await this.govVault.balanceOf(this.govVault.address)), '1100'); 34 | assert.equal(String(await this.govVault.balanceOf(bob)), '0'); 35 | assert.equal(String(await this.govVault.balanceOf(carol)), '0'); 36 | console.log('\n===== BEFORE setXxxPerBlock'); 37 | for (let i = 1; i <= 10; i++) { 38 | await time.advanceBlock(); 39 | console.log('latestBlock=%s', await time.latestBlock()); 40 | console.log('--> pendingValue(bob) = %s', String(await this.govVault.pendingValue(bob))); 41 | console.log('--> pendingVusd(bob) = %s', String(await this.govVault.pendingVusd(bob))); 42 | console.log('--> pendingValue(carol) = %s', String(await this.govVault.pendingValue(carol))); 43 | console.log('--> pendingVusd(carol) = %s', String(await this.govVault.pendingVusd(carol))); 44 | } 45 | // await this.govVault.unstake(0, 0x0, {from: carol}); 46 | await this.govVault.setValuePerBlock(20); 47 | await this.govVault.setVusdPerBlock(0); 48 | console.log('===== AFTER setXxxPerBlock'); 49 | for (let i = 1; i <= 10; i++) { 50 | await time.advanceBlock(); 51 | console.log('latestBlock=%s', await time.latestBlock()); 52 | console.log('--> pendingValue(bob) = %s', String(await this.govVault.pendingValue(bob))); 53 | console.log('--> pendingVusd(bob) = %s', String(await this.govVault.pendingVusd(bob))); 54 | console.log('--> pendingValue(carol) = %s', String(await this.govVault.pendingValue(carol))); 55 | console.log('--> pendingVusd(carol) = %s', String(await this.govVault.pendingVusd(carol))); 56 | } 57 | // console.log('--> userInfo(bob) = %s', JSON.stringify(await this.govVault.userInfo(bob))); 58 | // console.log('gvVALUE vault = %s', String(await this.govVault.balanceOf(this.govVault.address))); 59 | await this.govVault.withdrawAll(0x0, {from: bob}); 60 | // await this.govVault.unstake(100, 0x0, {from: bob}); 61 | console.log('VALUE bob = %s', String(await this.value.balanceOf(bob))); 62 | console.log('VALUE carol = %s', String(await this.value.balanceOf(carol))); 63 | console.log('gvVALUE bob = %s', String(await this.govVault.balanceOf(bob))); 64 | console.log('gvVALUE carol = %s', String(await this.govVault.balanceOf(carol))); 65 | 66 | console.log('\n===== BEFORE make_profit'); 67 | console.log('VALUE govVault = %s', String(await this.value.balanceOf(this.govVault.address))); 68 | console.log('getPricePerFullShare = %s', String(await this.govVault.getPricePerFullShare())); 69 | await this.value.transfer(this.govVault.address, '1000'); 70 | console.log('===== AFTER make_profit'); 71 | console.log('VALUE govVault = %s', String(await this.value.balanceOf(this.govVault.address))); 72 | console.log('getPricePerFullShare = %s', String(await this.govVault.getPricePerFullShare())); 73 | 74 | console.log('\n===== BEFORE buyShares'); 75 | console.log('VALUE bob = %s', String(await this.value.balanceOf(bob))); 76 | console.log('gvVALUE bob = %s', String(await this.govVault.balanceOf(bob))); 77 | await this.govVault.buyShares(100, 0x0, {from: bob}); 78 | console.log('===== AFTER buyShares'); 79 | console.log('VALUE bob = %s', String(await this.value.balanceOf(bob))); 80 | console.log('gvVALUE bob = %s', String(await this.govVault.balanceOf(bob))); 81 | console.log('--> userInfo(carol) = %s', JSON.stringify(await this.govVault.userInfo(carol))); 82 | console.log('VALUE carol = %s', String(await this.value.balanceOf(carol))); 83 | console.log('gvVALUE carol = %s', String(await this.govVault.balanceOf(carol))); 84 | console.log('VALUE govVault = %s', String(await this.value.balanceOf(this.govVault.address))); 85 | console.log('gvVALUE govVault = %s', String(await this.govVault.balanceOf(this.govVault.address))); 86 | 87 | console.log('\n===== AFTER carol withdrawAll'); 88 | await this.govVault.getRewardAndDepositAll(0x0, {from: carol}); 89 | await this.govVault.unstake(1000, 0x0, {from: carol}); 90 | await this.govVault.approve(this.govVault.address, '981', {from: carol}); 91 | await this.govVault.depositShares(981, bob, 0x0, {from: carol}); 92 | await this.govVault.withdrawAll(0x0, {from: carol}); 93 | // await this.govVault.withdraw(981, 0x0, {from: carol}); 94 | console.log('VALUE carol = %s', String(await this.value.balanceOf(carol))); 95 | console.log('gvVALUE carol = %s', String(await this.govVault.balanceOf(carol))); 96 | console.log('vUSD carol = %s', String(await this.vUSD.balanceOf(carol))); 97 | console.log('vETH carol = %s', String(await this.vETH.balanceOf(carol))); 98 | console.log('VALUE govVault = %s', String(await this.value.balanceOf(this.govVault.address))); 99 | console.log('gvVALUE govVault = %s', String(await this.govVault.balanceOf(this.govVault.address))); 100 | console.log('getPricePerFullShare = %s', String(await this.govVault.getPricePerFullShare())); 101 | 102 | console.log('\n===== AFTER bob withdraw'); 103 | await this.govVault.withdraw(50, 0x0, {from: bob}); 104 | console.log('VALUE bob = %s', String(await this.value.balanceOf(bob))); 105 | console.log('gvVALUE bob = %s', String(await this.govVault.balanceOf(bob))); 106 | console.log('vUSD bob = %s', String(await this.vUSD.balanceOf(bob))); 107 | console.log('vETH bob = %s', String(await this.vETH.balanceOf(bob))); 108 | console.log('VALUE govVault = %s', String(await this.value.balanceOf(this.govVault.address))); 109 | console.log('gvVALUE govVault = %s', String(await this.govVault.balanceOf(this.govVault.address))); 110 | console.log('getPricePerFullShare = %s', String(await this.govVault.getPricePerFullShare())); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /test/governance-vault/gov_vault_lock_and_boost.test.js: -------------------------------------------------------------------------------- 1 | const {expectRevert, time} = require('@openzeppelin/test-helpers'); 2 | 3 | const ValueLiquidityToken = artifacts.require('ValueLiquidityToken'); 4 | const ValueGovernanceVault = artifacts.require('ValueGovernanceVault'); 5 | const YFVReferral = artifacts.require('YFVReferral'); 6 | const MockERC20 = artifacts.require('MockERC20'); 7 | 8 | const ADDRESS_ZERO = '0x0000000000000000000000000000000000000000'; 9 | 10 | contract('gov_vault_lock_and_boost.test', ([alice, bob, carol, david, insuranceFund, minter]) => { 11 | beforeEach(async () => { 12 | this.vUSD = await MockERC20.new('Value USD', 'vUSD', 9, 10000000, {from: alice}); 13 | this.vETH = await MockERC20.new('Value ETH', 'vETH', 9, 10000000, {from: alice}); 14 | this.yfv = await MockERC20.new('YFValue', 'YFV', 18, 40000000, {from: alice}); 15 | this.value = await ValueLiquidityToken.new(this.yfv.address, 2370000, {from: alice}); 16 | await this.yfv.approve(this.value.address, '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', {from: alice}); 17 | await this.value.deposit(20000000, {from: alice}); 18 | }); 19 | 20 | it('should work', async () => { 21 | this.govVault = await ValueGovernanceVault.new(this.yfv.address, this.value.address, this.vUSD.address, this.vETH.address, 100, 500, 0); 22 | await this.value.addMinter(this.govVault.address, {from: alice}); 23 | await this.vUSD.addMinter(this.govVault.address, {from: alice}); 24 | await this.vETH.addMinter(this.govVault.address, {from: alice}); 25 | await this.value.transfer(bob, '1000'); 26 | await this.value.transfer(carol, '1000'); 27 | await this.value.transfer(david, '1000'); 28 | await this.value.approve(this.govVault.address, '2000', {from: bob}); 29 | await this.value.approve(this.govVault.address, '2000', {from: carol}); 30 | await this.value.approve(this.govVault.address, '2000', {from: david}); 31 | await this.govVault.deposit(1000, ADDRESS_ZERO, 0x0, {from: bob}); 32 | await this.govVault.deposit(1000, ADDRESS_ZERO, 0x0, {from: carol}); 33 | await this.govVault.deposit(1000, ADDRESS_ZERO, 0x0, {from: david}); 34 | assert.equal(String(await this.govVault.totalSupply()), '3000'); 35 | assert.equal(String(await this.govVault.balanceOf(this.govVault.address)), '3000'); 36 | assert.equal(String(await this.govVault.balanceOf(bob)), '0'); 37 | assert.equal(String(await this.govVault.balanceOf(carol)), '0'); 38 | assert.equal(String(await this.govVault.balanceOf(david)), '0'); 39 | console.log('\n===== BEFORE LOCK'); 40 | for (let i = 1; i <= 10; i++) { 41 | await time.advanceBlock(); 42 | console.log('latestBlock=%s', await time.latestBlock()); 43 | console.log('--> pendingValue(bob) = %s', String(await this.govVault.pendingValue(bob))); 44 | console.log('--> pendingValue(carol) = %s', String(await this.govVault.pendingValue(carol))); 45 | console.log('--> pendingValue(david) = %s', String(await this.govVault.pendingValue(david))); 46 | } 47 | await this.govVault.lockShares('1000', '7', 0x0, {from: carol}); 48 | await this.govVault.lockShares('300', '150', 0x0, {from: david}); 49 | console.log('===== AFTER LOCK'); 50 | for (let i = 1; i <= 10; i++) { 51 | await time.advanceBlock(); 52 | console.log('latestBlock=%s', await time.latestBlock()); 53 | console.log('--> pendingValue(bob) = %s', String(await this.govVault.pendingValue(bob))); 54 | console.log('--> pendingValue(carol) = %s', String(await this.govVault.pendingValue(carol))); 55 | console.log('--> pendingValue(david) = %s', String(await this.govVault.pendingValue(david))); 56 | } 57 | await this.govVault.withdrawAll(0x0, {from: bob}); 58 | await this.govVault.withdrawAll(0x0, {from: carol}); 59 | await expectRevert( 60 | this.govVault.unstake(701, 0x0, {from: david}), 61 | 'stakedBal-locked < _amount', 62 | ); 63 | await this.govVault.unstake(700, 0x0, {from: david}); 64 | await this.govVault.withdraw(687, 0x0, {from: david}); 65 | console.log('\n===== AFTER WITHDRAWALL'); 66 | console.log('VALUE bob = %s', String(await this.value.balanceOf(bob))); 67 | console.log('VALUE carol = %s', String(await this.value.balanceOf(carol))); 68 | console.log('VALUE david = %s', String(await this.value.balanceOf(david))); 69 | console.log('--> userInfo(bob) = %s', JSON.stringify(await this.govVault.userInfo(bob))); 70 | console.log('--> userInfo(carol) = %s', JSON.stringify(await this.govVault.userInfo(carol))); 71 | console.log('--> userInfo(david) = %s', JSON.stringify(await this.govVault.userInfo(david))); 72 | }); 73 | }); 74 | --------------------------------------------------------------------------------