From 1f7c3504ec5c67ac2dae5e5405ecee3fafd5c568 Mon Sep 17 00:00:00 2001 From: bout3fiddy <11488427+bout3fiddy@users.noreply.github.com> Date: Mon, 16 May 2022 12:02:36 +0100 Subject: [PATCH 1/7] feat: test for reward_forwarder; fix: smol bug in contract --- tests/reward_forwarder/test_deposit_reward.py | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 tests/reward_forwarder/test_deposit_reward.py diff --git a/tests/reward_forwarder/test_deposit_reward.py b/tests/reward_forwarder/test_deposit_reward.py new file mode 100644 index 0000000..7748158 --- /dev/null +++ b/tests/reward_forwarder/test_deposit_reward.py @@ -0,0 +1,44 @@ +import brownie + + +def test_deposit_reward_token( + alice, bob, charlie, chain, child_gauge, reward_forwarder, reward_token +): + + reward_token._mint_for_testing(charlie, 10 ** 26, {"from": alice}) + chain.snapshot() + + # only reward_forwarder can deposit rewards so far, but just a sanity check: + with brownie.reverts(): + child_gauge.deposit_reward_token(reward_token, 10 ** 26, {"from": alice}) + + # empty reward_forwarder cannot transfer tokens unless `allow` is called + with brownie.reverts(): + reward_token.transfer(reward_forwarder, 10 ** 20, {"from": bob}) + child_gauge.add_reward(reward_token, reward_forwarder, {"from": bob}) + reward_forwarder.deposit_reward_token(reward_token) + chain.revert() + + # empty reward_forwarder cannot transfer tokens if it is empty + with brownie.reverts(): + reward_forwarder.allow(reward_token, {"from": alice}) + child_gauge.add_reward(reward_token, reward_forwarder, {"from": bob}) + reward_forwarder.deposit_reward_token(reward_token), + chain.revert() + + # reward_forwarder cannot deposit unless it is added as a distributor for that token + # in the gauge contract + with brownie.reverts(): + reward_forwarder.allow(reward_token, {"from": alice}) + reward_token.transfer(reward_forwarder, 10 ** 20, {"from": bob}) + reward_forwarder.deposit_reward_token(reward_token) + chain.revert() + + # working flow: + reward_forwarder.allow(reward_token, {"from": alice}) + child_gauge.set_manager(bob, {"from": alice}) + child_gauge.add_reward(reward_token, reward_forwarder, {"from": bob}) + reward_token.transfer(reward_forwarder, 10 ** 20, {"from": charlie}) + reward_forwarder.deposit_reward_token(reward_token) + + assert reward_token.balanceOf(child_gauge) == 10 ** 20 From 2bd49ee9ee706ca6b1682323b2daa6eebfd33086 Mon Sep 17 00:00:00 2001 From: bout3fiddy <11488427+bout3fiddy@users.noreply.github.com> Date: Mon, 16 May 2022 12:42:20 +0100 Subject: [PATCH 2/7] feat: test for reward_forwarder; fix: smol bug in contract --- contracts/RewardForwarder.vy | 9 ++++++++- tests/fixtures/deployments.py | 6 ++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/contracts/RewardForwarder.vy b/contracts/RewardForwarder.vy index 55d22fa..e25a464 100644 --- a/contracts/RewardForwarder.vy +++ b/contracts/RewardForwarder.vy @@ -20,9 +20,12 @@ def __init__(_gauge: address): @external def deposit_reward_token(_reward_token: address): """ + @param _reward_token The address of token that gets forwarded to the gauge @notice Deposit a reward token in the gauge @dev This contract should be set as the distributor of `_reward_token` in the gauge, else the tx will fail. + @dev Any user can forward deposited reward tokens to a gauge, after calling + `allow`. """ Gauge(GAUGE).deposit_reward_token(_reward_token, ERC20(_reward_token).balanceOf(self)) @@ -30,11 +33,15 @@ def deposit_reward_token(_reward_token: address): @external def allow(_reward_token: address): """ + @param _reward_token The address of token that gets forwarded to the gauge @notice Allow `_reward_token` to be transferred from self to Gauge + @dev This method is a more gas efficient way to handle token approvals, by avoiding + a storage variable to verify it token was approved, and calls to the token to + check for approval. """ response: Bytes[32] = raw_call( _reward_token, - _abi_encode(GAUGE, MAX_UINT256, method_id=method_id("approve(address,uint256")), + _abi_encode(GAUGE, MAX_UINT256, method_id=method_id("approve(address,uint256)")), max_outsize=32, ) if len(response) != 0: diff --git a/tests/fixtures/deployments.py b/tests/fixtures/deployments.py index 5e65fd1..e4f552c 100644 --- a/tests/fixtures/deployments.py +++ b/tests/fixtures/deployments.py @@ -2,6 +2,7 @@ from brownie import Contract from brownie_tokens import ERC20 + # ANYCALL DEPLOYMENT @@ -48,6 +49,11 @@ def child_gauge(alice, child_gauge_impl, child_gauge_factory, lp_token, ChildGau return Contract.from_abi("Child Gauge", gauge_addr, ChildGauge.abi) +@pytest.fixture(scope="module") +def reward_forwarder(child_gauge, alice, RewardForwarder): + return RewardForwarder.deploy(child_gauge, {"from": alice}) + + # ROOT CHAIN DAO From 358b1c69e9bfe541d7478d2f72c510a0917382c5 Mon Sep 17 00:00:00 2001 From: bout3fiddy <11488427+bout3fiddy@users.noreply.github.com> Date: Mon, 16 May 2022 17:22:41 +0100 Subject: [PATCH 3/7] feat: granularised tests for reward forwarder --- tests/reward_forwarder/test_deposit_reward.py | 68 +++++++++++++------ 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/tests/reward_forwarder/test_deposit_reward.py b/tests/reward_forwarder/test_deposit_reward.py index 7748158..a1695d5 100644 --- a/tests/reward_forwarder/test_deposit_reward.py +++ b/tests/reward_forwarder/test_deposit_reward.py @@ -1,44 +1,72 @@ import brownie -def test_deposit_reward_token( - alice, bob, charlie, chain, child_gauge, reward_forwarder, reward_token -): +def test_reward_deposit(alice, bob, charlie, child_gauge, reward_forwarder, reward_token): reward_token._mint_for_testing(charlie, 10 ** 26, {"from": alice}) - chain.snapshot() - # only reward_forwarder can deposit rewards so far, but just a sanity check: - with brownie.reverts(): - child_gauge.deposit_reward_token(reward_token, 10 ** 26, {"from": alice}) + reward_forwarder.allow(reward_token, {"from": alice}) + child_gauge.set_manager(bob, {"from": alice}) + child_gauge.add_reward(reward_token, reward_forwarder, {"from": bob}) + reward_token.transfer(reward_forwarder, 10 ** 20, {"from": charlie}) + reward_forwarder.deposit_reward_token(reward_token) + + assert reward_token.balanceOf(child_gauge) == 10 ** 20 + + +def test_reward_token_approval(alice, bob, charlie, child_gauge, reward_forwarder, reward_token): + + reward_token._mint_for_testing(charlie, 10 ** 26, {"from": alice}) + reward_token.transfer(reward_forwarder, 10 ** 20, {"from": bob}) + child_gauge.set_manager(bob, {"from": alice}) + child_gauge.add_reward(reward_token, reward_forwarder, {"from": bob}) # empty reward_forwarder cannot transfer tokens unless `allow` is called with brownie.reverts(): - reward_token.transfer(reward_forwarder, 10 ** 20, {"from": bob}) - child_gauge.add_reward(reward_token, reward_forwarder, {"from": bob}) reward_forwarder.deposit_reward_token(reward_token) - chain.revert() + + +def test_insufficient_reward_token_balance( + alice, bob, charlie, child_gauge, reward_forwarder, reward_token +): + + reward_token._mint_for_testing(charlie, 10 ** 26, {"from": alice}) + reward_forwarder.allow(reward_token, {"from": alice}) + child_gauge.add_reward(reward_token, reward_forwarder, {"from": bob}) + + assert reward_token.balanceOf(reward_forwarder) == 0 # no tokens were sent to reward forwarder # empty reward_forwarder cannot transfer tokens if it is empty with brownie.reverts(): - reward_forwarder.allow(reward_token, {"from": alice}) - child_gauge.add_reward(reward_token, reward_forwarder, {"from": bob}) reward_forwarder.deposit_reward_token(reward_token), - chain.revert() + + +def test_unauthorised_distributor(alice, bob, charlie, child_gauge, reward_forwarder, reward_token): + + reward_token._mint_for_testing(charlie, 10 ** 26, {"from": alice}) + reward_forwarder.allow(reward_token, {"from": alice}) + reward_token.transfer(reward_forwarder, 10 ** 20, {"from": bob}) # reward_forwarder cannot deposit unless it is added as a distributor for that token # in the gauge contract with brownie.reverts(): - reward_forwarder.allow(reward_token, {"from": alice}) - reward_token.transfer(reward_forwarder, 10 ** 20, {"from": bob}) reward_forwarder.deposit_reward_token(reward_token) - chain.revert() - # working flow: + +def test_unauthorised_reward_token_for_authorised_distributor( + alice, bob, charlie, child_gauge, reward_forwarder, reward_token, unauthorised_token +): + + reward_token._mint_for_testing(charlie, 10 ** 26, {"from": alice}) + unauthorised_token._mint_for_testing(charlie, 10 ** 26, {"from": alice}) + reward_forwarder.allow(reward_token, {"from": alice}) + reward_forwarder.allow(unauthorised_token, {"from": alice}) + + # only add one token to gauge rewards child_gauge.set_manager(bob, {"from": alice}) child_gauge.add_reward(reward_token, reward_forwarder, {"from": bob}) - reward_token.transfer(reward_forwarder, 10 ** 20, {"from": charlie}) - reward_forwarder.deposit_reward_token(reward_token) - assert reward_token.balanceOf(child_gauge) == 10 ** 20 + reward_token.transfer(reward_forwarder, 10 ** 20, {"from": charlie}) + unauthorised_token.transfer(reward_forwarder, 10 ** 20, {"from": charlie}) + reward_forwarder.deposit_reward_token(unauthorised_token) From bf12ce12f87df780d972424fa49b9dc353d22595 Mon Sep 17 00:00:00 2001 From: bout3fiddy <11488427+bout3fiddy@users.noreply.github.com> Date: Mon, 16 May 2022 17:24:09 +0100 Subject: [PATCH 4/7] feat: granularised tests for reward forwarder --- tests/fixtures/deployments.py | 11 +++ tests/reward_forwarder/test_deposit_reward.py | 75 +++++++++++++------ 2 files changed, 63 insertions(+), 23 deletions(-) diff --git a/tests/fixtures/deployments.py b/tests/fixtures/deployments.py index e4f552c..5a160b1 100644 --- a/tests/fixtures/deployments.py +++ b/tests/fixtures/deployments.py @@ -36,6 +36,12 @@ def reward_token(alice): return ERC20("Dummy Reward Token", "dRT", 18, deployer=alice) +@pytest.fixture(scope="module") +def unauthorised_token(alice): + """This is for testing unauthorised token""" + return ERC20("Dummy Unauthorised Reward Token", "dURT", 18, deployer=alice) + + @pytest.fixture(scope="module") def child_gauge_impl(alice, child_crv_token, ChildGauge, child_gauge_factory): impl = ChildGauge.deploy(child_crv_token, child_gauge_factory, {"from": alice}) @@ -125,3 +131,8 @@ def root_gauge_impl( def root_gauge(alice, chain, root_gauge_factory, root_gauge_impl, RootGauge): gauge_addr = root_gauge_factory.deploy_gauge(chain.id, 0x0, {"from": alice}).return_value return Contract.from_abi("Root Gauge", gauge_addr, RootGauge.abi) + + +@pytest.fixture(scope="module") +def root_gauge_factory_proxy(alice, RootGaugeFactoryProxy): + return RootGaugeFactoryProxy.deploy({"from": alice}) diff --git a/tests/reward_forwarder/test_deposit_reward.py b/tests/reward_forwarder/test_deposit_reward.py index a1695d5..d4f4cf0 100644 --- a/tests/reward_forwarder/test_deposit_reward.py +++ b/tests/reward_forwarder/test_deposit_reward.py @@ -1,15 +1,19 @@ +import pytest import brownie +WEEK = 86400 * 7 + def test_reward_deposit(alice, bob, charlie, child_gauge, reward_forwarder, reward_token): reward_token._mint_for_testing(charlie, 10 ** 26, {"from": alice}) - reward_forwarder.allow(reward_token, {"from": alice}) + child_gauge.set_manager(bob, {"from": alice}) child_gauge.add_reward(reward_token, reward_forwarder, {"from": bob}) + reward_token.transfer(reward_forwarder, 10 ** 20, {"from": charlie}) - reward_forwarder.deposit_reward_token(reward_token) + reward_forwarder.deposit_reward_token(reward_token, {"from": charlie}) assert reward_token.balanceOf(child_gauge) == 10 ** 20 @@ -17,40 +21,26 @@ def test_reward_deposit(alice, bob, charlie, child_gauge, reward_forwarder, rewa def test_reward_token_approval(alice, bob, charlie, child_gauge, reward_forwarder, reward_token): reward_token._mint_for_testing(charlie, 10 ** 26, {"from": alice}) - reward_token.transfer(reward_forwarder, 10 ** 20, {"from": bob}) + reward_token.transfer(reward_forwarder, 10 ** 20, {"from": charlie}) + child_gauge.set_manager(bob, {"from": alice}) child_gauge.add_reward(reward_token, reward_forwarder, {"from": bob}) # empty reward_forwarder cannot transfer tokens unless `allow` is called with brownie.reverts(): - reward_forwarder.deposit_reward_token(reward_token) - - -def test_insufficient_reward_token_balance( - alice, bob, charlie, child_gauge, reward_forwarder, reward_token -): - - reward_token._mint_for_testing(charlie, 10 ** 26, {"from": alice}) - reward_forwarder.allow(reward_token, {"from": alice}) - child_gauge.add_reward(reward_token, reward_forwarder, {"from": bob}) - - assert reward_token.balanceOf(reward_forwarder) == 0 # no tokens were sent to reward forwarder - - # empty reward_forwarder cannot transfer tokens if it is empty - with brownie.reverts(): - reward_forwarder.deposit_reward_token(reward_token), + reward_forwarder.deposit_reward_token(reward_token, {"from": charlie}) -def test_unauthorised_distributor(alice, bob, charlie, child_gauge, reward_forwarder, reward_token): +def test_unauthorised_distributor(alice, charlie, reward_forwarder, reward_token): reward_token._mint_for_testing(charlie, 10 ** 26, {"from": alice}) reward_forwarder.allow(reward_token, {"from": alice}) - reward_token.transfer(reward_forwarder, 10 ** 20, {"from": bob}) + reward_token.transfer(reward_forwarder, 10 ** 20, {"from": charlie}) # reward_forwarder cannot deposit unless it is added as a distributor for that token # in the gauge contract with brownie.reverts(): - reward_forwarder.deposit_reward_token(reward_token) + reward_forwarder.deposit_reward_token(reward_token, {"from": charlie}) def test_unauthorised_reward_token_for_authorised_distributor( @@ -69,4 +59,43 @@ def test_unauthorised_reward_token_for_authorised_distributor( reward_token.transfer(reward_forwarder, 10 ** 20, {"from": charlie}) unauthorised_token.transfer(reward_forwarder, 10 ** 20, {"from": charlie}) - reward_forwarder.deposit_reward_token(unauthorised_token) + + with brownie.reverts(): + reward_forwarder.deposit_reward_token(unauthorised_token, {"from": charlie}) + + +def test_zero_reward_rate_claims( + alice, bob, charlie, child_gauge, chain, reward_forwarder, reward_token, lp_token +): + + # mint lptokens and deposit into gauge: + lp_token.approve(child_gauge, 10 ** 21, {"from": alice}) + lp_token._mint_for_testing(alice, 10 ** 21, {"from": alice}) + child_gauge.deposit(10 ** 21, {"from": alice}) + + # mint reward tokens and approve transfers for RewardForwarder: + reward_token._mint_for_testing(charlie, 10 ** 26, {"from": alice}) + reward_forwarder.allow(reward_token, {"from": alice}) + + # set gauge managers: + child_gauge.set_manager(bob, {"from": alice}) + child_gauge.add_reward(reward_token, reward_forwarder, {"from": bob}) + + # deposit rewards and check if claimable reward token rate is non-zero: + reward_token.transfer(reward_forwarder, 10 ** 20, {"from": charlie}) + reward_forwarder.deposit_reward_token(reward_token, {"from": charlie}) + assert reward_token.balanceOf(reward_forwarder) == 0 # no tokens in the reward forwarder + assert child_gauge.reward_data(reward_token)[2] > 0 # token distribution rate is non-zero + + # sleep for a week until after period finish: + chain.sleep(WEEK + 1) # sleep for 1 week and 1 second + assert chain.time() > child_gauge.reward_data(reward_token)[1] # `period_end` reached + + # transferring zero reward tokens: this will make reward_token distribution rate zero + reward_forwarder.deposit_reward_token(reward_token, {"from": charlie}) + assert child_gauge.reward_data(reward_token)[2] == 0 # token distribution rate becomes zero + + # check alice's balance before and after claims: + assert reward_token.balanceOf(alice) == 0 + child_gauge.claim_rewards({"from": alice}) + assert reward_token.balanceOf(alice) > 0 # even if rate is zero, user can claim. From 18abf821e956f7646340c673026ab20782969ef4 Mon Sep 17 00:00:00 2001 From: bout3fiddy <11488427+bout3fiddy@users.noreply.github.com> Date: Tue, 17 May 2022 17:30:02 +0200 Subject: [PATCH 5/7] feat: root gauge proxy admin tests; note: test_set_call_proxy currently fails --- .../test_root_gauge_factory_proxy_admin.py | 298 ++++++++++++++++++ 1 file changed, 298 insertions(+) create mode 100644 tests/root_gauge_factory_proxy/test_root_gauge_factory_proxy_admin.py diff --git a/tests/root_gauge_factory_proxy/test_root_gauge_factory_proxy_admin.py b/tests/root_gauge_factory_proxy/test_root_gauge_factory_proxy_admin.py new file mode 100644 index 0000000..7d428cf --- /dev/null +++ b/tests/root_gauge_factory_proxy/test_root_gauge_factory_proxy_admin.py @@ -0,0 +1,298 @@ +import brownie +from brownie import ETH_ADDRESS + + +def test_set_manager(root_gauge_factory_proxy, alice, bob, charlie, chain): + + default_ownership_admin = root_gauge_factory_proxy.ownership_admin() + default_emergency_admin = root_gauge_factory_proxy.emergency_admin() + assert root_gauge_factory_proxy.manager() == alice # contract deployer is manager + + # unauthorised users cannot change the manager: + with brownie.reverts(): + root_gauge_factory_proxy.set_manager(charlie, {"from": bob}) + + # emergency admin and ownership admin can become manager: + for acct in [default_emergency_admin, default_ownership_admin]: + root_gauge_factory_proxy.set_manager(acct, {"from": acct}) + assert root_gauge_factory_proxy.manager() == acct + chain.undo() + + # authorised users can change the manager to anyone: + for acct in [default_emergency_admin, default_ownership_admin, alice]: + root_gauge_factory_proxy.set_manager(bob, {"from": acct}) + assert root_gauge_factory_proxy.manager() == bob + chain.undo() + + +def test_transfer_proxy_admins(root_gauge_factory_proxy, alice, bob, charlie): + + default_ownership_admin = root_gauge_factory_proxy.ownership_admin() + default_emergency_admin = root_gauge_factory_proxy.emergency_admin() + + # --- + # commit future proxy owners + + # manager cannot commit new admins + with brownie.reverts(): + root_gauge_factory_proxy.commit_set_admins(bob, charlie, {"from": alice}) + + # unauthorised accounts cannot commit new admins + with brownie.reverts(): + root_gauge_factory_proxy.commit_set_admins(bob, bob, {"from": charlie}) + + # emergency admin cannot commit new admins + with brownie.reverts(): + root_gauge_factory_proxy.commit_set_admins(bob, charlie, {"from": default_emergency_admin}) + + # commit future owners + root_gauge_factory_proxy.commit_set_admins(bob, charlie, {"from": default_ownership_admin}) + assert root_gauge_factory_proxy.ownership_admin() == default_ownership_admin + assert root_gauge_factory_proxy.emergency_admin() == default_emergency_admin + assert root_gauge_factory_proxy.future_ownership_admin() == bob + assert root_gauge_factory_proxy.future_emergency_admin() == charlie + + # --- + # accept new proxy owners + + # unauthorised accts cannot accept future ownership and emergency admins on behalf: + for acct in [default_ownership_admin, default_emergency_admin, alice, charlie]: + with brownie.reverts(): + root_gauge_factory_proxy.accept_set_admins({"from": acct}) + + root_gauge_factory_proxy.accept_set_admins({"from": bob}) + assert root_gauge_factory_proxy.ownership_admin() == bob + assert root_gauge_factory_proxy.emergency_admin() == charlie + + +def test_transfer_ownership( + alice, bob, charlie, chain, root_gauge_factory, child_gauge_factory, root_gauge_factory_proxy +): + + default_ownership_admin = root_gauge_factory_proxy.ownership_admin() + default_emergency_admin = root_gauge_factory_proxy.emergency_admin() + + # transfer ownership for both root gauge factory and child gauge factory + for gauge_factory in [root_gauge_factory, child_gauge_factory]: + + # --- + # commit transfer ownership: set gauge proxy as future factory owner + + assert gauge_factory.owner() == alice # alice is the owner + # since proxy contract is not an owner yet, this will revert: + for acct in [ + default_ownership_admin, + default_emergency_admin, + bob, + charlie, + root_gauge_factory_proxy, + ]: + with brownie.reverts(): + root_gauge_factory_proxy.commit_transfer_ownership( + gauge_factory, root_gauge_factory_proxy, {"from": acct} + ) + + # set proxy as future owner: only factory owner can do this + gauge_factory.commit_transfer_ownership(root_gauge_factory_proxy, {"from": alice}) + assert gauge_factory.future_owner() == root_gauge_factory_proxy + assert gauge_factory.owner() == alice # alice is still the owner + + # --- + # accept transfer ownership: only proxy (root_gauge_factory.future_owner) can accept + # this is callable by anyone through the proxy + + # unauthorised accounts cannot complete ownership transfer through the factory + for acct in [default_ownership_admin, default_emergency_admin, alice, bob, charlie]: + with brownie.reverts(): + gauge_factory.accept_transfer_ownership({"from": acct}) + + # completing transfer can be only be done through the root gauge factory proxy now + for acct in [alice, bob, charlie]: + root_gauge_factory_proxy.accept_transfer_ownership(gauge_factory, {"from": acct}) + assert gauge_factory.owner() == root_gauge_factory_proxy + chain.undo() + + +def test_set_killed( + root_gauge, + child_gauge, + root_gauge_factory, + child_gauge_factory, + root_gauge_factory_proxy, + alice, + bob, + charlie, + chain, +): + + default_ownership_admin = root_gauge_factory_proxy.ownership_admin() + default_emergency_admin = root_gauge_factory_proxy.emergency_admin() + + # testing `set_killed` for root and child gauges + gauge_mapping = {root_gauge_factory: root_gauge, child_gauge_factory: child_gauge} + + for gauge_factory, gauge in gauge_mapping.items(): + # alice deployed the factory and set herself as the owner of the factory contract + assert gauge_factory.owner() == alice + + # alice is the only one who can kill gauges + gauge.set_killed(True, {"from": alice}) + assert gauge.is_killed() + if gauge == root_gauge: + assert gauge.inflation_params()[0] == 0 # inflation rate of root gauge should be 0 + chain.undo() + + # proxy cannot kill gauges yet, and neither can alice do it through the proxy: + for unauthorised_admins in [ + default_emergency_admin, + default_ownership_admin, + alice, + ]: + with brownie.reverts(): + root_gauge_factory_proxy.set_killed(gauge, True, {"from": unauthorised_admins}) + + # so transfer root gauge factory ownership to proxy: + gauge_factory.commit_transfer_ownership(root_gauge_factory_proxy, {"from": alice}) + root_gauge_factory_proxy.accept_transfer_ownership(gauge_factory, {"from": bob}) + + # only proxy admins can kill a gauge: + for authorised_admin in [default_emergency_admin, default_ownership_admin]: + root_gauge_factory_proxy.set_killed(gauge, True, {"from": authorised_admin}) + assert gauge.is_killed() + if gauge == root_gauge: + assert gauge.inflation_params()[0] == 0 # inflation rate of root gauge should be 0 + chain.undo() + + # unauthorised accounts cannot do so: + for unauthorised_acct in [alice, bob, charlie]: + with brownie.reverts(): + root_gauge_factory_proxy.set_killed(gauge, True, {"from": unauthorised_acct}) + + +def test_set_bridger(root_gauge_factory, root_gauge_factory_proxy, alice, bob, chain): + + default_ownership_admin = root_gauge_factory_proxy.ownership_admin() + default_emergency_admin = root_gauge_factory_proxy.emergency_admin() + + assert root_gauge_factory.owner() == alice + manager = root_gauge_factory_proxy.manager() + # proxy cannot set bridger yet: + for admin in [manager, default_ownership_admin]: + with brownie.reverts(): + root_gauge_factory_proxy.set_bridger( + root_gauge_factory, chain.id, ETH_ADDRESS, {"from": admin} + ) + + # so transfer root gauge factory ownership to proxy: + root_gauge_factory.commit_transfer_ownership(root_gauge_factory_proxy, {"from": alice}) + root_gauge_factory_proxy.accept_transfer_ownership(root_gauge_factory, {"from": bob}) + + for admin in [manager, default_ownership_admin]: + root_gauge_factory_proxy.set_bridger( + root_gauge_factory, chain.id, ETH_ADDRESS, {"from": admin} + ) + assert root_gauge_factory.get_bridger(chain.id) == ETH_ADDRESS + chain.undo() + + # emergency admin cannot set bridger: + with brownie.reverts(): + root_gauge_factory_proxy.set_bridger( + root_gauge_factory, chain.id, ETH_ADDRESS, {"from": default_emergency_admin} + ) + + # but emergency admin can set itself (or anyone) as manager and change bridger: + root_gauge_factory_proxy.set_manager(default_emergency_admin, {"from": default_emergency_admin}) + root_gauge_factory_proxy.set_bridger( + root_gauge_factory, chain.id, ETH_ADDRESS, {"from": default_emergency_admin} + ) + assert root_gauge_factory.get_bridger(chain.id) == ETH_ADDRESS + + +def test_set_implementation( + root_gauge_factory, child_gauge_factory, root_gauge_factory_proxy, alice, bob, chain +): + + default_ownership_admin = root_gauge_factory_proxy.ownership_admin() + default_emergency_admin = root_gauge_factory_proxy.emergency_admin() + + for gauge_factory in [root_gauge_factory, child_gauge_factory]: + print(f"\ngauge factory {gauge_factory} owner {gauge_factory.owner()}\n") + assert gauge_factory.owner() == alice + print(f"assertion that alice is the owner passed for {gauge_factory}") + manager = root_gauge_factory_proxy.manager() + # proxy cannot set gauge implementation contract yet: + for admin in [manager, default_ownership_admin]: + with brownie.reverts(): + root_gauge_factory_proxy.set_implementation( + gauge_factory, ETH_ADDRESS, {"from": admin} + ) + + # so transfer root gauge factory ownership to proxy: + gauge_factory.commit_transfer_ownership(root_gauge_factory_proxy, {"from": alice}) + root_gauge_factory_proxy.accept_transfer_ownership(gauge_factory, {"from": bob}) + + for admin in [manager, default_ownership_admin]: + root_gauge_factory_proxy.set_implementation(gauge_factory, ETH_ADDRESS, {"from": admin}) + assert gauge_factory.get_implementation() == ETH_ADDRESS + chain.undo() + + # emergency admin cannot set gauge implementation: + with brownie.reverts(): + root_gauge_factory_proxy.set_implementation( + gauge_factory, ETH_ADDRESS, {"from": default_emergency_admin} + ) + + # but emergency admin can set itself (or anyone) as manager and change implementation: + chain.snapshot() # cache state so we can revert back later to repeat the test + root_gauge_factory_proxy.set_manager( + default_emergency_admin, {"from": default_emergency_admin} + ) + root_gauge_factory_proxy.set_implementation( + gauge_factory, ETH_ADDRESS, {"from": default_emergency_admin} + ) + assert gauge_factory.get_implementation() == ETH_ADDRESS + chain.revert() # revert back to cached state + + +def test_set_call_proxy( + root_gauge_factory, child_gauge_factory, root_gauge_factory_proxy, alice, bob, chain +): + + default_ownership_admin = root_gauge_factory_proxy.ownership_admin() + default_emergency_admin = root_gauge_factory_proxy.emergency_admin() + + for gauge_factory in [root_gauge_factory, child_gauge_factory]: + print(f"\ngauge factory {gauge_factory} owner {gauge_factory.owner()}\n") + assert gauge_factory.owner() == alice + print(f"assertion that alice is the owner passed for {gauge_factory}") + manager = root_gauge_factory_proxy.manager() + # proxy cannot set call proxy yet (only possible by factory owner): + for admin in [manager, default_ownership_admin]: + with brownie.reverts(): + root_gauge_factory_proxy.set_call_proxy(gauge_factory, ETH_ADDRESS, {"from": admin}) + + # so transfer root gauge factory ownership to proxy: + gauge_factory.commit_transfer_ownership(root_gauge_factory_proxy, {"from": alice}) + root_gauge_factory_proxy.accept_transfer_ownership(gauge_factory, {"from": bob}) + + for admin in [manager, default_ownership_admin]: + root_gauge_factory_proxy.set_call_proxy(gauge_factory, ETH_ADDRESS, {"from": admin}) + assert gauge_factory.call_proxy() == ETH_ADDRESS + chain.undo() + + # emergency admin cannot set call proxy: + with brownie.reverts(): + root_gauge_factory_proxy.set_call_proxy( + root_gauge_factory, ETH_ADDRESS, {"from": default_emergency_admin} + ) + + # but emergency admin can set itself (or anyone) as manager and change the gauge factory's call proxy + chain.snapshot() # cache state so we can revert back later to repeat the test + root_gauge_factory_proxy.set_manager( + default_emergency_admin, {"from": default_emergency_admin} + ) + root_gauge_factory_proxy.set_call_proxy( + root_gauge_factory, ETH_ADDRESS, {"from": default_emergency_admin} + ) + assert gauge_factory.call_proxy() == ETH_ADDRESS + chain.revert() # revert back to cached state From 88b8d4792c854fe811e5dee6d248156581f585f4 Mon Sep 17 00:00:00 2001 From: bout3fiddy <11488427+bout3fiddy@users.noreply.github.com> Date: Tue, 17 May 2022 18:22:55 +0200 Subject: [PATCH 6/7] fix: remove child gauge from testing scope --- .../test_root_gauge_factory_proxy_admin.py | 259 ++++++++---------- 1 file changed, 118 insertions(+), 141 deletions(-) diff --git a/tests/root_gauge_factory_proxy/test_root_gauge_factory_proxy_admin.py b/tests/root_gauge_factory_proxy/test_root_gauge_factory_proxy_admin.py index 7d428cf..390bec4 100644 --- a/tests/root_gauge_factory_proxy/test_root_gauge_factory_proxy_admin.py +++ b/tests/root_gauge_factory_proxy/test_root_gauge_factory_proxy_admin.py @@ -66,58 +66,53 @@ def test_transfer_proxy_admins(root_gauge_factory_proxy, alice, bob, charlie): def test_transfer_ownership( - alice, bob, charlie, chain, root_gauge_factory, child_gauge_factory, root_gauge_factory_proxy + alice, bob, charlie, chain, root_gauge_factory, root_gauge_factory_proxy ): default_ownership_admin = root_gauge_factory_proxy.ownership_admin() default_emergency_admin = root_gauge_factory_proxy.emergency_admin() - # transfer ownership for both root gauge factory and child gauge factory - for gauge_factory in [root_gauge_factory, child_gauge_factory]: - - # --- - # commit transfer ownership: set gauge proxy as future factory owner - - assert gauge_factory.owner() == alice # alice is the owner - # since proxy contract is not an owner yet, this will revert: - for acct in [ - default_ownership_admin, - default_emergency_admin, - bob, - charlie, - root_gauge_factory_proxy, - ]: - with brownie.reverts(): - root_gauge_factory_proxy.commit_transfer_ownership( - gauge_factory, root_gauge_factory_proxy, {"from": acct} - ) - - # set proxy as future owner: only factory owner can do this - gauge_factory.commit_transfer_ownership(root_gauge_factory_proxy, {"from": alice}) - assert gauge_factory.future_owner() == root_gauge_factory_proxy - assert gauge_factory.owner() == alice # alice is still the owner - - # --- - # accept transfer ownership: only proxy (root_gauge_factory.future_owner) can accept - # this is callable by anyone through the proxy - - # unauthorised accounts cannot complete ownership transfer through the factory - for acct in [default_ownership_admin, default_emergency_admin, alice, bob, charlie]: - with brownie.reverts(): - gauge_factory.accept_transfer_ownership({"from": acct}) - - # completing transfer can be only be done through the root gauge factory proxy now - for acct in [alice, bob, charlie]: - root_gauge_factory_proxy.accept_transfer_ownership(gauge_factory, {"from": acct}) - assert gauge_factory.owner() == root_gauge_factory_proxy - chain.undo() + # --- + # commit transfer ownership: set gauge proxy as future factory owner + + assert root_gauge_factory.owner() == alice # alice is the owner + # since proxy contract is not an owner yet, this will revert: + for acct in [ + default_ownership_admin, + default_emergency_admin, + bob, + charlie, + root_gauge_factory_proxy, + ]: + with brownie.reverts(): + root_gauge_factory_proxy.commit_transfer_ownership( + root_gauge_factory, root_gauge_factory_proxy, {"from": acct} + ) + + # set proxy as future owner: only factory owner can do this + root_gauge_factory.commit_transfer_ownership(root_gauge_factory_proxy, {"from": alice}) + assert root_gauge_factory.future_owner() == root_gauge_factory_proxy + assert root_gauge_factory.owner() == alice # alice is still the owner + + # --- + # accept transfer ownership: only proxy (root_gauge_factory.future_owner) can accept + # this is callable by anyone through the proxy + + # unauthorised accounts cannot complete ownership transfer through the factory + for acct in [default_ownership_admin, default_emergency_admin, alice, bob, charlie]: + with brownie.reverts(): + root_gauge_factory.accept_transfer_ownership({"from": acct}) + + # completing transfer can be only be done through the root gauge factory proxy now + for acct in [alice, bob, charlie]: + root_gauge_factory_proxy.accept_transfer_ownership(root_gauge_factory, {"from": acct}) + assert root_gauge_factory.owner() == root_gauge_factory_proxy + chain.undo() def test_set_killed( root_gauge, - child_gauge, root_gauge_factory, - child_gauge_factory, root_gauge_factory_proxy, alice, bob, @@ -128,45 +123,40 @@ def test_set_killed( default_ownership_admin = root_gauge_factory_proxy.ownership_admin() default_emergency_admin = root_gauge_factory_proxy.emergency_admin() - # testing `set_killed` for root and child gauges - gauge_mapping = {root_gauge_factory: root_gauge, child_gauge_factory: child_gauge} + # alice deployed the factory and set herself as the owner of the factory contract + assert root_gauge_factory.owner() == alice + + # alice is the only one who can kill gauges + root_gauge.set_killed(True, {"from": alice}) + assert root_gauge.is_killed() + assert root_gauge.inflation_params()[0] == 0 # inflation rate of root gauge should be 0 + chain.undo() + + # proxy cannot kill gauges yet, and neither can alice do it through the proxy: + for unauthorised_admins in [ + default_emergency_admin, + default_ownership_admin, + alice, + ]: + with brownie.reverts(): + root_gauge_factory_proxy.set_killed(root_gauge, True, {"from": unauthorised_admins}) - for gauge_factory, gauge in gauge_mapping.items(): - # alice deployed the factory and set herself as the owner of the factory contract - assert gauge_factory.owner() == alice + # so transfer root gauge factory ownership to proxy: + root_gauge_factory.commit_transfer_ownership(root_gauge_factory_proxy, {"from": alice}) + root_gauge_factory_proxy.accept_transfer_ownership(root_gauge_factory, {"from": bob}) - # alice is the only one who can kill gauges - gauge.set_killed(True, {"from": alice}) - assert gauge.is_killed() - if gauge == root_gauge: - assert gauge.inflation_params()[0] == 0 # inflation rate of root gauge should be 0 + # only proxy admins can kill a gauge: + for authorised_admin in [default_emergency_admin, default_ownership_admin]: + root_gauge_factory_proxy.set_killed(root_gauge, True, {"from": authorised_admin}) + assert root_gauge.is_killed() + if root_gauge == root_gauge: + assert root_gauge.inflation_params()[0] == 0 # inflation rate of root gauge should be 0 chain.undo() - # proxy cannot kill gauges yet, and neither can alice do it through the proxy: - for unauthorised_admins in [ - default_emergency_admin, - default_ownership_admin, - alice, - ]: - with brownie.reverts(): - root_gauge_factory_proxy.set_killed(gauge, True, {"from": unauthorised_admins}) - - # so transfer root gauge factory ownership to proxy: - gauge_factory.commit_transfer_ownership(root_gauge_factory_proxy, {"from": alice}) - root_gauge_factory_proxy.accept_transfer_ownership(gauge_factory, {"from": bob}) - - # only proxy admins can kill a gauge: - for authorised_admin in [default_emergency_admin, default_ownership_admin]: - root_gauge_factory_proxy.set_killed(gauge, True, {"from": authorised_admin}) - assert gauge.is_killed() - if gauge == root_gauge: - assert gauge.inflation_params()[0] == 0 # inflation rate of root gauge should be 0 - chain.undo() - - # unauthorised accounts cannot do so: - for unauthorised_acct in [alice, bob, charlie]: - with brownie.reverts(): - root_gauge_factory_proxy.set_killed(gauge, True, {"from": unauthorised_acct}) + # unauthorised accounts cannot do so: + for unauthorised_acct in [alice, bob, charlie]: + with brownie.reverts(): + root_gauge_factory_proxy.set_killed(root_gauge, True, {"from": unauthorised_acct}) def test_set_bridger(root_gauge_factory, root_gauge_factory_proxy, alice, bob, chain): @@ -208,91 +198,78 @@ def test_set_bridger(root_gauge_factory, root_gauge_factory_proxy, alice, bob, c assert root_gauge_factory.get_bridger(chain.id) == ETH_ADDRESS -def test_set_implementation( - root_gauge_factory, child_gauge_factory, root_gauge_factory_proxy, alice, bob, chain -): +def test_set_implementation(root_gauge_factory, root_gauge_factory_proxy, alice, bob, chain): default_ownership_admin = root_gauge_factory_proxy.ownership_admin() default_emergency_admin = root_gauge_factory_proxy.emergency_admin() - for gauge_factory in [root_gauge_factory, child_gauge_factory]: - print(f"\ngauge factory {gauge_factory} owner {gauge_factory.owner()}\n") - assert gauge_factory.owner() == alice - print(f"assertion that alice is the owner passed for {gauge_factory}") - manager = root_gauge_factory_proxy.manager() - # proxy cannot set gauge implementation contract yet: - for admin in [manager, default_ownership_admin]: - with brownie.reverts(): - root_gauge_factory_proxy.set_implementation( - gauge_factory, ETH_ADDRESS, {"from": admin} - ) - - # so transfer root gauge factory ownership to proxy: - gauge_factory.commit_transfer_ownership(root_gauge_factory_proxy, {"from": alice}) - root_gauge_factory_proxy.accept_transfer_ownership(gauge_factory, {"from": bob}) - - for admin in [manager, default_ownership_admin]: - root_gauge_factory_proxy.set_implementation(gauge_factory, ETH_ADDRESS, {"from": admin}) - assert gauge_factory.get_implementation() == ETH_ADDRESS - chain.undo() - - # emergency admin cannot set gauge implementation: + assert root_gauge_factory.owner() == alice + manager = root_gauge_factory_proxy.manager() + # proxy cannot set gauge implementation contract yet: + for admin in [manager, default_ownership_admin]: with brownie.reverts(): root_gauge_factory_proxy.set_implementation( - gauge_factory, ETH_ADDRESS, {"from": default_emergency_admin} + root_gauge_factory, ETH_ADDRESS, {"from": admin} ) - # but emergency admin can set itself (or anyone) as manager and change implementation: - chain.snapshot() # cache state so we can revert back later to repeat the test - root_gauge_factory_proxy.set_manager( - default_emergency_admin, {"from": default_emergency_admin} + # so transfer root gauge factory ownership to proxy: + root_gauge_factory.commit_transfer_ownership(root_gauge_factory_proxy, {"from": alice}) + root_gauge_factory_proxy.accept_transfer_ownership(root_gauge_factory, {"from": bob}) + + for admin in [manager, default_ownership_admin]: + root_gauge_factory_proxy.set_implementation( + root_gauge_factory, ETH_ADDRESS, {"from": admin} ) + assert root_gauge_factory.get_implementation() == ETH_ADDRESS + chain.undo() + + # emergency admin cannot set gauge implementation: + with brownie.reverts(): root_gauge_factory_proxy.set_implementation( - gauge_factory, ETH_ADDRESS, {"from": default_emergency_admin} + root_gauge_factory, ETH_ADDRESS, {"from": default_emergency_admin} ) - assert gauge_factory.get_implementation() == ETH_ADDRESS - chain.revert() # revert back to cached state + # but emergency admin can set itself (or anyone) as manager and change implementation: + root_gauge_factory_proxy.set_manager(default_emergency_admin, {"from": default_emergency_admin}) + root_gauge_factory_proxy.set_implementation( + root_gauge_factory, ETH_ADDRESS, {"from": default_emergency_admin} + ) + assert root_gauge_factory.get_implementation() == ETH_ADDRESS -def test_set_call_proxy( - root_gauge_factory, child_gauge_factory, root_gauge_factory_proxy, alice, bob, chain -): + +def test_set_call_proxy(root_gauge_factory, root_gauge_factory_proxy, alice, bob, chain): default_ownership_admin = root_gauge_factory_proxy.ownership_admin() default_emergency_admin = root_gauge_factory_proxy.emergency_admin() - for gauge_factory in [root_gauge_factory, child_gauge_factory]: - print(f"\ngauge factory {gauge_factory} owner {gauge_factory.owner()}\n") - assert gauge_factory.owner() == alice - print(f"assertion that alice is the owner passed for {gauge_factory}") - manager = root_gauge_factory_proxy.manager() - # proxy cannot set call proxy yet (only possible by factory owner): - for admin in [manager, default_ownership_admin]: - with brownie.reverts(): - root_gauge_factory_proxy.set_call_proxy(gauge_factory, ETH_ADDRESS, {"from": admin}) - - # so transfer root gauge factory ownership to proxy: - gauge_factory.commit_transfer_ownership(root_gauge_factory_proxy, {"from": alice}) - root_gauge_factory_proxy.accept_transfer_ownership(gauge_factory, {"from": bob}) - - for admin in [manager, default_ownership_admin]: - root_gauge_factory_proxy.set_call_proxy(gauge_factory, ETH_ADDRESS, {"from": admin}) - assert gauge_factory.call_proxy() == ETH_ADDRESS - chain.undo() - - # emergency admin cannot set call proxy: + assert root_gauge_factory.owner() == alice + manager = root_gauge_factory_proxy.manager() + # proxy cannot set call proxy yet (only possible by factory owner): + for admin in [manager, default_ownership_admin]: with brownie.reverts(): root_gauge_factory_proxy.set_call_proxy( - root_gauge_factory, ETH_ADDRESS, {"from": default_emergency_admin} + root_gauge_factory, ETH_ADDRESS, {"from": admin} ) - # but emergency admin can set itself (or anyone) as manager and change the gauge factory's call proxy - chain.snapshot() # cache state so we can revert back later to repeat the test - root_gauge_factory_proxy.set_manager( - default_emergency_admin, {"from": default_emergency_admin} - ) + # so transfer root gauge factory ownership to proxy: + root_gauge_factory.commit_transfer_ownership(root_gauge_factory_proxy, {"from": alice}) + root_gauge_factory_proxy.accept_transfer_ownership(root_gauge_factory, {"from": bob}) + + for admin in [manager, default_ownership_admin]: + root_gauge_factory_proxy.set_call_proxy(root_gauge_factory, ETH_ADDRESS, {"from": admin}) + assert root_gauge_factory.call_proxy() == ETH_ADDRESS + chain.undo() + + # emergency admin cannot set call proxy: + with brownie.reverts(): root_gauge_factory_proxy.set_call_proxy( root_gauge_factory, ETH_ADDRESS, {"from": default_emergency_admin} ) - assert gauge_factory.call_proxy() == ETH_ADDRESS - chain.revert() # revert back to cached state + + # but emergency admin can set itself (or anyone) as manager and + # change the gauge factory's call proxy + root_gauge_factory_proxy.set_manager(default_emergency_admin, {"from": default_emergency_admin}) + root_gauge_factory_proxy.set_call_proxy( + root_gauge_factory, ETH_ADDRESS, {"from": default_emergency_admin} + ) + assert root_gauge_factory.call_proxy() == ETH_ADDRESS From 62038fe372f9c69d9c3b2eeb1e8868472c0d69ce Mon Sep 17 00:00:00 2001 From: bout3fiddy <11488427+bout3fiddy@users.noreply.github.com> Date: Sat, 21 May 2022 17:14:22 +0200 Subject: [PATCH 7/7] feat: simplified/granularised tests --- tests/fixtures/deployments.py | 1 - tests/reward_forwarder/test_deposit_reward.py | 93 ++--- .../test_root_gauge_factory_proxy_admin.py | 326 ++++++++---------- 3 files changed, 188 insertions(+), 232 deletions(-) diff --git a/tests/fixtures/deployments.py b/tests/fixtures/deployments.py index 5a160b1..adfc902 100644 --- a/tests/fixtures/deployments.py +++ b/tests/fixtures/deployments.py @@ -2,7 +2,6 @@ from brownie import Contract from brownie_tokens import ERC20 - # ANYCALL DEPLOYMENT diff --git a/tests/reward_forwarder/test_deposit_reward.py b/tests/reward_forwarder/test_deposit_reward.py index d4f4cf0..f861afc 100644 --- a/tests/reward_forwarder/test_deposit_reward.py +++ b/tests/reward_forwarder/test_deposit_reward.py @@ -1,29 +1,46 @@ -import pytest import brownie +import pytest WEEK = 86400 * 7 -def test_reward_deposit(alice, bob, charlie, child_gauge, reward_forwarder, reward_token): +@pytest.fixture(scope="module", autouse=True) +def setup(alice, bob, charlie, child_gauge, reward_token, lp_token): - reward_token._mint_for_testing(charlie, 10 ** 26, {"from": alice}) - reward_forwarder.allow(reward_token, {"from": alice}) + lp_token.approve(child_gauge, 10**21, {"from": alice}) + lp_token._mint_for_testing(alice, 10**21, {"from": alice}) + child_gauge.deposit(10**21, {"from": alice}) + reward_token._mint_for_testing(charlie, 10**26, {"from": alice}) child_gauge.set_manager(bob, {"from": alice}) + + +@pytest.fixture(scope="module", autouse=False) +def setup_with_deposited_rewards(alice, bob, charlie, reward_forwarder, child_gauge, reward_token): + child_gauge.add_reward(reward_token, reward_forwarder, {"from": bob}) + reward_token.transfer(reward_forwarder, 10**20, {"from": charlie}) - reward_token.transfer(reward_forwarder, 10 ** 20, {"from": charlie}) + reward_forwarder.allow(reward_token, {"from": alice}) reward_forwarder.deposit_reward_token(reward_token, {"from": charlie}) - assert reward_token.balanceOf(child_gauge) == 10 ** 20 +def test_reward_deposit(alice, bob, charlie, child_gauge, reward_forwarder, reward_token): -def test_reward_token_approval(alice, bob, charlie, child_gauge, reward_forwarder, reward_token): + reward_forwarder.allow(reward_token, {"from": alice}) + child_gauge.add_reward(reward_token, reward_forwarder, {"from": bob}) + reward_token.transfer(reward_forwarder, 10**20, {"from": charlie}) + reward_forwarder.deposit_reward_token(reward_token, {"from": charlie}) - reward_token._mint_for_testing(charlie, 10 ** 26, {"from": alice}) - reward_token.transfer(reward_forwarder, 10 ** 20, {"from": charlie}) + assert reward_token.balanceOf(child_gauge) == 10**20 + assert child_gauge.reward_data(reward_token)["rate"] > 0 - child_gauge.set_manager(bob, {"from": alice}) + +def test_reward_deposit_reverts_without_allowance( + bob, charlie, child_gauge, reward_forwarder, reward_token +): + + reward_token.transfer(reward_forwarder, 10**20, {"from": charlie}) child_gauge.add_reward(reward_token, reward_forwarder, {"from": bob}) # empty reward_forwarder cannot transfer tokens unless `allow` is called @@ -31,11 +48,12 @@ def test_reward_token_approval(alice, bob, charlie, child_gauge, reward_forwarde reward_forwarder.deposit_reward_token(reward_token, {"from": charlie}) -def test_unauthorised_distributor(alice, charlie, reward_forwarder, reward_token): +def test_reward_deposit_reverts_with_unauthorised_distributor( + alice, charlie, reward_forwarder, reward_token +): - reward_token._mint_for_testing(charlie, 10 ** 26, {"from": alice}) reward_forwarder.allow(reward_token, {"from": alice}) - reward_token.transfer(reward_forwarder, 10 ** 20, {"from": charlie}) + reward_token.transfer(reward_forwarder, 10**20, {"from": charlie}) # reward_forwarder cannot deposit unless it is added as a distributor for that token # in the gauge contract @@ -43,57 +61,44 @@ def test_unauthorised_distributor(alice, charlie, reward_forwarder, reward_token reward_forwarder.deposit_reward_token(reward_token, {"from": charlie}) -def test_unauthorised_reward_token_for_authorised_distributor( +def test_reward_deposit_revert_for_unauthorised_token( alice, bob, charlie, child_gauge, reward_forwarder, reward_token, unauthorised_token ): - reward_token._mint_for_testing(charlie, 10 ** 26, {"from": alice}) - unauthorised_token._mint_for_testing(charlie, 10 ** 26, {"from": alice}) + unauthorised_token._mint_for_testing(charlie, 10**26, {"from": alice}) reward_forwarder.allow(reward_token, {"from": alice}) reward_forwarder.allow(unauthorised_token, {"from": alice}) # only add one token to gauge rewards - child_gauge.set_manager(bob, {"from": alice}) child_gauge.add_reward(reward_token, reward_forwarder, {"from": bob}) - reward_token.transfer(reward_forwarder, 10 ** 20, {"from": charlie}) - unauthorised_token.transfer(reward_forwarder, 10 ** 20, {"from": charlie}) + reward_token.transfer(reward_forwarder, 10**20, {"from": charlie}) + unauthorised_token.transfer(reward_forwarder, 10**20, {"from": charlie}) with brownie.reverts(): reward_forwarder.deposit_reward_token(unauthorised_token, {"from": charlie}) -def test_zero_reward_rate_claims( - alice, bob, charlie, child_gauge, chain, reward_forwarder, reward_token, lp_token +def test_reward_claim_when_reward_rate_is_zero( + alice, + bob, + charlie, + child_gauge, + chain, + reward_forwarder, + reward_token, + setup_with_deposited_rewards, ): - # mint lptokens and deposit into gauge: - lp_token.approve(child_gauge, 10 ** 21, {"from": alice}) - lp_token._mint_for_testing(alice, 10 ** 21, {"from": alice}) - child_gauge.deposit(10 ** 21, {"from": alice}) - - # mint reward tokens and approve transfers for RewardForwarder: - reward_token._mint_for_testing(charlie, 10 ** 26, {"from": alice}) - reward_forwarder.allow(reward_token, {"from": alice}) - - # set gauge managers: - child_gauge.set_manager(bob, {"from": alice}) - child_gauge.add_reward(reward_token, reward_forwarder, {"from": bob}) - - # deposit rewards and check if claimable reward token rate is non-zero: - reward_token.transfer(reward_forwarder, 10 ** 20, {"from": charlie}) - reward_forwarder.deposit_reward_token(reward_token, {"from": charlie}) - assert reward_token.balanceOf(reward_forwarder) == 0 # no tokens in the reward forwarder - assert child_gauge.reward_data(reward_token)[2] > 0 # token distribution rate is non-zero - - # sleep for a week until after period finish: chain.sleep(WEEK + 1) # sleep for 1 week and 1 second - assert chain.time() > child_gauge.reward_data(reward_token)[1] # `period_end` reached - # transferring zero reward tokens: this will make reward_token distribution rate zero + # reward forwarder has zero balance. Transferring zero reward tokens. reward_forwarder.deposit_reward_token(reward_token, {"from": charlie}) - assert child_gauge.reward_data(reward_token)[2] == 0 # token distribution rate becomes zero + + # Every deposit of a reward token checkpoints reward distribution, updating integrals for users + # Token distribution rate should become zero: + assert child_gauge.reward_data(reward_token)[2] == 0 # check alice's balance before and after claims: assert reward_token.balanceOf(alice) == 0 diff --git a/tests/root_gauge_factory_proxy/test_root_gauge_factory_proxy_admin.py b/tests/root_gauge_factory_proxy/test_root_gauge_factory_proxy_admin.py index 390bec4..b110f8b 100644 --- a/tests/root_gauge_factory_proxy/test_root_gauge_factory_proxy_admin.py +++ b/tests/root_gauge_factory_proxy/test_root_gauge_factory_proxy_admin.py @@ -1,275 +1,227 @@ import brownie +import pytest from brownie import ETH_ADDRESS -def test_set_manager(root_gauge_factory_proxy, alice, bob, charlie, chain): +@pytest.fixture(scope="module") +def default_owner(root_gauge_factory_proxy): + yield root_gauge_factory_proxy.ownership_admin() - default_ownership_admin = root_gauge_factory_proxy.ownership_admin() - default_emergency_admin = root_gauge_factory_proxy.emergency_admin() - assert root_gauge_factory_proxy.manager() == alice # contract deployer is manager - # unauthorised users cannot change the manager: +@pytest.fixture(scope="module") +def default_e_admin(root_gauge_factory_proxy): + yield root_gauge_factory_proxy.emergency_admin() + + +@pytest.fixture(scope="module") +def transfer_factory_ownership_to_proxy(alice, bob, root_gauge_factory, root_gauge_factory_proxy): + root_gauge_factory.commit_transfer_ownership(root_gauge_factory_proxy, {"from": alice}) + root_gauge_factory_proxy.accept_transfer_ownership(root_gauge_factory, {"from": bob}) + + +def test_set_manager_reverts_for_unauthorised_users(bob, charlie, root_gauge_factory_proxy): + with brownie.reverts(): root_gauge_factory_proxy.set_manager(charlie, {"from": bob}) - # emergency admin and ownership admin can become manager: - for acct in [default_emergency_admin, default_ownership_admin]: - root_gauge_factory_proxy.set_manager(acct, {"from": acct}) - assert root_gauge_factory_proxy.manager() == acct - chain.undo() - # authorised users can change the manager to anyone: - for acct in [default_emergency_admin, default_ownership_admin, alice]: +def test_set_manager_success_for_authorised_users( + alice, bob, root_gauge_factory_proxy, chain, default_owner, default_e_admin +): + + for acct in [alice, default_owner, default_e_admin]: root_gauge_factory_proxy.set_manager(bob, {"from": acct}) assert root_gauge_factory_proxy.manager() == bob chain.undo() -def test_transfer_proxy_admins(root_gauge_factory_proxy, alice, bob, charlie): - - default_ownership_admin = root_gauge_factory_proxy.ownership_admin() - default_emergency_admin = root_gauge_factory_proxy.emergency_admin() - - # --- - # commit future proxy owners +def test_commit_admin_reverts_for_unauthorised_users( + alice, bob, charlie, root_gauge_factory_proxy, default_e_admin +): - # manager cannot commit new admins - with brownie.reverts(): - root_gauge_factory_proxy.commit_set_admins(bob, charlie, {"from": alice}) + for user in [alice, bob, charlie, default_e_admin]: + with brownie.reverts(): + root_gauge_factory_proxy.commit_set_admins(bob, charlie, {"from": user}) - # unauthorised accounts cannot commit new admins - with brownie.reverts(): - root_gauge_factory_proxy.commit_set_admins(bob, bob, {"from": charlie}) - # emergency admin cannot commit new admins - with brownie.reverts(): - root_gauge_factory_proxy.commit_set_admins(bob, charlie, {"from": default_emergency_admin}) +@pytest.fixture(scope="module") +def test_commit_admin_successful_for_authorised_user( + alice, bob, charlie, root_gauge_factory_proxy, default_owner +): - # commit future owners - root_gauge_factory_proxy.commit_set_admins(bob, charlie, {"from": default_ownership_admin}) - assert root_gauge_factory_proxy.ownership_admin() == default_ownership_admin - assert root_gauge_factory_proxy.emergency_admin() == default_emergency_admin + root_gauge_factory_proxy.commit_set_admins(bob, charlie, {"from": default_owner}) assert root_gauge_factory_proxy.future_ownership_admin() == bob assert root_gauge_factory_proxy.future_emergency_admin() == charlie - # --- - # accept new proxy owners - # unauthorised accts cannot accept future ownership and emergency admins on behalf: - for acct in [default_ownership_admin, default_emergency_admin, alice, charlie]: +def test_accept_admin_revert_for_unauthorised_user( + alice, + charlie, + root_gauge_factory_proxy, + test_commit_admin_successful_for_authorised_user, + default_owner, + default_e_admin, +): + + for acct in [alice, charlie, default_owner, default_e_admin]: with brownie.reverts(): root_gauge_factory_proxy.accept_set_admins({"from": acct}) + +def test_accept_admin_success_for_future_ownership_admin( + root_gauge_factory_proxy, bob, charlie, test_commit_admin_successful_for_authorised_user +): + root_gauge_factory_proxy.accept_set_admins({"from": bob}) assert root_gauge_factory_proxy.ownership_admin() == bob assert root_gauge_factory_proxy.emergency_admin() == charlie -def test_transfer_ownership( - alice, bob, charlie, chain, root_gauge_factory, root_gauge_factory_proxy +def test_commit_transfer_ownership_reverts_for_unauthorised_users( + bob, charlie, root_gauge_factory, root_gauge_factory_proxy, default_owner, default_e_admin ): - default_ownership_admin = root_gauge_factory_proxy.ownership_admin() - default_emergency_admin = root_gauge_factory_proxy.emergency_admin() - - # --- - # commit transfer ownership: set gauge proxy as future factory owner - - assert root_gauge_factory.owner() == alice # alice is the owner - # since proxy contract is not an owner yet, this will revert: - for acct in [ - default_ownership_admin, - default_emergency_admin, - bob, - charlie, - root_gauge_factory_proxy, - ]: + for acct in [bob, charlie, root_gauge_factory_proxy, default_owner, default_e_admin]: with brownie.reverts(): root_gauge_factory_proxy.commit_transfer_ownership( root_gauge_factory, root_gauge_factory_proxy, {"from": acct} ) - # set proxy as future owner: only factory owner can do this + +def test_commit_transfer_ownership_success_for_factory_owner( + alice, root_gauge_factory, root_gauge_factory_proxy +): + root_gauge_factory.commit_transfer_ownership(root_gauge_factory_proxy, {"from": alice}) assert root_gauge_factory.future_owner() == root_gauge_factory_proxy - assert root_gauge_factory.owner() == alice # alice is still the owner + assert root_gauge_factory.owner() == alice - # --- - # accept transfer ownership: only proxy (root_gauge_factory.future_owner) can accept - # this is callable by anyone through the proxy - # unauthorised accounts cannot complete ownership transfer through the factory - for acct in [default_ownership_admin, default_emergency_admin, alice, bob, charlie]: - with brownie.reverts(): - root_gauge_factory.accept_transfer_ownership({"from": acct}) +def test_accept_transfer_ownership_success_for_authorised_admin( + alice, bob, charlie, chain, root_gauge_factory, root_gauge_factory_proxy +): - # completing transfer can be only be done through the root gauge factory proxy now + root_gauge_factory.commit_transfer_ownership(root_gauge_factory_proxy, {"from": alice}) for acct in [alice, bob, charlie]: root_gauge_factory_proxy.accept_transfer_ownership(root_gauge_factory, {"from": acct}) assert root_gauge_factory.owner() == root_gauge_factory_proxy chain.undo() -def test_set_killed( +def test_set_killed_success_for_authorised_admin( + chain, root_gauge, - root_gauge_factory, root_gauge_factory_proxy, - alice, - bob, - charlie, - chain, + transfer_factory_ownership_to_proxy, + default_owner, + default_e_admin, ): - default_ownership_admin = root_gauge_factory_proxy.ownership_admin() - default_emergency_admin = root_gauge_factory_proxy.emergency_admin() - - # alice deployed the factory and set herself as the owner of the factory contract - assert root_gauge_factory.owner() == alice - - # alice is the only one who can kill gauges - root_gauge.set_killed(True, {"from": alice}) - assert root_gauge.is_killed() - assert root_gauge.inflation_params()[0] == 0 # inflation rate of root gauge should be 0 - chain.undo() - - # proxy cannot kill gauges yet, and neither can alice do it through the proxy: - for unauthorised_admins in [ - default_emergency_admin, - default_ownership_admin, - alice, - ]: - with brownie.reverts(): - root_gauge_factory_proxy.set_killed(root_gauge, True, {"from": unauthorised_admins}) - - # so transfer root gauge factory ownership to proxy: - root_gauge_factory.commit_transfer_ownership(root_gauge_factory_proxy, {"from": alice}) - root_gauge_factory_proxy.accept_transfer_ownership(root_gauge_factory, {"from": bob}) - - # only proxy admins can kill a gauge: - for authorised_admin in [default_emergency_admin, default_ownership_admin]: + for authorised_admin in [default_owner, default_e_admin]: root_gauge_factory_proxy.set_killed(root_gauge, True, {"from": authorised_admin}) assert root_gauge.is_killed() - if root_gauge == root_gauge: - assert root_gauge.inflation_params()[0] == 0 # inflation rate of root gauge should be 0 + assert root_gauge.inflation_params()[0] == 0 # inflation rate of root gauge should be 0 chain.undo() - # unauthorised accounts cannot do so: + +def test_set_killed_reverts_for_unauthorised_users( + alice, bob, charlie, root_gauge, root_gauge_factory_proxy, transfer_factory_ownership_to_proxy +): + for unauthorised_acct in [alice, bob, charlie]: with brownie.reverts(): root_gauge_factory_proxy.set_killed(root_gauge, True, {"from": unauthorised_acct}) -def test_set_bridger(root_gauge_factory, root_gauge_factory_proxy, alice, bob, chain): - - default_ownership_admin = root_gauge_factory_proxy.ownership_admin() - default_emergency_admin = root_gauge_factory_proxy.emergency_admin() +def test_set_bridger_success_for_authorised_users( + root_gauge_factory, + root_gauge_factory_proxy, + chain, + transfer_factory_ownership_to_proxy, + default_owner, +): - assert root_gauge_factory.owner() == alice manager = root_gauge_factory_proxy.manager() - # proxy cannot set bridger yet: - for admin in [manager, default_ownership_admin]: - with brownie.reverts(): - root_gauge_factory_proxy.set_bridger( - root_gauge_factory, chain.id, ETH_ADDRESS, {"from": admin} - ) - - # so transfer root gauge factory ownership to proxy: - root_gauge_factory.commit_transfer_ownership(root_gauge_factory_proxy, {"from": alice}) - root_gauge_factory_proxy.accept_transfer_ownership(root_gauge_factory, {"from": bob}) - - for admin in [manager, default_ownership_admin]: + for acct in [manager, default_owner]: root_gauge_factory_proxy.set_bridger( - root_gauge_factory, chain.id, ETH_ADDRESS, {"from": admin} + root_gauge_factory, chain.id, ETH_ADDRESS, {"from": acct} ) assert root_gauge_factory.get_bridger(chain.id) == ETH_ADDRESS chain.undo() - # emergency admin cannot set bridger: - with brownie.reverts(): - root_gauge_factory_proxy.set_bridger( - root_gauge_factory, chain.id, ETH_ADDRESS, {"from": default_emergency_admin} - ) - # but emergency admin can set itself (or anyone) as manager and change bridger: - root_gauge_factory_proxy.set_manager(default_emergency_admin, {"from": default_emergency_admin}) - root_gauge_factory_proxy.set_bridger( - root_gauge_factory, chain.id, ETH_ADDRESS, {"from": default_emergency_admin} - ) - assert root_gauge_factory.get_bridger(chain.id) == ETH_ADDRESS - - -def test_set_implementation(root_gauge_factory, root_gauge_factory_proxy, alice, bob, chain): - - default_ownership_admin = root_gauge_factory_proxy.ownership_admin() - default_emergency_admin = root_gauge_factory_proxy.emergency_admin() +def test_set_bridger_revert_for_unauthorised_users( + bob, + charlie, + root_gauge_factory, + root_gauge_factory_proxy, + chain, + transfer_factory_ownership_to_proxy, + default_e_admin, +): - assert root_gauge_factory.owner() == alice - manager = root_gauge_factory_proxy.manager() - # proxy cannot set gauge implementation contract yet: - for admin in [manager, default_ownership_admin]: + for acct in [bob, charlie, default_e_admin]: with brownie.reverts(): - root_gauge_factory_proxy.set_implementation( - root_gauge_factory, ETH_ADDRESS, {"from": admin} + root_gauge_factory_proxy.set_bridger( + root_gauge_factory, chain.id, ETH_ADDRESS, {"from": acct} ) - # so transfer root gauge factory ownership to proxy: - root_gauge_factory.commit_transfer_ownership(root_gauge_factory_proxy, {"from": alice}) - root_gauge_factory_proxy.accept_transfer_ownership(root_gauge_factory, {"from": bob}) - for admin in [manager, default_ownership_admin]: - root_gauge_factory_proxy.set_implementation( - root_gauge_factory, ETH_ADDRESS, {"from": admin} - ) +def test_set_implementation_success_for_authorised_users( + root_gauge_factory, + root_gauge_factory_proxy, + chain, + transfer_factory_ownership_to_proxy, + default_owner, +): + + manager = root_gauge_factory_proxy.manager() + for acct in [manager, default_owner]: + root_gauge_factory_proxy.set_implementation(root_gauge_factory, ETH_ADDRESS, {"from": acct}) assert root_gauge_factory.get_implementation() == ETH_ADDRESS chain.undo() - # emergency admin cannot set gauge implementation: - with brownie.reverts(): - root_gauge_factory_proxy.set_implementation( - root_gauge_factory, ETH_ADDRESS, {"from": default_emergency_admin} - ) - - # but emergency admin can set itself (or anyone) as manager and change implementation: - root_gauge_factory_proxy.set_manager(default_emergency_admin, {"from": default_emergency_admin}) - root_gauge_factory_proxy.set_implementation( - root_gauge_factory, ETH_ADDRESS, {"from": default_emergency_admin} - ) - assert root_gauge_factory.get_implementation() == ETH_ADDRESS - -def test_set_call_proxy(root_gauge_factory, root_gauge_factory_proxy, alice, bob, chain): - - default_ownership_admin = root_gauge_factory_proxy.ownership_admin() - default_emergency_admin = root_gauge_factory_proxy.emergency_admin() +def test_set_implementation_revert_for_unauthorised_users( + bob, + charlie, + root_gauge_factory, + root_gauge_factory_proxy, + transfer_factory_ownership_to_proxy, + default_e_admin, +): - assert root_gauge_factory.owner() == alice - manager = root_gauge_factory_proxy.manager() - # proxy cannot set call proxy yet (only possible by factory owner): - for admin in [manager, default_ownership_admin]: + for acct in [bob, charlie, default_e_admin]: with brownie.reverts(): - root_gauge_factory_proxy.set_call_proxy( - root_gauge_factory, ETH_ADDRESS, {"from": admin} + root_gauge_factory_proxy.set_implementation( + root_gauge_factory, ETH_ADDRESS, {"from": acct} ) - # so transfer root gauge factory ownership to proxy: - root_gauge_factory.commit_transfer_ownership(root_gauge_factory_proxy, {"from": alice}) - root_gauge_factory_proxy.accept_transfer_ownership(root_gauge_factory, {"from": bob}) - for admin in [manager, default_ownership_admin]: - root_gauge_factory_proxy.set_call_proxy(root_gauge_factory, ETH_ADDRESS, {"from": admin}) +def test_set_call_proxy_success_for_authorised_users( + root_gauge_factory, + root_gauge_factory_proxy, + chain, + transfer_factory_ownership_to_proxy, + default_owner, +): + + manager = root_gauge_factory_proxy.manager() + for acct in [manager, default_owner]: + root_gauge_factory_proxy.set_call_proxy(root_gauge_factory, ETH_ADDRESS, {"from": acct}) assert root_gauge_factory.call_proxy() == ETH_ADDRESS chain.undo() - # emergency admin cannot set call proxy: - with brownie.reverts(): - root_gauge_factory_proxy.set_call_proxy( - root_gauge_factory, ETH_ADDRESS, {"from": default_emergency_admin} - ) - # but emergency admin can set itself (or anyone) as manager and - # change the gauge factory's call proxy - root_gauge_factory_proxy.set_manager(default_emergency_admin, {"from": default_emergency_admin}) - root_gauge_factory_proxy.set_call_proxy( - root_gauge_factory, ETH_ADDRESS, {"from": default_emergency_admin} - ) - assert root_gauge_factory.call_proxy() == ETH_ADDRESS +def test_set_call_proxy_revert_for_unauthorised_users( + bob, + charlie, + root_gauge_factory, + root_gauge_factory_proxy, + transfer_factory_ownership_to_proxy, + default_e_admin, +): + + for acct in [bob, charlie, default_e_admin]: + with brownie.reverts(): + root_gauge_factory_proxy.set_call_proxy(root_gauge_factory, ETH_ADDRESS, {"from": acct})