From 4fe74153e448727c66d83b1e377325c208ff9d61 Mon Sep 17 00:00:00 2001 From: Schlag <89420541+Schlagonia@users.noreply.github.com> Date: Mon, 6 Nov 2023 09:23:00 -0700 Subject: [PATCH 1/2] fix: readme link (#21) * fix: readme link * test: update for protocol fees --- README.md | 2 +- tests/test_operation.py | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index bd8a04a..3a13fa6 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,6 @@ Tip: You can make them persistent by adding the variables in ~/.env (ENVVAR=... ## Strategy Writing -For a complete guide to creating a Tokenized Strategy please visit: https://docs.yearn.fi/developers/v3/strategy_development +For a complete guide to creating a Tokenized Strategy please visit: https://docs.yearn.fi/developers/v3/strategy_writing_guide See the ApeWorx [documentation](https://docs.apeworx.io/ape/stable/) and [github](https://github.com/ApeWorX/ape) for more information. diff --git a/tests/test_operation.py b/tests/test_operation.py index ea8f803..20b8fb1 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -102,6 +102,7 @@ def test__profitable_report__with_fee( rewards, amount, whale, + factory, RELATIVE_APPROX, keeper, ): @@ -135,7 +136,11 @@ def test__profitable_report__with_fee( assert profit > 0 - expected_performance_fee = profit * performance_fee // MAX_BPS + (protocol_fee, protocol_fee_recipient) = factory.protocol_fee_config() + + expected_performance_fee = ( + (profit * performance_fee // MAX_BPS) * (10_000 - protocol_fee) // MAX_BPS + ) # TODO: Implement logic so totalDebt == amount + profit check_strategy_totals( @@ -159,8 +164,6 @@ def test__profitable_report__with_fee( strategy.redeem(expected_performance_fee, rewards, rewards, sender=rewards) - check_strategy_totals(strategy, total_assets=0, total_debt=0, total_idle=0) - assert asset.balanceOf(rewards) >= rewards_balance_before + expected_performance_fee From 4a89ba2809c32b041d81d95926a1d3745722286e Mon Sep 17 00:00:00 2001 From: Schlag <89420541+Schlagonia@users.noreply.github.com> Date: Wed, 29 Nov 2023 08:32:00 -0700 Subject: [PATCH 2/2] fix: test (#22) * fix: readme link * fix: oracle test * test: function signatures * feat: deployment script * test: get correct protocol fee --- scripts/deploy.py | 30 +++++++++++++++ tests/test_function_signatures.py | 64 +++++++++++++++++++++++++++++++ tests/test_operation.py | 16 +++++--- tests/test_oracle.py | 4 +- 4 files changed, 106 insertions(+), 8 deletions(-) create mode 100644 scripts/deploy.py create mode 100644 tests/test_function_signatures.py diff --git a/scripts/deploy.py b/scripts/deploy.py new file mode 100644 index 0000000..23b646e --- /dev/null +++ b/scripts/deploy.py @@ -0,0 +1,30 @@ +from ape import project, accounts, chain +import click + +deployer = accounts.load("v3_deployer") + + +def deploy(): + print(f"You are using: 'deployer' [{deployer.address}]") + print("Deploying a new strategy on ChainID", chain.chain_id) + + if input("Do you want to continue? [y/N]: ").lower() != "y": + return + + publish_source = click.confirm("Verify source on etherscan?") + + # Address of the underlying asset to use + asset = "" + # Name for your strategy + name = "" + + if input(f"Deploy strategy for {asset}, called {name}? [y/N]: ").lower() != "y": + return + + strategy = deployer.deploy(project.Strategy, asset, name, publish=publish_source) + + print(f"Deployed new strategy to: {strategy.address}") + + +def main(): + deploy() diff --git a/tests/test_function_signatures.py b/tests/test_function_signatures.py new file mode 100644 index 0000000..4773d28 --- /dev/null +++ b/tests/test_function_signatures.py @@ -0,0 +1,64 @@ +import ape +from ape import Contract + +# This test should not be overridden and checks that +# no function signature collisions occurred from the custom functions. +# Does not check functions that are strategy dependant and will be checked in other tests +def test_function_collisions(strategy, asset, management, rewards, user, keeper): + wad = int(1e18) + + with ape.reverts("initialized"): + strategy.init(asset, "name", management, rewards, keeper, sender=management) + + # Check view functions + assert strategy.convertToAssets(wad) == wad + assert strategy.convertToShares(wad) == wad + assert strategy.previewDeposit(wad) == wad + assert strategy.previewMint(wad) == wad + assert strategy.previewWithdraw(wad) == wad + assert strategy.previewRedeem(wad) == wad + assert strategy.totalAssets() == 0 + assert strategy.totalSupply() == 0 + assert strategy.unlockedShares() == 0 + assert strategy.asset() == asset + assert strategy.apiVersion() == "3.0.1" + assert strategy.totalIdle() == 0 + assert strategy.totalDebt() == 0 + assert strategy.MAX_FEE() == 5_000 + assert strategy.MIN_FEE() == 500 + assert strategy.fullProfitUnlockDate() == 0 + assert strategy.profitUnlockingRate() == 0 + assert strategy.lastReport() > 0 + assert strategy.pricePerShare() == 10 ** asset.decimals() + assert not strategy.isShutdown() + assert strategy.symbol() == f"ys{asset.symbol()}" + assert strategy.decimals() == asset.decimals() + + # Assure modifiers are working + with ape.reverts("!management"): + strategy.setPendingManagement(user, sender=user) + with ape.reverts("!pending"): + strategy.acceptManagement(sender=user) + with ape.reverts("!management"): + strategy.setKeeper(user, sender=user) + with ape.reverts("!management"): + strategy.setEmergencyAdmin(user, sender=user) + with ape.reverts("!management"): + strategy.setPerformanceFee(int(2_000), sender=user) + with ape.reverts("!management"): + strategy.setPerformanceFeeRecipient(user, sender=user) + with ape.reverts("!management"): + strategy.setProfitMaxUnlockTime(1, sender=user) + + # Assure checks are being used + with ape.reverts("MIN FEE"): + strategy.setPerformanceFee(int(0), sender=management) + with ape.reverts("Cannot be self"): + strategy.setPerformanceFeeRecipient(strategy.address, sender=management) + with ape.reverts("too long"): + strategy.setProfitMaxUnlockTime(int(2**256 - 1), sender=management) + + assert strategy.balanceOf(user) == 0 + assert strategy.allowance(keeper, user) == 0 + assert strategy.approve(user, wad, sender=keeper) + assert strategy.allowance(keeper, user) == wad diff --git a/tests/test_operation.py b/tests/test_operation.py index 20b8fb1..7670d60 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -20,7 +20,7 @@ def test__operation( # Deposit to the strategy deposit() - # TODO: Implement logic so totalDebt ends > 0 + # TODO: Implement logic so total_debt ends > 0 check_strategy_totals( strategy, total_assets=amount, total_debt=0, total_idle=amount ) @@ -52,7 +52,7 @@ def test_profitable_report( # Deposit to the strategy deposit() - # TODO: Implement logic so totalDebt ends > 0 + # TODO: Implement logic so total_debt ends > 0 check_strategy_totals( strategy, total_assets=amount, total_debt=0, total_idle=amount ) @@ -73,7 +73,7 @@ def test_profitable_report( assert profit >= to_airdrop - # TODO: Implement logic so totalDebt == amount + profit + # TODO: Implement logic so total_debt == amount + profit check_strategy_totals( strategy, total_assets=amount + profit, total_debt=0, total_idle=amount + profit ) @@ -81,6 +81,7 @@ def test_profitable_report( # needed for profits to unlock increase_time(chain, strategy.profitMaxUnlockTime() - 1) + # TODO: Implement logic so total_debt == amount + profit check_strategy_totals( strategy, total_assets=amount + profit, total_debt=0, total_idle=amount + profit ) @@ -116,7 +117,7 @@ def test__profitable_report__with_fee( # Deposit to the strategy deposit() - # TODO: Implement logic so totalDebt ends > 0 + # TODO: Implement logic so total_debt ends > 0 check_strategy_totals( strategy, total_assets=amount, total_debt=0, total_idle=amount ) @@ -136,13 +137,15 @@ def test__profitable_report__with_fee( assert profit > 0 - (protocol_fee, protocol_fee_recipient) = factory.protocol_fee_config() + (protocol_fee, protocol_fee_recipient) = factory.protocol_fee_config( + sender=strategy.address + ) expected_performance_fee = ( (profit * performance_fee // MAX_BPS) * (10_000 - protocol_fee) // MAX_BPS ) - # TODO: Implement logic so totalDebt == amount + profit + # TODO: Implement logic so total_debt == amount + profit check_strategy_totals( strategy, total_assets=amount + profit, total_debt=0, total_idle=amount + profit ) @@ -150,6 +153,7 @@ def test__profitable_report__with_fee( # needed for profits to unlock increase_time(chain, strategy.profitMaxUnlockTime() - 1) + # TODO: Implement logic so total_debt == amount + profit check_strategy_totals( strategy, total_assets=amount + profit, total_debt=0, total_idle=amount + profit ) diff --git a/tests/test_oracle.py b/tests/test_oracle.py index f9e05e2..630e435 100644 --- a/tests/test_oracle.py +++ b/tests/test_oracle.py @@ -17,7 +17,7 @@ def check_oracle(oracle, strategy, user): # TODO: Uncomment if there are setter functions to test. """ - with reverts("Ownable: caller is not the owner"): + with reverts("!governance"): oracle.setterFunction(setterVariable, sender=user) management = strategy.management() @@ -30,4 +30,4 @@ def test__oracle(create_oracle, strategy, user): oracle = create_oracle() - check_oracle(oracle, strategy, strategy) + check_oracle(oracle, strategy, user)