From 7acbb4fc47e3e13c54d4df89e00614b2c6c2a238 Mon Sep 17 00:00:00 2001 From: Steffel <2143646+steffenix@users.noreply.github.com> Date: Thu, 29 Apr 2021 17:26:15 +0200 Subject: [PATCH] fix: prevent clone of clone (#301) * fix: prevent clone of clone * fix: prettier --- contracts/BaseStrategy.sol | 2 ++ contracts/test/AffiliateToken.sol | 2 +- tests/functional/strategy/test_clone.py | 20 ++++++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/contracts/BaseStrategy.sol b/contracts/BaseStrategy.sol index 36e1374d..ef2417fa 100644 --- a/contracts/BaseStrategy.sol +++ b/contracts/BaseStrategy.sol @@ -842,6 +842,7 @@ abstract contract BaseStrategy { } abstract contract BaseStrategyInitializable is BaseStrategy { + bool public isOriginal = true; event Cloned(address indexed clone); constructor(address _vault) public BaseStrategy(_vault) {} @@ -856,6 +857,7 @@ abstract contract BaseStrategyInitializable is BaseStrategy { } function clone(address _vault) external returns (address) { + require(isOriginal, "!clone"); return this.clone(_vault, msg.sender, msg.sender, msg.sender); } diff --git a/contracts/test/AffiliateToken.sol b/contracts/test/AffiliateToken.sol index cede6bf6..3a1dc83a 100644 --- a/contracts/test/AffiliateToken.sol +++ b/contracts/test/AffiliateToken.sol @@ -84,7 +84,7 @@ contract AffiliateToken is ERC20, BaseWrapper { function deposit(uint256 amount) public returns (uint256 deposited) { deposited = _deposit(msg.sender, address(this), amount, true); // `true` = pull from `msg.sender` - uint256 shares = _sharesForValue(deposited); // NOTE: Must be calculated after deposit is handled + uint256 shares = _sharesForValue(deposited); // NOTE: Must be calculated after deposit is handled _mint(msg.sender, shares); } diff --git a/tests/functional/strategy/test_clone.py b/tests/functional/strategy/test_clone.py index b712ac4c..79a1e0c3 100644 --- a/tests/functional/strategy/test_clone.py +++ b/tests/functional/strategy/test_clone.py @@ -15,6 +15,22 @@ def other_vault(gov, Vault, other_token): yield vault +@pytest.fixture +def strategy(gov, strategist, keeper, rewards, vault, TestStrategy): + strategy = strategist.deploy(TestStrategy, vault) + + strategy.setKeeper(keeper, {"from": strategist}) + vault.addStrategy( + strategy, + 4_000, # 40% of Vault + 0, # Minimum debt increase per harvest + 2 ** 256 - 1, # maximum debt increase per harvest + 1000, # 10% performance fee for Strategist + {"from": gov}, + ) + yield strategy + + def test_clone( Token, token, @@ -43,6 +59,10 @@ def test_clone( address = tx.events["Cloned"]["clone"] new_strategy = TestStrategy.at(address) + assert new_strategy.isOriginal() == False + with brownie.reverts(): + new_strategy.clone(other_vault, {"from": rando}) + assert new_strategy.strategist() == gov assert new_strategy.rewards() == guardian assert new_strategy.keeper() == strategist