difftreelog
add contracts consts
in: master
7 files changed
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -376,6 +376,7 @@
type TreasuryAccountId: Get<Self::AccountId>;
/// Address under which the CollectionHelper contract would be available.
+ #[pallet::constant]
type ContractAddress: Get<H160>;
/// Mapper for token addresses to Ethereum addresses.
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;25use frame_support::storage::bounded_btree_map::BoundedBTreeMap;26pub mod eth;2728/// Maximum number of methods per contract that could have fee limit29pub const MAX_FEE_LIMITED_METHODS: u32 = 5;3031#[frame_support::pallet]32pub mod pallet {33 pub use super::*;34 use crate::eth::ContractHelpersEvents;35 use frame_support::pallet_prelude::*;36 use pallet_evm_coder_substrate::DispatchResult;37 use sp_core::{H160, U256};38 use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};39 use up_data_structs::SponsorshipState;40 use evm_coder::ToLog;4142 #[pallet::config]43 pub trait Config:44 frame_system::Config + pallet_evm_coder_substrate::Config + pallet_evm::Config45 {46 /// Overarching event type.47 type RuntimeEvent: IsType<<Self as frame_system::Config>::RuntimeEvent> + From<Event<Self>>;4849 /// Address, under which magic contract will be available50 type ContractAddress: Get<H160>;5152 /// In case of enabled sponsoring, but no sponsoring rate limit set,53 /// this value will be used implicitly54 type DefaultSponsoringRateLimit: Get<Self::BlockNumber>;55 }5657 #[pallet::error]58 pub enum Error<T> {59 /// This method is only executable by contract owner60 NoPermission,6162 /// No pending sponsor for contract.63 NoPendingSponsor,6465 /// Number of methods that sponsored limit is defined for exceeds maximum.66 TooManyMethodsHaveSponsoredLimit,67 }6869 #[pallet::pallet]70 #[pallet::generate_store(pub(super) trait Store)]71 pub struct Pallet<T>(_);7273 /// Store owner for contract.74 ///75 /// * **Key** - contract address.76 /// * **Value** - owner for contract.77 #[pallet::storage]78 pub(super) type Owner<T: Config> =79 StorageMap<Hasher = Twox128, Key = H160, Value = H160, QueryKind = ValueQuery>;8081 #[pallet::storage]82 #[deprecated]83 pub(super) type SelfSponsoring<T: Config> =84 StorageMap<Hasher = Twox128, Key = H160, Value = bool, QueryKind = ValueQuery>;8586 /// Store for contract sponsorship state.87 ///88 /// * **Key** - contract address.89 /// * **Value** - sponsorship state.90 #[pallet::storage]91 pub(super) type Sponsoring<T: Config> = StorageMap<92 Hasher = Twox64Concat,93 Key = H160,94 Value = SponsorshipState<T::CrossAccountId>,95 QueryKind = ValueQuery,96 >;9798 /// Store for sponsoring mode.99 ///100 /// ### Usage101 /// Prefer to delete collection from storage if mode chaged to [`Disabled`](SponsoringModeT::Disabled).102 ///103 /// * **Key** - contract address.104 /// * **Value** - [`sponsoring mode`](SponsoringModeT).105 #[pallet::storage]106 pub(super) type SponsoringMode<T: Config> =107 StorageMap<Hasher = Twox128, Key = H160, Value = SponsoringModeT, QueryKind = OptionQuery>;108109 /// Storage for sponsoring rate limit in blocks.110 ///111 /// * **Key** - contract address.112 /// * **Value** - amount of sponsored blocks.113 #[pallet::storage]114 pub(super) type SponsoringRateLimit<T: Config> = StorageMap<115 Hasher = Twox128,116 Key = H160,117 Value = T::BlockNumber,118 QueryKind = ValueQuery,119 OnEmpty = T::DefaultSponsoringRateLimit,120 >;121122 /// Storage for last sponsored block.123 ///124 /// * **Key1** - contract address.125 /// * **Key2** - sponsored user address.126 /// * **Value** - last sponsored block number.127 #[pallet::storage]128 pub(super) type SponsoringFeeLimit<T: Config> = StorageMap<129 Hasher = Twox128,130 Key = H160,131 Value = BoundedBTreeMap<u32, U256, ConstU32<MAX_FEE_LIMITED_METHODS>>,132 QueryKind = ValueQuery,133 >;134135 #[pallet::storage]136 pub(super) type SponsorBasket<T: Config> = StorageDoubleMap<137 Hasher1 = Twox128,138 Key1 = H160,139 Hasher2 = Twox128,140 Key2 = H160,141 Value = T::BlockNumber,142 QueryKind = OptionQuery,143 >;144145 /// Storege for contracts with [`Allowlisted`](SponsoringModeT::Allowlisted) sponsoring mode.146 ///147 /// ### Usage148 /// Prefer to delete collection from storage if mode chaged to non `Allowlisted`, than set **Value** to **false**.149 ///150 /// * **Key** - contract address.151 /// * **Value** - is contract in [`Allowlisted`](SponsoringModeT::Allowlisted) mode.152 #[pallet::storage]153 pub(super) type AllowlistEnabled<T: Config> =154 StorageMap<Hasher = Twox128, Key = H160, Value = bool, QueryKind = ValueQuery>;155156 /// Storage for users that allowed for sponsorship.157 ///158 /// ### Usage159 /// Prefer to delete record from storage if user no more allowed for sponsorship.160 ///161 /// * **Key1** - contract address.162 /// * **Key2** - user that allowed for sponsorship.163 /// * **Value** - allowance for sponsorship.164 #[pallet::storage]165 pub(super) type Allowlist<T: Config> = StorageDoubleMap<166 Hasher1 = Twox128,167 Key1 = H160,168 Hasher2 = Twox128,169 Key2 = H160,170 Value = bool,171 QueryKind = ValueQuery,172 >;173174 #[pallet::event]175 #[pallet::generate_deposit(fn deposit_event)]176 pub enum Event<T: Config> {177 /// Contract sponsor was set.178 ContractSponsorSet(179 /// Contract address of the affected collection.180 H160,181 /// New sponsor address.182 T::AccountId,183 ),184185 /// New sponsor was confirm.186 ContractSponsorshipConfirmed(187 /// Contract address of the affected collection.188 H160,189 /// New sponsor address.190 T::AccountId,191 ),192193 /// Collection sponsor was removed.194 ContractSponsorRemoved(195 /// Contract address of the affected collection.196 H160,197 ),198 }199200 impl<T: Config> Pallet<T> {201 /// Get contract owner.202 pub fn contract_owner(contract: H160) -> H160 {203 <Owner<T>>::get(contract)204 }205206 /// Set `sponsor` for `contract`.207 ///208 /// `sender` must be owner of contract.209 pub fn set_sponsor(210 sender: &T::CrossAccountId,211 contract: H160,212 sponsor: &T::CrossAccountId,213 ) -> DispatchResult {214 Pallet::<T>::ensure_owner(contract, *sender.as_eth())?;215 Sponsoring::<T>::insert(216 contract,217 SponsorshipState::<T::CrossAccountId>::Unconfirmed(sponsor.clone()),218 );219220 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorSet(221 contract,222 sponsor.as_sub().clone(),223 ));224 <PalletEvm<T>>::deposit_log(225 ContractHelpersEvents::ContractSponsorSet {226 contract_address: contract,227 sponsor: *sponsor.as_eth(),228 }229 .to_log(contract),230 );231 Ok(())232 }233234 /// Force set `sponsor` for `contract`.235 ///236 /// Differs from `set_sponsor` in that confirmation237 /// from the sponsor is not required.238 pub fn force_set_sponsor(239 contract_address: H160,240 sponsor: &T::CrossAccountId,241 ) -> DispatchResult {242 Sponsoring::<T>::insert(243 contract_address,244 SponsorshipState::<T::CrossAccountId>::Confirmed(sponsor.clone()),245 );246247 let eth_sponsor = *sponsor.as_eth();248 let sub_sponsor = sponsor.as_sub().clone();249250 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorSet(251 contract_address,252 sub_sponsor.clone(),253 ));254 <PalletEvm<T>>::deposit_log(255 ContractHelpersEvents::ContractSponsorSet {256 contract_address,257 sponsor: eth_sponsor,258 }259 .to_log(contract_address),260 );261262 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorshipConfirmed(263 contract_address,264 sub_sponsor,265 ));266 <PalletEvm<T>>::deposit_log(267 ContractHelpersEvents::ContractSponsorshipConfirmed {268 contract_address,269 sponsor: eth_sponsor,270 }271 .to_log(contract_address),272 );273274 Ok(())275 }276277 /// Remove sponsor for `contract`.278 ///279 /// `sender` must be owner of contract.280 pub fn remove_sponsor(281 sender: &T::CrossAccountId,282 contract_address: H160,283 ) -> DispatchResult {284 Self::ensure_owner(contract_address, *sender.as_eth())?;285 Self::force_remove_sponsor(contract_address)286 }287288 /// Force remove `sponsor` for `contract`.289 ///290 /// Differs from `remove_sponsor` in that291 /// it doesn't require consent from the `owner` of the contract.292 pub fn force_remove_sponsor(contract_address: H160) -> DispatchResult {293 Sponsoring::<T>::remove(contract_address);294295 Self::deposit_event(Event::<T>::ContractSponsorRemoved(contract_address));296 <PalletEvm<T>>::deposit_log(297 ContractHelpersEvents::ContractSponsorRemoved { contract_address }298 .to_log(contract_address),299 );300301 Ok(())302 }303304 /// Confirm sponsorship.305 ///306 /// `sender` must be same that set via [`set_sponsor`].307 pub fn confirm_sponsorship(308 sender: &T::CrossAccountId,309 contract_address: H160,310 ) -> DispatchResult {311 match Sponsoring::<T>::get(contract_address) {312 SponsorshipState::Unconfirmed(sponsor) => {313 ensure!(sponsor == *sender, Error::<T>::NoPermission);314 let eth_sponsor = *sponsor.as_eth();315 let sub_sponsor = sponsor.as_sub().clone();316 Sponsoring::<T>::insert(317 contract_address,318 SponsorshipState::<T::CrossAccountId>::Confirmed(sponsor),319 );320321 <Pallet<T>>::deposit_event(Event::<T>::ContractSponsorshipConfirmed(322 contract_address,323 sub_sponsor,324 ));325 <PalletEvm<T>>::deposit_log(326 ContractHelpersEvents::ContractSponsorshipConfirmed {327 contract_address,328 sponsor: eth_sponsor,329 }330 .to_log(contract_address),331 );332333 Ok(())334 }335 SponsorshipState::Disabled | SponsorshipState::Confirmed(_) => {336 Err(Error::<T>::NoPendingSponsor.into())337 }338 }339 }340341 /// Get sponsor.342 pub fn get_sponsor(contract: H160) -> Option<T::CrossAccountId> {343 match Sponsoring::<T>::get(contract) {344 SponsorshipState::Disabled | SponsorshipState::Unconfirmed(_) => None,345 SponsorshipState::Confirmed(sponsor) => Some(sponsor),346 }347 }348349 /// Get current sponsoring mode, performing lazy migration from legacy storage350 pub fn sponsoring_mode(contract: H160) -> SponsoringModeT {351 <SponsoringMode<T>>::get(contract)352 .or_else(|| {353 #[allow(deprecated)]354 <SelfSponsoring<T>>::get(contract).then(|| SponsoringModeT::Allowlisted)355 })356 .unwrap_or_default()357 }358359 /// Reconfigure contract sponsoring mode360 pub fn set_sponsoring_mode(contract: H160, mode: SponsoringModeT) {361 if mode == SponsoringModeT::Disabled {362 <SponsoringMode<T>>::remove(contract);363 } else {364 <SponsoringMode<T>>::insert(contract, mode);365 }366 #[allow(deprecated)]367 <SelfSponsoring<T>>::remove(contract)368 }369370 /// Set duration between two sponsored contract calls371 pub fn set_sponsoring_rate_limit(contract: H160, rate_limit: T::BlockNumber) {372 <SponsoringRateLimit<T>>::insert(contract, rate_limit);373 }374375 /// Set maximum for gas limit of transaction376 pub fn set_sponsoring_fee_limit(contract: H160, fee_limit: U256) -> DispatchResult {377 <SponsoringFeeLimit<T>>::try_mutate(contract, |limits_map| {378 limits_map379 .try_insert(0xffffffff, fee_limit)380 .map_err(|_| <Error<T>>::TooManyMethodsHaveSponsoredLimit)381 })?;382 Ok(())383 }384385 /// Is user added to allowlist, or he is owner of specified contract386 pub fn allowed(contract: H160, user: H160) -> bool {387 <Allowlist<T>>::get(&contract, &user) || <Owner<T>>::get(&contract) == user388 }389390 /// Toggle contract allowlist access391 pub fn toggle_allowlist(contract: H160, enabled: bool) {392 <AllowlistEnabled<T>>::insert(contract, enabled)393 }394395 /// Toggle user presence in contract's allowlist396 pub fn toggle_allowed(contract: H160, user: H160, allowed: bool) {397 <Allowlist<T>>::insert(contract, user, allowed);398 }399400 /// Throw error if user is not allowed to reconfigure target contract401 pub fn ensure_owner(contract: H160, user: H160) -> DispatchResult {402 ensure!(<Owner<T>>::get(&contract) == user, Error::<T>::NoPermission);403 Ok(())404 }405 }406}407408/// Available contract sponsoring modes409#[derive(Encode, Decode, PartialEq, TypeInfo, MaxEncodedLen, Default)]410pub enum SponsoringModeT {411 /// Sponsoring is disabled412 #[default]413 Disabled,414 /// Only users from allowlist will be sponsored415 Allowlisted,416 /// All users will be sponsored417 Generous,418}419420impl SponsoringModeT {421 fn from_eth(v: u8) -> Option<Self> {422 Some(match v {423 0 => Self::Disabled,424 1 => Self::Allowlisted,425 2 => Self::Generous,426 _ => return None,427 })428 }429 #[allow(dead_code)]430 fn to_eth(self) -> u8 {431 match self {432 SponsoringModeT::Disabled => 0,433 SponsoringModeT::Allowlisted => 1,434 SponsoringModeT::Generous => 2,435 }436 }437}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;25use frame_support::storage::bounded_btree_map::BoundedBTreeMap;26pub mod eth;2728/// Maximum number of methods per contract that could have fee limit29pub const MAX_FEE_LIMITED_METHODS: u32 = 5;3031#[frame_support::pallet]32pub mod pallet {33 pub use super::*;34 use crate::eth::ContractHelpersEvents;35 use frame_support::pallet_prelude::*;36 use pallet_evm_coder_substrate::DispatchResult;37 use sp_core::{H160, U256};38 use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};39 use up_data_structs::SponsorshipState;40 use evm_coder::ToLog;4142 #[pallet::config]43 pub trait Config:44 frame_system::Config + pallet_evm_coder_substrate::Config + pallet_evm::Config45 {46 /// Overarching event type.47 type RuntimeEvent: IsType<<Self as frame_system::Config>::RuntimeEvent> + From<Event<Self>>;4849 /// Address, under which magic contract will be available50 #[pallet::constant]51 type ContractAddress: Get<H160>;5253 /// In case of enabled sponsoring, but no sponsoring rate limit set,54 /// this value will be used implicitly55 type DefaultSponsoringRateLimit: Get<Self::BlockNumber>;56 }5758 #[pallet::error]59 pub enum Error<T> {60 /// This method is only executable by contract owner61 NoPermission,6263 /// No pending sponsor for contract.64 NoPendingSponsor,6566 /// Number of methods that sponsored limit is defined for exceeds maximum.67 TooManyMethodsHaveSponsoredLimit,68 }6970 #[pallet::pallet]71 #[pallet::generate_store(pub(super) trait Store)]72 pub struct Pallet<T>(_);7374 /// Store owner for contract.75 ///76 /// * **Key** - contract address.77 /// * **Value** - owner for contract.78 #[pallet::storage]79 pub(super) type Owner<T: Config> =80 StorageMap<Hasher = Twox128, Key = H160, Value = H160, QueryKind = ValueQuery>;8182 #[pallet::storage]83 #[deprecated]84 pub(super) 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(Encode, Decode, PartialEq, TypeInfo, MaxEncodedLen, Default)]411pub enum SponsoringModeT {412 /// Sponsoring is disabled413 #[default]414 Disabled,415 /// Only users from allowlist will be sponsored416 Allowlisted,417 /// All users will be sponsored418 Generous,419}420421impl SponsoringModeT {422 fn from_eth(v: u8) -> Option<Self> {423 Some(match v {424 0 => Self::Disabled,425 1 => Self::Allowlisted,426 2 => Self::Generous,427 _ => return None,428 })429 }430 #[allow(dead_code)]431 fn to_eth(self) -> u8 {432 match self {433 SponsoringModeT::Disabled => 0,434 SponsoringModeT::Allowlisted => 1,435 SponsoringModeT::Generous => 2,436 }437 }438}tests/src/apiConsts.test.tsdiffbeforeafterboth--- a/tests/src/apiConsts.test.ts
+++ b/tests/src/apiConsts.test.ts
@@ -15,6 +15,7 @@
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
import {ApiPromise} from '@polkadot/api';
+import {ApiBase} from '@polkadot/api/base';
import {usingPlaygrounds, itSub, expect} from './util';
@@ -41,6 +42,9 @@
transfersEnabled: true,
};
+const EVM_COLLECTION_HELPERS_ADDRESS = '0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f';
+const HELPERS_CONTRACT_ADDRESS = '0x842899ECF380553E8a4de75bF534cdf6fBF64049';
+
describe('integration test: API UNIQUE consts', () => {
let api: ApiPromise;
@@ -101,6 +105,14 @@
itSub('COLLECTION_ADMINS_LIMIT', () => {
checkConst(api.consts.unique.collectionAdminsLimit, COLLECTION_ADMINS_LIMIT);
});
+
+ itSub('HELPERS_CONTRACT_ADDRESS', () => {
+ expect(api.consts.evmContractHelpers.contractAddress.toString().toLowerCase()).to.be.equal(HELPERS_CONTRACT_ADDRESS.toLowerCase());
+ });
+
+ itSub('EVM_COLLECTION_HELPERS_ADDRESS', () => {
+ expect(api.consts.common.contractAddress.toString().toLowerCase()).to.be.equal(EVM_COLLECTION_HELPERS_ADDRESS.toLowerCase());
+ });
});
function checkConst<T>(constValue: any, expectedValue: T) {
tests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth--- a/tests/src/eth/util/playgrounds/unique.dev.ts
+++ b/tests/src/eth/util/playgrounds/unique.dev.ts
@@ -103,12 +103,12 @@
contractHelpers(caller: string): Contract {
const web3 = this.helper.getWeb3();
- return new web3.eth.Contract(contractHelpersAbi as any, '0x842899ECF380553E8a4de75bF534cdf6fBF64049', {from: caller, gas: this.helper.eth.DEFAULT_GAS});
+ return new web3.eth.Contract(contractHelpersAbi as any, this.helper.getApi().consts.evmContractHelpers.contractAddress.toString(), {from: caller, gas: this.helper.eth.DEFAULT_GAS});
}
collectionHelpers(caller: string) {
const web3 = this.helper.getWeb3();
- return new web3.eth.Contract(collectionHelpersAbi as any, '0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f', {from: caller, gas: this.helper.eth.DEFAULT_GAS});
+ return new web3.eth.Contract(collectionHelpersAbi as any, this.helper.getApi().consts.common.contractAddress.toString(), {from: caller, gas: this.helper.eth.DEFAULT_GAS});
}
collection(address: string, mode: TCollectionMode, caller?: string, mergeDeprecated = false): Contract {
tests/src/interfaces/augment-api-consts.tsdiffbeforeafterboth--- a/tests/src/interfaces/augment-api-consts.ts
+++ b/tests/src/interfaces/augment-api-consts.ts
@@ -8,7 +8,7 @@
import type { ApiTypes, AugmentedConst } from '@polkadot/api-base/types';
import type { Option, u128, u16, u32, u64, u8 } from '@polkadot/types-codec';
import type { Codec } from '@polkadot/types-codec/types';
-import type { Perbill, Permill, Weight } from '@polkadot/types/interfaces/runtime';
+import type { H160, Perbill, Permill, Weight } from '@polkadot/types/interfaces/runtime';
import type { FrameSupportPalletId, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, SpVersionRuntimeVersion, SpWeightsRuntimeDbWeight, UpDataStructsCollectionLimits, XcmV1MultiLocation } from '@polkadot/types/lookup';
export type __AugmentedConst<ApiType extends ApiTypes> = AugmentedConst<ApiType>;
@@ -70,6 +70,10 @@
**/
collectionCreationPrice: u128 & AugmentedConst<ApiType>;
/**
+ * Address under which the CollectionHelper contract would be available.
+ **/
+ contractAddress: H160 & AugmentedConst<ApiType>;
+ /**
* Generic const
**/
[key: string]: Codec;
@@ -82,6 +86,16 @@
**/
[key: string]: Codec;
};
+ evmContractHelpers: {
+ /**
+ * Address, under which magic contract will be available
+ **/
+ contractAddress: H160 & AugmentedConst<ApiType>;
+ /**
+ * Generic const
+ **/
+ [key: string]: Codec;
+ };
inflation: {
/**
* Number of blocks that pass between treasury balance updates due to inflation
tests/src/interfaces/lookup.tsdiffbeforeafterboth--- a/tests/src/interfaces/lookup.ts
+++ b/tests/src/interfaces/lookup.ts
@@ -2936,13 +2936,13 @@
}
},
/**
- * Lookup340: pallet_maintenance::pallet::Call<T>
+ * Lookup338: pallet_maintenance::pallet::Call<T>
**/
PalletMaintenanceCall: {
_enum: ['enable', 'disable']
},
/**
- * Lookup341: pallet_test_utils::pallet::Call<T>
+ * Lookup339: pallet_test_utils::pallet::Call<T>
**/
PalletTestUtilsCall: {
_enum: {
tests/src/interfaces/types-lookup.tsdiffbeforeafterboth--- a/tests/src/interfaces/types-lookup.ts
+++ b/tests/src/interfaces/types-lookup.ts
@@ -3175,14 +3175,14 @@
readonly type: 'Begin' | 'SetData' | 'Finish' | 'InsertEthLogs' | 'InsertEvents';
}
- /** @name PalletMaintenanceCall (340) */
+ /** @name PalletMaintenanceCall (338) */
interface PalletMaintenanceCall extends Enum {
readonly isEnable: boolean;
readonly isDisable: boolean;
readonly type: 'Enable' | 'Disable';
}
- /** @name PalletTestUtilsCall (341) */
+ /** @name PalletTestUtilsCall (339) */
interface PalletTestUtilsCall extends Enum {
readonly isEnable: boolean;
readonly isSetTestValue: boolean;