git.delta.rocks / unique-network / refs/commits / e256f7e1e4e2

difftreelog

source

tests/src/eth/fractionalizer/fractionalizer.test.ts16.1 KiBsourcehistory
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161718import Web3 from 'web3';19import {ApiPromise} from '@polkadot/api';20import {evmToAddress} from '@polkadot/util-crypto';21import {readFile} from 'fs/promises';22import fractionalizerAbi from './FractionalizerAbi.json';23import {submitTransactionAsync} from '../../substrate/substrate-api';24import {UNIQUE} from '../../util/helpers';25import {collectionIdToAddress, createEthAccountWithBalance, createNonfungibleCollection, createRefungibleCollection, GAS_ARGS, itWeb3, tokenIdFromAddress, uniqueNFT, uniqueRefungible, uniqueRefungibleToken} from '../util/helpers';26import {Contract} from 'web3-eth-contract';2728import chai from 'chai';29import chaiAsPromised from 'chai-as-promised';30import chaiLike from 'chai-like';31import {IKeyringPair} from '@polkadot/types/types';32chai.use(chaiAsPromised);33chai.use(chaiLike);34const expect = chai.expect;3536async function deployFractionalizer(api: ApiPromise, web3: Web3, owner: string) {37  const fractionalizerContract = new web3.eth.Contract(fractionalizerAbi as any, undefined, {38    from: owner,39    ...GAS_ARGS,40  });41  return await fractionalizerContract.deploy({data: (await readFile(`${__dirname}/Fractionalizer.bin`)).toString()}).send({from: owner});42}4344async function initFractionalizer(api: ApiPromise, web3: Web3, privateKeyWrapper: (account: string) => IKeyringPair, owner: string) {45  const fractionalizer = await deployFractionalizer(api, web3, owner);46  const tx = api.tx.balances.transfer(evmToAddress(fractionalizer.options.address), 10n * UNIQUE);47  const alice = privateKeyWrapper('//Alice');48  await submitTransactionAsync(alice, tx);49  const result = await fractionalizer.methods.mintRFTCollection('A', 'B', 'C').send();50  const rftCollectionAddress = result.events.RFTCollectionSet.returnValues._collection;51  return {fractionalizer, rftCollectionAddress};52}5354async function createRFTToken(api: ApiPromise, web3: Web3, owner: string, fractionalizer: Contract, amount: bigint) {55  const {collectionIdAddress: nftCollectionAddress} = await createNonfungibleCollection(api, web3, owner);56  const nftContract = uniqueNFT(web3, nftCollectionAddress, owner);57  const nftTokenId = await nftContract.methods.nextTokenId().call();58  await nftContract.methods.mint(owner, nftTokenId).send();5960  await fractionalizer.methods.setAllowlist(nftCollectionAddress, true).send();61  await nftContract.methods.approve(fractionalizer.options.address, nftTokenId).send();62  const result = await fractionalizer.methods.nft2rft(nftCollectionAddress, nftTokenId, amount).send();63  const {_collection, _tokenId, _rftToken} = result.events.Fractionalized.returnValues;64  return {65    nftCollectionAddress: _collection,66    nftTokenId: _tokenId,67    rftTokenAddress: _rftToken,68  };69}7071describe('Fractionalizer contract usage', () => {72  itWeb3('Set RFT collection', async ({api, web3, privateKeyWrapper}) => {73    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);74    const fractionalizer = await deployFractionalizer(api, web3, owner);75    const {collectionIdAddress} = await createRefungibleCollection(api, web3, owner);76    const refungibleContract = uniqueRefungible(web3, collectionIdAddress, owner);77    await refungibleContract.methods.addCollectionAdmin(fractionalizer.options.address).send();78    const result = await fractionalizer.methods.setRFTCollection(collectionIdAddress).send();79    expect(result.events).to.be.like({80      RFTCollectionSet: {81        returnValues: {82          _collection: collectionIdAddress,83        },84      },85    });86  });8788  itWeb3('Mint RFT collection', async ({api, web3, privateKeyWrapper}) => {89    const alice = privateKeyWrapper('//Alice');90    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);91    const fractionalizer = await deployFractionalizer(api, web3, owner);92    const tx = api.tx.balances.transfer(evmToAddress(fractionalizer.options.address), 10n * UNIQUE);93    await submitTransactionAsync(alice, tx);9495    const result = await fractionalizer.methods.mintRFTCollection('A', 'B', 'C').send({from: owner});96    expect(result.events).to.be.like({97      RFTCollectionSet: {},98    });99    expect(result.events.RFTCollectionSet.returnValues._collection).to.be.ok;100  });101102  itWeb3('Set Allowlist', async ({api, web3, privateKeyWrapper}) => {103    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);104    const {fractionalizer} = await initFractionalizer(api, web3, privateKeyWrapper, owner);    105106    const {collectionIdAddress: nftCollectionAddress} = await createNonfungibleCollection(api, web3, owner);107    const result1 = await fractionalizer.methods.setAllowlist(nftCollectionAddress, true).send({from: owner});108    expect(result1.events).to.be.like({109      AllowListSet: {110        returnValues: {111          _collection: nftCollectionAddress,112          _status: true,113        },114      },115    });116    const result2 = await fractionalizer.methods.setAllowlist(nftCollectionAddress, false).send({from: owner});117    expect(result2.events).to.be.like({118      AllowListSet: {119        returnValues: {120          _collection: nftCollectionAddress,121          _status: false,122        },123      },124    });125  });126127  itWeb3('NFT to RFT', async ({api, web3, privateKeyWrapper}) => {128    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);129130    const {collectionIdAddress: nftCollectionAddress} = await createNonfungibleCollection(api, web3, owner);131    const nftContract = uniqueNFT(web3, nftCollectionAddress, owner);132    const nftTokenId = await nftContract.methods.nextTokenId().call();133    await nftContract.methods.mint(owner, nftTokenId).send();134135    const {fractionalizer} = await initFractionalizer(api, web3, privateKeyWrapper, owner);136137    await fractionalizer.methods.setAllowlist(nftCollectionAddress, true).send();138    await nftContract.methods.approve(fractionalizer.options.address, nftTokenId).send();139    const result = await fractionalizer.methods.nft2rft(nftCollectionAddress, nftTokenId, 100).send();140    expect(result.events).to.be.like({141      Fractionalized: {142        returnValues: {143          _collection: nftCollectionAddress,144          _tokenId: nftTokenId,145          _amount: '100',146        },147      },148    });149    const rftTokenAddress = result.events.Fractionalized.returnValues._rftToken;150    const rftTokenContract = uniqueRefungibleToken(web3, rftTokenAddress, owner);151    expect(await rftTokenContract.methods.balanceOf(owner).call()).to.equal('100');152  });153154  itWeb3('RFT to NFT', async ({api, web3, privateKeyWrapper}) => {155    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);156157    const {fractionalizer, rftCollectionAddress} = await initFractionalizer(api, web3, privateKeyWrapper, owner);158    const {rftTokenAddress, nftCollectionAddress, nftTokenId} = await createRFTToken(api, web3, owner, fractionalizer, 100n);159160    const {collectionId, tokenId} = tokenIdFromAddress(rftTokenAddress);161    const refungibleAddress = collectionIdToAddress(collectionId);162    expect(rftCollectionAddress).to.be.equal(refungibleAddress);163    const refungibleTokenContract = uniqueRefungibleToken(web3, rftTokenAddress, owner);164    await refungibleTokenContract.methods.approve(fractionalizer.options.address, 100).send();165    const result = await fractionalizer.methods.rft2nft(refungibleAddress, tokenId).send();166    expect(result.events).to.be.like({167      DeFractionalized: {168        returnValues: {169          _rftToken: rftTokenAddress,170          _nftCollection: nftCollectionAddress,171          _nftTokenId: nftTokenId,172        },173      },174    });175  });176});177178179180describe('Negative Integration Tests for fractionalizer', () => {181  itWeb3('call setRFTCollection twice', async ({api, web3, privateKeyWrapper}) => {182    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);183    const fractionalizer = await deployFractionalizer(api, web3, owner);184    const {collectionIdAddress} = await createRefungibleCollection(api, web3, owner);185    const refungibleContract = uniqueRefungible(web3, collectionIdAddress, owner);186    await refungibleContract.methods.addCollectionAdmin(fractionalizer.options.address).send();187    await fractionalizer.methods.setRFTCollection(collectionIdAddress).send();188189    await expect(fractionalizer.methods.setRFTCollection(collectionIdAddress).send()).to.be.eventually.rejected;190  });191192  itWeb3('call setRFTCollection with NFT collection', async ({api, web3, privateKeyWrapper}) => {193    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);194    const fractionalizer = await deployFractionalizer(api, web3, owner);195    const {collectionIdAddress} = await createNonfungibleCollection(api, web3, owner);196197    await expect(fractionalizer.methods.setRFTCollection(collectionIdAddress).send()).to.be.eventually.rejected;198  });199200  itWeb3('call setRFTCollection while not collection admin', async ({api, web3, privateKeyWrapper}) => {201    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);202    const fractionalizer = await deployFractionalizer(api, web3, owner);203    const {collectionIdAddress} = await createRefungibleCollection(api, web3, owner);204205    await expect(fractionalizer.methods.setRFTCollection(collectionIdAddress).send()).to.be.eventually.rejected;206  });207208  itWeb3('call setRFTCollection after mintRFTCollection', async ({api, web3, privateKeyWrapper}) => {209    const alice = privateKeyWrapper('//Alice');210    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);211    const fractionalizer = await deployFractionalizer(api, web3, owner);212    const tx = api.tx.balances.transfer(evmToAddress(fractionalizer.options.address), 10n * UNIQUE);213    await submitTransactionAsync(alice, tx);214215    const result = await fractionalizer.methods.mintRFTCollection('A', 'B', 'C').send({from: owner});216    const collectionIdAddress = result.events.RFTCollectionSet.returnValues._collection;217218    await expect(fractionalizer.methods.setRFTCollection(collectionIdAddress).send()).to.be.eventually.rejected;219  });220221  itWeb3('call nft2rft without setting RFT collection for contract', async ({api, web3, privateKeyWrapper}) => {222    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);223224    const {collectionIdAddress: nftCollectionAddress} = await createNonfungibleCollection(api, web3, owner);225    const nftContract = uniqueNFT(web3, nftCollectionAddress, owner);226    const nftTokenId = await nftContract.methods.nextTokenId().call();227    await nftContract.methods.mint(owner, nftTokenId).send();228229    const fractionalizer = await deployFractionalizer(api, web3, owner);230231    await expect(fractionalizer.methods.nft2rft(nftCollectionAddress, nftTokenId, 100).send()).to.be.eventually.rejected;232  });233234  itWeb3('call nft2rft while not owner of NFT token', async ({api, web3, privateKeyWrapper}) => {235    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);236    const nftOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);237238    const {collectionIdAddress: nftCollectionAddress} = await createNonfungibleCollection(api, web3, owner);239    const nftContract = uniqueNFT(web3, nftCollectionAddress, owner);240    const nftTokenId = await nftContract.methods.nextTokenId().call();241    await nftContract.methods.mint(owner, nftTokenId).send();242    await nftContract.methods.transfer(nftOwner, 1).send();243244245    const {fractionalizer} = await initFractionalizer(api, web3, privateKeyWrapper, owner);246247    await expect(fractionalizer.methods.nft2rft(nftCollectionAddress, nftTokenId, 100).send()).to.be.eventually.rejected;248  });249250  itWeb3('call nft2rft while not in list of allowed accounts', async ({api, web3, privateKeyWrapper}) => {251    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);252253    const {collectionIdAddress: nftCollectionAddress} = await createNonfungibleCollection(api, web3, owner);254    const nftContract = uniqueNFT(web3, nftCollectionAddress, owner);255    const nftTokenId = await nftContract.methods.nextTokenId().call();256    await nftContract.methods.mint(owner, nftTokenId).send();257258    const {fractionalizer} = await initFractionalizer(api, web3, privateKeyWrapper, owner);259260    await nftContract.methods.approve(fractionalizer.options.address, nftTokenId).send();261    await expect(fractionalizer.methods.nft2rft(nftCollectionAddress, nftTokenId, 100).send()).to.be.eventually.rejected;262  });263264  itWeb3('call nft2rft while fractionalizer doesnt have approval for nft token', async ({api, web3, privateKeyWrapper}) => {265    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);266267    const {collectionIdAddress: nftCollectionAddress} = await createNonfungibleCollection(api, web3, owner);268    const nftContract = uniqueNFT(web3, nftCollectionAddress, owner);269    const nftTokenId = await nftContract.methods.nextTokenId().call();270    await nftContract.methods.mint(owner, nftTokenId).send();271272    const {fractionalizer} = await initFractionalizer(api, web3, privateKeyWrapper, owner);273274    await fractionalizer.methods.setAllowlist(nftCollectionAddress, true).send();275    await expect(fractionalizer.methods.nft2rft(nftCollectionAddress, nftTokenId, 100).send()).to.be.eventually.rejected;276  });277278  itWeb3('call rft2nft without setting RFT collection for contract', async ({api, web3, privateKeyWrapper}) => {279    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);280281    const fractionalizer = await deployFractionalizer(api, web3, owner);282    const {collectionIdAddress: rftCollectionAddress} = await createRefungibleCollection(api, web3, owner);283    const refungibleContract = uniqueRefungible(web3, rftCollectionAddress, owner);284    const rftTokenId = await refungibleContract.methods.nextTokenId().call();285    await refungibleContract.methods.mint(owner, rftTokenId).send();286    287    await expect(fractionalizer.methods.rft2nft(rftCollectionAddress, rftTokenId).send()).to.be.eventually.rejected;288  });289290  itWeb3('call rft2nft for RFT token that is not from configured RFT collection', async ({api, web3, privateKeyWrapper}) => {291    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);292293    const {fractionalizer} = await initFractionalizer(api, web3, privateKeyWrapper, owner);294    const {collectionIdAddress: rftCollectionAddress} = await createRefungibleCollection(api, web3, owner);295    const refungibleContract = uniqueRefungible(web3, rftCollectionAddress, owner);296    const rftTokenId = await refungibleContract.methods.nextTokenId().call();297    await refungibleContract.methods.mint(owner, rftTokenId).send();298    299    await expect(fractionalizer.methods.rft2nft(rftCollectionAddress, rftTokenId).send()).to.be.eventually.rejected;300  });301302  itWeb3('call rft2nft without owning all RFT pieces', async ({api, web3, privateKeyWrapper}) => {303    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);304    const receiver = await createEthAccountWithBalance(api, web3, privateKeyWrapper);305306    const {fractionalizer, rftCollectionAddress} = await initFractionalizer(api, web3, privateKeyWrapper, owner);307    const {rftTokenAddress} = await createRFTToken(api, web3, owner, fractionalizer, 100n);308    309    const {tokenId} = tokenIdFromAddress(rftTokenAddress);310    const refungibleTokenContract = uniqueRefungibleToken(web3, rftTokenAddress, owner);311    await refungibleTokenContract.methods.transfer(receiver, 50).send();312    await refungibleTokenContract.methods.approve(fractionalizer.options.address, 50).send();313    await expect(fractionalizer.methods.rft2nft(rftCollectionAddress, tokenId).send()).to.be.eventually.rejected;314  });315});