difftreelog
Fix rebase and uncomment rft sponsoring tests.
in: master
4 files changed
runtime/common/config/pallets/app_promotion.rsdiffbeforeafterboth--- a/runtime/common/config/pallets/app_promotion.rs
+++ b/runtime/common/config/pallets/app_promotion.rs
@@ -22,7 +22,7 @@
use frame_support::{parameter_types, PalletId};
use sp_arithmetic::Perbill;
use up_common::{
- constants::{UNIQUE, RELAY_DAYS},
+ constants::{UNIQUE, RELAY_DAYS, DAYS},
types::Balance,
};
runtime/common/ethereum/sponsoring.rsdiffbeforeafterboth1// 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/>.1617//! Implements EVM sponsoring logic via TransactionValidityHack1819use core::{convert::TryInto, marker::PhantomData};20use evm_coder::{Call, abi::AbiReader};21use pallet_common::{CollectionHandle, eth::map_eth_to_id};22use pallet_evm::account::CrossAccountId;23use pallet_evm_transaction_payment::CallContext;24use pallet_nonfungible::{25 Config as NonfungibleConfig,26 erc::{27 UniqueNFTCall, ERC721UniqueExtensionsCall, ERC721UniqueMintableCall, ERC721Call,28 TokenPropertiesCall,29 },30};31use pallet_fungible::{32 Config as FungibleConfig,33 erc::{UniqueFungibleCall, ERC20Call},34};35use pallet_refungible::{36 Config as RefungibleConfig,37 erc::UniqueRefungibleCall,38 erc_token::{RefungibleTokenHandle, UniqueRefungibleTokenCall},39 RefungibleHandle,40};41use pallet_unique::Config as UniqueConfig;42use sp_std::prelude::*;43use up_data_structs::{44 CollectionMode, CreateItemData, CreateNftData, mapping::TokenAddressMapping, TokenId,45};46use up_sponsorship::SponsorshipHandler;47use crate::{Runtime, runtime_common::sponsoring::*};4849mod refungible;5051pub type EvmSponsorshipHandler = (52 UniqueEthSponsorshipHandler<Runtime>,53 pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,54);5556pub struct UniqueEthSponsorshipHandler<T: UniqueConfig>(PhantomData<*const T>);57impl<T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig>58 SponsorshipHandler<T::CrossAccountId, CallContext> for UniqueEthSponsorshipHandler<T>59{60 fn get_sponsor(61 who: &T::CrossAccountId,62 call_context: &CallContext,63 ) -> Option<T::CrossAccountId> {64 if let Some(collection_id) = map_eth_to_id(&call_context.contract_address) {65 let collection = <CollectionHandle<T>>::new(collection_id)?;66 let sponsor = collection.sponsorship.sponsor()?.clone();67 let (method_id, mut reader) = AbiReader::new_call(&call_context.input).ok()?;68 Some(T::CrossAccountId::from_sub(match &collection.mode {69 CollectionMode::NFT => {70 let call = <UniqueNFTCall<T>>::parse(method_id, &mut reader).ok()??;71 match call {72 UniqueNFTCall::TokenProperties(TokenPropertiesCall::SetProperty {73 token_id,74 key,75 value,76 ..77 }) => {78 let token_id: TokenId = token_id.try_into().ok()?;79 withdraw_set_token_property::<T>(80 &collection,81 &who,82 &token_id,83 key.len() + value.len(),84 )85 .map(|()| sponsor)86 }87 UniqueNFTCall::ERC721UniqueExtensions(88 ERC721UniqueExtensionsCall::Transfer { token_id, .. },89 ) => {90 let token_id: TokenId = token_id.try_into().ok()?;91 withdraw_transfer::<T>(&collection, &who, &token_id).map(|()| sponsor)92 }93 UniqueNFTCall::ERC721UniqueMintable(94 ERC721UniqueMintableCall::Mint { .. }95 | ERC721UniqueMintableCall::MintCheckId { .. }96 | ERC721UniqueMintableCall::MintWithTokenUri { .. }97 | ERC721UniqueMintableCall::MintWithTokenUriCheckId { .. },98 ) => withdraw_create_item::<T>(99 &collection,100 &who,101 &CreateItemData::NFT(CreateNftData::default()),102 )103 .map(|()| sponsor),104 UniqueNFTCall::ERC721(ERC721Call::TransferFrom {105 token_id, from, ..106 }) => {107 let token_id: TokenId = token_id.try_into().ok()?;108 let from = T::CrossAccountId::from_eth(from);109 withdraw_transfer::<T>(&collection, &from, &token_id).map(|()| sponsor)110 }111 UniqueNFTCall::ERC721(ERC721Call::Approve { token_id, .. }) => {112 let token_id: TokenId = token_id.try_into().ok()?;113 withdraw_approve::<T>(&collection, who.as_sub(), &token_id)114 .map(|()| sponsor)115 }116 _ => None,117 }118 }119 CollectionMode::ReFungible => {120 let call = <UniqueRefungibleCall<T>>::parse(method_id, &mut reader).ok()??;121 refungible::call_sponsor(call, collection, who).map(|()| sponsor)122 }123 CollectionMode::Fungible(_) => {124 let call = <UniqueFungibleCall<T>>::parse(method_id, &mut reader).ok()??;125 match call {126 UniqueFungibleCall::ERC20(ERC20Call::Transfer { .. }) => {127 withdraw_transfer::<T>(&collection, who, &TokenId::default())128 .map(|()| sponsor)129 }130 UniqueFungibleCall::ERC20(ERC20Call::TransferFrom { from, .. }) => {131 let from = T::CrossAccountId::from_eth(from);132 withdraw_transfer::<T>(&collection, &from, &TokenId::default())133 .map(|()| sponsor)134 }135 UniqueFungibleCall::ERC20(ERC20Call::Approve { .. }) => {136 withdraw_approve::<T>(&collection, who.as_sub(), &TokenId::default())137 .map(|()| sponsor)138 }139 _ => None,140 }141 }142 }?))143 } else {144 let (collection_id, token_id) =145 T::EvmTokenAddressMapping::address_to_token(&call_context.contract_address)?;146 let collection = <CollectionHandle<T>>::new(collection_id)?;147 let sponsor = collection.sponsorship.sponsor()?.clone();148 let rft_collection = RefungibleHandle::cast(collection);149 let token = RefungibleTokenHandle(rft_collection, token_id);150 let (method_id, mut reader) = AbiReader::new_call(&call_context.input).ok()?;151 let call = <UniqueRefungibleTokenCall<T>>::parse(method_id, &mut reader).ok()??;152 Some(T::CrossAccountId::from_sub(153 refungible::token_call_sponsor(call, token, who).map(|()| sponsor)?,154 ))155 }156 }157}158159mod common {160 use super::*;161162 use pallet_common::erc::{CollectionCall};163164 pub fn collection_call_sponsor<T>(165 call: CollectionCall<T>,166 _collection: CollectionHandle<T>,167 _who: &T::CrossAccountId,168 ) -> Option<()>169 where170 T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig,171 {172 use CollectionCall::*;173174 match call {175 // Readonly176 ERC165Call(_, _)177 | CollectionProperty { .. }178 | CollectionProperties { .. }179 | HasCollectionPendingSponsor180 | CollectionSponsor181 | ContractAddress182 | AllowlistedCross { .. }183 | IsOwnerOrAdminEth { .. }184 | IsOwnerOrAdminCross { .. }185 | CollectionOwner186 | CollectionAdmins187 | UniqueCollectionType => None,188189 // Not sponsored190 AddToCollectionAllowList { .. }191 | AddToCollectionAllowListCross { .. }192 | RemoveFromCollectionAllowList { .. }193 | RemoveFromCollectionAllowListCross { .. }194 | AddCollectionAdminCross { .. }195 | RemoveCollectionAdminCross { .. }196 | AddCollectionAdmin { .. }197 | RemoveCollectionAdmin { .. }198 | SetNestingBool { .. }199 | SetNesting { .. }200 | SetCollectionAccess { .. }201 | SetCollectionMintMode { .. }202 | SetOwner { .. }203 | ChangeCollectionOwnerCross { .. }204 | SetCollectionProperty { .. }205 | SetCollectionProperties { .. }206 | DeleteCollectionProperty { .. }207 | DeleteCollectionProperties { .. }208 | SetCollectionSponsor { .. }209 | SetCollectionSponsorCross { .. }210 | ConfirmCollectionSponsorship211 | RemoveCollectionSponsor212 | SetIntLimit { .. } => None,213 }214 }215}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/>.1617//! Implements EVM sponsoring logic via TransactionValidityHack1819use core::{convert::TryInto, marker::PhantomData};20use evm_coder::{Call, abi::AbiReader};21use pallet_common::{CollectionHandle, eth::map_eth_to_id};22use pallet_evm::account::CrossAccountId;23use pallet_evm_transaction_payment::CallContext;24use pallet_nonfungible::{25 Config as NonfungibleConfig,26 erc::{27 UniqueNFTCall, ERC721UniqueExtensionsCall, ERC721UniqueMintableCall, ERC721Call,28 TokenPropertiesCall,29 },30};31use pallet_fungible::{32 Config as FungibleConfig,33 erc::{UniqueFungibleCall, ERC20Call},34};35use pallet_refungible::{36 Config as RefungibleConfig,37 erc::UniqueRefungibleCall,38 erc_token::{RefungibleTokenHandle, UniqueRefungibleTokenCall},39 RefungibleHandle,40};41use pallet_unique::Config as UniqueConfig;42use sp_std::prelude::*;43use up_data_structs::{44 CollectionMode, CreateItemData, CreateNftData, mapping::TokenAddressMapping, TokenId,45};46use up_sponsorship::SponsorshipHandler;47use crate::{Runtime, runtime_common::sponsoring::*};4849mod refungible;5051pub type EvmSponsorshipHandler = (52 UniqueEthSponsorshipHandler<Runtime>,53 pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,54);5556pub struct UniqueEthSponsorshipHandler<T: UniqueConfig>(PhantomData<*const T>);57impl<T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig>58 SponsorshipHandler<T::CrossAccountId, CallContext> for UniqueEthSponsorshipHandler<T>59{60 fn get_sponsor(61 who: &T::CrossAccountId,62 call_context: &CallContext,63 ) -> Option<T::CrossAccountId> {64 if let Some(collection_id) = map_eth_to_id(&call_context.contract_address) {65 let collection = <CollectionHandle<T>>::new(collection_id)?;66 let sponsor = collection.sponsorship.sponsor()?.clone();67 let (method_id, mut reader) = AbiReader::new_call(&call_context.input).ok()?;68 Some(T::CrossAccountId::from_sub(match &collection.mode {69 CollectionMode::NFT => {70 let call = <UniqueNFTCall<T>>::parse(method_id, &mut reader).ok()??;71 match call {72 UniqueNFTCall::TokenProperties(TokenPropertiesCall::SetProperty {73 token_id,74 key,75 value,76 ..77 }) => {78 let token_id: TokenId = token_id.try_into().ok()?;79 withdraw_set_token_property::<T>(80 &collection,81 &who,82 &token_id,83 key.len() + value.len(),84 )85 .map(|()| sponsor)86 }87 UniqueNFTCall::ERC721UniqueExtensions(88 ERC721UniqueExtensionsCall::Transfer { token_id, .. },89 ) => {90 let token_id: TokenId = token_id.try_into().ok()?;91 withdraw_transfer::<T>(&collection, &who, &token_id).map(|()| sponsor)92 }93 UniqueNFTCall::ERC721UniqueMintable(94 ERC721UniqueMintableCall::Mint { .. }95 | ERC721UniqueMintableCall::MintCheckId { .. }96 | ERC721UniqueMintableCall::MintWithTokenUri { .. }97 | ERC721UniqueMintableCall::MintWithTokenUriCheckId { .. },98 ) => withdraw_create_item::<T>(99 &collection,100 &who,101 &CreateItemData::NFT(CreateNftData::default()),102 )103 .map(|()| sponsor),104 UniqueNFTCall::ERC721(ERC721Call::TransferFrom {105 token_id, from, ..106 }) => {107 let token_id: TokenId = token_id.try_into().ok()?;108 let from = T::CrossAccountId::from_eth(from);109 withdraw_transfer::<T>(&collection, &from, &token_id).map(|()| sponsor)110 }111 UniqueNFTCall::ERC721(ERC721Call::Approve { token_id, .. }) => {112 let token_id: TokenId = token_id.try_into().ok()?;113 withdraw_approve::<T>(&collection, who.as_sub(), &token_id)114 .map(|()| sponsor)115 }116 _ => None,117 }118 }119 CollectionMode::ReFungible => {120 let call = <UniqueRefungibleCall<T>>::parse(method_id, &mut reader).ok()??;121 refungible::call_sponsor(call, collection, who).map(|()| sponsor)122 }123 CollectionMode::Fungible(_) => {124 let call = <UniqueFungibleCall<T>>::parse(method_id, &mut reader).ok()??;125 match call {126 UniqueFungibleCall::ERC20(ERC20Call::Transfer { .. }) => {127 withdraw_transfer::<T>(&collection, who, &TokenId::default())128 .map(|()| sponsor)129 }130 UniqueFungibleCall::ERC20(ERC20Call::TransferFrom { from, .. }) => {131 let from = T::CrossAccountId::from_eth(from);132 withdraw_transfer::<T>(&collection, &from, &TokenId::default())133 .map(|()| sponsor)134 }135 UniqueFungibleCall::ERC20(ERC20Call::Approve { .. }) => {136 withdraw_approve::<T>(&collection, who.as_sub(), &TokenId::default())137 .map(|()| sponsor)138 }139 _ => None,140 }141 }142 }?))143 } else {144 let (collection_id, token_id) =145 T::EvmTokenAddressMapping::address_to_token(&call_context.contract_address)?;146 let collection = <CollectionHandle<T>>::new(collection_id)?;147 let sponsor = collection.sponsorship.sponsor()?.clone();148 let rft_collection = RefungibleHandle::cast(collection);149 let token = RefungibleTokenHandle(rft_collection, token_id);150 let (method_id, mut reader) = AbiReader::new_call(&call_context.input).ok()?;151 let call = <UniqueRefungibleTokenCall<T>>::parse(method_id, &mut reader).ok()??;152 Some(T::CrossAccountId::from_sub(153 refungible::token_call_sponsor(call, token, who).map(|()| sponsor)?,154 ))155 }156 }157}158159mod common {160 use super::*;161162 use pallet_common::erc::{CollectionCall};163164 pub fn collection_call_sponsor<T>(165 call: CollectionCall<T>,166 _collection: CollectionHandle<T>,167 _who: &T::CrossAccountId,168 ) -> Option<()>169 where170 T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig,171 {172 use CollectionCall::*;173174 match call {175 // Readonly176 ERC165Call(_, _)177 | CollectionProperty { .. }178 | CollectionProperties { .. }179 | HasCollectionPendingSponsor180 | CollectionSponsor181 | ContractAddress182 | AllowlistedCross { .. }183 | IsOwnerOrAdminEth { .. }184 | IsOwnerOrAdminCross { .. }185 | CollectionOwner186 | CollectionAdmins187 | CollectionLimits188 | CollectionNestingRestrictedIds189 | CollectionNestingPermissions190 | UniqueCollectionType => None,191192 // Not sponsored193 AddToCollectionAllowList { .. }194 | AddToCollectionAllowListCross { .. }195 | RemoveFromCollectionAllowList { .. }196 | RemoveFromCollectionAllowListCross { .. }197 | AddCollectionAdminCross { .. }198 | RemoveCollectionAdminCross { .. }199 | AddCollectionAdmin { .. }200 | RemoveCollectionAdmin { .. }201 | SetNestingBool { .. }202 | SetNesting { .. }203 | SetCollectionAccess { .. }204 | SetCollectionMintMode { .. }205 | SetOwner { .. }206 | ChangeCollectionOwnerCross { .. }207 | SetCollectionProperty { .. }208 | SetCollectionProperties { .. }209 | DeleteCollectionProperty { .. }210 | DeleteCollectionProperties { .. }211 | SetCollectionSponsor { .. }212 | SetCollectionSponsorCross { .. }213 | SetCollectionLimit { .. }214 | ConfirmCollectionSponsorship215 | RemoveCollectionSponsor => None,216 }217 }218}runtime/common/ethereum/sponsoring/refungible.rsdiffbeforeafterboth--- a/runtime/common/ethereum/sponsoring/refungible.rs
+++ b/runtime/common/ethereum/sponsoring/refungible.rs
@@ -79,10 +79,11 @@
match call {
// Readonly
- ERC165Call(_, _) | Property { .. } => None,
+ ERC165Call(_, _) | Property { .. } | TokenPropertyPermissions => None,
// Not sponsored
SetTokenPropertyPermission { .. }
+ | SetTokenPropertyPermissions { .. }
| SetProperties { .. }
| DeleteProperty { .. }
| DeleteProperties { .. } => None,
@@ -236,6 +237,7 @@
| TransferFromCross { .. }
| BurnFrom { .. }
| BurnFromCross { .. }
+ | MintCross { .. }
| MintBulk { .. }
| MintBulkWithTokenUri { .. } => None,
@@ -332,7 +334,12 @@
ERC165Call(_, _) => None,
// Not sponsored
- BurnFrom { .. } | Repartition { .. } => None,
+ BurnFrom { .. }
+ | BurnFromCross { .. }
+ | ApproveCross { .. }
+ | TransferCross { .. }
+ | TransferFromCross { .. }
+ | Repartition { .. } => None,
}
}
}
tests/src/eth/collectionSponsoring.test.tsdiffbeforeafterboth--- a/tests/src/eth/collectionSponsoring.test.ts
+++ b/tests/src/eth/collectionSponsoring.test.ts
@@ -359,27 +359,6 @@
});
});
- // TODO: Temprorary off. Need refactor
- // itWeb3('Set substrate sponsor', async ({api, web3, privateKeyWrapper}) => {
- // const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- // const collectionHelpers = evmCollectionHelpers(web3, owner);
- // let result = await collectionHelpers.methods.createRFTCollection('Sponsor collection', '1', '1').send();
- // const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
- // const sponsor = privateKeyWrapper('//Alice');
- // const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
-
- // expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;
- // result = await collectionEvm.methods.setCollectionSponsorSubstrate(sponsor.addressRaw).send({from: owner});
- // expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.true;
-
- // const confirmTx = await api.tx.unique.confirmSponsorship(collectionId);
- // await submitTransactionAsync(sponsor, confirmTx);
- // expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;
-
- // const sponsorTuple = await collectionEvm.methods.collectionSponsor().call({from: owner});
- // expect(bigIntToSub(api, BigInt(sponsorTuple[1]))).to.be.eq(sponsor.address);
- // });
-
[
'setCollectionSponsorCross',
'setCollectionSponsor', // Soft-deprecated
@@ -404,7 +383,7 @@
await collectionEvm.methods.removeCollectionSponsor().send({from: owner});
const sponsorTuple = await collectionEvm.methods.collectionSponsor().call({from: owner});
- expect(sponsorTuple.field_0).to.be.eq('0x0000000000000000000000000000000000000000');
+ expect(sponsorTuple.eth).to.be.eq('0x0000000000000000000000000000000000000000');
}));
[
@@ -426,7 +405,8 @@
let sponsorship = (await collectionSub.getData())!.raw.sponsorship;
expect(sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsorEth, true));
// Account cannot confirm sponsorship if it is not set as a sponsor
- await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');
+ //await collectionEvm.methods.confirmCollectionSponsorship().call();
+ await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');
// Sponsor can confirm sponsorship:
await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsorEth});
@@ -480,63 +460,7 @@
expect(sponsorBalanceBefore > sponsorBalanceAfter).to.be.true;
}
}));
-
- // TODO: Temprorary off. Need refactor
- // itWeb3('Sponsoring collection from substrate address via access list', async ({api, web3, privateKeyWrapper}) => {
- // const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- // const collectionHelpers = evmCollectionHelpers(web3, owner);
- // const result = await collectionHelpers.methods.createERC721MetadataCompatibleRFTCollection('Sponsor collection', '1', '1', '').send();
- // const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
- // const sponsor = privateKeyWrapper('//Alice');
- // const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
-
- // await collectionEvm.methods.setCollectionSponsorSubstrate(sponsor.addressRaw).send({from: owner});
-
- // const confirmTx = await api.tx.unique.confirmSponsorship(collectionId);
- // await submitTransactionAsync(sponsor, confirmTx);
-
- // const user = createEthAccount(web3);
- // const nextTokenId = await collectionEvm.methods.nextTokenId().call();
- // expect(nextTokenId).to.be.equal('1');
-
- // await collectionEvm.methods.setCollectionAccess(1 /*'AllowList'*/).send({from: owner});
- // await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner});
- // await collectionEvm.methods.setCollectionMintMode(true).send({from: owner});
-
- // const ownerBalanceBefore = await ethBalanceViaSub(api, owner);
- // const sponsorBalanceBefore = (await getBalance(api, [sponsor.address]))[0];
-
- // {
- // const nextTokenId = await collectionEvm.methods.nextTokenId().call();
- // expect(nextTokenId).to.be.equal('1');
- // const result = await collectionEvm.methods.mintWithTokenURI(
- // user,
- // nextTokenId,
- // 'Test URI',
- // ).send({from: user});
- // const events = normalizeEvents(result.events);
-
- // expect(events).to.be.deep.equal([
- // {
- // address: collectionIdAddress,
- // event: 'Transfer',
- // args: {
- // from: '0x0000000000000000000000000000000000000000',
- // to: user,
- // tokenId: nextTokenId,
- // },
- // },
- // ]);
- // const ownerBalanceAfter = await ethBalanceViaSub(api, owner);
- // const sponsorBalanceAfter = (await getBalance(api, [sponsor.address]))[0];
-
- // expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');
- // expect(ownerBalanceBefore).to.be.eq(ownerBalanceAfter);
- // expect(sponsorBalanceBefore > sponsorBalanceAfter).to.be.true;
- // }
- // });
-
[
'setCollectionSponsorCross',
'setCollectionSponsor', // Soft-deprecated
@@ -554,7 +478,7 @@
await collectionEvm.methods[testCase](testCase === 'setCollectionSponsor' ? sponsor : sponsorCross).send();
let collectionData = (await collectionSub.getData())!;
expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));
- await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');
+ await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');
await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});
collectionData = (await collectionSub.getData())!;
@@ -600,9 +524,12 @@
const collectionSub = helper.rft.getCollectionObject(collectionId);
const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner, false);
// Set collection sponsor:
+ expect(await collectionEvm.methods.hasCollectionPendingSponsor().call()).to.be.false;
await collectionEvm.methods.setCollectionSponsorCross(sponsorCross).send();
+ expect(await collectionEvm.methods.hasCollectionPendingSponsor().call()).to.be.true;
await collectionSub.confirmSponsorship(sponsor);
+ expect(await collectionEvm.methods.hasCollectionPendingSponsor().call()).to.be.false;
const user = helper.eth.createAccount();
const userCross = helper.ethCrossAccount.fromAddress(user);
@@ -615,10 +542,9 @@
const tokenId = mintingResult.events.Transfer.returnValues.tokenId;
const events = helper.eth.normalizeEvents(mintingResult.events);
- const address = helper.ethAddress.fromCollectionId(collectionId);
expect(events).to.deep.include({
- address,
+ address: collectionAddress,
event: 'Transfer',
args: {
from: '0x0000000000000000000000000000000000000000',
@@ -634,6 +560,62 @@
expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;
});
+ itEth('Sponsoring collection from substrate address via access list', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const user = helper.eth.createAccount();
+ const userCross = helper.ethCrossAccount.fromAddress(user);
+ const sponsor = alice;
+ const sponsorCross = helper.ethCrossAccount.fromKeyringPair(sponsor);
+
+ const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner,'Sponsor collection', '1', '1', '');
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner, false);
+
+ await collectionEvm.methods.setCollectionSponsorCross(sponsorCross).send({from: owner});
+
+ const collectionSub = helper.rft.getCollectionObject(collectionId);
+ await collectionSub.confirmSponsorship(sponsor);
+
+ const nextTokenId = await collectionEvm.methods.nextTokenId().call();
+ expect(nextTokenId).to.be.equal('1');
+
+ await collectionEvm.methods.setCollectionAccess(1 /*'AllowList'*/).send({from: owner});
+
+ await collectionEvm.methods.addToCollectionAllowListCross(userCross).send({from: owner});
+ await collectionEvm.methods.setCollectionMintMode(true).send({from: owner});
+
+ const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
+ const sponsorBalanceBefore = await helper.balance.getSubstrate(sponsor.address);
+
+ {
+ const nextTokenId = await collectionEvm.methods.nextTokenId().call();
+ expect(nextTokenId).to.be.equal('1');
+ const mintingResult = await collectionEvm.methods.mintWithTokenURI(
+ user,
+ 'Test URI',
+ ).send({from: user});
+
+ const events = helper.eth.normalizeEvents(mintingResult.events);
+
+
+ expect(events).to.deep.include({
+ address: collectionAddress,
+ event: 'Transfer',
+ args: {
+ from: '0x0000000000000000000000000000000000000000',
+ to: user,
+ tokenId: nextTokenId,
+ },
+ });
+
+ const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
+ const sponsorBalanceAfter = await helper.balance.getSubstrate(sponsor.address);
+
+ expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');
+ expect(ownerBalanceBefore).to.be.eq(ownerBalanceAfter);
+ expect(sponsorBalanceBefore > sponsorBalanceAfter).to.be.true;
+ }
+ });
+
itEth('Can reassign collection sponsor', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const sponsorEth = await helper.eth.createAccountWithBalance(donor);