diff --git a/.github/workflows/subgraph-test.yaml b/.github/workflows/subgraph-test.yaml new file mode 100644 index 0000000..3496257 --- /dev/null +++ b/.github/workflows/subgraph-test.yaml @@ -0,0 +1,43 @@ +name: flow-subgraph-test +on: [push, pull_request] + +env: + GRAPH_TOKEN: ${{ secrets.GRAPH_ACCESS_TOKEN }} + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Use Node.js version + uses: actions/setup-node@v2 + with: + node-version: 16 + + - name: Install dependencies + run: | + npm ci + + - name: Build Docker Compose images + run: | + docker-compose down + docker-compose up --build -d + + - name: Run Subgraph tests + run: | + npm run ci-test + + - name: Stop containers + run: docker-compose down + + - name: Graph Authentication + run: npx graph auth --product hosted-service $GRAPH_TOKEN + + - name: Prepare subgraph manifest + run: npx mustache config/mumbai.json subgraph.template.yaml subgraph.yaml + + - name: Graph Deployments + run: npx graph deploy --product hosted-service gildlab/offchainassetvault-mumbai \ No newline at end of file diff --git a/.gitignore b/.gitignore index a6a588c..4b0d4f0 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ docker generated typechain build -.env \ No newline at end of file +.env +data \ No newline at end of file diff --git a/config/hardhat.json b/config/hardhat.json new file mode 100644 index 0000000..aea1495 --- /dev/null +++ b/config/hardhat.json @@ -0,0 +1,5 @@ +{ + "network": "hardhat", + "offchainAssetReceiptVaultFactory": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0", + "offchainAssetReceiptVaultFactoryBlock": 3 +} \ No newline at end of file diff --git a/config/localhost.json b/config/localhost.json index ae697e7..1ef5e94 100644 --- a/config/localhost.json +++ b/config/localhost.json @@ -1,5 +1,5 @@ { "network": "localhost", - "offchainAssetReceiptVaultFactory": "0x2625760C4A8e8101801D3a48eE64B2bEA42f1E96", - "offchainAssetReceiptVaultFactoryBlock": 214 + "offchainAssetReceiptVaultFactory": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0", + "offchainAssetReceiptVaultFactoryBlock": 3 } \ No newline at end of file diff --git a/config/mumbai.json b/config/mumbai.json index a25464a..143f0b4 100644 --- a/config/mumbai.json +++ b/config/mumbai.json @@ -1,5 +1,5 @@ { "network": "mumbai", - "offchainAssetReceiptVaultFactoryBlock": 31787036, - "offchainAssetReceiptVaultFactory": "0x8707993CEE55bdeB8064D3883CFB17ebd81c7B1A" + "offchainAssetReceiptVaultFactoryBlock": 32253649, + "offchainAssetReceiptVaultFactory": "0x94927792b88d518f9a429572dd3d40400b8be906" } \ No newline at end of file diff --git a/config/polygon.json b/config/polygon.json index 63163d0..ba64014 100644 --- a/config/polygon.json +++ b/config/polygon.json @@ -1,5 +1,5 @@ { "network": "matic", - "offchainAssetReceiptVaultFactoryBlock": 38971381, - "offchainAssetReceiptVaultFactory": "0x9329bf1b69a3CE69eC7694453eDC433800643B73" + "offchainAssetReceiptVaultFactoryBlock": 39549051, + "offchainAssetReceiptVaultFactory": "0xFE259001e141A41f3bcCDBc315A8F0D23Ef84b0b" } \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..02a4f9d --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,54 @@ +version: '3' +services: + hardhat: + image: vishalkale151071/hardhat-node + ports: + - '8545:8545' + graph-node: + image: graphprotocol/graph-node + ports: + - '8000:8000' + - '8001:8001' + - '8020:8020' + - '8030:8030' + - '8040:8040' + depends_on: + - ipfs + - postgres + - hardhat + extra_hosts: + - host.docker.internal:host-gateway + environment: + postgres_host: postgres + postgres_user: graph-node + postgres_pass: let-me-in + postgres_db: graph-node + ipfs: 'ipfs:5001' + ethereum: 'localhost:http://hardhat:8545' + GRAPH_LOG: info + ipfs: + image: ipfs/go-ipfs:v0.10.0 + ports: + - '5001:5001' + volumes: + - ./data/ipfs:/data/ipfs + postgres: + image: postgres + ports: + - '5432:5432' + command: + [ + "postgres", + "-cshared_preload_libraries=pg_stat_statements" + ] + environment: + POSTGRES_USER: graph-node + POSTGRES_PASSWORD: let-me-in + POSTGRES_DB: graph-node + # FIXME: remove this env. var. which we shouldn't need. Introduced by + # , maybe as a + # workaround for https://github.com/docker/for-mac/issues/6270? + PGDATA: "/var/lib/postgresql/data" + POSTGRES_INITDB_ARGS: "-E UTF8 --locale=C" + volumes: + - ./data/postgres:/var/lib/postgresql/data \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index a6a3032..e8ddff3 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -6,7 +6,7 @@ import "@nomiclabs/hardhat-etherscan"; require("dotenv").config(); function createLocalHostConfig() { - const url = "http://192.168.0.215:8545"; + const url = "http://localhost:8545"; const mnemonic = "test test test test test test test test test test test junk"; return { diff --git a/package.json b/package.json index c97fcf3..f80eff3 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "main": "index.js", "scripts": { "test": "npx hardhat test", + "ci-test": "npx hardhat test --network localhost", "codegen": "graph codegen", "build": "graph build", "deploy-subgraph": "ts-node scripts/index.ts", @@ -12,9 +13,9 @@ "deploy-polygon": "ts-node scripts/index.ts --config config/polygon.json --subgraphTemplate subgraph.template.yaml --subgraphName gildlab/offchainassetvault-polygon", "deploy-goerli": "ts-node scripts/index.ts --config config/goerli.json --subgraphTemplate subgraph.template.yaml --subgraphName gildlab/offchainassetvault-goerli", "deploy-mainnet": "ts-node scripts/index.ts --config config/ethereum.json --subgraphTemplate subgraph.template.yaml --subgraphName gildlab/offchainassetvault-ethereum", - "create-local": "graph create --node http://192.168.0.215:8020/ gildlab/offchainassetvault", - "remove-local": "graph remove --node http://192.168.0.215:8020/ gildlab/offchainassetvault", - "deploy-local": "npx mustache config/localhost.json subgraph.template.yaml subgraph.yaml && graph deploy --node http://192.168.0.215:8020/ --ipfs http://192.168.0.215:5001 gildlab/offchainassetvault --version-label 1" + "create-local": "graph create --node http://localhost:8020/ gildlab/offchainassetvault", + "remove-local": "graph remove --node http://localhost:8020/ gildlab/offchainassetvault", + "deploy-local": "npx mustache config/localhost.json subgraph.template.yaml subgraph.yaml && npm run codegen && graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 gildlab/offchainassetvault --version-label 1" }, "repository": { "type": "git", diff --git a/src/OffchainAssetReceiptVault.ts b/src/OffchainAssetReceiptVault.ts index 7f17132..7f9b50f 100644 --- a/src/OffchainAssetReceiptVault.ts +++ b/src/OffchainAssetReceiptVault.ts @@ -254,9 +254,12 @@ export function handleOffchainAssetVaultInitialized( export function handleReceiptVaultInformation( event: ReceiptVaultInformationEvent ): void { - let receiptVaultInformation = new ReceiptVaultInformation( - `ReceiptInformation-${event.address}` + let receiptVaultInformation = new ReceiptVaultInformation(event.transaction.hash.toHex()); + + let offchainAssetReceiptVault = OffchainAssetReceiptVault.load( + event.address.toHex() ); + receiptVaultInformation.transaction = getTransaction( event.block, event.transaction.hash.toHex() @@ -273,6 +276,20 @@ export function handleReceiptVaultInformation( event.address.toHex() ).id; receiptVaultInformation.save(); + + if (offchainAssetReceiptVault) { + let hash = new Hash(event.transaction.hash.toHex()); + hash.owner = receiptVaultInformation.caller; + hash.offchainAssetReceiptVault = offchainAssetReceiptVault.id; + hash.offchainAssetReceiptVaultDeployer = offchainAssetReceiptVault.deployer.toHex(); + hash.hash = event.params.vaultInformation.toString(); + hash.timestamp = event.block.timestamp; + hash.save(); + + offchainAssetReceiptVault.hashCount = + offchainAssetReceiptVault.hashCount.plus(ONE); + offchainAssetReceiptVault.save(); + } } export function handleRoleAdminChanged(event: RoleAdminChanged): void { diff --git a/subgraph.yaml b/subgraph.yaml index 7183355..8ef4cc3 100644 --- a/subgraph.yaml +++ b/subgraph.yaml @@ -6,9 +6,9 @@ dataSources: name: OffchainAssetReceiptVaultFactory network: localhost source: - address: "0x2625760C4A8e8101801D3a48eE64B2bEA42f1E96" + address: "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0" abi: OffchainAssetReceiptVaultFactory - startBlock: 214 + startBlock: 3 mapping: kind: ethereum/events apiVersion: 0.0.7 diff --git a/test/1_factory.test.ts b/test/1_factory.test.ts index 32c212b..66770b2 100644 --- a/test/1_factory.test.ts +++ b/test/1_factory.test.ts @@ -41,11 +41,11 @@ describe("Deploy Factory Test", () => { const configPath = path.resolve( __dirname, - `../config/${hre.network.name}.json` + `../config/localhost.json` ); const config = JSON.parse(fetchFile(configPath)); - config.network = hre.network.name; + config.network = "localhost"; config.offchainAssetReceiptVaultFactory = factory.address; config.offchainAssetReceiptVaultFactoryBlock = factory.deployTransaction.blockNumber; diff --git a/test/3_offChainAssetReceiptVault.test.ts b/test/3_offChainAssetReceiptVault.test.ts index d21465d..a5f50fc 100644 --- a/test/3_offChainAssetReceiptVault.test.ts +++ b/test/3_offChainAssetReceiptVault.test.ts @@ -2,36 +2,20 @@ import { ReadWriteTier, TestErc20 } from "../typechain"; import { ethers } from "hardhat"; import { - getEventArgs, - ADDRESS_ZERO, fixedPointMul, ONE, fixedPointDiv, - fixedPointDivRound, waitForSubgraphToBeSynced, } from "./utils"; -import { - SetERC20TierEvent, - CertifyEvent, - SnapshotEvent, - ConfiscateSharesEvent, - ConfiscateReceiptEvent, - SetERC1155TierEvent, - SnapshotWithDataEvent, -} from "../typechain/contracts/vault/offchainAsset/OffchainAssetReceiptVault"; -import { DepositWithReceiptEvent } from "../typechain/contracts/vault/receipt/ReceiptVault"; import { receipt, vault } from "./2_createChild.test"; import { subgraph } from "./1_factory.test"; import { FetchResult } from "apollo-fetch"; -import { expect } from "chai"; const assert = require("assert"); let TierV2TestContract: ReadWriteTier; -let expectedName = "OffchainAssetVaul"; -let expectedSymbol = "OAV"; describe("OffChainAssetReceiptVault", async function () { beforeEach(async () => { @@ -40,205 +24,6 @@ describe("OffChainAssetReceiptVault", async function () { await TierV2TestContract.deployed(); }); - - it("Check vault is the owner of its receipt", async function () { - const signers = await ethers.getSigners(); - const alice = signers[0]; - - const owner = await receipt.connect(alice).owner(); - assert( - vault.address === (await receipt.connect(alice).owner()), - `wrong owner expected ${vault.address} got ${owner}` - ); - }); - it("Checks SetERC20Tier event is emitted", async function () { - - const signers = await ethers.getSigners(); - const alice = signers[0]; - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).ERC20TIERER(), alice.address); - const minTier = ethers.BigNumber.from(10); - - const { sender, tier, minimumTier, data } = (await getEventArgs( - await vault - .connect(alice) - .setERC20Tier(TierV2TestContract.address, minTier, [], [1]), - "SetERC20Tier", - vault - )) as SetERC20TierEvent["args"]; - - }); - it("Checks setERC1155Tier event is emitted", async function () { - - const signers = await ethers.getSigners(); - const alice = signers[0]; - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).ERC1155TIERER(), alice.address); - const minTier = ethers.BigNumber.from(100); - - const { sender, tier, minimumTier, data } = (await getEventArgs( - await vault - .connect(alice) - .setERC1155Tier(TierV2TestContract.address, minTier, [], [1]), - "SetERC1155Tier", - vault - )) as SetERC1155TierEvent["args"]; - - assert( - sender === alice.address, - `wrong sender expected ${alice.address} got ${sender}` - ); - assert( - tier === TierV2TestContract.address, - `wrong tier expected ${TierV2TestContract.address} got ${tier}` - ); - assert( - minimumTier.eq(minTier), - `wrong minimumTier expected ${minTier} got ${minimumTier}` - ); - assert(data === "0x01", `wrong data expected 0x01 got ${data}`); - }); - it("Checks totalAssets", async function () { - const signers = await ethers.getSigners(); - - const testErc20 = await ethers.getContractFactory("TestErc20"); - const asset = (await testErc20.deploy()) as TestErc20; - await asset.deployed(); - - const alice = signers[0]; - const bob = signers[2]; - - const shareRatio = ONE; - const aliceAssets = ethers.BigNumber.from(1000); - - await asset.connect(alice).transfer(alice.address, aliceAssets); - - await asset.connect(alice).increaseAllowance(vault.address, aliceAssets); - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).DEPOSITOR(), alice.address); - - await vault - .connect(alice) - ["deposit(uint256,address,uint256,bytes)"]( - aliceAssets, - bob.address, - shareRatio, - [] - ); - - const totalSupply = await vault.connect(alice).totalSupply(); - const totalAssets = await vault.connect(alice).totalAssets(); - - await waitForSubgraphToBeSynced(1000, 1, 60, "gildlab/offchainassetvault"); - - const query = ` - { - offchainAssetReceiptVault(id: "${vault.address.toLowerCase()}"){ - totalShares - } - }`; - - const response = (await subgraph({query})) as FetchResult; - console.log(response.data); - expect(response.data.totalShares).to.equals(totalAssets); - - }); - it("PreviewDeposit returns correct shares", async function () { - const assets = ethers.BigNumber.from(100); - - const signers = await ethers.getSigners(); - const alice = signers[0]; - - const hasRoleDepositor = await vault - .connect(alice) - .hasRole(await vault.connect(alice).DEPOSITOR(), alice.address); - - //Alice does not have role of depositor, so it should throw an error unless role is granted - assert( - !hasRoleDepositor, - `AccessControl: account ${alice.address.toLowerCase()} is missing role DEPOSITOR` - ); - - //grant depositor role to alice - await vault - .connect(alice) - .grantRole(await vault.connect(alice).DEPOSITOR(), alice.address); - - const shares = await vault.connect(alice).previewDeposit(assets); - - assert( - shares.eq(assets), - `Wrong shares: expected ${assets} got ${shares} ` - ); - }); - it("PreviewMint returns correct assets", async function () { - const shares = ethers.BigNumber.from(10); - - const signers = await ethers.getSigners(); - const alice = signers[0]; - - //grant depositor role to alice - await vault - .connect(alice) - .grantRole(await vault.connect(alice).DEPOSITOR(), alice.address); - - const assets = await vault.connect(alice).previewMint(shares); - const expectedAssets = fixedPointDivRound(shares, ONE); - assert( - assets.eq(expectedAssets), - `Wrong assets: expected ${expectedAssets} got ${assets}` - ); - }); - it("PreviewWithdraw returns 0 shares if no withdrawer role", async function () { - const assets = ethers.BigNumber.from(100); - - const signers = await ethers.getSigners(); - const alice = signers[0]; - - const id = ethers.BigNumber.from(1); - - const expectedShares = ethers.BigNumber.from(0); - - const shares = await vault - .connect(alice) - ["previewWithdraw(uint256,uint256)"](assets, id); - - assert( - shares.eq(expectedShares), - `Wrong shares: expected ${expectedShares} got ${shares} ` - ); - }); - it("PreviewWithdraw returns correct shares", async function () { - const assets = ethers.BigNumber.from(10); - - const signers = await ethers.getSigners(); - const alice = signers[0]; - - //assets are always deposited 1:1 with shares - const id = ONE; - - //grant withdrawer role to alice - await vault - .connect(alice) - .grantRole(await vault.connect(alice).WITHDRAWER(), alice.address); - - const expectedShares = fixedPointMul(assets, id); - - const shares = await vault - .connect(alice) - ["previewWithdraw(uint256,uint256)"](assets, id); - - assert( - shares.eq(expectedShares), - `Wrong shares: expected ${expectedShares} got ${shares} ` - ); - }); it("Mints with data", async function () { const signers = await ethers.getSigners(); const alice = signers[0]; @@ -271,849 +56,26 @@ describe("OffChainAssetReceiptVault", async function () { `wrong assets. expected ${expectedAssets} got ${aliceBalanceAfter}` ); }); - it("PreviewRedeem returns correct assets", async function () { - const shares = ethers.BigNumber.from(100); - - const signers = await ethers.getSigners(); - const alice = signers[0]; - - const id = ONE; - - const hasRoleDepositor = await vault - .connect(alice) - .hasRole(await vault.connect(alice).WITHDRAWER(), alice.address); - - //Alice does not have role of withdrawer, so it should throw an error unless role is granted - assert( - !hasRoleDepositor, - `AccessControl: account ${alice.address.toLowerCase()} is missing role WITHDRAWER` - ); - - //grant withdrawer role to alice - await vault - .connect(alice) - .grantRole(await vault.connect(alice).WITHDRAWER(), alice.address); - - const expectedAssets = fixedPointDiv(shares, id); - const assets = await vault - .connect(alice) - ["previewRedeem(uint256,uint256)"](shares, id); - - assert( - assets.eq(expectedAssets), - `Wrong assets: expected ${expectedAssets} got ${assets} ` - ); - }); - it("PreviewRedeem returns 0 shares if no withdrawer role", async function () { - - const signers = await ethers.getSigners(); - const alice = signers[0]; - - const testErc20 = await ethers.getContractFactory("TestErc20"); - const asset = (await testErc20.deploy()) as TestErc20; - await asset.deployed(); - - const receiptId = ethers.BigNumber.from(1); - const aliceAssets = ethers.BigNumber.from(20); - - const shares = fixedPointMul(aliceAssets, receiptId); - - await asset.connect(alice).transfer(alice.address, aliceAssets); - - await asset.connect(alice).increaseAllowance(vault.address, aliceAssets); - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).DEPOSITOR(), alice.address); - - const assetToDeposit = aliceAssets.div(2); - await vault - .connect(alice) - ["deposit(uint256,address,uint256,bytes)"]( - assetToDeposit, - alice.address, - receiptId, - [] - ); - - const expectedAssets = ethers.BigNumber.from(0); - const assets = await vault - .connect(alice) - ["previewRedeem(uint256,uint256)"](shares, receiptId); - - assert( - assets.eq(expectedAssets), - `Wrong assets: expected ${expectedAssets} got ${assets} ` - ); - }); - it("Redeposit - should be receipt holder", async function () { - const signers = await ethers.getSigners(); - const alice = signers[0]; - - const aliceReceiptBalance = await receipt - .connect(alice) - .balanceOf(alice.address, ONE); - - assert(aliceReceiptBalance.eq(0), `NOT_RECEIPT_HOLDER`); - }); - it("Redeposits", async function () { - const signers = await ethers.getSigners(); - - const testErc20 = await ethers.getContractFactory("TestErc20"); - const asset = (await testErc20.deploy()) as TestErc20; - await asset.deployed(); - - const alice = signers[0]; - - const receiptId = ethers.BigNumber.from(1); - const aliceAssets = ethers.BigNumber.from(20); - - await asset.connect(alice).transfer(alice.address, aliceAssets); - - await asset.connect(alice).increaseAllowance(vault.address, aliceAssets); - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).DEPOSITOR(), alice.address); - - const assetToDeposit = aliceAssets.div(2); - const assetToReDeposit = ethers.BigNumber.from(10); - await vault - .connect(alice) - ["deposit(uint256,address,uint256,bytes)"]( - assetToDeposit, - alice.address, - receiptId, - [] - ); - - const aliceReceiptBalance = await receipt - .connect(alice) - .balanceOf(alice.address, receiptId); - - await vault - .connect(alice) - .redeposit(assetToReDeposit, alice.address, 1, [1]); - - const aliceReceiptBalanceAfterRedeposit = await receipt - .connect(alice) - .balanceOf(alice.address, receiptId); - - assert( - aliceReceiptBalanceAfterRedeposit.eq( - aliceReceiptBalance.add(assetToReDeposit) - ), - `Incorrect balance ${aliceReceiptBalance.add( - assetToReDeposit - )} got ${aliceReceiptBalanceAfterRedeposit}` - ); - }); - - - it("Snapshot event is emitted", async function () { - const signers = await ethers.getSigners(); - const alice = signers[0]; - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).ERC20SNAPSHOTTER(), alice.address); - - const { id } = (await getEventArgs( - await vault.connect(alice).snapshot([]), - "Snapshot", - vault - )) as SnapshotEvent["args"]; - - assert(id.eq(ethers.BigNumber.from(1)), `ID not set`); - }); - it("SnapshotWithData event is emitted", async function () { - const signers = await ethers.getSigners(); - const alice = signers[0]; - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).ERC20SNAPSHOTTER(), alice.address); - - const { sender, id, data } = (await getEventArgs( - await vault.connect(alice).snapshot([1]), - "SnapshotWithData", - vault - )) as SnapshotWithDataEvent["args"]; - - assert(id.eq(ethers.BigNumber.from(1)), `ID not set`); - - assert( - sender === alice.address, - `Wrong sender. Expected ${alice.address}, got ${sender}` - ); - assert(data === "0x01", `Wrong information. Expected 0x01, got ${data}`); - }); - it("Sets correct erc20Tier and mintier", async function () { - - const signers = await ethers.getSigners(); - const alice = signers[0]; - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).ERC20TIERER(), alice.address); - const minTier = ethers.BigNumber.from(10); - - const { tier, minimumTier } = (await getEventArgs( - await vault - .connect(alice) - .setERC20Tier(TierV2TestContract.address, minTier, [], []), - "SetERC20Tier", - vault - )) as SetERC20TierEvent["args"]; - - await vault - .connect(alice) - .setERC20Tier(TierV2TestContract.address, minTier, [], []); - - assert( - tier === TierV2TestContract.address, - `wrong tier expected ${TierV2TestContract.address} got ${tier}` - ); - assert( - minimumTier.eq(minTier), - `wrong minimumTier expected ${minTier} got ${minimumTier}` - ); - }); - it("Sets correct erc11Tier and mintier", async function () { - - const signers = await ethers.getSigners(); - const alice = signers[0]; - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).ERC1155TIERER(), alice.address); - const minTier = ethers.BigNumber.from(10); - - const { tier, minimumTier } = (await getEventArgs( - await vault - .connect(alice) - .setERC1155Tier(TierV2TestContract.address, minTier, [], []), - "SetERC1155Tier", - vault - )) as SetERC20TierEvent["args"]; - - await vault - .connect(alice) - .setERC1155Tier(TierV2TestContract.address, minTier, [], []); - - assert( - tier === TierV2TestContract.address, - `wrong tier expected ${TierV2TestContract.address} got ${tier}` - ); - assert( - minimumTier.eq(minTier), - `wrong minimumTier expected ${minTier} got ${minimumTier}` - ); - }); - it("Checks Certify event is emitted", async function () { - - const signers = await ethers.getSigners(); - const alice = signers[0]; - - //get block timestamp and add 100 to get _until - const blockNum = await ethers.provider.getBlockNumber(); - const block = await ethers.provider.getBlock(blockNum); - const _until = block.timestamp + 100; - const _referenceBlockNumber = block.number; - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).CERTIFIER(), alice.address); - - const { sender, certifyUntil, referenceBlockNumber } = (await getEventArgs( - await vault - .connect(alice) - .certify(_until, _referenceBlockNumber, false, []), - "Certify", - vault - )) as CertifyEvent["args"]; - - assert( - sender === alice.address, - `wrong sender expected ${alice.address} got ${sender}` - ); - assert( - certifyUntil.eq(_until), - `wrong until expected ${_until} got ${certifyUntil}` - ); - assert( - referenceBlockNumber.eq(_referenceBlockNumber), - `wrong referenceBlockNumber expected ${_referenceBlockNumber} got ${referenceBlockNumber}` - ); - }); - it("Certifies with data", async function () { - - const signers = await ethers.getSigners(); - const alice = signers[0]; - - //get block timestamp and add 100 to get _until - const blockNum = await ethers.provider.getBlockNumber(); - const block = await ethers.provider.getBlock(blockNum); - const _until = block.timestamp + 100; - const _referenceBlockNumber = block.number; - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).CERTIFIER(), alice.address); - - const { sender, certifyUntil, referenceBlockNumber, data } = - (await getEventArgs( - await vault - .connect(alice) - .certify(_until, _referenceBlockNumber, false, [1, 7]), - "Certify", - vault - )) as CertifyEvent["args"]; - - assert( - sender === alice.address, - `wrong sender expected ${alice.address} got ${sender}` - ); - assert(data === "0x0107", `wrong data expected 0x0107 got ${data}`); - assert( - certifyUntil.eq(_until), - `wrong until expected ${_until} got ${certifyUntil}` - ); - assert( - referenceBlockNumber.eq(_referenceBlockNumber), - `wrong referenceBlockNumber expected ${_referenceBlockNumber} got ${referenceBlockNumber}` - ); - }); - it("Certify in the past relative to the existing certification time with forceUntil true", async function () { - - const signers = await ethers.getSigners(); - const alice = signers[0]; - - const blockNum = await ethers.provider.getBlockNumber(); - const block = await ethers.provider.getBlock(blockNum); - const _until = block.timestamp + 100; - const _referenceBlockNumber = block.number; - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).CERTIFIER(), alice.address); - - const { certifyUntil } = (await getEventArgs( - await vault - .connect(alice) - .certify(_until, _referenceBlockNumber, false, []), - "Certify", - vault - )) as CertifyEvent["args"]; - - const _untilPast = certifyUntil.sub(100); - - const eventArgs = (await getEventArgs( - await vault - .connect(alice) - .certify(_untilPast, _referenceBlockNumber, true, []), - "Certify", - vault - )) as CertifyEvent["args"]; - - assert( - eventArgs.certifyUntil.eq(_untilPast), - `wrong until expected ${_untilPast} got ${eventArgs.certifyUntil}` - ); - }); - - - it("Certifies", async function () { - const signers = await ethers.getSigners(); - const alice = signers[0]; - - const blockNum = await ethers.provider.getBlockNumber(); - const block = await ethers.provider.getBlock(blockNum); - const _certifiedUntil = block.timestamp + 100; - const _referenceBlockNumber = block.number; - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).CERTIFIER(), alice.address); - - const { certifyUntil } = (await getEventArgs( - await vault - .connect(alice) - .certify(_certifiedUntil, _referenceBlockNumber, false, []), - "Certify", - vault - )) as CertifyEvent["args"]; - - assert( - certifyUntil.eq(_certifiedUntil), - `wrong until expected ${_certifiedUntil} got ${certifyUntil}` - ); - }); - - it("Confiscate - Checks ConfiscateShares is NOT emitted on Zero balance", async function () { - const signers = await ethers.getSigners(); - const alice = signers[0]; - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).CONFISCATOR(), alice.address); - - try { - await getEventArgs( - await vault.connect(alice).confiscateShares(alice.address, [1]), - "ConfiscateShares", - vault - ); - } catch (err) { - assert( - err - .toString() - .includes("Error: Could not find event with name ConfiscateShares"), - `ConfiscateShares was emitted` - ); - } - }); - it("Confiscate - Checks ConfiscateShares is emitted", async function () { - const signers = await ethers.getSigners(); - const alice = signers[0]; - - const testErc20 = await ethers.getContractFactory("TestErc20"); - const asset = (await testErc20.deploy()) as TestErc20; - await asset.deployed(); - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).CONFISCATOR(), alice.address); - await vault - .connect(alice) - .grantRole(await vault.connect(alice).DEPOSITOR(), alice.address); - - const assets = ethers.BigNumber.from(100); - - await asset.transfer(alice.address, assets); - - await asset - .connect(alice) - .increaseAllowance(vault.connect(alice).address, assets); - - await vault - .connect(alice) - ["deposit(uint256,address,uint256,bytes)"]( - assets, - alice.address, - ONE, - [] - ); - - const { sender, confiscatee, justification } = (await getEventArgs( - await vault.connect(alice).confiscateShares(alice.address, [1]), - "ConfiscateShares", - vault - )) as ConfiscateSharesEvent["args"]; - - assert( - sender === alice.address, - `wrong sender expected ${alice.address} got ${sender}` - ); - assert( - confiscatee === alice.address, - `wrong confiscatee expected ${alice.address} got ${confiscatee}` - ); - assert( - justification === "0x01", - `wrong justification expected 0x01 got ${justification}` - ); - }); - it("Confiscate receipts - Checks ConfiscateReceipt is emitted", async function () { - const signers = await ethers.getSigners(); - - const testErc20 = await ethers.getContractFactory("TestErc20"); - const asset = (await testErc20.deploy()) as TestErc20; - await asset.deployed(); - - const _id = ethers.BigNumber.from(1); - - const alice = signers[0]; - - const aliceAssets = ethers.BigNumber.from(100); - - const blockNum = await ethers.provider.getBlockNumber(); - const block = await ethers.provider.getBlock(blockNum); - const _certifiedUntil = block.timestamp + 100; - const _referenceBlockNumber = block.number; - await vault - .connect(alice) - .grantRole(await vault.connect(alice).CERTIFIER(), alice.address); - await vault - .connect(alice) - .certify(_certifiedUntil, _referenceBlockNumber, false, []); - - await asset.transfer(alice.address, aliceAssets); - - await asset.connect(alice).increaseAllowance(vault.address, aliceAssets); - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).DEPOSITOR(), alice.address); - await vault - .connect(alice) - .grantRole(await vault.connect(alice).CONFISCATOR(), alice.address); - - await vault - .connect(alice) - ["deposit(uint256,address,uint256,bytes)"]( - aliceAssets, - alice.address, - _id, - [] - ); - - const { sender, confiscatee, id, justification } = (await getEventArgs( - await vault.connect(alice).confiscateReceipt(alice.address, _id, [1]), - "ConfiscateReceipt", - vault - )) as ConfiscateReceiptEvent["args"]; - - assert( - sender === alice.address, - `wrong sender expected ${alice.address} got ${sender}` - ); - assert( - confiscatee === alice.address, - `wrong confiscatee expected ${alice.address} got ${confiscatee}` - ); - assert(id.eq(_id), `wrong id expected ${_id} got ${id}`); - - assert( - justification === "0x01", - `wrong justification expected 0x01 got ${justification}` - ); - }); - it("Confiscate receipts - Checks ConfiscateReceipt is NOT emitted on zero balance", async function () { - const signers = await ethers.getSigners(); - - const alice = signers[0]; - - const _id = ethers.BigNumber.from(1); - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).CONFISCATOR(), alice.address); - - try { - await getEventArgs( - await vault.connect(alice).confiscateReceipt(alice.address, _id, [1]), - "ConfiscateReceipt", - vault - ); - } catch (err) { - assert( - err - .toString() - .includes("Error: Could not find event with name ConfiscateReceipt"), - `ConfiscateReceipt was emitted` - ); - } - }); - it("Checks confiscated is same as balance", async function () { - const signers = await ethers.getSigners(); - const alice = signers[0]; - - const testErc20 = await ethers.getContractFactory("TestErc20"); - const asset = (await testErc20.deploy()) as TestErc20; - await asset.deployed(); - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).CONFISCATOR(), alice.address); - await vault - .connect(alice) - .grantRole(await vault.connect(alice).DEPOSITOR(), alice.address); - - const assets = ethers.BigNumber.from(100); - - await asset.transfer(alice.address, assets); - - await asset - .connect(alice) - .increaseAllowance(vault.connect(alice).address, assets); - - await vault - .connect(alice) - ["deposit(uint256,address,uint256,bytes)"]( - assets, - alice.address, - ONE, - [] - ); - - const shares = await vault - .connect(alice) - ["balanceOf(address)"](alice.address); - - const { confiscated } = (await getEventArgs( - await vault.connect(alice).confiscateShares(alice.address, []), - "ConfiscateShares", - vault - )) as ConfiscateSharesEvent["args"]; - - assert( - confiscated.eq(shares), - `wrong confiscated expected ${shares} got ${confiscated}` - ); - }); - it("Checks confiscated is transferred", async function () { - const signers = await ethers.getSigners(); - const alice = signers[0]; - const bob = signers[1]; - - const testErc20 = await ethers.getContractFactory("TestErc20"); - const asset = (await testErc20.deploy()) as TestErc20; - await asset.deployed(); - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).CONFISCATOR(), alice.address); - await vault - .connect(alice) - .grantRole(await vault.connect(alice).DEPOSITOR(), alice.address); - - const assets = ethers.BigNumber.from(100); - - await asset.transfer(alice.address, assets); - - await asset - .connect(alice) - .increaseAllowance(vault.connect(alice).address, assets); - - await vault - .connect(alice) - ["deposit(uint256,address,uint256,bytes)"](assets, bob.address, ONE, []); - const aliceBalanceBef = await vault - .connect(alice) - ["balanceOf(address)"](alice.address); - - const { confiscated } = (await getEventArgs( - await vault.connect(alice).confiscateShares(bob.address, []), - "ConfiscateShares", - vault - )) as ConfiscateSharesEvent["args"]; - - const aliceBalanceAft = await vault - .connect(alice) - ["balanceOf(address)"](alice.address); - assert( - aliceBalanceAft.eq(aliceBalanceBef.add(confiscated)), - `Shares has not been confiscated` - ); - }); - it("Checks confiscated is same as receipt balance", async function () { - const signers = await ethers.getSigners(); - - const testErc20 = await ethers.getContractFactory("TestErc20"); - const asset = (await testErc20.deploy()) as TestErc20; - await asset.deployed(); - - const alice = signers[0]; - const bob = signers[1]; - - const aliceAssets = ethers.BigNumber.from(1000); - - const blockNum = await ethers.provider.getBlockNumber(); - const block = await ethers.provider.getBlock(blockNum); - const _certifiedUntil = block.timestamp + 100; - const _referenceBlockNumber = block.number; - await vault - .connect(alice) - .grantRole(await vault.connect(alice).CERTIFIER(), alice.address); - await vault - .connect(alice) - .certify(_certifiedUntil, _referenceBlockNumber, false, []); - - await asset.transfer(alice.address, aliceAssets); - - await asset.connect(alice).increaseAllowance(vault.address, aliceAssets); - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).DEPOSITOR(), alice.address); - await vault - .connect(alice) - .grantRole(await vault.connect(alice).CONFISCATOR(), alice.address); - - const { id } = (await getEventArgs( - await vault - .connect(alice) - ["deposit(uint256,address,uint256,bytes)"]( - aliceAssets, - bob.address, - ONE, - [] - ), - "DepositWithReceipt", - vault - )) as DepositWithReceiptEvent["args"]; - - const bobReceiptBalance = await receipt - .connect(alice) - ["balanceOf(address,uint256)"](bob.address, id); - - const erc20balanceBef = await vault.connect(alice).balanceOf(bob.address); - - const { confiscated } = (await getEventArgs( - await vault.connect(alice).confiscateReceipt(bob.address, id, []), - "ConfiscateReceipt", - vault - )) as ConfiscateSharesEvent["args"]; - - const erc20balanceAft = await vault.connect(alice).balanceOf(bob.address); - - assert( - confiscated.eq(bobReceiptBalance), - `wrong confiscated expected ${bobReceiptBalance} got ${confiscated}` - ); - //Check erc20 balance did not change - assert( - erc20balanceAft.eq(erc20balanceBef), - `wrong erc20 expected ${erc20balanceBef} got ${erc20balanceAft}` - ); - }); - it("Checks confiscated amount is transferred", async function () { - const signers = await ethers.getSigners(); - - const alice = signers[0]; - const bob = signers[1]; - - const testErc20 = await ethers.getContractFactory("TestErc20"); - const asset = (await testErc20.deploy()) as TestErc20; - await asset.deployed(); - - const aliceAssets = ethers.BigNumber.from(1000); - - const blockNum = await ethers.provider.getBlockNumber(); - const block = await ethers.provider.getBlock(blockNum); - const _certifiedUntil = block.timestamp + 100; - const _referenceBlockNumber = block.number; - await vault - .connect(alice) - .grantRole(await vault.connect(alice).CERTIFIER(), alice.address); - await vault - .connect(alice) - .certify(_certifiedUntil, _referenceBlockNumber, false, []); - - await asset.transfer(alice.address, aliceAssets); - - await asset.connect(alice).increaseAllowance(vault.address, aliceAssets); - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).DEPOSITOR(), alice.address); - await vault - .connect(alice) - .grantRole(await vault.connect(alice).CONFISCATOR(), alice.address); - - const { id } = (await getEventArgs( - await vault - .connect(alice) - ["deposit(uint256,address,uint256,bytes)"]( - aliceAssets, - bob.address, - ONE, - [] - ), - "DepositWithReceipt", - vault - )) as DepositWithReceiptEvent["args"]; - - const aliceBalanceBef = await receipt - .connect(alice) - ["balanceOf(address,uint256)"](alice.address, id); - - const { confiscated } = (await getEventArgs( - await vault.connect(alice).confiscateReceipt(bob.address, id, []), - "ConfiscateReceipt", - vault - )) as ConfiscateSharesEvent["args"]; - - const aliceBalanceAft = await receipt - .connect(alice) - ["balanceOf(address,uint256)"](alice.address, id); - - assert( - aliceBalanceAft.eq(aliceBalanceBef.add(confiscated)), - `Shares has not been confiscated` - ); - }); - it("Should call multicall", async () => { - this.timeout(0); + it("Checks ReceiptVaultInformation event data", async function () { const signers = await ethers.getSigners(); const alice = signers[0]; - const bob = signers[1]; - - const testErc20 = await ethers.getContractFactory("TestErc20"); - const testErc20Contract = (await testErc20.deploy()) as TestErc20; - await testErc20Contract.deployed(); - - const assets = ethers.BigNumber.from(30); - await testErc20Contract.transfer(bob.address, assets); - await testErc20Contract - .connect(bob) - .increaseAllowance(vault.address, assets); - - await vault - .connect(alice) - .grantRole(await vault.connect(alice).DEPOSITOR(), bob.address); - - const shares = ethers.BigNumber.from(10); - const shares2 = ethers.BigNumber.from(20); - await vault - .connect(bob) - ["mint(uint256,address,uint256,bytes)"](shares, bob.address, 1, []); - await vault - .connect(bob) - ["mint(uint256,address,uint256,bytes)"](shares2, bob.address, 2, []); - let ABI = [ - "function redeem(uint256 shares_, address receiver_, address owner_, uint256 id_, bytes receiptInformation_)", - ]; - let iface = new ethers.utils.Interface(ABI); - await vault - .connect(alice) - .grantRole(await vault.connect(alice).WITHDRAWER(), bob.address); + await vault.connect(alice).receiptVaultInformation([3]); - await vault - .connect(bob) - .multicall( - [ - iface.encodeFunctionData("redeem", [ - ethers.BigNumber.from(10), - bob.address, - bob.address, - 1, - [], - ]), - iface.encodeFunctionData("redeem", [ - ethers.BigNumber.from(20), - bob.address, - bob.address, - 2, - [], - ]), - ], - { from: bob.address } - ); + const query = `{ + offchainAssetReceiptVault(id:"${vault.address.toLowerCase()}"){ + id + receiptVaultInformations { + information + } + } + }`; + await waitForSubgraphToBeSynced(1000, 1, 60, "gildlab/offchainassetvault"); - let balance1 = await receipt - .connect(alice) - ["balanceOf(address,uint256)"](bob.address, 1); - let balance2 = await receipt - .connect(alice) - ["balanceOf(address,uint256)"](bob.address, 2); + const response = (await subgraph({ query })) as FetchResult; + const vaultData = response.data.offchainAssetReceiptVault; - assert( - balance1.eq(ethers.BigNumber.from(0)) && - balance2.eq(ethers.BigNumber.from(0)), - `Shares has not been redeemed` - ); + assert.equal(vaultData.id, vault.address.toLowerCase()); + assert.equal(vaultData.receiptVaultInformations[0].information, '0x03'); }); });