difftreelog
chore add `deprecated` comments
in: master
1 file changed
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};22use evm_coder::AbiCoder;23pub use pallet::*;24pub use eth::*;25use scale_info::TypeInfo;26use frame_support::storage::bounded_btree_map::BoundedBTreeMap;27pub mod eth;2829/// Maximum number of methods per contract that could have fee limit30pub const MAX_FEE_LIMITED_METHODS: u32 = 5;3132#[frame_support::pallet]33pub mod pallet {34 pub use super::*;35 use crate::eth::ContractHelpersEvents;36 use frame_support::pallet_prelude::*;37 use pallet_evm_coder_substrate::DispatchResult;38 use sp_core::{H160, U256};39 use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};40 use up_data_structs::SponsorshipState;41 use evm_coder::ToLog;4243 #[pallet::config]44 pub trait Config:45 frame_system::Config + pallet_evm_coder_substrate::Config + pallet_evm::Config46 {47 /// Overarching event type.48 type RuntimeEvent: IsType<<Self as frame_system::Config>::RuntimeEvent> + From<Event<Self>>;4950 /// Address, under which magic contract will be available51 #[pallet::constant]52 type ContractAddress: Get<H160>;5354 /// In case of enabled sponsoring, but no sponsoring rate limit set,55 /// this value will be used implicitly56 type DefaultSponsoringRateLimit: Get<Self::BlockNumber>;57 }5859 #[pallet::error]60 pub enum Error<T> {61 /// This method is only executable by contract owner62 NoPermission,6364 /// No pending sponsor for contract.65 NoPendingSponsor,6667 /// Number of methods that sponsored limit is defined for exceeds maximum.68 TooManyMethodsHaveSponsoredLimit,69 }7071 #[pallet::pallet]72 #[pallet::generate_store(trait Store)]73 pub struct Pallet<T>(_);7475 /// Store owner for contract.76 ///77 /// * **Key** - contract address.78 /// * **Value** - owner for contract.79 #[pallet::storage]80 pub(super) type Owner<T: Config> =81 StorageMap<Hasher = Twox128, Key = H160, Value = H160, QueryKind = ValueQuery>;8283 #[pallet::storage]84 type SelfSponsoring<T: Config> =85 StorageMap<Hasher = Twox128, Key = H160, Value = bool, QueryKind = ValueQuery>;8687 /// Store for contract sponsorship state.88 ///89 /// * **Key** - contract address.90 /// * **Value** - sponsorship state.91 #[pallet::storage]92 pub(super) type Sponsoring<T: Config> = StorageMap<93 Hasher = Twox64Concat,94 Key = H160,95 Value = SponsorshipState<T::CrossAccountId>,96 QueryKind = ValueQuery,97 >;9899 /// Store for sponsoring mode.100 ///101 /// ### Usage102 /// Prefer to delete collection from storage if mode chaged to [`Disabled`](SponsoringModeT::Disabled).103 ///104 /// * **Key** - contract address.105 /// * **Value** - [`sponsoring mode`](SponsoringModeT).106 #[pallet::storage]107 pub(super) type SponsoringMode<T: Config> =108 StorageMap<Hasher = Twox128, Key = H160, Value = SponsoringModeT, QueryKind = OptionQuery>;109110 /// Storage for sponsoring rate limit in blocks.111 ///112 /// * **Key** - contract address.113 /// * **Value** - amount of sponsored blocks.114 #[pallet::storage]115 pub(super) type SponsoringRateLimit<T: Config> = StorageMap<116 Hasher = Twox128,117 Key = H160,118 Value = T::BlockNumber,119 QueryKind = ValueQuery,120 OnEmpty = T::DefaultSponsoringRateLimit,121 >;122123 /// Storage for last sponsored block.124 ///125 /// * **Key1** - contract address.126 /// * **Key2** - sponsored user address.127 /// * **Value** - last sponsored block number.128 #[pallet::storage]129 pub(super) type SponsoringFeeLimit<T: Config> = StorageMap<130 Hasher = Twox128,131 Key = H160,132 Value = BoundedBTreeMap<u32, U256, ConstU32<MAX_FEE_LIMITED_METHODS>>,133 QueryKind = ValueQuery,134 >;135136 #[pallet::storage]137 pub(super) type SponsorBasket<T: Config> = StorageDoubleMap<138 Hasher1 = Twox128,139 Key1 = H160,140 Hasher2 = Twox128,141 Key2 = H160,142 Value = T::BlockNumber,143 QueryKind = OptionQuery,144 >;145146 /// Storege for contracts with [`Allowlisted`](SponsoringModeT::Allowlisted) sponsoring mode.147 ///148 /// ### Usage149 /// Prefer to delete collection from storage if mode chaged to non `Allowlisted`, than set **Value** to **false**.150 ///151 /// * **Key** - contract address.152 /// * **Value** - is contract in [`Allowlisted`](SponsoringModeT::Allowlisted) mode.153 #[pallet::storage]154 pub(super) type AllowlistEnabled<T: Config> =155 StorageMap<Hasher = Twox128, Key = H160, Value = bool, QueryKind = ValueQuery>;156157 /// Storage for users that allowed for sponsorship.158 ///159 /// ### Usage160 /// Prefer to delete record from storage if user no more allowed for sponsorship.161 ///162 /// * **Key1** - contract address.163 /// * **Key2** - user that allowed for sponsorship.164 /// * **Value** - allowance for sponsorship.165 #[pallet::storage]166 pub(super) type Allowlist<T: Config> = StorageDoubleMap<167 Hasher1 = Twox128,168 Key1 = H160,169 Hasher2 = Twox128,170 Key2 = H160,171 Value = bool,172 QueryKind = ValueQuery,173 >;174175 #[pallet::event]176 #[pallet::generate_deposit(fn deposit_event)]177 pub enum Event<T: Config> {178 /// Contract sponsor was set.179 ContractSponsorSet(180 /// Contract address of the affected collection.181 H160,182 /// New sponsor address.183 T::AccountId,184 ),185186 /// New sponsor was confirm.187 ContractSponsorshipConfirmed(188 /// Contract address of the affected collection.189 H160,190 /// New sponsor address.191 T::AccountId,192 ),193194 /// Collection sponsor was removed.195 ContractSponsorRemoved(196 /// Contract address of the affected collection.197 H160,198 ),199 }200201 impl<T: Config> Pallet<T> {202 /// Get contract owner.203 pub fn contract_owner(contract: H160) -> H160 {204 <Owner<T>>::get(contract)205 }206207 /// Set `sponsor` for `contract`.208 ///209 /// `sender` must be owner of contract.210 pub fn set_sponsor(211 sender: &T::CrossAccountId,212 contract: H160,213 sponsor: &T::CrossAccountId,214 ) -> DispatchResult {215 Pallet::<T>::ensure_owner(contract, *sender.as_eth())?;216 Sponsoring::<T>::insert(217 contract,218 SponsorshipState::<T::CrossAccountId>::Unconfirmed(sponsor.clone()),219 );220221 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorSet(222 contract,223 sponsor.as_sub().clone(),224 ));225 <PalletEvm<T>>::deposit_log(226 ContractHelpersEvents::ContractSponsorSet {227 contract_address: contract,228 sponsor: *sponsor.as_eth(),229 }230 .to_log(contract),231 );232 Ok(())233 }234235 /// Force set `sponsor` for `contract`.236 ///237 /// Differs from `set_sponsor` in that confirmation238 /// from the sponsor is not required.239 pub fn force_set_sponsor(240 contract_address: H160,241 sponsor: &T::CrossAccountId,242 ) -> DispatchResult {243 Sponsoring::<T>::insert(244 contract_address,245 SponsorshipState::<T::CrossAccountId>::Confirmed(sponsor.clone()),246 );247248 let eth_sponsor = *sponsor.as_eth();249 let sub_sponsor = sponsor.as_sub().clone();250251 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorSet(252 contract_address,253 sub_sponsor.clone(),254 ));255 <PalletEvm<T>>::deposit_log(256 ContractHelpersEvents::ContractSponsorSet {257 contract_address,258 sponsor: eth_sponsor,259 }260 .to_log(contract_address),261 );262263 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorshipConfirmed(264 contract_address,265 sub_sponsor,266 ));267 <PalletEvm<T>>::deposit_log(268 ContractHelpersEvents::ContractSponsorshipConfirmed {269 contract_address,270 sponsor: eth_sponsor,271 }272 .to_log(contract_address),273 );274275 Ok(())276 }277278 /// Remove sponsor for `contract`.279 ///280 /// `sender` must be owner of contract.281 pub fn remove_sponsor(282 sender: &T::CrossAccountId,283 contract_address: H160,284 ) -> DispatchResult {285 Self::ensure_owner(contract_address, *sender.as_eth())?;286 Self::force_remove_sponsor(contract_address)287 }288289 /// Force remove `sponsor` for `contract`.290 ///291 /// Differs from `remove_sponsor` in that292 /// it doesn't require consent from the `owner` of the contract.293 pub fn force_remove_sponsor(contract_address: H160) -> DispatchResult {294 Sponsoring::<T>::remove(contract_address);295296 Self::deposit_event(Event::<T>::ContractSponsorRemoved(contract_address));297 <PalletEvm<T>>::deposit_log(298 ContractHelpersEvents::ContractSponsorRemoved { contract_address }299 .to_log(contract_address),300 );301302 Ok(())303 }304305 /// Confirm sponsorship.306 ///307 /// `sender` must be same that set via [`set_sponsor`].308 pub fn confirm_sponsorship(309 sender: &T::CrossAccountId,310 contract_address: H160,311 ) -> DispatchResult {312 match Sponsoring::<T>::get(contract_address) {313 SponsorshipState::Unconfirmed(sponsor) => {314 ensure!(sponsor == *sender, Error::<T>::NoPermission);315 let eth_sponsor = *sponsor.as_eth();316 let sub_sponsor = sponsor.as_sub().clone();317 Sponsoring::<T>::insert(318 contract_address,319 SponsorshipState::<T::CrossAccountId>::Confirmed(sponsor),320 );321322 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorshipConfirmed(323 contract_address,324 sub_sponsor,325 ));326 <PalletEvm<T>>::deposit_log(327 ContractHelpersEvents::ContractSponsorshipConfirmed {328 contract_address,329 sponsor: eth_sponsor,330 }331 .to_log(contract_address),332 );333334 Ok(())335 }336 SponsorshipState::Disabled | SponsorshipState::Confirmed(_) => {337 Err(Error::<T>::NoPendingSponsor.into())338 }339 }340 }341342 /// Get sponsor.343 pub fn get_sponsor(contract: H160) -> Option<T::CrossAccountId> {344 match Sponsoring::<T>::get(contract) {345 SponsorshipState::Disabled | SponsorshipState::Unconfirmed(_) => None,346 SponsorshipState::Confirmed(sponsor) => Some(sponsor),347 }348 }349350 /// Get current sponsoring mode, performing lazy migration from legacy storage351 pub fn sponsoring_mode(contract: H160) -> SponsoringModeT {352 <SponsoringMode<T>>::get(contract)353 .or_else(|| {354 #[allow(deprecated)]355 <SelfSponsoring<T>>::get(contract).then(|| SponsoringModeT::Allowlisted)356 })357 .unwrap_or_default()358 }359360 /// Reconfigure contract sponsoring mode361 pub fn set_sponsoring_mode(contract: H160, mode: SponsoringModeT) {362 if mode == SponsoringModeT::Disabled {363 <SponsoringMode<T>>::remove(contract);364 } else {365 <SponsoringMode<T>>::insert(contract, mode);366 }367 #[allow(deprecated)]368 <SelfSponsoring<T>>::remove(contract)369 }370371 /// Set duration between two sponsored contract calls372 pub fn set_sponsoring_rate_limit(contract: H160, rate_limit: T::BlockNumber) {373 <SponsoringRateLimit<T>>::insert(contract, rate_limit);374 }375376 /// Set maximum for gas limit of transaction377 pub fn set_sponsoring_fee_limit(contract: H160, fee_limit: U256) -> DispatchResult {378 <SponsoringFeeLimit<T>>::try_mutate(contract, |limits_map| {379 limits_map380 .try_insert(0xffffffff, fee_limit)381 .map_err(|_| <Error<T>>::TooManyMethodsHaveSponsoredLimit)382 })?;383 Ok(())384 }385386 /// Is user added to allowlist, or he is owner of specified contract387 pub fn allowed(contract: H160, user: H160) -> bool {388 <Allowlist<T>>::get(&contract, &user) || <Owner<T>>::get(&contract) == user389 }390391 /// Toggle contract allowlist access392 pub fn toggle_allowlist(contract: H160, enabled: bool) {393 <AllowlistEnabled<T>>::insert(contract, enabled)394 }395396 /// Toggle user presence in contract's allowlist397 pub fn toggle_allowed(contract: H160, user: H160, allowed: bool) {398 <Allowlist<T>>::insert(contract, user, allowed);399 }400401 /// Throw error if user is not allowed to reconfigure target contract402 pub fn ensure_owner(contract: H160, user: H160) -> DispatchResult {403 ensure!(<Owner<T>>::get(&contract) == user, Error::<T>::NoPermission);404 Ok(())405 }406 }407}408409/// Available contract sponsoring modes410#[derive(411 Encode, Decode, Debug, PartialEq, TypeInfo, MaxEncodedLen, Default, AbiCoder, Clone, Copy,412)]413#[repr(u8)]414pub enum SponsoringModeT {415 /// Sponsoring is disabled416 #[default]417 Disabled,418 /// Only users from allowlist will be sponsored419 Allowlisted,420 /// All users will be sponsored421 Generous,422}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};22use evm_coder::AbiCoder;23pub use pallet::*;24pub use eth::*;25use scale_info::TypeInfo;26use frame_support::storage::bounded_btree_map::BoundedBTreeMap;27pub mod eth;2829/// Maximum number of methods per contract that could have fee limit30pub const MAX_FEE_LIMITED_METHODS: u32 = 5;3132#[frame_support::pallet]33pub mod pallet {34 pub use super::*;35 use crate::eth::ContractHelpersEvents;36 use frame_support::pallet_prelude::*;37 use pallet_evm_coder_substrate::DispatchResult;38 use sp_core::{H160, U256};39 use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};40 use up_data_structs::SponsorshipState;41 use evm_coder::ToLog;4243 #[pallet::config]44 pub trait Config:45 frame_system::Config + pallet_evm_coder_substrate::Config + pallet_evm::Config46 {47 /// Overarching event type.48 type RuntimeEvent: IsType<<Self as frame_system::Config>::RuntimeEvent> + From<Event<Self>>;4950 /// Address, under which magic contract will be available51 #[pallet::constant]52 type ContractAddress: Get<H160>;5354 /// In case of enabled sponsoring, but no sponsoring rate limit set,55 /// this value will be used implicitly56 type DefaultSponsoringRateLimit: Get<Self::BlockNumber>;57 }5859 #[pallet::error]60 pub enum Error<T> {61 /// This method is only executable by contract owner62 NoPermission,6364 /// No pending sponsor for contract.65 NoPendingSponsor,6667 /// Number of methods that sponsored limit is defined for exceeds maximum.68 TooManyMethodsHaveSponsoredLimit,69 }7071 #[pallet::pallet]72 #[pallet::generate_store(trait Store)]73 pub struct Pallet<T>(_);7475 /// Store owner for contract.76 ///77 /// * **Key** - contract address.78 /// * **Value** - owner for contract.79 #[pallet::storage]80 pub(super) type Owner<T: Config> =81 StorageMap<Hasher = Twox128, Key = H160, Value = H160, QueryKind = ValueQuery>;8283 /// Deprecated: this storage is deprecated84 #[pallet::storage]85 type SelfSponsoring<T: Config> =86 StorageMap<Hasher = Twox128, Key = H160, Value = bool, QueryKind = ValueQuery>;8788 /// Store for contract sponsorship state.89 ///90 /// * **Key** - contract address.91 /// * **Value** - sponsorship state.92 #[pallet::storage]93 pub(super) type Sponsoring<T: Config> = StorageMap<94 Hasher = Twox64Concat,95 Key = H160,96 Value = SponsorshipState<T::CrossAccountId>,97 QueryKind = ValueQuery,98 >;99100 /// Store for sponsoring mode.101 ///102 /// ### Usage103 /// Prefer to delete collection from storage if mode chaged to [`Disabled`](SponsoringModeT::Disabled).104 ///105 /// * **Key** - contract address.106 /// * **Value** - [`sponsoring mode`](SponsoringModeT).107 #[pallet::storage]108 pub(super) type SponsoringMode<T: Config> =109 StorageMap<Hasher = Twox128, Key = H160, Value = SponsoringModeT, QueryKind = OptionQuery>;110111 /// Storage for sponsoring rate limit in blocks.112 ///113 /// * **Key** - contract address.114 /// * **Value** - amount of sponsored blocks.115 #[pallet::storage]116 pub(super) type SponsoringRateLimit<T: Config> = StorageMap<117 Hasher = Twox128,118 Key = H160,119 Value = T::BlockNumber,120 QueryKind = ValueQuery,121 OnEmpty = T::DefaultSponsoringRateLimit,122 >;123124 /// Storage for last sponsored block.125 ///126 /// * **Key1** - contract address.127 /// * **Key2** - sponsored user address.128 /// * **Value** - last sponsored block number.129 #[pallet::storage]130 pub(super) type SponsoringFeeLimit<T: Config> = StorageMap<131 Hasher = Twox128,132 Key = H160,133 Value = BoundedBTreeMap<u32, U256, ConstU32<MAX_FEE_LIMITED_METHODS>>,134 QueryKind = ValueQuery,135 >;136137 #[pallet::storage]138 pub(super) type SponsorBasket<T: Config> = StorageDoubleMap<139 Hasher1 = Twox128,140 Key1 = H160,141 Hasher2 = Twox128,142 Key2 = H160,143 Value = T::BlockNumber,144 QueryKind = OptionQuery,145 >;146147 /// Storege for contracts with [`Allowlisted`](SponsoringModeT::Allowlisted) sponsoring mode.148 ///149 /// ### Usage150 /// Prefer to delete collection from storage if mode chaged to non `Allowlisted`, than set **Value** to **false**.151 ///152 /// * **Key** - contract address.153 /// * **Value** - is contract in [`Allowlisted`](SponsoringModeT::Allowlisted) mode.154 #[pallet::storage]155 pub(super) type AllowlistEnabled<T: Config> =156 StorageMap<Hasher = Twox128, Key = H160, Value = bool, QueryKind = ValueQuery>;157158 /// Storage for users that allowed for sponsorship.159 ///160 /// ### Usage161 /// Prefer to delete record from storage if user no more allowed for sponsorship.162 ///163 /// * **Key1** - contract address.164 /// * **Key2** - user that allowed for sponsorship.165 /// * **Value** - allowance for sponsorship.166 #[pallet::storage]167 pub(super) type Allowlist<T: Config> = StorageDoubleMap<168 Hasher1 = Twox128,169 Key1 = H160,170 Hasher2 = Twox128,171 Key2 = H160,172 Value = bool,173 QueryKind = ValueQuery,174 >;175176 #[pallet::event]177 #[pallet::generate_deposit(fn deposit_event)]178 pub enum Event<T: Config> {179 /// Contract sponsor was set.180 ContractSponsorSet(181 /// Contract address of the affected collection.182 H160,183 /// New sponsor address.184 T::AccountId,185 ),186187 /// New sponsor was confirm.188 ContractSponsorshipConfirmed(189 /// Contract address of the affected collection.190 H160,191 /// New sponsor address.192 T::AccountId,193 ),194195 /// Collection sponsor was removed.196 ContractSponsorRemoved(197 /// Contract address of the affected collection.198 H160,199 ),200 }201202 impl<T: Config> Pallet<T> {203 /// Get contract owner.204 pub fn contract_owner(contract: H160) -> H160 {205 <Owner<T>>::get(contract)206 }207208 /// Set `sponsor` for `contract`.209 ///210 /// `sender` must be owner of contract.211 pub fn set_sponsor(212 sender: &T::CrossAccountId,213 contract: H160,214 sponsor: &T::CrossAccountId,215 ) -> DispatchResult {216 Pallet::<T>::ensure_owner(contract, *sender.as_eth())?;217 Sponsoring::<T>::insert(218 contract,219 SponsorshipState::<T::CrossAccountId>::Unconfirmed(sponsor.clone()),220 );221222 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorSet(223 contract,224 sponsor.as_sub().clone(),225 ));226 <PalletEvm<T>>::deposit_log(227 ContractHelpersEvents::ContractSponsorSet {228 contract_address: contract,229 sponsor: *sponsor.as_eth(),230 }231 .to_log(contract),232 );233 Ok(())234 }235236 /// Force set `sponsor` for `contract`.237 ///238 /// Differs from `set_sponsor` in that confirmation239 /// from the sponsor is not required.240 pub fn force_set_sponsor(241 contract_address: H160,242 sponsor: &T::CrossAccountId,243 ) -> DispatchResult {244 Sponsoring::<T>::insert(245 contract_address,246 SponsorshipState::<T::CrossAccountId>::Confirmed(sponsor.clone()),247 );248249 let eth_sponsor = *sponsor.as_eth();250 let sub_sponsor = sponsor.as_sub().clone();251252 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorSet(253 contract_address,254 sub_sponsor.clone(),255 ));256 <PalletEvm<T>>::deposit_log(257 ContractHelpersEvents::ContractSponsorSet {258 contract_address,259 sponsor: eth_sponsor,260 }261 .to_log(contract_address),262 );263264 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorshipConfirmed(265 contract_address,266 sub_sponsor,267 ));268 <PalletEvm<T>>::deposit_log(269 ContractHelpersEvents::ContractSponsorshipConfirmed {270 contract_address,271 sponsor: eth_sponsor,272 }273 .to_log(contract_address),274 );275276 Ok(())277 }278279 /// Remove sponsor for `contract`.280 ///281 /// `sender` must be owner of contract.282 pub fn remove_sponsor(283 sender: &T::CrossAccountId,284 contract_address: H160,285 ) -> DispatchResult {286 Self::ensure_owner(contract_address, *sender.as_eth())?;287 Self::force_remove_sponsor(contract_address)288 }289290 /// Force remove `sponsor` for `contract`.291 ///292 /// Differs from `remove_sponsor` in that293 /// it doesn't require consent from the `owner` of the contract.294 pub fn force_remove_sponsor(contract_address: H160) -> DispatchResult {295 Sponsoring::<T>::remove(contract_address);296297 Self::deposit_event(Event::<T>::ContractSponsorRemoved(contract_address));298 <PalletEvm<T>>::deposit_log(299 ContractHelpersEvents::ContractSponsorRemoved { contract_address }300 .to_log(contract_address),301 );302303 Ok(())304 }305306 /// Confirm sponsorship.307 ///308 /// `sender` must be same that set via [`set_sponsor`].309 pub fn confirm_sponsorship(310 sender: &T::CrossAccountId,311 contract_address: H160,312 ) -> DispatchResult {313 match Sponsoring::<T>::get(contract_address) {314 SponsorshipState::Unconfirmed(sponsor) => {315 ensure!(sponsor == *sender, Error::<T>::NoPermission);316 let eth_sponsor = *sponsor.as_eth();317 let sub_sponsor = sponsor.as_sub().clone();318 Sponsoring::<T>::insert(319 contract_address,320 SponsorshipState::<T::CrossAccountId>::Confirmed(sponsor),321 );322323 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorshipConfirmed(324 contract_address,325 sub_sponsor,326 ));327 <PalletEvm<T>>::deposit_log(328 ContractHelpersEvents::ContractSponsorshipConfirmed {329 contract_address,330 sponsor: eth_sponsor,331 }332 .to_log(contract_address),333 );334335 Ok(())336 }337 SponsorshipState::Disabled | SponsorshipState::Confirmed(_) => {338 Err(Error::<T>::NoPendingSponsor.into())339 }340 }341 }342343 /// Get sponsor.344 pub fn get_sponsor(contract: H160) -> Option<T::CrossAccountId> {345 match Sponsoring::<T>::get(contract) {346 SponsorshipState::Disabled | SponsorshipState::Unconfirmed(_) => None,347 SponsorshipState::Confirmed(sponsor) => Some(sponsor),348 }349 }350351 /// Get current sponsoring mode, performing lazy migration from legacy storage352 /// Deprecated: this method is for deprecated storage353 pub fn sponsoring_mode(contract: H160) -> SponsoringModeT {354 <SponsoringMode<T>>::get(contract)355 .or_else(|| {356 #[allow(deprecated)]357 <SelfSponsoring<T>>::get(contract).then(|| SponsoringModeT::Allowlisted)358 })359 .unwrap_or_default()360 }361362 /// Reconfigure contract sponsoring mode363 /// Deprecated: this method is for deprecated storage364 pub fn set_sponsoring_mode(contract: H160, mode: SponsoringModeT) {365 if mode == SponsoringModeT::Disabled {366 <SponsoringMode<T>>::remove(contract);367 } else {368 <SponsoringMode<T>>::insert(contract, mode);369 }370 #[allow(deprecated)]371 <SelfSponsoring<T>>::remove(contract)372 }373374 /// Set duration between two sponsored contract calls375 pub fn set_sponsoring_rate_limit(contract: H160, rate_limit: T::BlockNumber) {376 <SponsoringRateLimit<T>>::insert(contract, rate_limit);377 }378379 /// Set maximum for gas limit of transaction380 pub fn set_sponsoring_fee_limit(contract: H160, fee_limit: U256) -> DispatchResult {381 <SponsoringFeeLimit<T>>::try_mutate(contract, |limits_map| {382 limits_map383 .try_insert(0xffffffff, fee_limit)384 .map_err(|_| <Error<T>>::TooManyMethodsHaveSponsoredLimit)385 })?;386 Ok(())387 }388389 /// Is user added to allowlist, or he is owner of specified contract390 pub fn allowed(contract: H160, user: H160) -> bool {391 <Allowlist<T>>::get(&contract, &user) || <Owner<T>>::get(&contract) == user392 }393394 /// Toggle contract allowlist access395 pub fn toggle_allowlist(contract: H160, enabled: bool) {396 <AllowlistEnabled<T>>::insert(contract, enabled)397 }398399 /// Toggle user presence in contract's allowlist400 pub fn toggle_allowed(contract: H160, user: H160, allowed: bool) {401 <Allowlist<T>>::insert(contract, user, allowed);402 }403404 /// Throw error if user is not allowed to reconfigure target contract405 pub fn ensure_owner(contract: H160, user: H160) -> DispatchResult {406 ensure!(<Owner<T>>::get(&contract) == user, Error::<T>::NoPermission);407 Ok(())408 }409 }410}411412/// Available contract sponsoring modes413#[derive(414 Encode, Decode, Debug, PartialEq, TypeInfo, MaxEncodedLen, Default, AbiCoder, Clone, Copy,415)]416#[repr(u8)]417pub enum SponsoringModeT {418 /// Sponsoring is disabled419 #[default]420 Disabled,421 /// Only users from allowlist will be sponsored422 Allowlisted,423 /// All users will be sponsored424 Generous,425}