diff --git a/contracts/interfaces/products/ISolaceCoverProduct.sol b/contracts/interfaces/products/ISolaceCoverProduct.sol index bc794633..433b660a 100644 --- a/contracts/interfaces/products/ISolaceCoverProduct.sol +++ b/contracts/interfaces/products/ISolaceCoverProduct.sol @@ -77,11 +77,8 @@ interface ISolaceCoverProduct { uint256 rewardPointsEarned ); - /// @notice Emitted when stablecoin is added to accepted stablecoin list - event StablecoinAdded(address stablecoin); - - /// @notice Emitted when stablecoin is removed from accepted stablecoin list - event StablecoinRemoved(address stablecoin); + /// @notice Emitted when baseURI is set + event BaseURISet(string baseURI); /*************************************** POLICY FUNCTIONS @@ -273,10 +270,28 @@ interface ISolaceCoverProduct { * @notice True if a policyholder has previously used a valid referral code, false if not * * A policyholder can only use a referral code once. Afterwards a policyholder is ineligible to receive further rewards from additional referral codes. - * @return isReferralCodeUsed_ True if the policyholder has previoulsy used a valid referral code, false if not + * @return isReferralCodeUsed_ True if the policyholder has previously used a valid referral code, false if not */ function isReferralCodeUsed(address policyholder) external view returns (bool isReferralCodeUsed_); + /** + * @notice Returns true if valid referral code, false otherwise. + * @param referralCode The referral code. + */ + function isReferralCodeValid(bytes calldata referralCode) external view returns (bool); + + /** + * @notice Get referrer from referral code, returns 0 address if invalid referral code. + * @param referralCode The referral code. + * @return referrer The referrer address, returns 0 address if invalid referral code. + */ + function getReferrerFromReferralCode(bytes calldata referralCode) external view returns (address referrer); + /** + * @notice Calculate minimum required account balance for a given cover limit. Equals the maximum chargeable fee for one epoch. + * @param coverLimit Cover limit. + */ + function minRequiredAccountBalance(uint256 coverLimit) external view returns (uint256 minRequiredAccountBalance_); + /*************************************** GOVERNANCE FUNCTIONS ***************************************/ @@ -338,6 +353,12 @@ interface ISolaceCoverProduct { */ function setIsReferralOn(bool isReferralOn_) external; + /** + * @notice Sets the base URI for computing `tokenURI`. + * @param baseURI_ The new base URI. + */ + function setBaseURI(string memory baseURI_) external; + /*************************************** COVER PROMOTION ADMIN FUNCTIONS ***************************************/ diff --git a/contracts/products/SolaceCoverProduct.sol b/contracts/products/SolaceCoverProduct.sol index 2d350e51..b5b7ea87 100644 --- a/contracts/products/SolaceCoverProduct.sol +++ b/contracts/products/SolaceCoverProduct.sol @@ -51,12 +51,12 @@ contract SolaceCoverProduct is /// @notice Cannot buy new policies while paused. (Default is False) bool internal _paused; - /** - * @notice Referral typehash. - */ - // solhint-disable-next-line var-name-mixedcase + /// @notice Referral typehash. + /// solhint-disable-next-line var-name-mixedcase bytes32 private constant _REFERRAL_TYPEHASH = keccak256("SolaceReferral(uint256 version)"); + string public baseURI; + /*************************************** BOOK-KEEPING VARIABLES ***************************************/ @@ -165,7 +165,8 @@ contract SolaceCoverProduct is _chargeCycle = 604800; // One-week charge cycle _cooldownPeriod = 604800; // One-week cooldown period _referralReward = 50e18; // 50 DAI - _isReferralOn = true; // Referral rewards activate + _isReferralOn = true; // Referral rewards active + baseURI = string(abi.encodePacked("https://stats.solace.fi/policy/?chainID=", Strings.toString(block.chainid), "&policyID=")); } /*************************************** @@ -192,7 +193,8 @@ contract SolaceCoverProduct is policyID = policyOf(policyholder_); require(!policyStatus(policyID), "policy already activated"); require(_canPurchaseNewCover(0, coverLimit_), "insufficient capacity for new cover"); - require(IERC20(_getAsset()).balanceOf(msg.sender) >= amount_ && amount_ + accountBalanceOf(policyholder_) > _minRequiredAccountBalance(coverLimit_), "insufficient deposit for minimum required account balance"); + require(IERC20(_getAsset()).balanceOf(msg.sender) >= amount_, "insufficient caller balance for deposit"); + require(amount_ + accountBalanceOf(policyholder_) > _minRequiredAccountBalance(coverLimit_), "insufficient deposit for minimum required account balance"); // Exit cooldown _exitCooldown(policyholder_); @@ -258,6 +260,7 @@ contract SolaceCoverProduct is address policyholder, uint256 amount ) external override nonReentrant whileUnpaused { + require(policyholder != address(0x0), "zero address policyholder"); _deposit(msg.sender, policyholder, amount); } @@ -269,6 +272,7 @@ contract SolaceCoverProduct is * @notice If cooldown has not started, or has not passed, the user will not be able to withdraw their entire account. A minimum required account balance (one epoch's fee) will be left in the user's account. */ function withdraw() external override nonReentrant whileUnpaused { + require(_accountBalanceOf[msg.sender] > 0, "no account balance to withdraw"); if ( _hasCooldownPassed(msg.sender) ) { _withdraw(msg.sender, _accountBalanceOf[msg.sender]); _preDeactivateCoverLimitOf[_policyOf[msg.sender]] = 0; @@ -458,12 +462,49 @@ contract SolaceCoverProduct is * @notice True if a policyholder has previously used a valid referral code, false if not * * A policyholder can only use a referral code once. A policyholder is then ineligible to receive further rewards from additional referral codes. - * @return isReferralCodeUsed_ True if the policyholder has previoulsy used a valid referral code, false if not + * @return isReferralCodeUsed_ True if the policyholder has previously used a valid referral code, false if not */ function isReferralCodeUsed(address policyholder) external view override returns (bool isReferralCodeUsed_) { return _isReferralCodeUsed[_policyOf[policyholder]]; } + /** + * @notice Returns true if valid referral code, false otherwise. + * @param referralCode The referral code. + */ + function isReferralCodeValid(bytes calldata referralCode) external view override returns (bool) { + (address referrer,) = ECDSA.tryRecover(_getEIP712Hash(), referralCode); + if(referrer == address(0)) return false; + return true; + } + + /** + * @notice Get referrer from referral code, returns 0 address if invalid referral code. + * @param referralCode The referral code. + * @return referrer The referrer address, returns 0 address if invalid referral code. + */ + function getReferrerFromReferralCode(bytes calldata referralCode) external view override returns (address referrer) { + (referrer,) = ECDSA.tryRecover(_getEIP712Hash(), referralCode); + } + + /** + * @notice Calculate minimum required account balance for a given cover limit. Equals the maximum chargeable fee for one epoch. + * @param coverLimit Cover limit. + */ + function minRequiredAccountBalance(uint256 coverLimit) external view override returns (uint256 minRequiredAccountBalance_) { + return _minRequiredAccountBalance(coverLimit); + } + + /** + * @notice Returns the Uniform Resource Identifier (URI) for `policyID`. + * @param policyID The policy ID. + */ + function tokenURI(uint256 policyID) public view virtual override returns (string memory tokenURI_) { + require(_exists(policyID), "invalid policy"); + string memory baseURI_ = baseURI; + return string(abi.encodePacked( baseURI_, Strings.toString(policyID) )); + } + /*************************************** GOVERNANCE FUNCTIONS ***************************************/ @@ -553,6 +594,15 @@ contract SolaceCoverProduct is emit IsReferralOnSet(isReferralOn_); } + /** + * @notice Sets the base URI for computing `tokenURI`. + * @param baseURI_ The new base URI. + */ + function setBaseURI(string memory baseURI_) external override onlyGovernance { + baseURI = baseURI_; + emit BaseURISet(baseURI_); + } + /*************************************** COVER PROMOTION ADMIN FUNCTIONS ***************************************/ @@ -630,7 +680,7 @@ contract SolaceCoverProduct is } // single DAI transfer to the premium pool - SafeERC20.safeTransferFrom(_getAsset(), address(this), _registry.get("premiumPool"), amountToPayPremiumPool); + SafeERC20.safeTransfer(_getAsset(), _registry.get("premiumPool"), amountToPayPremiumPool); } /*************************************** @@ -647,6 +697,7 @@ contract SolaceCoverProduct is uint256 existingTotalCover_, uint256 newTotalCover_ ) internal view returns (bool acceptable) { + if (newTotalCover_ <= existingTotalCover_) return true; // Return if user is lowering cover limit uint256 changeInTotalCover = newTotalCover_ - existingTotalCover_; // This will revert if newTotalCover_ < existingTotalCover_ if (changeInTotalCover < availableCoverCapacity()) return true; else return false; @@ -677,7 +728,7 @@ contract SolaceCoverProduct is address policyholder, uint256 amount ) internal whileUnpaused { - SafeERC20.safeTransferFrom(_getAsset(), address(this), policyholder, amount); + SafeERC20.safeTransfer(_getAsset(), policyholder, amount); _accountBalanceOf[policyholder] -= amount; emit WithdrawMade(policyholder, amount); } diff --git a/scripts/deploy-rinkeby-4.ts b/scripts/deploy-rinkeby-4.ts index 256506ee..9c03c014 100644 --- a/scripts/deploy-rinkeby-4.ts +++ b/scripts/deploy-rinkeby-4.ts @@ -12,10 +12,11 @@ import { logContractAddress } from "./utils"; import { import_artifacts, ArtifactImports } from "./../test/utilities/artifact_importer"; import { Deployer, CoverageDataProvider, Registry, RiskManager, SolaceCoverProduct } from "../typechain"; +import { isDeployed } from "../test/utilities/expectDeployed"; const DEPLOYER_CONTRACT_ADDRESS = "0x501aCe4732E4A80CC1bc5cd081BEe7f88ff694EF"; -const DAI_ADDRESS = "0x5592ec0cfb4dbc12d3ab100b257153436a1f0fea"; // testnet +const DAI_ADDRESS = "0x8ad3aA5d5ff084307d28C8f514D7a193B2Bfe725"; // testnet DAI with approve, mint functions exposed on Etherscan // wallet addresses let COVERAGE_DATA_PROVIDER_UPDATER_ADDRESS = "0xc5683ea4888DadfdE421a1E593DfbD36290D63AB"; // the bot address to update underwriting pool values @@ -24,10 +25,10 @@ let COVER_PROMOTION_ADMIN_ADDRESS = "0x4770becA2628685F7C45102c7a649 const PREMIUM_COLLECTOR_ADDRESS = "0xF321be3577B1AcB436869493862bA18bDde6fc39"; // the bot address that will be set in registry // contract addresses -const REGISTRY_V2_ADDRESS = ""; -const RISK_MANAGER_V2_ADDRESS = ""; -const COVERAGE_DATA_PROVIDER_ADDRESS = ""; -const SOLACE_COVER_PRODUCT_ADDRESS = ""; +const REGISTRY_V2_ADDRESS = "0x501ACe0f576fc4ef9C0380AA46A578eA96b85776"; +const RISK_MANAGER_V2_ADDRESS = "0x501AcEf9020632a71CB25CFa9F554252eB51732b"; +const COVERAGE_DATA_PROVIDER_ADDRESS = "0x501ACE6C5fFf4d42EaC02357B6DD9b756E337355"; +const SOLACE_COVER_PRODUCT_ADDRESS = "0x501aceFe2DfB6496c421512Ed0e5bE42eE0dFA2a"; const DOMAIN_NAME = "Solace.fi-SolaceCoverProduct"; const VERSION = "1"; @@ -46,12 +47,12 @@ async function main() { signerAddress = await deployer.getAddress(); console.log(`Using ${signerAddress} as deployer and governor`); - if (!!COVERAGE_DATA_PROVIDER_ADDRESS) { + if (await isDeployed(COVERAGE_DATA_PROVIDER_ADDRESS)) { console.log(`Using ${signerAddress} as COVERAGE_DATA_PROVIDER_UPDATER_ADDRESS`); COVERAGE_DATA_PROVIDER_UPDATER_ADDRESS = signerAddress; } - if (!!COVER_PROMOTION_ADMIN_ADDRESS) { + if (await isDeployed(COVER_PROMOTION_ADMIN_ADDRESS)) { console.log(`Using ${signerAddress} as COVER_PROMOTION_ADMIN_ADDRESS`); COVER_PROMOTION_ADMIN_ADDRESS = signerAddress; } @@ -77,7 +78,7 @@ async function main() { } async function deployRegistry() { - if(!!REGISTRY_V2_ADDRESS) { + if(await isDeployed(REGISTRY_V2_ADDRESS)) { registryV2 = (await ethers.getContractAt(artifacts.Registry.abi, REGISTRY_V2_ADDRESS)) as Registry; } else { console.log("Deploying Registry(V2)"); @@ -98,7 +99,7 @@ async function deployRegistry() { } async function deployCoverageDataProvider() { - if (!!COVERAGE_DATA_PROVIDER_ADDRESS) { + if (await isDeployed(COVERAGE_DATA_PROVIDER_ADDRESS)) { coverageDataProvider = (await ethers.getContractAt(artifacts.CoverageDataProvider.abi, COVERAGE_DATA_PROVIDER_ADDRESS)) as CoverageDataProvider; } else { console.log("Deploying Coverage Data Provider"); @@ -127,7 +128,7 @@ async function deployCoverageDataProvider() { } async function deployRiskManager() { - if (!!RISK_MANAGER_V2_ADDRESS) { + if (await isDeployed(RISK_MANAGER_V2_ADDRESS)) { riskManagerV2 = (await ethers.getContractAt(artifacts.RiskManager.abi, RISK_MANAGER_V2_ADDRESS)) as RiskManager; } else { console.log("Deploying Risk Manager(V2)"); @@ -144,7 +145,7 @@ async function deployRiskManager() { } async function deploySolaceCoverProduct() { - if (!!SOLACE_COVER_PRODUCT_ADDRESS) { + if (await isDeployed(SOLACE_COVER_PRODUCT_ADDRESS)) { solaceCoverProduct = (await ethers.getContractAt(artifacts.SolaceCoverProduct.abi, SOLACE_COVER_PRODUCT_ADDRESS)) as SolaceCoverProduct; } else { console.log("Deploying Solace Cover Product"); diff --git a/test/products/SolaceCoverProduct.test.ts b/test/products/SolaceCoverProduct.test.ts index b15d2f6c..b870bb99 100644 --- a/test/products/SolaceCoverProduct.test.ts +++ b/test/products/SolaceCoverProduct.test.ts @@ -64,6 +64,9 @@ describe("SolaceCoverProduct", function() { const maxRateDenom = BN.from("315360000"); // We are testing with maxRateNum and maxRateDenom that gives us an annual max rate of 10% coverLimit const REFERRAL_REWARD = ONE_ETH.mul(50) // 50 DAI + // Random 130 character hex string + const FAKE_REFERRAL_CODE = "0xe4e7cba021ff6b83b14d54016198f31b04cba044d71d9a8b9bdf964aa2259cc3b207237f814aa56e516638b448edc43a6c3f4637dca5de54cb199e37b039a832e7" + const DAI_ADDRESS = "0x6B175474E89094C44Da98b954EedeAC495271d0F" const USDC_ADDRESS = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" const WETH_ADDRESS = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" @@ -137,6 +140,7 @@ describe("SolaceCoverProduct", function() { // Grant infinite ERC20 allowance from active test wallets to Soteria await dai.connect(policyholder1).approve(solaceCoverProduct.address, constants.MaxUint256) + await dai.connect(policyholder2).approve(solaceCoverProduct.address, constants.MaxUint256) await dai.connect(governor).approve(solaceCoverProduct.address, constants.MaxUint256) }) }); @@ -388,6 +392,41 @@ describe("SolaceCoverProduct", function() { }) }) + describe ("setBaseURI", () => { + it("should default as expected string", async () => { + expect(await solaceCoverProduct.baseURI()).eq("https://stats.solace.fi/policy/?chainID=31337&policyID=") + }) + it("cannot be set by non governance", async () => { + await expect(solaceCoverProduct.connect(policyholder1).setBaseURI("https://solace")).to.revertedWith("!governance"); + }) + it("can be set", async () => { + let tx = await solaceCoverProduct.connect(governor).setBaseURI("https://solace") + expect(tx).emit(solaceCoverProduct, "BaseURISet").withArgs("https://solace") + expect(await solaceCoverProduct.baseURI()).eq("https://solace") + }) + }) + + describe ("isReferralCodeValid", () => { + it("should return false for invalid referral code", async () => { + expect(await solaceCoverProduct.isReferralCodeValid("0x01")).eq(false) + expect(await solaceCoverProduct.isReferralCodeValid(FAKE_REFERRAL_CODE)).eq(false) + }) + it("should return true for valid referral code", async () => { + let referralCode = await getSolaceReferralCode(policyholder1, solaceCoverProduct) + expect(await solaceCoverProduct.isReferralCodeValid(referralCode)).eq(true) + }) + }) + + describe ("getReferrerFromReferralCode", () => { + it("should return 0 for invalid referral code", async () => { + expect(await solaceCoverProduct.getReferrerFromReferralCode(FAKE_REFERRAL_CODE)).eq(ZERO_ADDRESS) + }) + it("should return referrer address for valid referral code", async () => { + let referralCode = await getSolaceReferralCode(policyholder1, solaceCoverProduct) + expect(await solaceCoverProduct.getReferrerFromReferralCode(referralCode)).eq(policyholder1.address) + }) + }) + describe("activatePolicy", () => { let rmActiveCoverLimit:BN; let rmSoteriaactiveCoverLimit: BN; @@ -449,6 +488,11 @@ describe("SolaceCoverProduct", function() { await expect(solaceCoverProduct.connect(policyholder1).activatePolicy(policyholder1.address, maxCover.add(1), INITIAL_DEPOSIT, [])).to.revertedWith("insufficient capacity for new cover"); }); + it("cannot buy policy when insufficient user balance for deposit", async () => { + const userBalance = await dai.balanceOf(policyholder1.address) + await expect(solaceCoverProduct.connect(policyholder1).activatePolicy(policyholder1.address, ONE_ETH, userBalance.mul(2), [])).to.revertedWith("insufficient caller balance for deposit"); + }) + it("cannot buy policy when insufficient deposit provided", async () => { await expect(solaceCoverProduct.connect(policyholder1).activatePolicy(policyholder1.address, ONE_ETH, 0, [])).to.revertedWith("insufficient deposit for minimum required account balance"); }); @@ -527,6 +571,9 @@ describe("SolaceCoverProduct", function() { await solaceCoverProduct.connect(policyholder1).activatePolicy(policyholder1.address, initialCoverLimit, 0, []); expect (await solaceCoverProduct.cooldownStart(policyholder1.address)).eq(0) }) + it("cannot use an invalid referral code", async () => { + await expect(solaceCoverProduct.connect(governor).activatePolicy(policyholder3.address, INITIAL_COVER_LIMIT, INITIAL_DEPOSIT, FAKE_REFERRAL_CODE)).to.reverted + }) it("cannot use own referral code", async () => { // Create new wallet just for this unit test scope, to avoid creating side effects that impact other unit tests. It's a headfuck to work that out. const ownReferralCode = await getSolaceReferralCode(policyholder3, solaceCoverProduct) @@ -579,7 +626,19 @@ describe("SolaceCoverProduct", function() { }) }); + describe ("tokenURI", () => { + it("cannot get for invalid policy ID", async () => { + await expect(solaceCoverProduct.tokenURI(INVALID_POLICY_ID)).to.revertedWith("invalid policy"); + }) + it("can get for valid policy ID", async () => { + expect(await solaceCoverProduct.tokenURI(POLICY_ID_1)).eq("https://solace1") + }) + }) + describe("deposit", () => { + it("cannot deposit for zero address policyholder", async () => { + await expect(solaceCoverProduct.connect(policyholder1).deposit(ZERO_ADDRESS, INITIAL_DEPOSIT)).to.be.revertedWith("zero address policyholder"); + }) it("can deposit", async () => { let accountBalance = await solaceCoverProduct.accountBalanceOf(policyholder1.address); let soteriaContractDAIbalance = await dai.balanceOf(solaceCoverProduct.address) @@ -680,6 +739,16 @@ describe("SolaceCoverProduct", function() { expect(await solaceCoverProduct.connect(policyholder1).coverLimitOf(POLICY_ID_1)).to.equal(NEW_COVER_LIMIT); }); + it("policy owner can reduce cover limit", async () => { + let tx = await solaceCoverProduct.connect(policyholder1).updateCoverLimit(NEW_COVER_LIMIT.div(2), []); + await expect(tx).emit(solaceCoverProduct, "PolicyUpdated").withArgs(POLICY_ID_1); + expect(await solaceCoverProduct.connect(policyholder1).coverLimitOf(POLICY_ID_1)).to.equal(NEW_COVER_LIMIT.div(2)); + + // revert state changes + await solaceCoverProduct.connect(policyholder1).updateCoverLimit(NEW_COVER_LIMIT, []); + expect(await solaceCoverProduct.connect(policyholder1).coverLimitOf(POLICY_ID_1)).to.equal(NEW_COVER_LIMIT); + }) + it("should update risk manager active cover limit", async () => { let amount1 = initialRMActiveCoverLimit.add(NEW_COVER_LIMIT).sub(initialPolicyCoverLimit); let amount2 = initialRMActiveCoverLimitForSoteria.add(NEW_COVER_LIMIT).sub(initialPolicyCoverLimit); @@ -704,6 +773,10 @@ describe("SolaceCoverProduct", function() { await solaceCoverProduct.connect(policyholder1).updateCoverLimit(initialCoverLimit, []); expect (await solaceCoverProduct.cooldownStart(policyholder1.address)).eq(0) }) + it("cannot use invalid referral code", async () => { + let coverLimit = await solaceCoverProduct.coverLimitOf(POLICY_ID_1); + await expect(solaceCoverProduct.connect(policyholder1).updateCoverLimit(coverLimit, FAKE_REFERRAL_CODE)).to.be.reverted; + }) it("cannot use own referral code", async () => { let ownReferralCode = await getSolaceReferralCode(policyholder1, solaceCoverProduct) let coverLimit = await solaceCoverProduct.coverLimitOf(POLICY_ID_1); @@ -848,11 +921,40 @@ describe("SolaceCoverProduct", function() { cooldownPeriod = await solaceCoverProduct.cooldownPeriod() }) + it("minRequiredAccountBalance view function working", async () => { + expect(await solaceCoverProduct.minRequiredAccountBalance(INITIAL_COVER_LIMIT)).eq(minRequiredAccountBalance) + }) + it("cannot withdraw while paused", async () => { await solaceCoverProduct.connect(governor).setPaused(true); await expect(solaceCoverProduct.connect(policyholder3).withdraw()).to.revertedWith("contract paused"); await solaceCoverProduct.connect(governor).setPaused(false); }); + + it("cannot withdraw with no account balance", async () => { + expect(await solaceCoverProduct.accountBalanceOf(governor.address)).eq(0) + await expect(solaceCoverProduct.connect(governor).withdraw()).to.revertedWith("no account balance to withdraw"); + }) + + it("when cooldown not started, will withdraw such that remaining balance = minRequiredAccountBalance", async () => { + const initialPolicyholder2DAIBalance = await dai.balanceOf(policyholder2.address) + const initialAccountBalanceOfPolicyHolder2 = await solaceCoverProduct.accountBalanceOf(policyholder2.address) + expect(await solaceCoverProduct.cooldownStart(policyholder2.address)).eq(0) + + withdrawAmount = initialAccountBalanceOfPolicyHolder2.sub(minRequiredAccountBalance) + let tx = await solaceCoverProduct.connect(policyholder2).withdraw(); + await expect(tx).emit(solaceCoverProduct, "WithdrawMade").withArgs(policyholder2.address, withdrawAmount); + + expect(initialAccountBalanceOfPolicyHolder2).gt(await solaceCoverProduct.accountBalanceOf(policyholder2.address)) + expect(await solaceCoverProduct.accountBalanceOf(policyholder2.address)).eq(minRequiredAccountBalance) + expect(await dai.balanceOf(policyholder2.address)).eq(initialPolicyholder2DAIBalance.add(withdrawAmount)) + expect(await dai.balanceOf(solaceCoverProduct.address)).eq(initialSoteriaDAIBalance.sub(withdrawAmount)) + + // reset state changes + await solaceCoverProduct.connect(policyholder2).deposit(policyholder2.address, withdrawAmount); + expect(await dai.balanceOf(policyholder2.address)).eq(initialPolicyholder2DAIBalance) + expect(await solaceCoverProduct.accountBalanceOf(policyholder2.address)).eq(initialAccountBalanceOfPolicyHolder2) + }) it("before cooldown complete, will withdraw such that remaining balance = minRequiredAccountBalance", async () => { // Ensure we are before cooldown completion const currentTimestamp = (await provider.getBlock('latest')).timestamp @@ -1110,7 +1212,7 @@ describe("SolaceCoverProduct", function() { let initialContractDAIBalance = await dai.balanceOf(solaceCoverProduct.address) let initialPremiumPoolDAIBalance = await dai.balanceOf(premiumPool.address) - tx = await solaceCoverProduct.connect(premiumCollector).chargePremiums([policyholder1.address, policyholder2.address, policyholder3.address], [WEEKLY_MAX_PREMIUM, WEEKLY_MAX_PREMIUM, WEEKLY_MAX_PREMIUM]) + tx = await solaceCoverProduct.connect(premiumCollector).chargePremiums([policyholder1.address, policyholder2.address, policyholder3.address, premiumPool.address], [WEEKLY_MAX_PREMIUM, WEEKLY_MAX_PREMIUM, WEEKLY_MAX_PREMIUM, WEEKLY_MAX_PREMIUM]) expect(tx).to.emit(solaceCoverProduct, "PremiumCharged").withArgs(policyholder1.address, WEEKLY_MAX_PREMIUM); expect(tx).to.emit(solaceCoverProduct, "PremiumCharged").withArgs(policyholder2.address, WEEKLY_MAX_PREMIUM); expect(tx).to.emit(solaceCoverProduct, "PremiumPartiallyCharged").withArgs(policyholder3.address, WEEKLY_MAX_PREMIUM, initialHolder3AccountBalance.add(initialRewardPoints3)); diff --git a/test/utilities/artifact_importer.ts b/test/utilities/artifact_importer.ts index 5f69d278..909b6626 100644 --- a/test/utilities/artifact_importer.ts +++ b/test/utilities/artifact_importer.ts @@ -69,7 +69,6 @@ export async function import_artifacts() { artifacts.MockFaultyReceiver = await tryImport(`${artifact_dir}/mocks/MockFaultyReceiver.sol/MockFaultyReceiver.json`); artifacts.GasGriefer = await tryImport(`${artifact_dir}/mocks/GasGriefer.sol/GasGriefer.json`); artifacts.Blacklist = await tryImport(`${artifact_dir}/interface/IBlacklist.sol/IBlacklist.json`); - artifacts.SingletonFactory = await tryImport(`${artifact_dir}/interface/ISingletonFactory.sol/ISingletonFactory.json`); artifacts.Deployer = await tryImport(`${artifact_dir}/utils/Deployer.sol/Deployer.json`); artifacts.MockSLP = await tryImport(`${artifact_dir}/mocks/MockSLP.sol/MockSLP.json`); // risk strategy imports