├── .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 |
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 |
--------------------------------------------------------------------------------