difftreelog
fix Events for contract sponsoring.
in: master
2 files changed
pallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth--- a/pallets/evm-contract-helpers/src/eth.rs
+++ b/pallets/evm-contract-helpers/src/eth.rs
@@ -124,8 +124,12 @@
self.recorder().consume_sload()?;
self.recorder().consume_sstore()?;
- Pallet::<T>::force_set_sponsor(&T::CrossAccountId::from_eth(caller), contract_address)
- .map_err(dispatch_to_evm::<T>)?;
+ Pallet::<T>::force_set_sponsor(
+ &T::CrossAccountId::from_eth(caller),
+ contract_address,
+ &T::CrossAccountId::from_eth(contract_address),
+ )
+ .map_err(dispatch_to_evm::<T>)?;
Ok(())
}
pallets/evm-contract-helpers/src/lib.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#![doc = include_str!("../README.md")]18#![cfg_attr(not(feature = "std"), no_std)]19#![warn(missing_docs)]2021use codec::{Decode, Encode, MaxEncodedLen};22pub use pallet::*;23pub use eth::*;24use scale_info::TypeInfo;25pub mod eth;2627#[frame_support::pallet]28pub mod pallet {29 pub use super::*;30 use crate::eth::ContractHelpersEvents;31 use frame_support::pallet_prelude::*;32 use pallet_evm_coder_substrate::DispatchResult;33 use sp_core::H160;34 use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};35 use up_data_structs::SponsorshipState;36 use evm_coder::ToLog;3738 #[pallet::config]39 pub trait Config:40 frame_system::Config + pallet_evm_coder_substrate::Config + pallet_evm::account::Config41 {42 /// Overarching event type.43 type Event: IsType<<Self as frame_system::Config>::Event> + From<Event<Self>>;4445 /// Address, under which magic contract will be available46 type ContractAddress: Get<H160>;4748 /// In case of enabled sponsoring, but no sponsoring rate limit set,49 /// this value will be used implicitly50 type DefaultSponsoringRateLimit: Get<Self::BlockNumber>;51 }5253 #[pallet::error]54 pub enum Error<T> {55 /// This method is only executable by contract owner56 NoPermission,5758 /// No pending sponsor for contract.59 NoPendingSponsor,60 }6162 #[pallet::pallet]63 #[pallet::generate_store(pub(super) trait Store)]64 pub struct Pallet<T>(_);6566 /// Store owner for contract.67 ///68 /// * **Key** - contract address.69 /// * **Value** - owner for contract.70 #[pallet::storage]71 pub(super) type Owner<T: Config> =72 StorageMap<Hasher = Twox128, Key = H160, Value = H160, QueryKind = ValueQuery>;7374 #[pallet::storage]75 #[deprecated]76 pub(super) type SelfSponsoring<T: Config> =77 StorageMap<Hasher = Twox128, Key = H160, Value = bool, QueryKind = ValueQuery>;7879 /// Store for contract sponsorship state.80 ///81 /// * **Key** - contract address.82 /// * **Value** - sponsorship state.83 #[pallet::storage]84 pub type Sponsoring<T: Config> = StorageMap<85 Hasher = Twox64Concat,86 Key = H160,87 Value = SponsorshipState<T::CrossAccountId>,88 QueryKind = ValueQuery,89 >;9091 /// Store for sponsoring mode.92 ///93 /// ### Usage94 /// Prefer to delete collection from storage if mode chaged to [`Disabled`](SponsoringModeT::Disabled).95 ///96 /// * **Key** - contract address.97 /// * **Value** - [`sponsoring mode`](SponsoringModeT).98 #[pallet::storage]99 pub(super) type SponsoringMode<T: Config> =100 StorageMap<Hasher = Twox128, Key = H160, Value = SponsoringModeT, QueryKind = OptionQuery>;101102 /// Storage for sponsoring rate limit in blocks.103 ///104 /// * **Key** - contract address.105 /// * **Value** - amount of sponsored blocks.106 #[pallet::storage]107 pub(super) type SponsoringRateLimit<T: Config> = StorageMap<108 Hasher = Twox128,109 Key = H160,110 Value = T::BlockNumber,111 QueryKind = ValueQuery,112 OnEmpty = T::DefaultSponsoringRateLimit,113 >;114115 /// Storage for last sponsored block.116 ///117 /// * **Key1** - contract address.118 /// * **Key2** - sponsored user address.119 /// * **Value** - last sponsored block number.120 #[pallet::storage]121 pub(super) type SponsorBasket<T: Config> = StorageDoubleMap<122 Hasher1 = Twox128,123 Key1 = H160,124 Hasher2 = Twox128,125 Key2 = H160,126 Value = T::BlockNumber,127 QueryKind = OptionQuery,128 >;129130 /// Storege for contracts with [`Allowlisted`](SponsoringModeT::Allowlisted) sponsoring mode.131 ///132 /// ### Usage133 /// Prefer to delete collection from storage if mode chaged to non `Allowlisted`, than set **Value** to **false**.134 ///135 /// * **Key** - contract address.136 /// * **Value** - is contract in [`Allowlisted`](SponsoringModeT::Allowlisted) mode.137 #[pallet::storage]138 pub(super) type AllowlistEnabled<T: Config> =139 StorageMap<Hasher = Twox128, Key = H160, Value = bool, QueryKind = ValueQuery>;140141 /// Storage for users that allowed for sponsorship.142 ///143 /// ### Usage144 /// Prefer to delete record from storage if user no more allowed for sponsorship.145 ///146 /// * **Key1** - contract address.147 /// * **Key2** - user that allowed for sponsorship.148 /// * **Value** - allowance for sponsorship.149 #[pallet::storage]150 pub(super) type Allowlist<T: Config> = StorageDoubleMap<151 Hasher1 = Twox128,152 Key1 = H160,153 Hasher2 = Twox128,154 Key2 = H160,155 Value = bool,156 QueryKind = ValueQuery,157 >;158159 #[pallet::event]160 #[pallet::generate_deposit(pub fn deposit_event)]161 pub enum Event<T: Config> {162 /// Contract sponsor was set.163 ContractSponsorSet(164 /// Contract address of the affected collection.165 H160,166 /// New sponsor address.167 T::AccountId,168 ),169170 /// New sponsor was confirm.171 ContractSponsorshipConfirmed(172 /// Contract address of the affected collection.173 H160,174 /// New sponsor address.175 T::AccountId,176 ),177178 /// Collection sponsor was removed.179 ContractSponsorRemoved(180 /// Contract address of the affected collection.181 H160,182 ),183 }184185 impl<T: Config> Pallet<T> {186 /// Get contract owner.187 pub fn contract_owner(contract: H160) -> H160 {188 <Owner<T>>::get(contract)189 }190191 /// Set `sponsor` for `contract`.192 ///193 /// `sender` must be owner of contract.194 pub fn set_sponsor(195 sender: &T::CrossAccountId,196 contract: H160,197 sponsor: &T::CrossAccountId,198 ) -> DispatchResult {199 Pallet::<T>::ensure_owner(contract, *sender.as_eth())?;200 Sponsoring::<T>::insert(201 contract,202 SponsorshipState::<T::CrossAccountId>::Unconfirmed(sponsor.clone()),203 );204205 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorSet(206 contract,207 sponsor.as_sub().clone(),208 ));209 <PalletEvm<T>>::deposit_log(210 ContractHelpersEvents::ContractSponsorSet {211 contract,212 sponsor: *sponsor.as_eth(),213 }214 .to_log(contract),215 );216 Ok(())217 }218219 /// Set sponsor as already confirmed.220 ///221 /// `sender` must be owner of contract.222 pub fn force_set_sponsor(sender: &T::CrossAccountId, contract: H160) -> DispatchResult {223 Pallet::<T>::ensure_owner(contract, *sender.as_eth())?;224 Sponsoring::<T>::insert(225 contract,226 SponsorshipState::<T::CrossAccountId>::Confirmed(T::CrossAccountId::from_eth(227 contract,228 )),229 );230 Ok(())231 }232233 /// Remove sponsor for `contract`.234 ///235 /// `sender` must be owner of contract.236 pub fn remove_sponsor(sender: &T::CrossAccountId, contract: H160) -> DispatchResult {237 Pallet::<T>::ensure_owner(contract, *sender.as_eth())?;238 Sponsoring::<T>::remove(contract);239240 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorRemoved(contract));241 <PalletEvm<T>>::deposit_log(242 ContractHelpersEvents::ContractSponsorRemoved { contract }.to_log(contract),243 );244245 Ok(())246 }247248 /// Confirm sponsorship.249 ///250 /// `sender` must be same that set via [`set_sponsor`].251 pub fn confirm_sponsorship(sender: &T::CrossAccountId, contract: H160) -> DispatchResult {252 match Sponsoring::<T>::get(contract) {253 SponsorshipState::Unconfirmed(sponsor) => {254 ensure!(sponsor == *sender, Error::<T>::NoPermission);255 let eth_sponsor = *sponsor.as_eth();256 let sub_sponsor = sponsor.as_sub().clone();257 Sponsoring::<T>::insert(258 contract,259 SponsorshipState::<T::CrossAccountId>::Confirmed(sponsor),260 );261262 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorshipConfirmed(263 contract,264 sub_sponsor,265 ));266 <PalletEvm<T>>::deposit_log(267 ContractHelpersEvents::ContractSponsorshipConfirmed {268 contract,269 sponsor: eth_sponsor,270 }271 .to_log(contract),272 );273274 Ok(())275 }276 SponsorshipState::Disabled | SponsorshipState::Confirmed(_) => {277 Err(Error::<T>::NoPendingSponsor.into())278 }279 }280 }281282 /// Get sponsor.283 pub fn get_sponsor(contract: H160) -> Option<T::CrossAccountId> {284 match Sponsoring::<T>::get(contract) {285 SponsorshipState::Disabled | SponsorshipState::Unconfirmed(_) => None,286 SponsorshipState::Confirmed(sponsor) => Some(sponsor),287 }288 }289290 /// Get current sponsoring mode, performing lazy migration from legacy storage291 pub fn sponsoring_mode(contract: H160) -> SponsoringModeT {292 <SponsoringMode<T>>::get(contract)293 .or_else(|| {294 <SelfSponsoring<T>>::get(contract).then(|| SponsoringModeT::Allowlisted)295 })296 .unwrap_or_default()297 }298299 /// Reconfigure contract sponsoring mode300 pub fn set_sponsoring_mode(contract: H160, mode: SponsoringModeT) {301 if mode == SponsoringModeT::Disabled {302 <SponsoringMode<T>>::remove(contract);303 } else {304 <SponsoringMode<T>>::insert(contract, mode);305 }306 <SelfSponsoring<T>>::remove(contract)307 }308309 /// Set duration between two sponsored contract calls310 pub fn set_sponsoring_rate_limit(contract: H160, rate_limit: T::BlockNumber) {311 <SponsoringRateLimit<T>>::insert(contract, rate_limit);312 }313314 /// Is user added to allowlist, or he is owner of specified contract315 pub fn allowed(contract: H160, user: H160) -> bool {316 <Allowlist<T>>::get(&contract, &user) || <Owner<T>>::get(&contract) == user317 }318319 /// Toggle contract allowlist access320 pub fn toggle_allowlist(contract: H160, enabled: bool) {321 <AllowlistEnabled<T>>::insert(contract, enabled)322 }323324 /// Toggle user presence in contract's allowlist325 pub fn toggle_allowed(contract: H160, user: H160, allowed: bool) {326 <Allowlist<T>>::insert(contract, user, allowed);327 }328329 /// Throw error if user is not allowed to reconfigure target contract330 pub fn ensure_owner(contract: H160, user: H160) -> DispatchResult {331 ensure!(<Owner<T>>::get(&contract) == user, Error::<T>::NoPermission);332 Ok(())333 }334 }335}336337/// Available contract sponsoring modes338#[derive(Encode, Decode, PartialEq, TypeInfo, MaxEncodedLen, Default)]339pub enum SponsoringModeT {340 /// Sponsoring is disabled341 #[default]342 Disabled,343 /// Only users from allowlist will be sponsored344 Allowlisted,345 /// All users will be sponsored346 Generous,347}348349impl SponsoringModeT {350 fn from_eth(v: u8) -> Option<Self> {351 Some(match v {352 0 => Self::Disabled,353 1 => Self::Allowlisted,354 2 => Self::Generous,355 _ => return None,356 })357 }358 fn to_eth(self) -> u8 {359 match self {360 SponsoringModeT::Disabled => 0,361 SponsoringModeT::Allowlisted => 1,362 SponsoringModeT::Generous => 2,363 }364 }365}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#![doc = include_str!("../README.md")]18#![cfg_attr(not(feature = "std"), no_std)]19#![warn(missing_docs)]2021use codec::{Decode, Encode, MaxEncodedLen};22pub use pallet::*;23pub use eth::*;24use scale_info::TypeInfo;25pub mod eth;2627#[frame_support::pallet]28pub mod pallet {29 pub use super::*;30 use crate::eth::ContractHelpersEvents;31 use frame_support::pallet_prelude::*;32 use pallet_evm_coder_substrate::DispatchResult;33 use sp_core::H160;34 use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};35 use up_data_structs::SponsorshipState;36 use evm_coder::ToLog;3738 #[pallet::config]39 pub trait Config:40 frame_system::Config + pallet_evm_coder_substrate::Config + pallet_evm::account::Config41 {42 /// Overarching event type.43 type Event: IsType<<Self as frame_system::Config>::Event> + From<Event<Self>>;4445 /// Address, under which magic contract will be available46 type ContractAddress: Get<H160>;4748 /// In case of enabled sponsoring, but no sponsoring rate limit set,49 /// this value will be used implicitly50 type DefaultSponsoringRateLimit: Get<Self::BlockNumber>;51 }5253 #[pallet::error]54 pub enum Error<T> {55 /// This method is only executable by contract owner56 NoPermission,5758 /// No pending sponsor for contract.59 NoPendingSponsor,60 }6162 #[pallet::pallet]63 #[pallet::generate_store(pub(super) trait Store)]64 pub struct Pallet<T>(_);6566 /// Store owner for contract.67 ///68 /// * **Key** - contract address.69 /// * **Value** - owner for contract.70 #[pallet::storage]71 pub(super) type Owner<T: Config> =72 StorageMap<Hasher = Twox128, Key = H160, Value = H160, QueryKind = ValueQuery>;7374 #[pallet::storage]75 #[deprecated]76 pub(super) type SelfSponsoring<T: Config> =77 StorageMap<Hasher = Twox128, Key = H160, Value = bool, QueryKind = ValueQuery>;7879 /// Store for contract sponsorship state.80 ///81 /// * **Key** - contract address.82 /// * **Value** - sponsorship state.83 #[pallet::storage]84 pub type Sponsoring<T: Config> = StorageMap<85 Hasher = Twox64Concat,86 Key = H160,87 Value = SponsorshipState<T::CrossAccountId>,88 QueryKind = ValueQuery,89 >;9091 /// Store for sponsoring mode.92 ///93 /// ### Usage94 /// Prefer to delete collection from storage if mode chaged to [`Disabled`](SponsoringModeT::Disabled).95 ///96 /// * **Key** - contract address.97 /// * **Value** - [`sponsoring mode`](SponsoringModeT).98 #[pallet::storage]99 pub(super) type SponsoringMode<T: Config> =100 StorageMap<Hasher = Twox128, Key = H160, Value = SponsoringModeT, QueryKind = OptionQuery>;101102 /// Storage for sponsoring rate limit in blocks.103 ///104 /// * **Key** - contract address.105 /// * **Value** - amount of sponsored blocks.106 #[pallet::storage]107 pub(super) type SponsoringRateLimit<T: Config> = StorageMap<108 Hasher = Twox128,109 Key = H160,110 Value = T::BlockNumber,111 QueryKind = ValueQuery,112 OnEmpty = T::DefaultSponsoringRateLimit,113 >;114115 /// Storage for last sponsored block.116 ///117 /// * **Key1** - contract address.118 /// * **Key2** - sponsored user address.119 /// * **Value** - last sponsored block number.120 #[pallet::storage]121 pub(super) type SponsorBasket<T: Config> = StorageDoubleMap<122 Hasher1 = Twox128,123 Key1 = H160,124 Hasher2 = Twox128,125 Key2 = H160,126 Value = T::BlockNumber,127 QueryKind = OptionQuery,128 >;129130 /// Storege for contracts with [`Allowlisted`](SponsoringModeT::Allowlisted) sponsoring mode.131 ///132 /// ### Usage133 /// Prefer to delete collection from storage if mode chaged to non `Allowlisted`, than set **Value** to **false**.134 ///135 /// * **Key** - contract address.136 /// * **Value** - is contract in [`Allowlisted`](SponsoringModeT::Allowlisted) mode.137 #[pallet::storage]138 pub(super) type AllowlistEnabled<T: Config> =139 StorageMap<Hasher = Twox128, Key = H160, Value = bool, QueryKind = ValueQuery>;140141 /// Storage for users that allowed for sponsorship.142 ///143 /// ### Usage144 /// Prefer to delete record from storage if user no more allowed for sponsorship.145 ///146 /// * **Key1** - contract address.147 /// * **Key2** - user that allowed for sponsorship.148 /// * **Value** - allowance for sponsorship.149 #[pallet::storage]150 pub(super) type Allowlist<T: Config> = StorageDoubleMap<151 Hasher1 = Twox128,152 Key1 = H160,153 Hasher2 = Twox128,154 Key2 = H160,155 Value = bool,156 QueryKind = ValueQuery,157 >;158159 #[pallet::event]160 #[pallet::generate_deposit(pub fn deposit_event)]161 pub enum Event<T: Config> {162 /// Contract sponsor was set.163 ContractSponsorSet(164 /// Contract address of the affected collection.165 H160,166 /// New sponsor address.167 T::AccountId,168 ),169170 /// New sponsor was confirm.171 ContractSponsorshipConfirmed(172 /// Contract address of the affected collection.173 H160,174 /// New sponsor address.175 T::AccountId,176 ),177178 /// Collection sponsor was removed.179 ContractSponsorRemoved(180 /// Contract address of the affected collection.181 H160,182 ),183 }184185 impl<T: Config> Pallet<T> {186 /// Get contract owner.187 pub fn contract_owner(contract: H160) -> H160 {188 <Owner<T>>::get(contract)189 }190191 /// Set `sponsor` for `contract`.192 ///193 /// `sender` must be owner of contract.194 pub fn set_sponsor(195 sender: &T::CrossAccountId,196 contract: H160,197 sponsor: &T::CrossAccountId,198 ) -> DispatchResult {199 Pallet::<T>::ensure_owner(contract, *sender.as_eth())?;200 Sponsoring::<T>::insert(201 contract,202 SponsorshipState::<T::CrossAccountId>::Unconfirmed(sponsor.clone()),203 );204205 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorSet(206 contract,207 sponsor.as_sub().clone(),208 ));209 <PalletEvm<T>>::deposit_log(210 ContractHelpersEvents::ContractSponsorSet {211 contract,212 sponsor: *sponsor.as_eth(),213 }214 .to_log(contract),215 );216 Ok(())217 }218219 /// Set sponsor as already confirmed.220 ///221 /// `sender` must be owner of contract.222 pub fn force_set_sponsor(223 sender: &T::CrossAccountId,224 contract: H160,225 sponsor: &T::CrossAccountId,226 ) -> DispatchResult {227 Pallet::<T>::ensure_owner(contract, *sender.as_eth())?;228 Sponsoring::<T>::insert(229 contract,230 SponsorshipState::<T::CrossAccountId>::Confirmed(T::CrossAccountId::from_eth(231 contract,232 )),233 );234235 let eth_sponsor = *sponsor.as_eth();236 let sub_sponsor = sponsor.as_sub().clone();237238 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorSet(239 contract,240 sub_sponsor.clone(),241 ));242 <PalletEvm<T>>::deposit_log(243 ContractHelpersEvents::ContractSponsorSet {244 contract,245 sponsor: eth_sponsor,246 }247 .to_log(contract),248 );249250 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorshipConfirmed(251 contract,252 sub_sponsor,253 ));254 <PalletEvm<T>>::deposit_log(255 ContractHelpersEvents::ContractSponsorshipConfirmed {256 contract,257 sponsor: eth_sponsor,258 }259 .to_log(contract),260 );261262 Ok(())263 }264265 /// Remove sponsor for `contract`.266 ///267 /// `sender` must be owner of contract.268 pub fn remove_sponsor(sender: &T::CrossAccountId, contract: H160) -> DispatchResult {269 Pallet::<T>::ensure_owner(contract, *sender.as_eth())?;270 Sponsoring::<T>::remove(contract);271272 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorRemoved(contract));273 <PalletEvm<T>>::deposit_log(274 ContractHelpersEvents::ContractSponsorRemoved { contract }.to_log(contract),275 );276277 Ok(())278 }279280 /// Confirm sponsorship.281 ///282 /// `sender` must be same that set via [`set_sponsor`].283 pub fn confirm_sponsorship(sender: &T::CrossAccountId, contract: H160) -> DispatchResult {284 match Sponsoring::<T>::get(contract) {285 SponsorshipState::Unconfirmed(sponsor) => {286 ensure!(sponsor == *sender, Error::<T>::NoPermission);287 let eth_sponsor = *sponsor.as_eth();288 let sub_sponsor = sponsor.as_sub().clone();289 Sponsoring::<T>::insert(290 contract,291 SponsorshipState::<T::CrossAccountId>::Confirmed(sponsor),292 );293294 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorshipConfirmed(295 contract,296 sub_sponsor,297 ));298 <PalletEvm<T>>::deposit_log(299 ContractHelpersEvents::ContractSponsorshipConfirmed {300 contract,301 sponsor: eth_sponsor,302 }303 .to_log(contract),304 );305306 Ok(())307 }308 SponsorshipState::Disabled | SponsorshipState::Confirmed(_) => {309 Err(Error::<T>::NoPendingSponsor.into())310 }311 }312 }313314 /// Get sponsor.315 pub fn get_sponsor(contract: H160) -> Option<T::CrossAccountId> {316 match Sponsoring::<T>::get(contract) {317 SponsorshipState::Disabled | SponsorshipState::Unconfirmed(_) => None,318 SponsorshipState::Confirmed(sponsor) => Some(sponsor),319 }320 }321322 /// Get current sponsoring mode, performing lazy migration from legacy storage323 pub fn sponsoring_mode(contract: H160) -> SponsoringModeT {324 <SponsoringMode<T>>::get(contract)325 .or_else(|| {326 <SelfSponsoring<T>>::get(contract).then(|| SponsoringModeT::Allowlisted)327 })328 .unwrap_or_default()329 }330331 /// Reconfigure contract sponsoring mode332 pub fn set_sponsoring_mode(contract: H160, mode: SponsoringModeT) {333 if mode == SponsoringModeT::Disabled {334 <SponsoringMode<T>>::remove(contract);335 } else {336 <SponsoringMode<T>>::insert(contract, mode);337 }338 <SelfSponsoring<T>>::remove(contract)339 }340341 /// Set duration between two sponsored contract calls342 pub fn set_sponsoring_rate_limit(contract: H160, rate_limit: T::BlockNumber) {343 <SponsoringRateLimit<T>>::insert(contract, rate_limit);344 }345346 /// Is user added to allowlist, or he is owner of specified contract347 pub fn allowed(contract: H160, user: H160) -> bool {348 <Allowlist<T>>::get(&contract, &user) || <Owner<T>>::get(&contract) == user349 }350351 /// Toggle contract allowlist access352 pub fn toggle_allowlist(contract: H160, enabled: bool) {353 <AllowlistEnabled<T>>::insert(contract, enabled)354 }355356 /// Toggle user presence in contract's allowlist357 pub fn toggle_allowed(contract: H160, user: H160, allowed: bool) {358 <Allowlist<T>>::insert(contract, user, allowed);359 }360361 /// Throw error if user is not allowed to reconfigure target contract362 pub fn ensure_owner(contract: H160, user: H160) -> DispatchResult {363 ensure!(<Owner<T>>::get(&contract) == user, Error::<T>::NoPermission);364 Ok(())365 }366 }367}368369/// Available contract sponsoring modes370#[derive(Encode, Decode, PartialEq, TypeInfo, MaxEncodedLen, Default)]371pub enum SponsoringModeT {372 /// Sponsoring is disabled373 #[default]374 Disabled,375 /// Only users from allowlist will be sponsored376 Allowlisted,377 /// All users will be sponsored378 Generous,379}380381impl SponsoringModeT {382 fn from_eth(v: u8) -> Option<Self> {383 Some(match v {384 0 => Self::Disabled,385 1 => Self::Allowlisted,386 2 => Self::Generous,387 _ => return None,388 })389 }390 fn to_eth(self) -> u8 {391 match self {392 SponsoringModeT::Disabled => 0,393 SponsoringModeT::Allowlisted => 1,394 SponsoringModeT::Generous => 2,395 }396 }397}