From dd4e3624c40aebd99238e89f6b4e137e9d133efc Mon Sep 17 00:00:00 2001 From: "pata.eth" Date: Fri, 27 May 2022 19:35:19 -0400 Subject: [PATCH] updates following review from strategists and security on https://github.com/dudesahn/StrategyCurveTemplate/pull/8 --- brownie-config.yml | 20 ++-- contracts/StrategyCurveGeist.sol | 66 +++++------ contracts/interfaces/curve.sol | 125 ++------------------ contracts/interfaces/yearn.sol | 43 ------- scripts/deploy.py | 6 +- tests/conftest.py | 37 ++++-- tests/test_base_strategy.py | 2 +- tests/test_change_debt.py | 2 +- tests/test_change_debt_with_profit.py | 2 +- tests/test_emergency_exit.py | 6 +- tests/test_emergency_shutdown_from_vault.py | 2 +- tests/test_liq_gauge.py | 29 +++++ tests/test_migration.py | 93 +++++++++++++-- tests/test_odds_and_ends.py | 30 ++--- tests/test_remove_from_withdrawal_queue.py | 2 +- tests/test_revoke.py | 2 +- tests/test_setters.py | 2 +- tests/test_simple_harvest.py | 10 +- tests/test_sweep.py | 2 +- tests/test_triggers.py | 4 +- tests/test_withdraw_after_donation.py | 30 ++--- 21 files changed, 248 insertions(+), 267 deletions(-) delete mode 100644 contracts/interfaces/yearn.sol create mode 100644 tests/test_liq_gauge.py diff --git a/brownie-config.yml b/brownie-config.yml index f1c0e48..d9f8bc9 100644 --- a/brownie-config.yml +++ b/brownie-config.yml @@ -1,24 +1,24 @@ # use Ganache's forked mainnet mode as the default network # NOTE: You don't *have* to do this, but it is often helpful for testing networks: - default: mainnet-fork + default: ftm-main-fork # automatically fetch contract sources from Etherscan autofetch_sources: True # require OpenZepplin Contracts dependencies: - - yearn/yearn-vaults@0.4.3 - - OpenZeppelin/openzeppelin-contracts@3.1.0 + - yearn/yearn-vaults@0.4.3-1 + - OpenZeppelin/openzeppelin-contracts@3.1.0 # path remapping to support imports from GitHub/NPM compiler: - solc: - version: - remappings: - - "@yearnvaults=yearn/yearn-vaults@0.4.3" - - "@openzeppelin=OpenZeppelin/openzeppelin-contracts@3.1.0" + solc: + version: + remappings: + - "@yearnvaults=yearn/yearn-vaults@0.4.3-1" + - "@openzeppelin=OpenZeppelin/openzeppelin-contracts@3.1.0" reports: - exclude_contracts: - - SafeMath + exclude_contracts: + - SafeMath diff --git a/contracts/StrategyCurveGeist.sol b/contracts/StrategyCurveGeist.sol index 44060a3..bd433c5 100644 --- a/contracts/StrategyCurveGeist.sol +++ b/contracts/StrategyCurveGeist.sol @@ -9,32 +9,9 @@ import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; import "@openzeppelin/contracts/math/Math.sol"; -import "./interfaces/curve.sol"; -import "./interfaces/yearn.sol"; +import {IGauge, IGaugeFactory, ICurveFi} from "./interfaces/curve.sol"; import {IUniswapV2Router02} from "./interfaces/uniswap.sol"; -import { - BaseStrategy, - StrategyParams -} from "@yearnvaults/contracts/BaseStrategy.sol"; - -interface IBaseFee { - function isCurrentBaseFeeAcceptable() external view returns (bool); -} - -interface IUniV3 { - struct ExactInputParams { - bytes path; - address recipient; - uint256 deadline; - uint256 amountIn; - uint256 amountOutMinimum; - } - - function exactInput(ExactInputParams calldata params) - external - payable - returns (uint256 amountOut); -} +import {BaseStrategy, StrategyParams} from "@yearnvaults/contracts/BaseStrategy.sol"; abstract contract StrategyCurveBase is BaseStrategy { using SafeERC20 for IERC20; @@ -46,7 +23,10 @@ abstract contract StrategyCurveBase is BaseStrategy { // Curve stuff IGauge public constant gauge = - IGauge(0xd4F94D0aaa640BBb72b5EEc2D85F6D114D81a88E); // Curve gauge contract, most are tokenized, held by strategy + IGauge(0xF7b9c402c4D6c2eDbA04a7a515b53D11B1E9b2cc); // Curve gauge contract, most are tokenized, held by strategy + + IGaugeFactory public constant gaugeFactory = + IGaugeFactory(0xabC000d88f23Bb45525E447528DBF656A9D55bf5); // keepCRV stuff uint256 public keepCRV; // the percentage of CRV we re-lock for boost (in basis points) @@ -130,7 +110,23 @@ abstract contract StrategyCurveBase is BaseStrategy { return balanceOfWant(); } + function _claimRewards() internal { + // Claims any pending CRV + // + // Mints claimable CRV from the factory gauge. Reward tokens are sent to `msg.sender` + gaugeFactory.mint(address(gauge)); + + // harvest third-party rewards from the gauge, if any + gauge.claim_rewards(); + } + + function claimRewards() external onlyVaultManagers { + _claimRewards(); + } + function prepareMigration(address _newStrategy) internal override { + // Withdraw LP tokens from the gauge. The transfer to the new strategy is done + // by migrate() in BaseStrategy.sol uint256 _stakedBal = stakedBalance(); if (_stakedBal > 0) { gauge.withdraw(_stakedBal); @@ -215,8 +211,10 @@ contract StrategyCurveGeist is StrategyCurveBase { usdc.approve(address(curve), type(uint256).max); fusdt.safeApprove(address(curve), type(uint256).max); - // start off with fusdt - targetToken = address(fusdt); + //'targetToken' is the token with the least impact on the curve pool at the time of deposit + // or the one with the biggest bonus. 'targetToken' is updated by yearn when granted by + // market conditions. We start off with usdc. + targetToken = address(usdc); } /* ========== MUTATIVE FUNCTIONS ========== */ @@ -231,12 +229,14 @@ contract StrategyCurveGeist is StrategyCurveBase { uint256 _debtPayment ) { - // harvest our rewards from the gauge - gauge.claim_rewards(); + // Claim and get a fresh snapshot of the strategy's CRV and GEIST balance + _claimRewards(); + uint256 crvBalance = crv.balanceOf(address(this)); uint256 wftmBalance = wftm.balanceOf(address(this)); uint256 geistBalance = geist.balanceOf(address(this)); - // if we claimed any CRV, then sell it + + // Sell CRV if we have any if (crvBalance > 0) { // keep some of our CRV to increase our boost uint256 sendToVoter = crvBalance.mul(keepCRV).div(FEE_DENOMINATOR); @@ -257,7 +257,7 @@ contract StrategyCurveGeist is StrategyCurveBase { _sellToken(address(wftm), wftmBalance); } - // sell the rest of our CRV + // Sell GEIST if we have any if (geistBalance > 0) { _sellToken(address(geist), geistBalance); } @@ -374,7 +374,7 @@ contract StrategyCurveGeist is StrategyCurveBase { // These functions are useful for setting parameters of the strategy that may need to be adjusted. // Set optimal token to sell harvested funds for depositing to Curve. - // Default is fUSDT, but can be set to USDC or DAI as needed by strategist or governance. + // Default is USDC, but can be set to fUSDT or DAI as needed by strategist or governance. function setOptimal(uint256 _optimal) external onlyAuthorized { if (_optimal == 0) { targetToken = address(dai); diff --git a/contracts/interfaces/curve.sol b/contracts/interfaces/curve.sol index f6a02de..5a49c06 100644 --- a/contracts/interfaces/curve.sol +++ b/contracts/interfaces/curve.sol @@ -2,138 +2,31 @@ pragma solidity 0.6.12; pragma experimental ABIEncoderV2; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; - interface IGauge { function deposit(uint256) external; function balanceOf(address) external view returns (uint256); + function withdraw(uint256) external; + function claim_rewards() external; - function claimable_tokens(address) external view returns (uint256); + // CRV + function claimable_tokens(address) external returns (uint256); - function claimable_reward(address _addressToCheck, address _rewardToken) - external - view - returns (uint256); + // Third-party tokens only + function claimable_reward(address, address) external view returns (uint256); +} - function withdraw(uint256) external; +interface IGaugeFactory { + function mint(address _gauge) external; } interface ICurveFi { - function get_virtual_price() external view returns (uint256); - - function add_liquidity( - // EURt - uint256[2] calldata amounts, - uint256 min_mint_amount - ) external payable; - - function add_liquidity( - // Compound, sAave - uint256[2] calldata amounts, - uint256 min_mint_amount, - bool _use_underlying - ) external payable returns (uint256); - function add_liquidity( // Iron Bank, Aave uint256[3] calldata amounts, uint256 min_mint_amount, bool _use_underlying ) external payable returns (uint256); - - function add_liquidity( - // 3Crv Metapools - address pool, - uint256[4] calldata amounts, - uint256 min_mint_amount - ) external; - - function add_liquidity( - // Y and yBUSD - uint256[4] calldata amounts, - uint256 min_mint_amount, - bool _use_underlying - ) external payable returns (uint256); - - function add_liquidity( - // 3pool - uint256[3] calldata amounts, - uint256 min_mint_amount - ) external payable; - - function add_liquidity( - // sUSD - uint256[4] calldata amounts, - uint256 min_mint_amount - ) external payable; - - function remove_liquidity_imbalance( - uint256[2] calldata amounts, - uint256 max_burn_amount - ) external; - - function remove_liquidity(uint256 _amount, uint256[2] calldata amounts) - external; - - function remove_liquidity_one_coin( - uint256 _token_amount, - int128 i, - uint256 min_amount - ) external; - - function exchange( - int128 from, - int128 to, - uint256 _from_amount, - uint256 _min_to_amount - ) external; - - function balances(uint256) external view returns (uint256); - - function get_dy( - int128 from, - int128 to, - uint256 _from_amount - ) external view returns (uint256); - - // EURt - function calc_token_amount(uint256[2] calldata _amounts, bool _is_deposit) - external - view - returns (uint256); - - // 3Crv Metapools - function calc_token_amount( - address _pool, - uint256[4] calldata _amounts, - bool _is_deposit - ) external view returns (uint256); - - // sUSD, Y pool, etc - function calc_token_amount(uint256[4] calldata _amounts, bool _is_deposit) - external - view - returns (uint256); - - // 3pool, Iron Bank, etc - function calc_token_amount(uint256[3] calldata _amounts, bool _is_deposit) - external - view - returns (uint256); - - function calc_withdraw_one_coin(uint256 amount, int128 i) - external - view - returns (uint256); -} - -interface ICrvV3 is IERC20 { - function minter() external view returns (address); -} - -interface IMinter { - function mint(address) external; } diff --git a/contracts/interfaces/yearn.sol b/contracts/interfaces/yearn.sol deleted file mode 100644 index fa8104e..0000000 --- a/contracts/interfaces/yearn.sol +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0 -pragma solidity 0.6.12; -pragma experimental ABIEncoderV2; - -import {IERC20} from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; - -interface ICurveStrategyProxy { - function proxy() external returns (address); - - function balanceOf(address _gauge) external view returns (uint256); - - function deposit(address _gauge, address _token) external; - - function withdraw( - address _gauge, - address _token, - uint256 _amount - ) external returns (uint256); - - function withdrawAll(address _gauge, address _token) - external - returns (uint256); - - function harvest(address _gauge) external; - - function lock() external; - - function approveStrategy(address) external; - - function revokeStrategy(address) external; - - function claimRewards(address _gauge, address _token) external; -} - -interface IVoter { - function execute( - address to, - uint256 value, - bytes calldata data - ) external returns (bool, bytes memory); - - function increaseAmount(uint256) external; -} diff --git a/scripts/deploy.py b/scripts/deploy.py index 61ded47..55af9f2 100644 --- a/scripts/deploy.py +++ b/scripts/deploy.py @@ -1,6 +1,6 @@ from pathlib import Path -from brownie import Strategy, accounts, config, network, project, web3 +from brownie import StrategyCurveGeist, accounts, config, network, project, web3 from eth_utils import is_checksum_address import click @@ -55,4 +55,6 @@ def main(): if input("Deploy Strategy? y/[N]: ").lower() != "y": return - strategy = Strategy.deploy(vault, {"from": dev}, publish_source=publish_source) + strategy = StrategyCurveGeist.deploy( + vault, "StrategyCurveGeist", {"from": dev}, publish_source=publish_source + ) diff --git a/tests/conftest.py b/tests/conftest.py index d785e73..8aa9b2b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -11,7 +11,7 @@ def isolation(fn_isolation): def whale(accounts): # Totally in it for the tech # Update this with a large holder of your want token (the largest EOA holder of LP) - whale = accounts.at("0xe1Bf2277E023184d412E00C13022012cc7b06aba", force=True) + whale = accounts.at("0xbEc6E4AC010114e515483060FDA81Cf9088040fF", force=True) yield whale @@ -38,16 +38,37 @@ def voter(): yield Contract("0x72a34AbafAB09b15E7191822A679f28E067C4a16") +## List of reward tokens since the inception of the curve pool. Not necesarily active currently @pytest.fixture(scope="function") def crv(): yield Contract("0x1E4F97b9f9F913c46F1632781732927B9019C68b") +@pytest.fixture(scope="function") +def geist(): + yield Contract("0xd8321AA83Fb0a4ECd6348D4577431310A6E0814d") + + +@pytest.fixture(scope="function") +def wftm(): + yield Contract("0x21be370D5312f44cB42ce377BC9b8a0cEF1A4C83") + + +# end of list of reward tokens + + @pytest.fixture(scope="module") def other_vault_strategy(): yield Contract("0xfF8bb7261E4D51678cB403092Ae219bbEC52aa51") +# only applicable if you are migrating an existing strategy (i.e., you are not +# deploying a brand new one). This strat is using an old version of a curve gauge +@pytest.fixture(scope="module") +def strategy_to_migrate_from(): + yield Contract("0x7ff6fe5bDa1b26fa46880dF8AF844326DAd50d13") + + @pytest.fixture(scope="module") def farmed(): yield Contract("0x7d016eec9c25232b01F23EF992D98ca97fc2AF5a") @@ -77,7 +98,7 @@ def zero_address(): @pytest.fixture(scope="module") def gauge(): # this should be the address of the convex deposit token - gauge = "0xd4F94D0aaa640BBb72b5EEc2D85F6D114D81a88E" + gauge = "0xF7b9c402c4D6c2eDbA04a7a515b53D11B1E9b2cc" yield Contract(gauge) @@ -139,17 +160,17 @@ def vault(pm, gov, rewards, guardian, management, token, chain): Vault = pm(config["dependencies"][0]).Vault vault = guardian.deploy(Vault) vault.initialize(token, gov, rewards, "", "", guardian) - vault.setDepositLimit(2 ** 256 - 1, {"from": gov}) + vault.setDepositLimit(2**256 - 1, {"from": gov}) vault.setManagement(management, {"from": gov}) chain.sleep(1) yield vault # use this if your vault is already deployed -# @pytest.fixture(scope="function") -# def vault(pm, gov, rewards, guardian, management, token, chain): -# vault = Contract("0x497590d2d57f05cf8B42A36062fA53eBAe283498") -# yield vault +@pytest.fixture(scope="function") +def vaultDeployed(): + vaultDeployed = Contract("0xF137D22d7B23eeB1950B3e19d1f578c053ed9715") + yield vaultDeployed # replace the first value with the name of your strategy @@ -179,7 +200,7 @@ def strategy( # set our management fee to zero so it doesn't mess with our profit checking vault.setManagementFee(0, {"from": gov}) # add our new strategy - vault.addStrategy(strategy, 10_000, 0, 2 ** 256 - 1, 1_000, {"from": gov}) + vault.addStrategy(strategy, 10_000, 0, 2**256 - 1, 1_000, {"from": gov}) strategy.setHealthCheck(healthCheck, {"from": gov}) strategy.setDoHealthCheck(True, {"from": gov}) chain.sleep(1) diff --git a/tests/test_base_strategy.py b/tests/test_base_strategy.py index bb1c62e..689fb0b 100644 --- a/tests/test_base_strategy.py +++ b/tests/test_base_strategy.py @@ -16,7 +16,7 @@ def test_base_strategy( ): ## deposit to the vault after approving startingWhale = token.balanceOf(whale) - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) newWhale = token.balanceOf(whale) diff --git a/tests/test_change_debt.py b/tests/test_change_debt.py index 8d8ad04..eee73b7 100644 --- a/tests/test_change_debt.py +++ b/tests/test_change_debt.py @@ -16,7 +16,7 @@ def test_change_debt( ): ## deposit to the vault after approving startingWhale = token.balanceOf(whale) - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) diff --git a/tests/test_change_debt_with_profit.py b/tests/test_change_debt_with_profit.py index 4c36ea2..45e2ab3 100644 --- a/tests/test_change_debt_with_profit.py +++ b/tests/test_change_debt_with_profit.py @@ -15,7 +15,7 @@ def test_change_debt_with_profit( ): ## deposit to the vault after approving - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) diff --git a/tests/test_emergency_exit.py b/tests/test_emergency_exit.py index 6bb4eae..298a2fb 100644 --- a/tests/test_emergency_exit.py +++ b/tests/test_emergency_exit.py @@ -15,7 +15,7 @@ def test_emergency_exit( ): ## deposit to the vault after approving startingWhale = token.balanceOf(whale) - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) @@ -56,7 +56,7 @@ def test_emergency_exit_with_profit( ## deposit to the vault after approving. turn off health check since we're doing weird shit strategy.setDoHealthCheck(False, {"from": gov}) startingWhale = token.balanceOf(whale) - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) @@ -102,7 +102,7 @@ def test_emergency_exit_with_no_gain_or_loss( ## deposit to the vault after approving. turn off health check since we're doing weird shit strategy.setDoHealthCheck(False, {"from": gov}) startingWhale = token.balanceOf(whale) - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) diff --git a/tests/test_emergency_shutdown_from_vault.py b/tests/test_emergency_shutdown_from_vault.py index b93b626..62a4bda 100644 --- a/tests/test_emergency_shutdown_from_vault.py +++ b/tests/test_emergency_shutdown_from_vault.py @@ -15,7 +15,7 @@ def test_emergency_shutdown_from_vault( ): ## deposit to the vault after approving startingWhale = token.balanceOf(whale) - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) diff --git a/tests/test_liq_gauge.py b/tests/test_liq_gauge.py new file mode 100644 index 0000000..8dd77af --- /dev/null +++ b/tests/test_liq_gauge.py @@ -0,0 +1,29 @@ +from warnings import warn +from brownie import chain + + +def test_gauge_is_properly_setup(gauge, geist): + + assert ( + gauge.reward_count() == 1 + ), "We only currently expect 1 third-party reward token (i.e. GEIST)" + + reward_tokens = [] + + for i in range(gauge.reward_count()): + reward_tokens.append(gauge.reward_tokens(i)) + + assert geist.address in reward_tokens + + WEEK = 86400 * 7 + + weeksNum = chain.time() // WEEK + + # Pull current inflation_rate and verify it's not 0; i.e., the + # reward APY is greater than 0%. + # if gauge.inflation_rate(weeksNum) > 0: + # warn("This gauge is not currently rewarding any CRV") + + assert ( + gauge.inflation_rate(weeksNum) > 0 + ), "This gauge is not currently rewarding any CRV" diff --git a/tests/test_migration.py b/tests/test_migration.py index d0252a6..ee8ab14 100644 --- a/tests/test_migration.py +++ b/tests/test_migration.py @@ -1,8 +1,6 @@ import brownie -from brownie import Contract -from brownie import config import math - +from warnings import warn def test_migration( StrategyCurveGeist, @@ -20,6 +18,8 @@ def test_migration( pool, strategy_name, gauge, + crv, + geist, ): ## deposit to the vault after approving @@ -47,11 +47,37 @@ def test_migration( chain.sleep(86400) chain.mine(1) + claimable_crv_tokens = gauge.claimable_tokens.call(strategy) + + assert claimable_crv_tokens > 0, "No CRV to be claimed" + + claimable_geist = gauge.claimable_reward(strategy, geist) + + if claimable_geist > 0: + warn("No GEIST tokens to be claimed") + # migrate our old strategy vault.migrateStrategy(strategy, new_strategy, {"from": gov}) new_strategy.setHealthCheck(healthCheck, {"from": gov}) new_strategy.setDoHealthCheck(True, {"from": gov}) + with brownie.reverts("!authorized"): + strategy.claimRewards({"from": whale}) + + strategy.claimRewards({"from": gov}) + + assert crv.balanceOf(strategy) > 0, "No tokens were claimed" + + strategy.sweep(crv, {"from": gov}) + + assert crv.balanceOf(strategy) == 0, "Tokens were not swept" + + assert geist.balanceOf(strategy) >= 0, "No tokens were claimed" + + strategy.sweep(geist, {"from": gov}) + + assert geist.balanceOf(strategy) == 0, "Tokens were not swept" + # assert that our old strategy is empty updated_total_old = strategy.estimatedTotalAssets() assert updated_total_old == 0 @@ -66,8 +92,8 @@ def test_migration( new_strat_balance, total_old, abs_tol=5 ) - startingVault = vault.totalAssets() - print("\nVault starting assets with new strategy: ", startingVault) + starting_vault_assets = vault.totalAssets() + print("\nVault starting assets with new strategy: ", starting_vault_assets) # simulate one day of earnings chain.sleep(86400) @@ -77,7 +103,60 @@ def test_migration( new_strategy.harvest({"from": gov}) vaultAssets_2 = vault.totalAssets() # confirm we made money, or at least that we have about the same - assert vaultAssets_2 >= startingVault or math.isclose( - vaultAssets_2, startingVault, abs_tol=5 + assert vaultAssets_2 >= starting_vault_assets or math.isclose( + vaultAssets_2, starting_vault_assets, abs_tol=5 ) print("\nAssets after 1 day harvest: ", vaultAssets_2) + + +def test_migration_from_real_strat( + gov, + vaultDeployed, + strategist, + chain, + healthCheck, + strategy_to_migrate_from, + StrategyCurveGeist, + strategy_name, +): + + strategy_to_migrate_from.harvest({"from": gov}) + + total_old = strategy_to_migrate_from.estimatedTotalAssets() + + # deploy our new strategy + new_strategy = strategist.deploy( + StrategyCurveGeist, + vaultDeployed, + strategy_name, + ) + + # migrate our old strategy + vaultDeployed.migrateStrategy(strategy_to_migrate_from, new_strategy, {"from": gov}) + new_strategy.setHealthCheck(healthCheck, {"from": gov}) + new_strategy.setDoHealthCheck(True, {"from": gov}) + + # assert that our old strategy is empty + updated_total_old = strategy_to_migrate_from.estimatedTotalAssets() + assert updated_total_old == 0 + + # harvest to get funds back in strategy + new_strategy.harvest({"from": gov}) + new_strat_balance = new_strategy.estimatedTotalAssets() + + # confirm that at least the same amount of assets were moved to the new strat + assert new_strat_balance >= total_old + + starting_vault_assets = vaultDeployed.totalAssets() + print("\nVault starting assets with new strategy: ", starting_vault_assets) + + # simulate one day of earnings + chain.sleep(86400) + chain.mine(1) + + # Test out our migrated strategy, confirm we're making a profit + new_strategy.harvest({"from": gov}) + vaultAssets_2 = vaultDeployed.totalAssets() + + # confirm we made money, or remained the same + assert vaultAssets_2 >= starting_vault_assets diff --git a/tests/test_odds_and_ends.py b/tests/test_odds_and_ends.py index e63167e..58a3d71 100644 --- a/tests/test_odds_and_ends.py +++ b/tests/test_odds_and_ends.py @@ -24,7 +24,7 @@ def test_odds_and_ends( ## deposit to the vault after approving. turn off health check before each harvest since we're doing weird shit strategy.setDoHealthCheck(False, {"from": gov}) startingWhale = token.balanceOf(whale) - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) @@ -75,8 +75,8 @@ def test_odds_and_ends( new_strat_balance = new_strategy.estimatedTotalAssets() assert new_strat_balance >= total_old - startingVault = vault.totalAssets() - print("\nVault starting assets with new strategy: ", startingVault) + starting_vault_assets = vault.totalAssets() + print("\nVault starting assets with new strategy: ", starting_vault_assets) # simulate one day of earnings chain.sleep(86400) @@ -85,7 +85,7 @@ def test_odds_and_ends( # Test out our migrated strategy, confirm we're making a profit new_strategy.harvest({"from": gov}) vaultAssets_2 = vault.totalAssets() - assert vaultAssets_2 >= startingVault + assert vaultAssets_2 >= starting_vault_assets print("\nAssets after 1 day harvest: ", vaultAssets_2) # check our oracle @@ -121,7 +121,7 @@ def test_odds_and_ends_2( ## deposit to the vault after approving. turn off health check since we're doing weird shit strategy.setDoHealthCheck(False, {"from": gov}) startingWhale = token.balanceOf(whale) - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) @@ -161,7 +161,7 @@ def test_odds_and_ends_migration( ): ## deposit to the vault after approving - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) @@ -201,8 +201,8 @@ def test_odds_and_ends_migration( new_strat_balance, total_old, abs_tol=5 ) - startingVault = vault.totalAssets() - print("\nVault starting assets with new strategy: ", startingVault) + starting_vault_assets = vault.totalAssets() + print("\nVault starting assets with new strategy: ", starting_vault_assets) # simulate one day of earnings chain.sleep(86400) @@ -216,8 +216,8 @@ def test_odds_and_ends_migration( new_strategy.harvest({"from": gov}) vaultAssets_2 = vault.totalAssets() # confirm we made money, or at least that we have about the same - assert vaultAssets_2 >= startingVault or math.isclose( - vaultAssets_2, startingVault, abs_tol=5 + assert vaultAssets_2 >= starting_vault_assets or math.isclose( + vaultAssets_2, starting_vault_assets, abs_tol=5 ) print("\nAssets after 1 day harvest: ", vaultAssets_2) @@ -237,7 +237,7 @@ def test_odds_and_ends_liquidatePosition( ): ## deposit to the vault after approving startingWhale = token.balanceOf(whale) - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) newWhale = token.balanceOf(whale) @@ -308,7 +308,7 @@ def test_odds_and_ends_rekt( ## deposit to the vault after approving. turn off health check since we're doing weird shit strategy.setDoHealthCheck(False, {"from": gov}) startingWhale = token.balanceOf(whale) - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) @@ -349,7 +349,7 @@ def test_odds_and_ends_liquidate_rekt( ## deposit to the vault after approving. turn off health check since we're doing weird shit strategy.setDoHealthCheck(False, {"from": gov}) startingWhale = token.balanceOf(whale) - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) @@ -408,7 +408,7 @@ def test_odds_and_ends_inactive_strat( amount, ): ## deposit to the vault after approving - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) @@ -440,7 +440,7 @@ def test_odds_and_ends_weird_amounts( ): ## deposit to the vault after approving - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) strategy.harvest({"from": gov}) diff --git a/tests/test_remove_from_withdrawal_queue.py b/tests/test_remove_from_withdrawal_queue.py index 2d1c2fa..94a7293 100644 --- a/tests/test_remove_from_withdrawal_queue.py +++ b/tests/test_remove_from_withdrawal_queue.py @@ -15,7 +15,7 @@ def test_remove_from_withdrawal_queue( ): ## deposit to the vault after approving startingWhale = token.balanceOf(whale) - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) diff --git a/tests/test_revoke.py b/tests/test_revoke.py index 4e2bac0..f9d1555 100644 --- a/tests/test_revoke.py +++ b/tests/test_revoke.py @@ -16,7 +16,7 @@ def test_revoke_strategy_from_vault( ## deposit to the vault after approving startingWhale = token.balanceOf(whale) - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) diff --git a/tests/test_setters.py b/tests/test_setters.py index 5db6e45..eb98e23 100644 --- a/tests/test_setters.py +++ b/tests/test_setters.py @@ -38,7 +38,7 @@ def test_setters( ## deposit to the vault after approving startingWhale = token.balanceOf(whale) - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) diff --git a/tests/test_simple_harvest.py b/tests/test_simple_harvest.py index d810303..58377bb 100644 --- a/tests/test_simple_harvest.py +++ b/tests/test_simple_harvest.py @@ -19,7 +19,7 @@ def test_simple_harvest( ): ## deposit to the vault after approving startingWhale = token.balanceOf(whale) - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) newWhale = token.balanceOf(whale) @@ -52,7 +52,7 @@ def test_simple_harvest( chain.sleep(1) new_assets = vault.totalAssets() # confirm we made money, or at least that we have about the same - assert new_assets >= old_assets + assert new_assets > old_assets print("\nAssets after 1 day: ", new_assets / 1e18) # Display estimated APR @@ -83,7 +83,7 @@ def test_simple_harvest( chain.sleep(1) after_usdc_assets = vault.totalAssets() # confirm we made money, or at least that we have about the same - assert after_usdc_assets >= before_usdc_assets + assert after_usdc_assets > before_usdc_assets # Display estimated APR print( @@ -114,7 +114,7 @@ def test_simple_harvest( chain.sleep(1) after_usdc_assets = vault.totalAssets() # confirm we made money, or at least that we have about the same - assert after_usdc_assets >= before_usdc_assets + assert after_usdc_assets > before_usdc_assets # Display estimated APR print( @@ -131,4 +131,4 @@ def test_simple_harvest( # withdraw and confirm we made money, or at least that we have about the same vault.withdraw({"from": whale}) - assert token.balanceOf(whale) >= startingWhale + assert token.balanceOf(whale) > startingWhale diff --git a/tests/test_sweep.py b/tests/test_sweep.py index 26965fa..cc9df50 100644 --- a/tests/test_sweep.py +++ b/tests/test_sweep.py @@ -17,7 +17,7 @@ def test_sweep( ): ## deposit to the vault after approving - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) diff --git a/tests/test_triggers.py b/tests/test_triggers.py index 8c2b0c1..3b826a3 100644 --- a/tests/test_triggers.py +++ b/tests/test_triggers.py @@ -17,7 +17,7 @@ def test_triggers( ): ## deposit to the vault after approving startingWhale = token.balanceOf(whale) - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) newWhale = token.balanceOf(whale) starting_assets = vault.totalAssets() @@ -71,7 +71,7 @@ def test_less_useful_triggers( ): ## deposit to the vault after approving startingWhale = token.balanceOf(whale) - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) newWhale = token.balanceOf(whale) starting_assets = vault.totalAssets() diff --git a/tests/test_withdraw_after_donation.py b/tests/test_withdraw_after_donation.py index ec41a2d..af5376c 100644 --- a/tests/test_withdraw_after_donation.py +++ b/tests/test_withdraw_after_donation.py @@ -15,7 +15,7 @@ def test_withdraw_after_donation_1( ): ## deposit to the vault after approving - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) @@ -58,7 +58,7 @@ def test_withdraw_after_donation_1( assert profit > 0 # specifically check that our gain is greater than our donation or confirm we're no more than 5 wei off. - assert new_params["totalGain"] - prev_params["totalGain"] > donation + assert profit > donation # check to make sure that our debtRatio is about half of our previous debt assert new_params["debtRatio"] == currentDebt / 2 @@ -89,7 +89,7 @@ def test_withdraw_after_donation_2( ): ## deposit to the vault after approving - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) @@ -132,7 +132,7 @@ def test_withdraw_after_donation_2( assert profit > 0 # specifically check that our gain is greater than our donation or confirm we're no more than 5 wei off. - assert new_params["totalGain"] - prev_params["totalGain"] > donation + assert profit > donation # check that we didn't add any more loss, or at least no more than 2 wei assert new_params["totalLoss"] == prev_params["totalLoss"] @@ -160,7 +160,7 @@ def test_withdraw_after_donation_3( ): ## deposit to the vault after approving - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) @@ -203,7 +203,7 @@ def test_withdraw_after_donation_3( assert profit > 0 # specifically check that our gain is greater than our donation or confirm we're no more than 5 wei off. - assert new_params["totalGain"] - prev_params["totalGain"] > donation + assert profit > donation # check that we didn't add any more loss, or at least no more than 2 wei assert new_params["totalLoss"] == prev_params["totalLoss"] @@ -231,7 +231,7 @@ def test_withdraw_after_donation_4( ): ## deposit to the vault after approving - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) @@ -309,7 +309,7 @@ def test_withdraw_after_donation_5( ): ## deposit to the vault after approving - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) @@ -343,7 +343,7 @@ def test_withdraw_after_donation_5( assert profit > 0 # specifically check that our gain is greater than our donation or confirm we're no more than 5 wei off. - assert new_params["totalGain"] - prev_params["totalGain"] > donation + assert profit > donation # check that we didn't add any more loss, or at least no more than 2 wei assert new_params["totalLoss"] == prev_params["totalLoss"] @@ -371,7 +371,7 @@ def test_withdraw_after_donation_6( ): ## deposit to the vault after approving - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) @@ -405,7 +405,7 @@ def test_withdraw_after_donation_6( assert profit > 0 # specifically check that our gain is greater than our donation or confirm we're no more than 5 wei off. - assert new_params["totalGain"] - prev_params["totalGain"] > donation + assert profit > donation # check that we didn't add any more loss, or at least no more than 2 wei assert new_params["totalLoss"] == prev_params["totalLoss"] @@ -435,7 +435,7 @@ def test_withdraw_after_donation_7( ): ## deposit to the vault after approving - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) @@ -497,7 +497,7 @@ def test_withdraw_after_donation_7( assert profit > 0 # specifically check that our gain is greater than our donation or confirm we're no more than 5 wei off. - assert new_params["totalGain"] - prev_params["totalGain"] > donation + assert profit > donation # check that we didn't add any more loss, or at least no more than 2 wei assert new_params["totalLoss"] == prev_params["totalLoss"] @@ -518,7 +518,7 @@ def test_withdraw_after_donation_8( ): ## deposit to the vault after approving - token.approve(vault, 2 ** 256 - 1, {"from": whale}) + token.approve(vault, 2**256 - 1, {"from": whale}) vault.deposit(amount, {"from": whale}) chain.sleep(1) strategy.harvest({"from": gov}) @@ -580,7 +580,7 @@ def test_withdraw_after_donation_8( assert profit > 0 # specifically check that our gain is greater than our donation or confirm we're no more than 5 wei off. - assert new_params["totalGain"] - prev_params["totalGain"] > donation + assert profit > donation # check that we didn't add any more loss, or at least no more than 2 wei assert new_params["totalLoss"] == prev_params["totalLoss"]