From fcae5c10d0005055673b0e246ead9600e9091e7a Mon Sep 17 00:00:00 2001 From: ninokeldishvili Date: Wed, 10 Jul 2024 01:30:11 +0400 Subject: [PATCH] Test ERC20PriceOracleReceiptVault is constracted --- ...C20PriceOracleReceiptVault.construct.t.sol | 78 ++++++++ test/priceOracle/Initialize.test.ts | 176 ------------------ 2 files changed, 78 insertions(+), 176 deletions(-) create mode 100644 test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.construct.t.sol delete mode 100644 test/priceOracle/Initialize.test.ts diff --git a/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.construct.t.sol b/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.construct.t.sol new file mode 100644 index 00000000..72e6b18e --- /dev/null +++ b/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.construct.t.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: CAL +pragma solidity =0.8.25; + +import {ReceiptVaultConfig, VaultConfig} from "../../../../../contracts/abstract/ReceiptVault.sol"; +import { + ERC20PriceOracleReceiptVault, + ERC20PriceOracleReceiptVaultConfig +} from "../../../../../contracts/concrete/vault/ERC20PriceOracleReceiptVault.sol"; +import {ERC20PriceOracleReceiptVaultTest, Vm} from "test/foundry/abstract/ERC20PriceOracleReceiptVaultTest.sol"; +import {TwoPriceOracle} from "../../../../../contracts/oracle/price/TwoPriceOracle.sol"; + +contract ERC20PriceOracleReceiptVaultConstructionTest is ERC20PriceOracleReceiptVaultTest { + /// Test ERC20PriceOracleReceiptVault is constracted + function testCheckConstructionEvent( + uint256 fuzzedKeyAlice, + string memory assetName, + string memory assetSymbol, + uint256 timestamp, + uint8 xauDecimals, + uint8 usdDecimals, + uint80 answeredInRound + ) external { + // Ensure the fuzzed key is within the valid range for secp256 + address alice = vm.addr((fuzzedKeyAlice % (SECP256K1_ORDER - 1)) + 1); + // Use common decimal bounds for price feeds + // Use 0-20 so we at least have some coverage higher than 18 + usdDecimals = uint8(bound(usdDecimals, 0, 20)); + xauDecimals = uint8(bound(xauDecimals, 0, 20)); + timestamp = bound(timestamp, 0, type(uint32).max); + + vm.warp(timestamp); + TwoPriceOracle twoPriceOracle = createTwoPriceOracle(usdDecimals, usdDecimals, timestamp, answeredInRound); + vm.startPrank(alice); + + // Start recording logs + vm.recordLogs(); + + ERC20PriceOracleReceiptVault vault = createVault(address(twoPriceOracle), assetName, assetSymbol); + // Get the logs + Vm.Log[] memory logs = vm.getRecordedLogs(); + + // Note: To use vm.expectEmit receipt address is needed to be known. + // Find the OffchainAssetReceiptVaultInitialized event log + address msgSender = address(0); + address priceOracle = address(0); + address assetAddress = address(0); + string memory name = ""; + string memory symbol = ""; + bool eventFound = false; // Flag to indicate whether the event log was found + for (uint256 i = 0; i < logs.length; i++) { + if ( + logs[i].topics[0] + == keccak256( + "ERC20PriceOracleReceiptVaultInitialized(address,(address,(address,(address,string,string))))" + ) + ) { + // Decode the event data + (address sender, ERC20PriceOracleReceiptVaultConfig memory config) = + abi.decode(logs[i].data, (address, ERC20PriceOracleReceiptVaultConfig)); + msgSender = sender; + priceOracle = config.priceOracle; + name = config.receiptVaultConfig.vaultConfig.name; + symbol = config.receiptVaultConfig.vaultConfig.symbol; + assetAddress = address(config.receiptVaultConfig.vaultConfig.asset); + eventFound = true; // Set the flag to true since event log was found + break; + } + } + // Assert that the event log was found + assertTrue(eventFound, "ERC20PriceOracleReceiptVaultInitialized event log not found"); + + assertEq(msgSender, address(iFactory)); + assertEq(priceOracle, address(twoPriceOracle)); + assert(address(vault) != address(0)); + assertEq(keccak256(bytes(vault.name())), keccak256(bytes(name))); + assertEq(keccak256(bytes(vault.symbol())), keccak256(bytes(symbol))); + } +} diff --git a/test/priceOracle/Initialize.test.ts b/test/priceOracle/Initialize.test.ts deleted file mode 100644 index ce8b7163..00000000 --- a/test/priceOracle/Initialize.test.ts +++ /dev/null @@ -1,176 +0,0 @@ -import { artifacts, ethers } from "hardhat"; -import { - basePrice, - expectedName, - expectedSymbol, - latestBlockNow, - quotePrice, - usdDecimals, - xauDecimals, -} from "../util"; -import { - ERC20PriceOracleReceiptVault, - ERC20PriceOracleReceiptVaultInitializedEvent, -} from "../../typechain-types/contracts/vault/priceOracle/ERC20PriceOracleReceiptVault"; -import { - ERC20PriceOracleReceiptVaultFactory, - NewChildEvent, -} from "../../typechain-types/contracts/vault/priceOracle/ERC20PriceOracleReceiptVaultFactory"; - -import { getEventArgs } from "../util"; -import { - ReceiptFactory, - MockChainlinkDataFeed, - TestErc20, - TwoPriceOracle, -} from "../../typechain-types"; -import { Contract } from "ethers"; - -const assert = require("assert"); - -describe("PriceOracle construction", async function () { - it("Checks construction event", async function () { - const now = await latestBlockNow(); - - const oracleFactory = await ethers.getContractFactory( - "MockChainlinkDataFeed" - ); - const basePriceOracle = - (await oracleFactory.deploy()) as MockChainlinkDataFeed; - await basePriceOracle.deployed(); - // ETHUSD as of 2022-06-30 - - await basePriceOracle.setDecimals(usdDecimals); - await basePriceOracle.setRoundData(1, { - startedAt: now, - updatedAt: now, - answer: basePrice, - answeredInRound: 1, - }); - - const quotePriceOracle = - (await oracleFactory.deploy()) as MockChainlinkDataFeed; - await quotePriceOracle.deployed(); - // XAUUSD as of 2022-06-30 - await quotePriceOracle.setDecimals(xauDecimals); - await quotePriceOracle.setRoundData(1, { - startedAt: now, - updatedAt: now, - answer: quotePrice, - answeredInRound: 1, - }); - - // 1 hour - const baseStaleAfter = 60 * 60; - // 48 hours - const quoteStaleAfter = 48 * 60 * 60; - - const testErc20 = await ethers.getContractFactory("TestErc20"); - const asset = (await testErc20.deploy()) as TestErc20; - await asset.deployed(); - - const chainlinkFeedPriceOracleFactory = await ethers.getContractFactory( - "ChainlinkFeedPriceOracle" - ); - const chainlinkFeedPriceOracleBase = - await chainlinkFeedPriceOracleFactory.deploy({ - feed: basePriceOracle.address, - staleAfter: baseStaleAfter, - }); - const chainlinkFeedPriceOracleQuote = - await chainlinkFeedPriceOracleFactory.deploy({ - feed: quotePriceOracle.address, - staleAfter: quoteStaleAfter, - }); - await chainlinkFeedPriceOracleBase.deployed(); - await chainlinkFeedPriceOracleQuote.deployed(); - - const twoPriceOracleFactory = await ethers.getContractFactory( - "TwoPriceOracle" - ); - const twoPriceOracle = (await twoPriceOracleFactory.deploy({ - base: chainlinkFeedPriceOracleBase.address, - quote: chainlinkFeedPriceOracleQuote.address, - })) as TwoPriceOracle; - - const ERC20PriceOracleReceiptVaultImplementationFactory = - await ethers.getContractFactory("ERC20PriceOracleReceiptVault"); - const ERC20PriceOracleReceiptVaultImplementation = - (await ERC20PriceOracleReceiptVaultImplementationFactory.deploy()) as ERC20PriceOracleReceiptVault; - - const receiptFactoryFactory = await ethers.getContractFactory( - "ReceiptFactory" - ); - const receiptFactoryContract = - (await receiptFactoryFactory.deploy()) as ReceiptFactory; - await receiptFactoryContract.deployed(); - - const erc20PriceOracleVaultConfig = { - priceOracle: twoPriceOracle.address, - vaultConfig: { - asset: asset.address, - name: "PriceOracleVault", - symbol: "POV", - }, - }; - - const erc20PriceOracleVaultFactoryFactory = await ethers.getContractFactory( - "ERC20PriceOracleReceiptVaultFactory" - ); - - let erc20PriceOracleReceiptVaultFactory = - (await erc20PriceOracleVaultFactoryFactory.deploy({ - implementation: ERC20PriceOracleReceiptVaultImplementation.address, - receiptFactory: receiptFactoryContract.address, - })) as ERC20PriceOracleReceiptVaultFactory; - await erc20PriceOracleReceiptVaultFactory.deployed(); - - let tx = await erc20PriceOracleReceiptVaultFactory.createChildTyped( - erc20PriceOracleVaultConfig - ); - let { child } = (await getEventArgs( - tx, - "NewChild", - erc20PriceOracleReceiptVaultFactory - )) as NewChildEvent["args"]; - - let receiptFactoryArgs = (await getEventArgs( - tx, - "NewChild", - receiptFactoryContract - )) as NewChildEvent["args"]; - - let childContract = new Contract( - child, - (await artifacts.readArtifact("ERC20PriceOracleReceiptVault")).abi - ); - - let { sender, config } = (await getEventArgs( - tx, - "ERC20PriceOracleReceiptVaultInitialized", - childContract - )) as ERC20PriceOracleReceiptVaultInitializedEvent["args"]; - - assert( - sender === erc20PriceOracleReceiptVaultFactory.address, - "wrong deploy sender" - ); - assert( - config.receiptVaultConfig.vaultConfig.asset === asset.address, - "wrong asset address" - ); - assert( - config.receiptVaultConfig.vaultConfig.name === expectedName, - "wrong deploy name" - ); - assert( - config.receiptVaultConfig.vaultConfig.symbol === expectedSymbol, - "wrong deploy symbol" - ); - assert(config.receiptVaultConfig.receipt === receiptFactoryArgs.child); - assert( - config.priceOracle === twoPriceOracle.address, - `wrong deploy priceOracle address: expected ${config.priceOracle} got ${twoPriceOracle.address}` - ); - }); -});