difftreelog
refactor `collection_limits`, add docs for `CollectionLimits`
in: master
9 files changed
pallets/common/src/erc.rsdiffbeforeafterboth--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -358,18 +358,16 @@
),
limits
.sponsored_data_rate_limit
- .map(|limit| {
- (
- EvmCollectionLimits::SponsoredDataRateLimit,
- match limit {
- SponsoringRateLimit::Blocks(_) => true,
- _ => false,
- },
- match limit {
- SponsoringRateLimit::Blocks(blocks) => blocks.into(),
- _ => Default::default(),
- },
- )
+ .and_then(|limit| {
+ if let SponsoringRateLimit::Blocks(blocks) = limit {
+ Some((
+ EvmCollectionLimits::SponsoredDataRateLimit,
+ true,
+ blocks.into(),
+ ))
+ } else {
+ None
+ }
})
.unwrap_or((
EvmCollectionLimits::SponsoredDataRateLimit,
pallets/common/src/eth.rsdiffbeforeafterboth--- a/pallets/common/src/eth.rs
+++ b/pallets/common/src/eth.rs
@@ -155,6 +155,8 @@
}
}
}
+
+/// [`CollectionLimits`](up_data_structs::CollectionLimits) representation for EVM.
#[derive(Debug, Default, Clone, Copy, AbiCoder)]
#[repr(u8)]
pub enum CollectionLimits {
tests/src/eth/collectionLimits.test.tsdiffbeforeafterboth--- a/tests/src/eth/collectionLimits.test.ts
+++ b/tests/src/eth/collectionLimits.test.ts
@@ -1,6 +1,7 @@
import {IKeyringPair} from '@polkadot/types/types';
import {Pallets} from '../util';
-import {CollectionLimits, expect, itEth, usingEthPlaygrounds} from './util';
+import {expect, itEth, usingEthPlaygrounds} from './util';
+import {CollectionLimits} from './util/playgrounds/types';
describe('Can set collection limits', () => {
@@ -62,15 +63,15 @@
// Check limits from eth:
const limitsEvm = await collectionEvm.methods.collectionLimits().call({from: owner});
expect(limitsEvm).to.have.length(9);
- expect(limitsEvm[0]).to.deep.eq(['0', true, limits.accountTokenOwnershipLimit.toString()]);
- expect(limitsEvm[1]).to.deep.eq(['1', true, limits.sponsoredDataSize.toString()]);
- expect(limitsEvm[2]).to.deep.eq(['2', true, limits.sponsoredDataRateLimit.toString()]);
- expect(limitsEvm[3]).to.deep.eq(['3', true, limits.tokenLimit.toString()]);
- expect(limitsEvm[4]).to.deep.eq(['4', true, limits.sponsorTransferTimeout.toString()]);
- expect(limitsEvm[5]).to.deep.eq(['5', true, limits.sponsorApproveTimeout.toString()]);
- expect(limitsEvm[6]).to.deep.eq(['6', true, limits.ownerCanTransfer.toString()]);
- expect(limitsEvm[7]).to.deep.eq(['7', true, limits.ownerCanDestroy.toString()]);
- expect(limitsEvm[8]).to.deep.eq(['8', true, limits.transfersEnabled.toString()]);
+ expect(limitsEvm[0]).to.deep.eq([CollectionLimits.AccountTokenOwnership.toString(), true, limits.accountTokenOwnershipLimit.toString()]);
+ expect(limitsEvm[1]).to.deep.eq([CollectionLimits.SponsoredDataSize.toString(), true, limits.sponsoredDataSize.toString()]);
+ expect(limitsEvm[2]).to.deep.eq([CollectionLimits.SponsoredDataRateLimit.toString(), true, limits.sponsoredDataRateLimit.toString()]);
+ expect(limitsEvm[3]).to.deep.eq([CollectionLimits.TokenLimit.toString(), true, limits.tokenLimit.toString()]);
+ expect(limitsEvm[4]).to.deep.eq([CollectionLimits.SponsorTransferTimeout.toString(), true, limits.sponsorTransferTimeout.toString()]);
+ expect(limitsEvm[5]).to.deep.eq([CollectionLimits.SponsorApproveTimeout.toString(), true, limits.sponsorApproveTimeout.toString()]);
+ expect(limitsEvm[6]).to.deep.eq([CollectionLimits.OwnerCanTransfer.toString(), true, limits.ownerCanTransfer.toString()]);
+ expect(limitsEvm[7]).to.deep.eq([CollectionLimits.OwnerCanDestroy.toString(), true, limits.ownerCanDestroy.toString()]);
+ expect(limitsEvm[8]).to.deep.eq([CollectionLimits.TransferEnabled.toString(), true, limits.transfersEnabled.toString()]);
}));
});
tests/src/eth/createFTCollection.test.tsdiffbeforeafterboth--- a/tests/src/eth/createFTCollection.test.ts
+++ b/tests/src/eth/createFTCollection.test.ts
@@ -17,7 +17,8 @@
import {IKeyringPair} from '@polkadot/types/types';
import {evmToAddress} from '@polkadot/util-crypto';
import {Pallets, requirePalletsOrSkip} from '../util';
-import {CollectionLimits, expect, itEth, usingEthPlaygrounds} from './util';
+import {expect, itEth, usingEthPlaygrounds} from './util';
+import { CollectionLimits } from './util/playgrounds/types';
const DECIMALS = 18;
tests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth--- a/tests/src/eth/createNFTCollection.test.ts
+++ b/tests/src/eth/createNFTCollection.test.ts
@@ -16,7 +16,8 @@
import {evmToAddress} from '@polkadot/util-crypto';
import {IKeyringPair} from '@polkadot/types/types';
-import {CollectionLimits, expect, itEth, usingEthPlaygrounds} from './util';
+import {expect, itEth, usingEthPlaygrounds} from './util';
+import { CollectionLimits } from './util/playgrounds/types';
describe('Create NFT collection from EVM', () => {
tests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth1// 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.8//9// 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/>.1617import {evmToAddress} from '@polkadot/util-crypto';18import {IKeyringPair} from '@polkadot/types/types';19import {Pallets, requirePalletsOrSkip} from '../util';20import {CollectionLimits, expect, itEth, usingEthPlaygrounds} from './util';212223describe('Create RFT collection from EVM', () => {24 let donor: IKeyringPair;2526 before(async function() {27 await usingEthPlaygrounds(async (helper, privateKey) => {28 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);29 donor = await privateKey({filename: __filename});30 });31 });3233 itEth('Create collection', async ({helper}) => {34 const owner = await helper.eth.createAccountWithBalance(donor);35 36 const name = 'CollectionEVM';37 const description = 'Some description';38 const prefix = 'token prefix';39 40 const {collectionId} = await helper.eth.createRFTCollection(owner, name, description, prefix);41 const data = (await helper.rft.getData(collectionId))!;42 const collection = helper.rft.getCollectionObject(collectionId);4344 expect(data.name).to.be.eq(name);45 expect(data.description).to.be.eq(description);46 expect(data.raw.tokenPrefix).to.be.eq(prefix);47 expect(data.raw.mode).to.be.eq('ReFungible');4849 const options = await collection.getOptions();5051 expect(options.tokenPropertyPermissions).to.be.empty;52 });5354 5556 itEth('Create collection with properties & get description', async ({helper}) => {57 const owner = await helper.eth.createAccountWithBalance(donor);5859 const name = 'CollectionEVM';60 const description = 'Some description';61 const prefix = 'token prefix';62 const baseUri = 'BaseURI';6364 const {collectionId, collectionAddress} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner, name, description, prefix, baseUri);65 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft');6667 const collection = helper.rft.getCollectionObject(collectionId);68 const data = (await collection.getData())!;69 70 expect(data.name).to.be.eq(name);71 expect(data.description).to.be.eq(description);72 expect(data.raw.tokenPrefix).to.be.eq(prefix);73 expect(data.raw.mode).to.be.eq('ReFungible');7475 expect(await contract.methods.description().call()).to.deep.equal(description);7677 const options = await collection.getOptions();78 expect(options.tokenPropertyPermissions).to.be.deep.equal([79 {80 key: 'URI',81 permission: {mutable: true, collectionAdmin: true, tokenOwner: false},82 },83 {84 key: 'URISuffix',85 permission: {mutable: true, collectionAdmin: true, tokenOwner: false},86 },87 ]);88 });89 90 // this test will occasionally fail when in async environment.91 itEth.skip('Check collection address exist', async ({helper}) => {92 const owner = await helper.eth.createAccountWithBalance(donor);9394 const expectedCollectionId = +(await helper.callRpc('api.rpc.unique.collectionStats')).created + 1;95 const expectedCollectionAddress = helper.ethAddress.fromCollectionId(expectedCollectionId);96 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);9798 expect(await collectionHelpers.methods99 .isCollectionExist(expectedCollectionAddress)100 .call()).to.be.false;101102 await collectionHelpers.methods103 .createRFTCollection('A', 'A', 'A')104 .send({value: Number(2n * helper.balance.getOneTokenNominal())});105 106 expect(await collectionHelpers.methods107 .isCollectionExist(expectedCollectionAddress)108 .call()).to.be.true;109 });110 111 // Soft-deprecated112 itEth('[eth] Set sponsorship', async ({helper}) => {113 const owner = await helper.eth.createAccountWithBalance(donor);114 const sponsor = await helper.eth.createAccountWithBalance(donor);115 const ss58Format = helper.chain.getChainProperties().ss58Format;116 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Sponsor', 'absolutely anything', 'ENVY');117118 const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner, true);119 await collection.methods.setCollectionSponsor(sponsor).send();120121 let data = (await helper.rft.getData(collectionId))!;122 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));123124 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');125126 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);127 await sponsorCollection.methods.confirmCollectionSponsorship().send();128129 data = (await helper.rft.getData(collectionId))!;130 expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));131 });132133 itEth('[cross] Set sponsorship', async ({helper}) => {134 const owner = await helper.eth.createAccountWithBalance(donor);135 const sponsor = await helper.eth.createAccountWithBalance(donor);136 const ss58Format = helper.chain.getChainProperties().ss58Format;137 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Sponsor', 'absolutely anything', 'ENVY');138139 const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);140 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);141 await collection.methods.setCollectionSponsorCross(sponsorCross).send();142143 let data = (await helper.rft.getData(collectionId))!;144 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));145146 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');147148 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);149 await sponsorCollection.methods.confirmCollectionSponsorship().send();150151 data = (await helper.rft.getData(collectionId))!;152 expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));153 });154155 itEth('Collection address exist', async ({helper}) => {156 const owner = await helper.eth.createAccountWithBalance(donor);157 const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';158 expect(await helper.ethNativeContract.collectionHelpers(collectionAddressForNonexistentCollection)159 .methods.isCollectionExist(collectionAddressForNonexistentCollection).call())160 .to.be.false;161 162 const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Exister', 'absolutely anything', 'WIWT');163 expect(await helper.ethNativeContract.collectionHelpers(collectionAddress)164 .methods.isCollectionExist(collectionAddress).call())165 .to.be.true;166 });167});168169describe('(!negative tests!) Create RFT collection from EVM', () => {170 let donor: IKeyringPair;171 let nominal: bigint;172173 before(async function() {174 await usingEthPlaygrounds(async (helper, privateKey) => {175 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);176 donor = await privateKey({filename: __filename});177 nominal = helper.balance.getOneTokenNominal();178 });179 });180181 itEth('(!negative test!) Create collection (bad lengths)', async ({helper}) => {182 const owner = await helper.eth.createAccountWithBalance(donor);183 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);184 {185 const MAX_NAME_LENGTH = 64;186 const collectionName = 'A'.repeat(MAX_NAME_LENGTH + 1);187 const description = 'A';188 const tokenPrefix = 'A';189190 await expect(collectionHelper.methods191 .createRFTCollection(collectionName, description, tokenPrefix)192 .call({value: Number(2n * nominal)})).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGTH);193 }194 {195 const MAX_DESCRIPTION_LENGTH = 256;196 const collectionName = 'A';197 const description = 'A'.repeat(MAX_DESCRIPTION_LENGTH + 1);198 const tokenPrefix = 'A';199 await expect(collectionHelper.methods200 .createRFTCollection(collectionName, description, tokenPrefix)201 .call({value: Number(2n * nominal)})).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGTH);202 }203 {204 const MAX_TOKEN_PREFIX_LENGTH = 16;205 const collectionName = 'A';206 const description = 'A';207 const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGTH + 1);208 await expect(collectionHelper.methods209 .createRFTCollection(collectionName, description, tokenPrefix)210 .call({value: Number(2n * nominal)})).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGTH);211 }212 });213 214 itEth('(!negative test!) Create collection (no funds)', async ({helper}) => {215 const owner = await helper.eth.createAccountWithBalance(donor);216 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);217 await expect(collectionHelper.methods218 .createRFTCollection('Peasantry', 'absolutely anything', 'TWIW')219 .call({value: Number(1n * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');220 });221222 // Soft-deprecated223 itEth('(!negative test!) [eth] Check owner', async ({helper}) => {224 const owner = await helper.eth.createAccountWithBalance(donor);225 const peasant = helper.eth.createAccount();226 const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Transgressed', 'absolutely anything', 'YVNE');227 const peasantCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', peasant, true);228 const EXPECTED_ERROR = 'NoPermission';229 {230 const sponsor = await helper.eth.createAccountWithBalance(donor);231 await expect(peasantCollection.methods232 .setCollectionSponsor(sponsor)233 .call()).to.be.rejectedWith(EXPECTED_ERROR);234 235 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);236 await expect(sponsorCollection.methods237 .confirmCollectionSponsorship()238 .call()).to.be.rejectedWith('ConfirmSponsorshipFail');239 }240 {241 await expect(peasantCollection.methods242 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)243 .call()).to.be.rejectedWith(EXPECTED_ERROR);244 }245 });246247 itEth('(!negative test!) [cross] Check owner', async ({helper}) => {248 const owner = await helper.eth.createAccountWithBalance(donor);249 const peasant = helper.eth.createAccount();250 const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Transgressed', 'absolutely anything', 'YVNE');251 const peasantCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', peasant);252 const EXPECTED_ERROR = 'NoPermission';253 {254 const sponsor = await helper.eth.createAccountWithBalance(donor);255 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);256 await expect(peasantCollection.methods257 .setCollectionSponsorCross(sponsorCross)258 .call()).to.be.rejectedWith(EXPECTED_ERROR);259 260 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);261 await expect(sponsorCollection.methods262 .confirmCollectionSponsorship()263 .call()).to.be.rejectedWith('ConfirmSponsorshipFail');264 }265 {266 await expect(peasantCollection.methods267 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)268 .call()).to.be.rejectedWith(EXPECTED_ERROR);269 }270 });271 272 itEth('destroyCollection', async ({helper}) => {273 const owner = await helper.eth.createAccountWithBalance(donor);274 const {collectionAddress, collectionId} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');275 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);276 277 await expect(collectionHelper.methods278 .destroyCollection(collectionAddress)279 .send({from: owner})).to.be.fulfilled;280 281 expect(await collectionHelper.methods282 .isCollectionExist(collectionAddress)283 .call()).to.be.false;284 expect(await helper.collection.getData(collectionId)).to.be.null;285 });286});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.8//9// 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/>.1617import {evmToAddress} from '@polkadot/util-crypto';18import {IKeyringPair} from '@polkadot/types/types';19import {Pallets, requirePalletsOrSkip} from '../util';20import {expect, itEth, usingEthPlaygrounds} from './util';21import { CollectionLimits } from './util/playgrounds/types';222324describe('Create RFT collection from EVM', () => {25 let donor: IKeyringPair;2627 before(async function() {28 await usingEthPlaygrounds(async (helper, privateKey) => {29 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);30 donor = await privateKey({filename: __filename});31 });32 });3334 itEth('Create collection', async ({helper}) => {35 const owner = await helper.eth.createAccountWithBalance(donor);36 37 const name = 'CollectionEVM';38 const description = 'Some description';39 const prefix = 'token prefix';40 41 const {collectionId} = await helper.eth.createRFTCollection(owner, name, description, prefix);42 const data = (await helper.rft.getData(collectionId))!;43 const collection = helper.rft.getCollectionObject(collectionId);4445 expect(data.name).to.be.eq(name);46 expect(data.description).to.be.eq(description);47 expect(data.raw.tokenPrefix).to.be.eq(prefix);48 expect(data.raw.mode).to.be.eq('ReFungible');4950 const options = await collection.getOptions();5152 expect(options.tokenPropertyPermissions).to.be.empty;53 });5455 5657 itEth('Create collection with properties & get description', async ({helper}) => {58 const owner = await helper.eth.createAccountWithBalance(donor);5960 const name = 'CollectionEVM';61 const description = 'Some description';62 const prefix = 'token prefix';63 const baseUri = 'BaseURI';6465 const {collectionId, collectionAddress} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner, name, description, prefix, baseUri);66 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft');6768 const collection = helper.rft.getCollectionObject(collectionId);69 const data = (await collection.getData())!;70 71 expect(data.name).to.be.eq(name);72 expect(data.description).to.be.eq(description);73 expect(data.raw.tokenPrefix).to.be.eq(prefix);74 expect(data.raw.mode).to.be.eq('ReFungible');7576 expect(await contract.methods.description().call()).to.deep.equal(description);7778 const options = await collection.getOptions();79 expect(options.tokenPropertyPermissions).to.be.deep.equal([80 {81 key: 'URI',82 permission: {mutable: true, collectionAdmin: true, tokenOwner: false},83 },84 {85 key: 'URISuffix',86 permission: {mutable: true, collectionAdmin: true, tokenOwner: false},87 },88 ]);89 });90 91 // this test will occasionally fail when in async environment.92 itEth.skip('Check collection address exist', async ({helper}) => {93 const owner = await helper.eth.createAccountWithBalance(donor);9495 const expectedCollectionId = +(await helper.callRpc('api.rpc.unique.collectionStats')).created + 1;96 const expectedCollectionAddress = helper.ethAddress.fromCollectionId(expectedCollectionId);97 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);9899 expect(await collectionHelpers.methods100 .isCollectionExist(expectedCollectionAddress)101 .call()).to.be.false;102103 await collectionHelpers.methods104 .createRFTCollection('A', 'A', 'A')105 .send({value: Number(2n * helper.balance.getOneTokenNominal())});106 107 expect(await collectionHelpers.methods108 .isCollectionExist(expectedCollectionAddress)109 .call()).to.be.true;110 });111 112 // Soft-deprecated113 itEth('[eth] Set sponsorship', async ({helper}) => {114 const owner = await helper.eth.createAccountWithBalance(donor);115 const sponsor = await helper.eth.createAccountWithBalance(donor);116 const ss58Format = helper.chain.getChainProperties().ss58Format;117 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Sponsor', 'absolutely anything', 'ENVY');118119 const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner, true);120 await collection.methods.setCollectionSponsor(sponsor).send();121122 let data = (await helper.rft.getData(collectionId))!;123 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));124125 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');126127 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);128 await sponsorCollection.methods.confirmCollectionSponsorship().send();129130 data = (await helper.rft.getData(collectionId))!;131 expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));132 });133134 itEth('[cross] Set sponsorship', async ({helper}) => {135 const owner = await helper.eth.createAccountWithBalance(donor);136 const sponsor = await helper.eth.createAccountWithBalance(donor);137 const ss58Format = helper.chain.getChainProperties().ss58Format;138 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Sponsor', 'absolutely anything', 'ENVY');139140 const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);141 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);142 await collection.methods.setCollectionSponsorCross(sponsorCross).send();143144 let data = (await helper.rft.getData(collectionId))!;145 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));146147 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');148149 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);150 await sponsorCollection.methods.confirmCollectionSponsorship().send();151152 data = (await helper.rft.getData(collectionId))!;153 expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));154 });155156 itEth('Collection address exist', async ({helper}) => {157 const owner = await helper.eth.createAccountWithBalance(donor);158 const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';159 expect(await helper.ethNativeContract.collectionHelpers(collectionAddressForNonexistentCollection)160 .methods.isCollectionExist(collectionAddressForNonexistentCollection).call())161 .to.be.false;162 163 const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Exister', 'absolutely anything', 'WIWT');164 expect(await helper.ethNativeContract.collectionHelpers(collectionAddress)165 .methods.isCollectionExist(collectionAddress).call())166 .to.be.true;167 });168});169170describe('(!negative tests!) Create RFT collection from EVM', () => {171 let donor: IKeyringPair;172 let nominal: bigint;173174 before(async function() {175 await usingEthPlaygrounds(async (helper, privateKey) => {176 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);177 donor = await privateKey({filename: __filename});178 nominal = helper.balance.getOneTokenNominal();179 });180 });181182 itEth('(!negative test!) Create collection (bad lengths)', async ({helper}) => {183 const owner = await helper.eth.createAccountWithBalance(donor);184 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);185 {186 const MAX_NAME_LENGTH = 64;187 const collectionName = 'A'.repeat(MAX_NAME_LENGTH + 1);188 const description = 'A';189 const tokenPrefix = 'A';190191 await expect(collectionHelper.methods192 .createRFTCollection(collectionName, description, tokenPrefix)193 .call({value: Number(2n * nominal)})).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGTH);194 }195 {196 const MAX_DESCRIPTION_LENGTH = 256;197 const collectionName = 'A';198 const description = 'A'.repeat(MAX_DESCRIPTION_LENGTH + 1);199 const tokenPrefix = 'A';200 await expect(collectionHelper.methods201 .createRFTCollection(collectionName, description, tokenPrefix)202 .call({value: Number(2n * nominal)})).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGTH);203 }204 {205 const MAX_TOKEN_PREFIX_LENGTH = 16;206 const collectionName = 'A';207 const description = 'A';208 const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGTH + 1);209 await expect(collectionHelper.methods210 .createRFTCollection(collectionName, description, tokenPrefix)211 .call({value: Number(2n * nominal)})).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGTH);212 }213 });214 215 itEth('(!negative test!) Create collection (no funds)', async ({helper}) => {216 const owner = await helper.eth.createAccountWithBalance(donor);217 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);218 await expect(collectionHelper.methods219 .createRFTCollection('Peasantry', 'absolutely anything', 'TWIW')220 .call({value: Number(1n * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');221 });222223 // Soft-deprecated224 itEth('(!negative test!) [eth] Check owner', async ({helper}) => {225 const owner = await helper.eth.createAccountWithBalance(donor);226 const peasant = helper.eth.createAccount();227 const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Transgressed', 'absolutely anything', 'YVNE');228 const peasantCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', peasant, true);229 const EXPECTED_ERROR = 'NoPermission';230 {231 const sponsor = await helper.eth.createAccountWithBalance(donor);232 await expect(peasantCollection.methods233 .setCollectionSponsor(sponsor)234 .call()).to.be.rejectedWith(EXPECTED_ERROR);235 236 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);237 await expect(sponsorCollection.methods238 .confirmCollectionSponsorship()239 .call()).to.be.rejectedWith('ConfirmSponsorshipFail');240 }241 {242 await expect(peasantCollection.methods243 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)244 .call()).to.be.rejectedWith(EXPECTED_ERROR);245 }246 });247248 itEth('(!negative test!) [cross] Check owner', async ({helper}) => {249 const owner = await helper.eth.createAccountWithBalance(donor);250 const peasant = helper.eth.createAccount();251 const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Transgressed', 'absolutely anything', 'YVNE');252 const peasantCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', peasant);253 const EXPECTED_ERROR = 'NoPermission';254 {255 const sponsor = await helper.eth.createAccountWithBalance(donor);256 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);257 await expect(peasantCollection.methods258 .setCollectionSponsorCross(sponsorCross)259 .call()).to.be.rejectedWith(EXPECTED_ERROR);260 261 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);262 await expect(sponsorCollection.methods263 .confirmCollectionSponsorship()264 .call()).to.be.rejectedWith('ConfirmSponsorshipFail');265 }266 {267 await expect(peasantCollection.methods268 .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000)269 .call()).to.be.rejectedWith(EXPECTED_ERROR);270 }271 });272 273 itEth('destroyCollection', async ({helper}) => {274 const owner = await helper.eth.createAccountWithBalance(donor);275 const {collectionAddress, collectionId} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');276 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);277 278 await expect(collectionHelper.methods279 .destroyCollection(collectionAddress)280 .send({from: owner})).to.be.fulfilled;281 282 expect(await collectionHelper.methods283 .isCollectionExist(collectionAddress)284 .call()).to.be.false;285 expect(await helper.collection.getData(collectionId)).to.be.null;286 });287});tests/src/eth/events.test.tsdiffbeforeafterboth--- a/tests/src/eth/events.test.ts
+++ b/tests/src/eth/events.test.ts
@@ -16,10 +16,10 @@
import {expect} from 'chai';
import {IKeyringPair} from '@polkadot/types/types';
-import {CollectionLimits, EthUniqueHelper, itEth, usingEthPlaygrounds} from './util';
+import {EthUniqueHelper, itEth, usingEthPlaygrounds} from './util';
import {IEvent, TCollectionMode} from '../util/playgrounds/types';
import {Pallets, requirePalletsOrSkip} from '../util';
-import {EthTokenPermissions, NormalizedEvent} from './util/playgrounds/types';
+import {CollectionLimits, EthTokenPermissions, NormalizedEvent} from './util/playgrounds/types';
let donor: IKeyringPair;
tests/src/eth/util/index.tsdiffbeforeafterboth--- a/tests/src/eth/util/index.ts
+++ b/tests/src/eth/util/index.ts
@@ -26,18 +26,8 @@
Allowlisted = 1,
Generous = 2,
}
-export enum CollectionLimits {
- AccountTokenOwnership,
- SponsoredDataSize,
- SponsoredDataRateLimit,
- TokenLimit,
- SponsorTransferTimeout,
- SponsorApproveTimeout,
- OwnerCanTransfer,
- OwnerCanDestroy,
- TransferEnabled
-}
+
export const usingEthPlaygrounds = async (code: (helper: EthUniqueHelper, privateKey: (seed: string | {filename: string}) => Promise<IKeyringPair>) => Promise<void>) => {
const silentConsole = new SilentConsole();
silentConsole.enable();
tests/src/eth/util/playgrounds/types.tsdiffbeforeafterboth--- a/tests/src/eth/util/playgrounds/types.ts
+++ b/tests/src/eth/util/playgrounds/types.ts
@@ -24,4 +24,15 @@
Mutable,
TokenOwner,
CollectionAdmin
-}
\ No newline at end of file
+}
+export enum CollectionLimits {
+ AccountTokenOwnership,
+ SponsoredDataSize,
+ SponsoredDataRateLimit,
+ TokenLimit,
+ SponsorTransferTimeout,
+ SponsorApproveTimeout,
+ OwnerCanTransfer,
+ OwnerCanDestroy,
+ TransferEnabled
+}