git.delta.rocks / unique-network / refs/commits / 91e514bdbb72

difftreelog

source

runtime/common/ethereum/sponsoring.rs7.6 KiBsourcehistory
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.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			if collection.mode != CollectionMode::ReFungible {148				return None;149			}150			let sponsor = collection.sponsorship.sponsor()?.clone();151			let rft_collection = RefungibleHandle::cast(collection);152			// Token existance isn't checked at this point and should be checked in `withdraw` method.153			let token = RefungibleTokenHandle(rft_collection, token_id);154155			let (method_id, mut reader) = AbiReader::new_call(&call_context.input).ok()?;156			let call = <UniqueRefungibleTokenCall<T>>::parse(method_id, &mut reader).ok()??;157			Some(T::CrossAccountId::from_sub(158				refungible::token_call_sponsor(call, token, who).map(|()| sponsor)?,159			))160		}161	}162}163164mod common {165	use super::*;166167	use pallet_common::erc::{CollectionCall};168169	pub fn collection_call_sponsor<T>(170		call: CollectionCall<T>,171		_collection: CollectionHandle<T>,172		_who: &T::CrossAccountId,173	) -> Option<()>174	where175		T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig,176	{177		use CollectionCall::*;178179		match call {180			// Readonly181			ERC165Call(_, _)182			| CollectionProperty { .. }183			| CollectionProperties { .. }184			| HasCollectionPendingSponsor185			| CollectionSponsor186			| ContractAddress187			| AllowlistedCross { .. }188			| IsOwnerOrAdminEth { .. }189			| IsOwnerOrAdminCross { .. }190			| CollectionOwner191			| CollectionAdmins192			| CollectionLimits193			| CollectionNestingRestrictedIds194			| CollectionNestingPermissions195			| UniqueCollectionType => None,196197			// Not sponsored198			AddToCollectionAllowList { .. }199			| AddToCollectionAllowListCross { .. }200			| RemoveFromCollectionAllowList { .. }201			| RemoveFromCollectionAllowListCross { .. }202			| AddCollectionAdminCross { .. }203			| RemoveCollectionAdminCross { .. }204			| AddCollectionAdmin { .. }205			| RemoveCollectionAdmin { .. }206			| SetNestingBool { .. }207			| SetNesting { .. }208			| SetCollectionAccess { .. }209			| SetCollectionMintMode { .. }210			| SetOwner { .. }211			| ChangeCollectionOwnerCross { .. }212			| SetCollectionProperty { .. }213			| SetCollectionProperties { .. }214			| DeleteCollectionProperty { .. }215			| DeleteCollectionProperties { .. }216			| SetCollectionSponsor { .. }217			| SetCollectionSponsorCross { .. }218			| SetCollectionLimit { .. }219			| ConfirmCollectionSponsorship220			| RemoveCollectionSponsor => None,221		}222	}223}