diff --git a/contracts/modules/TreasuryModule.sol b/contracts/modules/TreasuryModule.sol index 18e1899..9f24d6d 100644 --- a/contracts/modules/TreasuryModule.sol +++ b/contracts/modules/TreasuryModule.sol @@ -8,6 +8,7 @@ import "./PoolController.sol"; import "../shared/CoreController.sol"; import "@etherisc/gif-interface/contracts/components/IComponent.sol"; +import "@etherisc/gif-interface/contracts/components/IProduct.sol"; import "@etherisc/gif-interface/contracts/modules/IPolicy.sol"; import "@etherisc/gif-interface/contracts/modules/ITreasury.sol"; @@ -72,8 +73,12 @@ contract TreasuryModule is require(address(_componentToken[productId]) == address(0), "ERROR:TRS-012:PRODUCT_TOKEN_ALREADY_SET"); uint256 riskpoolId = _pool.getRiskPoolForProduct(productId); - require(address(_componentToken[riskpoolId]) == address(0), "ERROR:TRS-013:RISKPOOL_TOKEN_ALREADY_SET"); + // require if riskpool token is already set and product token does match riskpool token + require(address(_componentToken[riskpoolId]) == address(0) + || address(_componentToken[riskpoolId]) == address(IProduct(address(component)).getToken()), + "ERROR:TRS-014:TOKEN_ADDRESS_NOT_MACHING"); + _componentToken[productId] = IERC20(erc20Address); _componentToken[riskpoolId] = IERC20(erc20Address); @@ -84,7 +89,7 @@ contract TreasuryModule is external override onlyInstanceOperator { - require(instanceWalletAddress != address(0), "ERROR:TRS-014:WALLET_ADDRESS_ZERO"); + require(instanceWalletAddress != address(0), "ERROR:TRS-015:WALLET_ADDRESS_ZERO"); _instanceWalletAddress = instanceWalletAddress; emit LogTreasuryInstanceWalletSet (instanceWalletAddress); @@ -95,8 +100,8 @@ contract TreasuryModule is onlyInstanceOperator { IComponent component = _component.getComponent(riskpoolId); - require(component.isRiskpool(), "ERROR:TRS-015:NOT_RISKPOOL"); - require(riskpoolWalletAddress != address(0), "ERROR:TRS-016:WALLET_ADDRESS_ZERO"); + require(component.isRiskpool(), "ERROR:TRS-016:NOT_RISKPOOL"); + require(riskpoolWalletAddress != address(0), "ERROR:TRS-017:WALLET_ADDRESS_ZERO"); _riskpoolWallet[riskpoolId] = riskpoolWalletAddress; emit LogTreasuryRiskpoolWalletSet (riskpoolId, riskpoolWalletAddress); diff --git a/contracts/test/TestCoin.sol b/contracts/test/TestCoin.sol index 8bf1859..446cd76 100644 --- a/contracts/test/TestCoin.sol +++ b/contracts/test/TestCoin.sol @@ -18,4 +18,21 @@ contract TestCoin is ERC20 { INITIAL_SUPPLY ); } -} \ No newline at end of file +} + +contract TestCoinX is ERC20 { + + string public constant NAME = "Test Dummy X"; + string public constant SYMBOL = "TDX"; + + uint256 public constant INITIAL_SUPPLY = 10**24; + + constructor() + ERC20(NAME, SYMBOL) + { + _mint( + _msgSender(), + INITIAL_SUPPLY + ); + } +} diff --git a/scripts/product.py b/scripts/product.py index c85c478..25137e3 100644 --- a/scripts/product.py +++ b/scripts/product.py @@ -241,4 +241,4 @@ def getContract(self) -> TestProduct: return self.product def getPolicy(self, policyId: str): - return self.policy.getPolicy(policyId) \ No newline at end of file + return self.policy.getPolicy(policyId) diff --git a/tests/conftest.py b/tests/conftest.py index ba13047..b1a7045 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -25,6 +25,7 @@ InstanceOperatorService, InstanceService, TestCoin, + TestCoinX, TestRiskpool, TestOracle, TestProduct, @@ -238,6 +239,10 @@ def registry(registryController, owner) -> RegistryController: def testCoin(owner) -> TestCoin: return TestCoin.deploy({'from': owner}) +@pytest.fixture(scope="module") +def testCoinX(owner) -> TestCoinX: + return TestCoinX.deploy({'from': owner}) + @pytest.fixture(scope="module") def bundleToken(owner) -> BundleToken: return BundleToken.deploy({'from': owner}) diff --git a/tests/test_treasury_module.py b/tests/test_treasury_module.py index 282ead0..4c706d5 100644 --- a/tests/test_treasury_module.py +++ b/tests/test_treasury_module.py @@ -1,4 +1,5 @@ import brownie +import pytest from brownie.network.account import Account @@ -8,6 +9,16 @@ from scripts.product import GifTestOracle, GifTestProduct, GifTestRiskpool from scripts.util import b2s +from scripts.setup import ( + fund_riskpool, + apply_for_policy, +) + +# enforce function isolation for tests below +@pytest.fixture(autouse=True) +def isolation(fn_isolation): + pass + def test_bundle_creation_with_instance_wallet_not_set( instanceNoInstanceWallet: GifInstance, owner: Account, @@ -18,7 +29,7 @@ def test_bundle_creation_with_instance_wallet_not_set( capitalOwner: Account, ): withRiskpoolWallet = True - (gifProduct, gifRiskpool) = getProductAndRiskpool( + (gifProduct, gifRiskpool, gifOracle) = getProductAndRiskpool( instanceNoInstanceWallet, owner, testCoin, @@ -61,7 +72,7 @@ def test_bundle_creation_with_riskpool_wallet_not_set( feeOwner: Account, ): withRiskpoolWallet = False - (gifProduct, gifRiskpool) = getProductAndRiskpool( + (gifProduct, gifRiskpool, gifOracle) = getProductAndRiskpool( instance, owner, testCoin, @@ -94,6 +105,80 @@ def test_bundle_creation_with_riskpool_wallet_not_set( {'from': bundleOwner}) +def test_two_products_different_coin_same_riskpool( + instance: GifInstance, + owner: Account, + testCoin, + testCoinX, + productOwner: Account, + oracleProvider: Account, + riskpoolKeeper: Account, + capitalOwner: Account, +): + withRiskpoolWallet = True + + # setup riskpool with a product + (gifProduct, gifRiskpool, gifOracle) = getProductAndRiskpool( + instance, + owner, + testCoin, + productOwner, + oracleProvider, + riskpoolKeeper, + capitalOwner, + withRiskpoolWallet + ) + + # ensure that creating of another product with different token is not allowed + with brownie.reverts("ERROR:TRS-014:TOKEN_ADDRESS_NOT_MACHING"): + GifTestProduct( + instance, + testCoinX, + capitalOwner, + productOwner, + gifOracle, + gifRiskpool, + 'Test.Product2') + + +def test_two_products_same_riskpool( + instance: GifInstance, + owner: Account, + testCoin, + productOwner: Account, + oracleProvider: Account, + riskpoolKeeper: Account, + capitalOwner: Account, + customer: Account, +): + withRiskpoolWallet = True + + # setup riskpool with a product + (gifProduct, gifRiskpool, gifOracle) = getProductAndRiskpool( + instance, + owner, + testCoin, + productOwner, + oracleProvider, + riskpoolKeeper, + capitalOwner, + withRiskpoolWallet + ) + + # ensure that creating of another product with different token succeeds + gifProduct2 = GifTestProduct( + instance, + testCoin, + capitalOwner, + productOwner, + gifOracle, + gifRiskpool, + 'Test.Product2') + + # ensure the two products are different + assert gifProduct2.getContract().getId() != gifProduct.getContract().getId() + + def getProductAndRiskpool( instance: GifInstance, owner: Account, @@ -127,5 +212,6 @@ def getProductAndRiskpool( return ( gifProduct, - gifRiskpool + gifRiskpool, + gifOracle )