git.delta.rocks / unique-network / refs/commits / e80fd26fb5bf

difftreelog

source

pallets/evm-contract-helpers/src/lib.rs8.2 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#![cfg_attr(not(feature = "std"), no_std)]1819use codec::{Decode, Encode, MaxEncodedLen};20pub use pallet::*;21pub use eth::*;22use scale_info::TypeInfo;23pub mod eth;2425#[frame_support::pallet]26pub mod pallet {27	pub use super::*;28	use frame_support::pallet_prelude::*;29	use pallet_evm_coder_substrate::DispatchResult;30	use sp_core::H160;31	use pallet_evm::account::CrossAccountId;32	use up_data_structs::SponsorshipState;3334	#[pallet::config]35	pub trait Config:36		frame_system::Config + pallet_evm_coder_substrate::Config + pallet_evm::account::Config37	{38		type ContractAddress: Get<H160>;39		type DefaultSponsoringRateLimit: Get<Self::BlockNumber>;40	}4142	#[pallet::error]43	pub enum Error<T> {44		/// This method is only executable by owner.45		NoPermission,4647		/// No pending sponsor for contract.48		NoPendingSponsor,49	}5051	#[pallet::pallet]52	#[pallet::generate_store(pub(super) trait Store)]53	pub struct Pallet<T>(_);5455	/// Store owner for contract.56	///57	/// * **Key** - contract address.58	/// * **Value** - owner for contract.59	#[pallet::storage]60	pub(super) type Owner<T: Config> =61		StorageMap<Hasher = Twox128, Key = H160, Value = H160, QueryKind = ValueQuery>;6263	#[pallet::storage]64	#[deprecated]65	pub(super) type SelfSponsoring<T: Config> =66		StorageMap<Hasher = Twox128, Key = H160, Value = bool, QueryKind = ValueQuery>;6768	/// Store for contract sponsorship state.69	///70	/// * **Key** - contract address.71	/// * **Value** - sponsorship state.72	#[pallet::storage]73	pub(super) type Sponsoring<T: Config> = StorageMap<74		Hasher = Twox64Concat,75		Key = H160,76		Value = SponsorshipState<T::CrossAccountId>,77		QueryKind = ValueQuery,78	>;7980	/// Store for sponsoring mode.81	///82	/// ### Usage83	/// Prefer to delete collection from storage if mode chaged to [`Disabled`](SponsoringModeT::Disabled).84	///85	/// * **Key** - contract address.86	/// * **Value** - [`sponsoring mode`](SponsoringModeT).87	#[pallet::storage]88	pub(super) type SponsoringMode<T: Config> =89		StorageMap<Hasher = Twox128, Key = H160, Value = SponsoringModeT, QueryKind = OptionQuery>;9091	/// Storage for sponsoring rate limit in blocks.92	///93	/// * **Key** - contract address.94	/// * **Value** - amount of sponsored blocks.95	#[pallet::storage]96	pub(super) type SponsoringRateLimit<T: Config> = StorageMap<97		Hasher = Twox128,98		Key = H160,99		Value = T::BlockNumber,100		QueryKind = ValueQuery,101		OnEmpty = T::DefaultSponsoringRateLimit,102	>;103104	/// Storage for last sponsored block.105	///106	/// * **Key1** - contract address.107	/// * **Key2** - sponsored user address.108	/// * **Value** - last sponsored block number.109	#[pallet::storage]110	pub(super) type SponsorBasket<T: Config> = StorageDoubleMap<111		Hasher1 = Twox128,112		Key1 = H160,113		Hasher2 = Twox128,114		Key2 = H160,115		Value = T::BlockNumber,116		QueryKind = OptionQuery,117	>;118119	/// Storege for contracts with [`Allowlisted`](SponsoringModeT::Allowlisted) sponsoring mode.120	///121	/// ### Usage122	/// Prefer to delete collection from storage if mode chaged to non `Allowlisted`, than set **Value** to **false**.123	///124	/// * **Key** - contract address.125	/// * **Value** - is contract in [`Allowlisted`](SponsoringModeT::Allowlisted) mode.126	#[pallet::storage]127	pub(super) type AllowlistEnabled<T: Config> =128		StorageMap<Hasher = Twox128, Key = H160, Value = bool, QueryKind = ValueQuery>;129130	/// Storage for users that allowed for sponsorship.131	///132	/// ### Usage133	/// Prefer to delete record from storage if user no more allowed for sponsorship.134	///135	/// * **Key1** - contract address.136	/// * **Key2** - user that allowed for sponsorship.137	/// * **Value** - allowance for sponsorship.138	#[pallet::storage]139	pub(super) type Allowlist<T: Config> = StorageDoubleMap<140		Hasher1 = Twox128,141		Key1 = H160,142		Hasher2 = Twox128,143		Key2 = H160,144		Value = bool,145		QueryKind = ValueQuery,146	>;147148	impl<T: Config> Pallet<T> {149		/// Get contract owner.150		pub fn contract_owner(contract: H160) -> H160 {151			<Owner<T>>::get(contract)152		}153154		/// Set `sponsor` for `contract`.155		///156		/// `sender` must be owner of contract.157		pub fn set_sponsor(158			sender: &T::CrossAccountId,159			contract: H160,160			sponsor: &T::CrossAccountId,161		) -> DispatchResult {162			Pallet::<T>::ensure_owner(contract, *sender.as_eth())?;163			Sponsoring::<T>::insert(164				contract,165				SponsorshipState::<T::CrossAccountId>::Unconfirmed(sponsor.clone()),166			);167			Ok(())168		}169170		/// Set `contract` as self sponsored.171		///172		/// `sender` must be owner of contract.173		pub fn self_sponsored_enable(sender: &T::CrossAccountId, contract: H160) -> DispatchResult {174			Pallet::<T>::ensure_owner(contract, *sender.as_eth())?;175			Sponsoring::<T>::insert(176				contract,177				SponsorshipState::<T::CrossAccountId>::Confirmed(T::CrossAccountId::from_eth(178					contract,179				)),180			);181			Ok(())182		}183184		/// Remove sponsor for `contract`.185		///186		/// `sender` must be owner of contract.187		pub fn remove_sponsor(sender: &T::CrossAccountId, contract: H160) -> DispatchResult {188			Pallet::<T>::ensure_owner(contract, *sender.as_eth())?;189			Sponsoring::<T>::remove(contract);190			Ok(())191		}192193		/// Confirm sponsorship.194		///195		/// `sender` must be same that set via [`set_sponsor`].196		pub fn confirm_sponsorship(sender: &T::CrossAccountId, contract: H160) -> DispatchResult {197			match Sponsoring::<T>::get(contract) {198				SponsorshipState::Unconfirmed(sponsor) => {199					ensure!(sponsor == *sender, Error::<T>::NoPermission);200					Sponsoring::<T>::insert(201						contract,202						SponsorshipState::<T::CrossAccountId>::Confirmed(sponsor),203					);204					Ok(())205				}206				SponsorshipState::Disabled | SponsorshipState::Confirmed(_) => {207					Err(Error::<T>::NoPendingSponsor.into())208				}209			}210		}211212		/// Get sponsor.213		pub fn get_sponsor(contract: H160) -> Option<T::CrossAccountId> {214			match Sponsoring::<T>::get(contract) {215				SponsorshipState::Disabled | SponsorshipState::Unconfirmed(_) => None,216				SponsorshipState::Confirmed(sponsor) => Some(sponsor),217			}218		}219220		pub fn sponsoring_mode(contract: H160) -> SponsoringModeT {221			<SponsoringMode<T>>::get(contract)222				.or_else(|| {223					<SelfSponsoring<T>>::get(contract).then(|| SponsoringModeT::Allowlisted)224				})225				.unwrap_or_default()226		}227228		pub fn set_sponsoring_mode(contract: H160, mode: SponsoringModeT) {229			if mode == SponsoringModeT::Disabled {230				<SponsoringMode<T>>::remove(contract);231			} else {232				<SponsoringMode<T>>::insert(contract, mode);233			}234			<SelfSponsoring<T>>::remove(contract)235		}236237		pub fn set_sponsoring_rate_limit(contract: H160, rate_limit: T::BlockNumber) {238			<SponsoringRateLimit<T>>::insert(contract, rate_limit);239		}240241		pub fn allowed(contract: H160, user: H160) -> bool {242			<Allowlist<T>>::get(&contract, &user) || <Owner<T>>::get(&contract) == user243		}244245		pub fn toggle_allowlist(contract: H160, enabled: bool) {246			<AllowlistEnabled<T>>::insert(contract, enabled)247		}248249		pub fn toggle_allowed(contract: H160, user: H160, allowed: bool) {250			<Allowlist<T>>::insert(contract, user, allowed);251		}252253		pub fn ensure_owner(contract: H160, user: H160) -> DispatchResult {254			ensure!(<Owner<T>>::get(&contract) == user, Error::<T>::NoPermission);255			Ok(())256		}257	}258}259260#[derive(Encode, Decode, PartialEq, TypeInfo, MaxEncodedLen)]261pub enum SponsoringModeT {262	Disabled,263	Allowlisted,264	Generous,265}266267impl SponsoringModeT {268	fn from_eth(v: u8) -> Option<Self> {269		Some(match v {270			0 => Self::Disabled,271			1 => Self::Allowlisted,272			2 => Self::Generous,273			_ => return None,274		})275	}276	fn to_eth(self) -> u8 {277		match self {278			SponsoringModeT::Disabled => 0,279			SponsoringModeT::Allowlisted => 1,280			SponsoringModeT::Generous => 2,281		}282	}283}284285impl Default for SponsoringModeT {286	fn default() -> Self {287		Self::Disabled288	}289}