--- a/pallets/nonfungible/src/common.rs +++ b/pallets/nonfungible/src/common.rs @@ -223,7 +223,7 @@ let weight = >::set_token_properties(properties.len() as u32); with_weight( - >::set_token_properties(self, &sender, token_id, properties), + >::set_token_properties(self, &sender, token_id, properties, false), weight, ) } --- a/pallets/nonfungible/src/erc.rs +++ b/pallets/nonfungible/src/erc.rs @@ -82,7 +82,7 @@ .map_err(|_| "key too long")?; let value = value.try_into().map_err(|_| "value too long")?; - >::set_token_property(self, &caller, TokenId(token_id), Property { key, value }) + >::set_token_property(self, &caller, TokenId(token_id), Property { key, value }, false) .map_err(dispatch_to_evm::) } --- a/pallets/nonfungible/src/lib.rs +++ b/pallets/nonfungible/src/lib.rs @@ -447,8 +447,9 @@ sender: &T::CrossAccountId, token_id: TokenId, property: Property, + is_token_create: bool, ) -> DispatchResult { - Self::check_token_change_permission(collection, sender, token_id, &property.key)?; + Self::check_token_change_permission(collection, sender, token_id, &property.key, is_token_create)?; >::try_mutate((collection.id, token_id), |properties| { let property = property.clone(); @@ -471,9 +472,10 @@ sender: &T::CrossAccountId, token_id: TokenId, properties: Vec, + is_token_create: bool, ) -> DispatchResult { for property in properties { - Self::set_token_property(collection, sender, token_id, property)?; + Self::set_token_property(collection, sender, token_id, property, is_token_create)?; } Ok(()) @@ -485,7 +487,7 @@ token_id: TokenId, property_key: PropertyKey, ) -> DispatchResult { - Self::check_token_change_permission(collection, sender, token_id, &property_key)?; + Self::check_token_change_permission(collection, sender, token_id, &property_key, false)?; >::try_mutate((collection.id, token_id), |properties| { properties.remove(&property_key) @@ -506,6 +508,7 @@ sender: &T::CrossAccountId, token_id: TokenId, property_key: &PropertyKey, + is_token_create: bool, ) -> DispatchResult { let permission = >::property_permissions(collection.id) .get(property_key) @@ -534,6 +537,10 @@ token_owner, .. } => { + if is_token_create && (collection_admin || token_owner) { + return Ok(()); + } + let mut check_result = Err(>::NoPermission.into()); if collection_admin { @@ -772,6 +779,7 @@ sender, TokenId(token), data.properties.clone().into_inner(), + true, ) { return TransactionOutcome::Rollback(Err(e)); } --- a/tests/src/eth/contractSponsoring.test.ts +++ b/tests/src/eth/contractSponsoring.test.ts @@ -221,68 +221,71 @@ expect(await helpers.methods.getSponsoringRateLimit(flipper.options.address).call()).to.be.equals('7200'); }); - //TODO: CORE-302 add eth methods - itWeb3.skip('Sponsoring collection from evm address via access list', async ({api, web3}) => { + itWeb3('Sponsoring collection from evm address via access list', async ({api, web3}) => { const owner = await createEthAccountWithBalance(api, web3); const collectionHelpers = evmCollectionHelpers(web3, owner); let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send(); const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result); const sponsor = await createEthAccountWithBalance(api, web3); const collectionEvm = evmCollection(web3, owner, collectionIdAddress); - result = await collectionEvm.methods.ethSetSponsor(sponsor).send({from: owner}); + result = await collectionEvm.methods.setCollectionSponsor(sponsor).send({from: owner}); let collectionSub = (await getDetailedCollectionInfo(api, collectionId))!; expect(collectionSub.sponsorship.isUnconfirmed).to.be.true; expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor)); - await expect(collectionEvm.methods.ethConfirmSponsorship().call()).to.be.rejectedWith('Caller is not set as sponsor'); + await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('Caller is not set as sponsor'); - await collectionEvm.methods.ethConfirmSponsorship().send({from: sponsor}); + await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor}); collectionSub = (await getDetailedCollectionInfo(api, collectionId))!; expect(collectionSub.sponsorship.isConfirmed).to.be.true; expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor)); const user = createEthAccount(web3); - const nextTokenId = await collectionEvm.methods.nextTokenId().call(); + let nextTokenId = await collectionEvm.methods.nextTokenId().call(); expect(nextTokenId).to.be.equal('1'); const oldPermissions = (await getDetailedCollectionInfo(api, collectionId))!.permissions.toHuman(); expect(oldPermissions.mintMode).to.be.false; expect(oldPermissions.access).to.be.equal('Normal'); - await collectionEvm.methods.setAccess('AllowList').send({from: owner}); - await collectionEvm.methods.addToAllowList(user).send({from: owner}); - await collectionEvm.methods.setMintMode(true).send({from: owner}); + await collectionEvm.methods.setCollectionAccess('AllowList').send({from: owner}); + await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner}); + await collectionEvm.methods.setCollectionMintMode(true).send({from: owner}); const newPermissions = (await getDetailedCollectionInfo(api, collectionId))!.permissions.toHuman(); expect(newPermissions.mintMode).to.be.true; expect(newPermissions.access).to.be.equal('AllowList'); - // const [alicesBalanceBefore] = await getBalance(api, [alicesPublicKey]); + const ownerBalanceBefore = await ethBalanceViaSub(api, owner); + const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor); - { - const nextTokenId = await collectionEvm.methods.nextTokenId().call(); - expect(nextTokenId).to.be.equal('1'); - const result = await collectionEvm.methods.mintWithTokenURI( - user, - nextTokenId, - 'Test URI', - ).call({from: user}); - console.log(result); - const events = normalizeEvents(result.events); + nextTokenId = await collectionEvm.methods.nextTokenId().call({from: user}); + expect(nextTokenId).to.be.equal('1'); + result = await collectionEvm.methods.mintWithTokenURI( + user, + nextTokenId, + 'Test URI', + ).send({from: user}); + const events = normalizeEvents(result.events); + events[0].address = events[0].address.toLocaleLowerCase(); - expect(events).to.be.deep.equal([ - { - collectionIdAddress, - event: 'Transfer', - args: { - from: '0x0000000000000000000000000000000000000000', - to: user, - tokenId: nextTokenId, - }, + expect(events).to.be.deep.equal([ + { + address: collectionIdAddress.toLocaleLowerCase(), + event: 'Transfer', + args: { + from: '0x0000000000000000000000000000000000000000', + to: user, + tokenId: nextTokenId, }, - ]); + }, + ]); - expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI'); - } + expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI'); + + const ownerBalanceAfter = await ethBalanceViaSub(api, owner); + expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore); + const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor); + expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true; }); itWeb3('Check that transaction via EVM spend money from sponsor address', async ({api, web3}) => { @@ -308,7 +311,6 @@ const ownerBalanceBefore = await ethBalanceViaSub(api, owner); const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor); - const userCollectionEvm = evmCollection(web3, user, collectionIdAddress); const nextTokenId = await userCollectionEvm.methods.nextTokenId().call();