git.delta.rocks / unique-network / refs/commits / 39a2c66a604b

difftreelog

Fix rebase and uncomment rft sponsoring tests.

Grigoriy Simonov2022-12-23parent: #26f0d33.patch.diff
in: master

4 files changed

modifiedruntime/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,
 };
 
modifiedruntime/common/ethereum/sponsoring.rsdiffbeforeafterboth
before · runtime/common/ethereum/sponsoring.rs
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			| 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}
after · runtime/common/ethereum/sponsoring.rs
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}
modifiedruntime/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,
 		}
 	}
 }
modifiedtests/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);