difftreelog
chore move contract address and transaction data to call context
in: master
13 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6360,7 +6360,7 @@
[[package]]
name = "pallet-template-transaction-payment"
version = "3.0.0"
-source = "git+https://github.com/uniquenetwork/pallet-sponsoring?rev=9ee7d6e57e03a2575cbab79431774b56f170018e#9ee7d6e57e03a2575cbab79431774b56f170018e"
+source = "git+https://github.com/uniquenetwork/pallet-sponsoring?branch=polkadot-v0.9.27#853766d6033ceb68a2bef196790b962dd0663a04"
dependencies = [
"frame-benchmarking",
"frame-support",
@@ -12528,7 +12528,7 @@
[[package]]
name = "up-sponsorship"
version = "0.1.0"
-source = "git+https://github.com/uniquenetwork/pallet-sponsoring?rev=9ee7d6e57e03a2575cbab79431774b56f170018e#9ee7d6e57e03a2575cbab79431774b56f170018e"
+source = "git+https://github.com/uniquenetwork/pallet-sponsoring?branch=polkadot-v0.9.27#853766d6033ceb68a2bef196790b962dd0663a04"
dependencies = [
"impl-trait-for-tuples",
]
pallets/evm-contract-helpers/Cargo.tomldiffbeforeafterboth--- a/pallets/evm-contract-helpers/Cargo.toml
+++ b/pallets/evm-contract-helpers/Cargo.toml
@@ -21,7 +21,7 @@
# Unique
pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", rev = "89a37c5a489f426cc7a42d7b94019974093a052d" }
fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", rev = "89a37c5a489f426cc7a42d7b94019974093a052d" }
-up-sponsorship = { version = "0.1.0", default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", rev="9ee7d6e57e03a2575cbab79431774b56f170018e" }
+up-sponsorship = { version = "0.1.0", default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" }
# Locals
evm-coder = { default-features = false, path = '../../crates/evm-coder' }
pallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth--- a/pallets/evm-contract-helpers/src/eth.rs
+++ b/pallets/evm-contract-helpers/src/eth.rs
@@ -379,27 +379,26 @@
/// Bridge to pallet-sponsoring
pub struct HelpersContractSponsoring<T: Config>(PhantomData<*const T>);
-impl<T: Config> SponsorshipHandler<T::CrossAccountId, (H160, Vec<u8>), CallContext>
+impl<T: Config> SponsorshipHandler<T::CrossAccountId, CallContext>
for HelpersContractSponsoring<T>
{
fn get_sponsor(
who: &T::CrossAccountId,
- call: &(H160, Vec<u8>),
call_context: &CallContext,
) -> Option<T::CrossAccountId> {
- let (contract_address, _) = call;
- let mode = <Pallet<T>>::sponsoring_mode(*contract_address);
+ let contract_address = call_context.contract_address;
+ let mode = <Pallet<T>>::sponsoring_mode(contract_address);
if mode == SponsoringModeT::Disabled {
return None;
}
- let sponsor = match <Pallet<T>>::get_sponsor(*contract_address) {
+ let sponsor = match <Pallet<T>>::get_sponsor(contract_address) {
Some(sponsor) => sponsor,
None => return None,
};
if mode == SponsoringModeT::Allowlisted
- && !<Pallet<T>>::allowed(*contract_address, *who.as_eth())
+ && !<Pallet<T>>::allowed(contract_address, *who.as_eth())
{
return None;
}
pallets/evm-transaction-payment/Cargo.tomldiffbeforeafterboth--- a/pallets/evm-transaction-payment/Cargo.toml
+++ b/pallets/evm-transaction-payment/Cargo.toml
@@ -17,7 +17,7 @@
pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", rev = "89a37c5a489f426cc7a42d7b94019974093a052d" }
fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", rev = "89a37c5a489f426cc7a42d7b94019974093a052d" }
pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", rev = "89a37c5a489f426cc7a42d7b94019974093a052d" }
-up-sponsorship = { version = "0.1.0", default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", rev = "9ee7d6e57e03a2575cbab79431774b56f170018e" }
+up-sponsorship = { version = "0.1.0", default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" }
fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", rev = "89a37c5a489f426cc7a42d7b94019974093a052d" }
[dependencies.codec]
pallets/evm-transaction-payment/src/lib.rsdiffbeforeafterboth--- a/pallets/evm-transaction-payment/src/lib.rs
+++ b/pallets/evm-transaction-payment/src/lib.rs
@@ -35,6 +35,10 @@
/// Contains call data
pub struct CallContext {
+ /// Contract address
+ pub contract_address: H160,
+ /// Transaction data
+ pub input: Vec<u8>,
/// Max fee for transaction - gasLimit * gasPrice
pub max_fee: U256,
}
@@ -42,11 +46,7 @@
#[pallet::config]
pub trait Config: frame_system::Config + pallet_evm::account::Config {
/// Loosly-coupled handlers for evm call sponsoring
- type EvmSponsorshipHandler: SponsorshipHandler<
- Self::CrossAccountId,
- (H160, Vec<u8>),
- CallContext,
- >;
+ type EvmSponsorshipHandler: SponsorshipHandler<Self::CrossAccountId, CallContext>;
}
#[pallet::pallet]
@@ -65,12 +65,12 @@
match reason {
WithdrawReason::Call { target, input } => {
let origin_sub = T::CrossAccountId::from_eth(origin);
- let call_context = CallContext { max_fee };
- T::EvmSponsorshipHandler::get_sponsor(
- &origin_sub,
- &(*target, input.clone()),
- &call_context,
- )
+ let call_context = CallContext {
+ contract_address: *target,
+ input: input.clone(),
+ max_fee,
+ };
+ T::EvmSponsorshipHandler::get_sponsor(&origin_sub, &call_context)
}
_ => None,
}
@@ -79,12 +79,12 @@
/// Implements sponsoring for evm calls performed from pallet-evm (via api.tx.ethereum.transact/api.tx.evm.call)
pub struct BridgeSponsorshipHandler<T>(PhantomData<T>);
-impl<T, C> SponsorshipHandler<T::AccountId, C, ()> for BridgeSponsorshipHandler<T>
+impl<T, C> SponsorshipHandler<T::AccountId, C> for BridgeSponsorshipHandler<T>
where
T: Config + pallet_evm::Config,
C: IsSubType<pallet_evm::Call<T>>,
{
- fn get_sponsor(who: &T::AccountId, call: &C, _call_context: &()) -> Option<T::AccountId> {
+ fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {
match call.is_sub_type()? {
pallet_evm::Call::call {
source,
@@ -101,16 +101,16 @@
.ok()?;
let who = T::CrossAccountId::from_sub(who.clone());
let max_fee = max_fee_per_gas.saturating_mul((*gas_limit).into());
- let call_context = CallContext { max_fee };
+ let call_context = CallContext {
+ contract_address: *target,
+ input: input.clone(),
+ max_fee,
+ };
// Effects from EvmSponsorshipHandler are applied by pallet_evm::runner
// TODO: Should we implement simulation mode (test, but do not apply effects) in `up-sponsorship`?
let sponsor = frame_support::storage::with_transaction(|| {
TransactionOutcome::Rollback(Ok::<_, DispatchError>(
- T::EvmSponsorshipHandler::get_sponsor(
- &who,
- &(*target, input.clone()),
- &call_context,
- ),
+ T::EvmSponsorshipHandler::get_sponsor(&who, &call_context),
))
})
// FIXME: it may fail with DispatchError in case of depth limit
pallets/scheduler/Cargo.tomldiffbeforeafterboth--- a/pallets/scheduler/Cargo.toml
+++ b/pallets/scheduler/Cargo.toml
@@ -24,7 +24,7 @@
sp-core = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.27' }
frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
-up-sponsorship = { version = "0.1.0", default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", rev="9ee7d6e57e03a2575cbab79431774b56f170018e" }
+up-sponsorship = { version = "0.1.0", default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" }
log = { version = "0.4.14", default-features = false }
[dev-dependencies]
pallets/unique/src/eth/mod.rsdiffbeforeafterboth--- a/pallets/unique/src/eth/mod.rs
+++ b/pallets/unique/src/eth/mod.rs
@@ -21,25 +21,23 @@
use evm_coder::{execution::*, generate_stubgen, solidity_interface, solidity, weight, types::*};
use frame_support::traits::Get;
use pallet_common::{
- CollectionById, CollectionHandle,
+ CollectionById,
dispatch::CollectionDispatch,
erc::{
CollectionHelpersEvents,
static_property::{key, value as property_value},
},
- Pallet as PalletCommon,
};
use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};
use pallet_evm::{account::CrossAccountId, OnMethodCall, PrecompileHandle, PrecompileResult};
-use pallet_evm_coder_substrate::dispatch_to_evm;
use up_data_structs::{
CollectionName, CollectionDescription, CollectionTokenPrefix, CreateCollectionData,
- CollectionMode, PropertyKeyPermission, PropertyPermission, PropertyScope, PropertyValue,
+ CollectionMode, PropertyValue,
};
use crate::{Config, SelfWeightOf, weights::WeightInfo};
-use sp_std::{vec, vec::Vec};
+use sp_std::vec::Vec;
use alloc::format;
/// See [`CollectionHelpersCall`]
runtime/common/ethereum/sponsoring.rsdiffbeforeafterboth--- a/runtime/common/ethereum/sponsoring.rs
+++ b/runtime/common/ethereum/sponsoring.rs
@@ -34,7 +34,6 @@
};
use pallet_refungible::Config as RefungibleConfig;
use pallet_unique::Config as UniqueConfig;
-use sp_core::H160;
use sp_std::prelude::*;
use up_data_structs::{CollectionMode, CreateItemData, CreateNftData, TokenId};
use up_sponsorship::SponsorshipHandler;
@@ -48,18 +47,16 @@
pub struct UniqueEthSponsorshipHandler<T: UniqueConfig>(PhantomData<*const T>);
impl<T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig>
- SponsorshipHandler<T::CrossAccountId, (H160, Vec<u8>), CallContext>
- for UniqueEthSponsorshipHandler<T>
+ SponsorshipHandler<T::CrossAccountId, CallContext> for UniqueEthSponsorshipHandler<T>
{
fn get_sponsor(
who: &T::CrossAccountId,
- call: &(H160, Vec<u8>),
- _fee_limit: &CallContext,
+ call_context: &CallContext,
) -> Option<T::CrossAccountId> {
- let collection_id = map_eth_to_id(&call.0)?;
+ let collection_id = map_eth_to_id(&call_context.contract_address)?;
let collection = <CollectionHandle<T>>::new(collection_id)?;
let sponsor = collection.sponsorship.sponsor()?.clone();
- let (method_id, mut reader) = AbiReader::new_call(&call.1).ok()?;
+ let (method_id, mut reader) = AbiReader::new_call(&call_context.input).ok()?;
Some(T::CrossAccountId::from_sub(match &collection.mode {
CollectionMode::NFT => {
let call = <UniqueNFTCall<T>>::parse(method_id, &mut reader).ok()??;
runtime/common/sponsoring.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/>.1617use core::marker::PhantomData;18use up_sponsorship::SponsorshipHandler;19use frame_support::{20 traits::{IsSubType},21 storage::{StorageMap, StorageDoubleMap, StorageNMap},22};23use up_data_structs::{24 CollectionId, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, NFT_SPONSOR_TRANSFER_TIMEOUT,25 REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, TokenId, CollectionMode, CreateItemData,26};27use sp_runtime::traits::Saturating;28use pallet_common::{CollectionHandle};29use pallet_evm::account::CrossAccountId;30use pallet_unique::{31 Call as UniqueCall, Config as UniqueConfig, FungibleApproveBasket, RefungibleApproveBasket,32 NftApproveBasket, CreateItemBasket, ReFungibleTransferBasket, FungibleTransferBasket,33 NftTransferBasket, TokenPropertyBasket,34};35use pallet_fungible::Config as FungibleConfig;36use pallet_nonfungible::Config as NonfungibleConfig;37use pallet_refungible::Config as RefungibleConfig;3839pub trait Config: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig {}40impl<T> Config for T where T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig {}4142// TODO: permission check?43pub fn withdraw_set_token_property<T: Config>(44 collection: &CollectionHandle<T>,45 who: &T::CrossAccountId,46 item_id: &TokenId,47 data_size: usize,48) -> Option<()> {49 // preliminary sponsoring correctness check50 match collection.mode {51 CollectionMode::NFT => {52 let owner = pallet_nonfungible::TokenData::<T>::get((collection.id, item_id))?.owner;53 if !owner.conv_eq(who) {54 return None;55 }56 }57 CollectionMode::Fungible(_) => {58 // Fungible tokens have no properties59 return None;60 }61 CollectionMode::ReFungible => {62 if !<pallet_refungible::Owned<T>>::get((collection.id, who, item_id)) {63 return None;64 }65 }66 }6768 if data_size > collection.limits.sponsored_data_size() as usize {69 return None;70 }7172 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;73 let limit = collection.limits.sponsored_data_rate_limit()?;7475 if let Some(last_tx_block) = TokenPropertyBasket::<T>::get(collection.id, item_id) {76 let timeout = last_tx_block + limit.into();77 if block_number < timeout {78 return None;79 }80 }8182 <TokenPropertyBasket<T>>::insert(collection.id, item_id, block_number);8384 Some(())85}8687pub fn withdraw_transfer<T: Config>(88 collection: &CollectionHandle<T>,89 who: &T::CrossAccountId,90 item_id: &TokenId,91) -> Option<()> {92 // preliminary sponsoring correctness check93 match collection.mode {94 CollectionMode::NFT => {95 let owner = pallet_nonfungible::TokenData::<T>::get((collection.id, item_id))?.owner;96 if !owner.conv_eq(who) {97 return None;98 }99 }100 CollectionMode::Fungible(_) => {101 if item_id != &TokenId::default() {102 return None;103 }104 if <pallet_fungible::Balance<T>>::get((collection.id, who)) == 0 {105 return None;106 }107 }108 CollectionMode::ReFungible => {109 if !<pallet_refungible::Owned<T>>::get((collection.id, who, item_id)) {110 return None;111 }112 }113 }114115 // sponsor timeout116 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;117 let limit = collection118 .limits119 .sponsor_transfer_timeout(match collection.mode {120 CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,121 CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,122 CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,123 });124125 let last_tx_block = match collection.mode {126 CollectionMode::NFT => <NftTransferBasket<T>>::get(collection.id, item_id),127 CollectionMode::Fungible(_) => {128 <FungibleTransferBasket<T>>::get(collection.id, who.as_sub())129 }130 CollectionMode::ReFungible => {131 <ReFungibleTransferBasket<T>>::get((collection.id, item_id, who.as_sub()))132 }133 };134135 if let Some(last_tx_block) = last_tx_block {136 let timeout = last_tx_block + limit.into();137 if block_number < timeout {138 return None;139 }140 }141142 match collection.mode {143 CollectionMode::NFT => <NftTransferBasket<T>>::insert(collection.id, item_id, block_number),144 CollectionMode::Fungible(_) => {145 <FungibleTransferBasket<T>>::insert(collection.id, who.as_sub(), block_number)146 }147 CollectionMode::ReFungible => <ReFungibleTransferBasket<T>>::insert(148 (collection.id, item_id, who.as_sub()),149 block_number,150 ),151 };152153 Some(())154}155156pub fn withdraw_create_item<T: Config>(157 collection: &CollectionHandle<T>,158 who: &T::CrossAccountId,159 properties: &CreateItemData,160) -> Option<()> {161 // sponsor timeout162 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;163 let limit = collection164 .limits165 .sponsor_transfer_timeout(match properties {166 CreateItemData::NFT(_) => NFT_SPONSOR_TRANSFER_TIMEOUT,167 CreateItemData::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,168 CreateItemData::ReFungible(_) => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,169 });170171 if let Some(last_tx_block) = <CreateItemBasket<T>>::get((collection.id, who.as_sub())) {172 let timeout = last_tx_block + limit.into();173 if block_number < timeout {174 return None;175 }176 }177178 CreateItemBasket::<T>::insert((collection.id, who.as_sub()), block_number);179180 Some(())181}182183pub fn withdraw_approve<T: Config>(184 collection: &CollectionHandle<T>,185 who: &T::AccountId,186 item_id: &TokenId,187) -> Option<()> {188 // sponsor timeout189 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;190 let limit = collection.limits.sponsor_approve_timeout();191192 let last_tx_block = match collection.mode {193 CollectionMode::NFT => <NftApproveBasket<T>>::get(collection.id, item_id),194 CollectionMode::Fungible(_) => <FungibleApproveBasket<T>>::get(collection.id, who),195 CollectionMode::ReFungible => {196 <RefungibleApproveBasket<T>>::get((collection.id, item_id, who))197 }198 };199200 if let Some(last_tx_block) = last_tx_block {201 let timeout = last_tx_block + limit.into();202 if block_number < timeout {203 return None;204 }205 }206207 match collection.mode {208 CollectionMode::NFT => <NftApproveBasket<T>>::insert(collection.id, item_id, block_number),209 CollectionMode::Fungible(_) => {210 <FungibleApproveBasket<T>>::insert(collection.id, who, block_number)211 }212 CollectionMode::ReFungible => {213 <RefungibleApproveBasket<T>>::insert((collection.id, item_id, who), block_number)214 }215 };216217 Some(())218}219220fn load<T: UniqueConfig>(id: CollectionId) -> Option<(T::AccountId, CollectionHandle<T>)> {221 let collection = CollectionHandle::new(id)?;222 let sponsor = collection.sponsorship.sponsor().cloned()?;223 Some((sponsor, collection))224}225226pub struct UniqueSponsorshipHandler<T>(PhantomData<T>);227impl<T, C> SponsorshipHandler<T::AccountId, C, ()> for UniqueSponsorshipHandler<T>228where229 T: Config,230 C: IsSubType<UniqueCall<T>>,231{232 fn get_sponsor(who: &T::AccountId, call: &C, _call_context: &()) -> Option<T::AccountId> {233 match IsSubType::<UniqueCall<T>>::is_sub_type(call)? {234 UniqueCall::set_token_properties {235 collection_id,236 token_id,237 properties,238 ..239 } => {240 let (sponsor, collection) = load::<T>(*collection_id)?;241 withdraw_set_token_property(242 &collection,243 &T::CrossAccountId::from_sub(who.clone()),244 &token_id,245 // No overflow may happen, as data larger than usize can't reach here246 properties.iter().map(|p| p.key.len() + p.value.len()).sum(),247 )248 .map(|()| sponsor)249 }250 UniqueCall::create_item {251 collection_id,252 data,253 ..254 } => {255 let (sponsor, collection) = load(*collection_id)?;256 withdraw_create_item::<T>(257 &collection,258 &T::CrossAccountId::from_sub(who.clone()),259 data,260 )261 .map(|()| sponsor)262 }263 UniqueCall::transfer {264 collection_id,265 item_id,266 ..267 } => {268 let (sponsor, collection) = load(*collection_id)?;269 withdraw_transfer::<T>(270 &collection,271 &T::CrossAccountId::from_sub(who.clone()),272 item_id,273 )274 .map(|()| sponsor)275 }276 UniqueCall::transfer_from {277 collection_id,278 item_id,279 from,280 ..281 } => {282 let (sponsor, collection) = load(*collection_id)?;283 withdraw_transfer::<T>(&collection, from, item_id).map(|()| sponsor)284 }285 UniqueCall::approve {286 collection_id,287 item_id,288 ..289 } => {290 let (sponsor, collection) = load(*collection_id)?;291 withdraw_approve::<T>(&collection, who, item_id).map(|()| sponsor)292 }293 _ => None,294 }295 }296}297298pub trait SponsorshipPredict<T: Config> {299 fn predict(collection: CollectionId, account: T::CrossAccountId, token: TokenId) -> Option<u64>300 where301 u64: From<<T as frame_system::Config>::BlockNumber>;302}303304pub struct UniqueSponsorshipPredict<T>(PhantomData<T>);305306impl<T: Config> SponsorshipPredict<T> for UniqueSponsorshipPredict<T> {307 fn predict(collection_id: CollectionId, who: T::CrossAccountId, token: TokenId) -> Option<u64>308 where309 u64: From<<T as frame_system::Config>::BlockNumber>,310 {311 let collection = <CollectionHandle<T>>::try_get(collection_id).ok()?;312 let _ = collection.sponsorship.sponsor()?;313314 // sponsor timeout315 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;316 let limit = collection317 .limits318 .sponsor_transfer_timeout(match collection.mode {319 CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,320 CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,321 CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,322 });323324 let last_tx_block = match collection.mode {325 CollectionMode::NFT => <NftTransferBasket<T>>::get(collection.id, token),326 CollectionMode::Fungible(_) => {327 <FungibleTransferBasket<T>>::get(collection.id, who.as_sub())328 }329 CollectionMode::ReFungible => {330 <ReFungibleTransferBasket<T>>::get((collection.id, token, who.as_sub()))331 }332 };333334 if let Some(last_tx_block) = last_tx_block {335 return Some(336 last_tx_block337 .saturating_add(limit.into())338 .saturating_sub(block_number)339 .into(),340 );341 }342343 let token_exists = match collection.mode {344 CollectionMode::NFT => {345 <pallet_nonfungible::TokenData<T>>::contains_key((collection.id, token))346 }347 CollectionMode::Fungible(_) => token == TokenId::default(),348 CollectionMode::ReFungible => {349 <pallet_refungible::TotalSupply<T>>::contains_key((collection.id, token))350 }351 };352353 if token_exists {354 Some(0)355 } else {356 None357 }358 }359}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/>.1617use core::marker::PhantomData;18use up_sponsorship::SponsorshipHandler;19use frame_support::{20 traits::{IsSubType},21 storage::{StorageMap, StorageDoubleMap, StorageNMap},22};23use up_data_structs::{24 CollectionId, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, NFT_SPONSOR_TRANSFER_TIMEOUT,25 REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, TokenId, CollectionMode, CreateItemData,26};27use sp_runtime::traits::Saturating;28use pallet_common::{CollectionHandle};29use pallet_evm::account::CrossAccountId;30use pallet_unique::{31 Call as UniqueCall, Config as UniqueConfig, FungibleApproveBasket, RefungibleApproveBasket,32 NftApproveBasket, CreateItemBasket, ReFungibleTransferBasket, FungibleTransferBasket,33 NftTransferBasket, TokenPropertyBasket,34};35use pallet_fungible::Config as FungibleConfig;36use pallet_nonfungible::Config as NonfungibleConfig;37use pallet_refungible::Config as RefungibleConfig;3839pub trait Config: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig {}40impl<T> Config for T where T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig {}4142// TODO: permission check?43pub fn withdraw_set_token_property<T: Config>(44 collection: &CollectionHandle<T>,45 who: &T::CrossAccountId,46 item_id: &TokenId,47 data_size: usize,48) -> Option<()> {49 // preliminary sponsoring correctness check50 match collection.mode {51 CollectionMode::NFT => {52 let owner = pallet_nonfungible::TokenData::<T>::get((collection.id, item_id))?.owner;53 if !owner.conv_eq(who) {54 return None;55 }56 }57 CollectionMode::Fungible(_) => {58 // Fungible tokens have no properties59 return None;60 }61 CollectionMode::ReFungible => {62 if !<pallet_refungible::Owned<T>>::get((collection.id, who, item_id)) {63 return None;64 }65 }66 }6768 if data_size > collection.limits.sponsored_data_size() as usize {69 return None;70 }7172 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;73 let limit = collection.limits.sponsored_data_rate_limit()?;7475 if let Some(last_tx_block) = TokenPropertyBasket::<T>::get(collection.id, item_id) {76 let timeout = last_tx_block + limit.into();77 if block_number < timeout {78 return None;79 }80 }8182 <TokenPropertyBasket<T>>::insert(collection.id, item_id, block_number);8384 Some(())85}8687pub fn withdraw_transfer<T: Config>(88 collection: &CollectionHandle<T>,89 who: &T::CrossAccountId,90 item_id: &TokenId,91) -> Option<()> {92 // preliminary sponsoring correctness check93 match collection.mode {94 CollectionMode::NFT => {95 let owner = pallet_nonfungible::TokenData::<T>::get((collection.id, item_id))?.owner;96 if !owner.conv_eq(who) {97 return None;98 }99 }100 CollectionMode::Fungible(_) => {101 if item_id != &TokenId::default() {102 return None;103 }104 if <pallet_fungible::Balance<T>>::get((collection.id, who)) == 0 {105 return None;106 }107 }108 CollectionMode::ReFungible => {109 if !<pallet_refungible::Owned<T>>::get((collection.id, who, item_id)) {110 return None;111 }112 }113 }114115 // sponsor timeout116 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;117 let limit = collection118 .limits119 .sponsor_transfer_timeout(match collection.mode {120 CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,121 CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,122 CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,123 });124125 let last_tx_block = match collection.mode {126 CollectionMode::NFT => <NftTransferBasket<T>>::get(collection.id, item_id),127 CollectionMode::Fungible(_) => {128 <FungibleTransferBasket<T>>::get(collection.id, who.as_sub())129 }130 CollectionMode::ReFungible => {131 <ReFungibleTransferBasket<T>>::get((collection.id, item_id, who.as_sub()))132 }133 };134135 if let Some(last_tx_block) = last_tx_block {136 let timeout = last_tx_block + limit.into();137 if block_number < timeout {138 return None;139 }140 }141142 match collection.mode {143 CollectionMode::NFT => <NftTransferBasket<T>>::insert(collection.id, item_id, block_number),144 CollectionMode::Fungible(_) => {145 <FungibleTransferBasket<T>>::insert(collection.id, who.as_sub(), block_number)146 }147 CollectionMode::ReFungible => <ReFungibleTransferBasket<T>>::insert(148 (collection.id, item_id, who.as_sub()),149 block_number,150 ),151 };152153 Some(())154}155156pub fn withdraw_create_item<T: Config>(157 collection: &CollectionHandle<T>,158 who: &T::CrossAccountId,159 properties: &CreateItemData,160) -> Option<()> {161 // sponsor timeout162 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;163 let limit = collection164 .limits165 .sponsor_transfer_timeout(match properties {166 CreateItemData::NFT(_) => NFT_SPONSOR_TRANSFER_TIMEOUT,167 CreateItemData::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,168 CreateItemData::ReFungible(_) => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,169 });170171 if let Some(last_tx_block) = <CreateItemBasket<T>>::get((collection.id, who.as_sub())) {172 let timeout = last_tx_block + limit.into();173 if block_number < timeout {174 return None;175 }176 }177178 CreateItemBasket::<T>::insert((collection.id, who.as_sub()), block_number);179180 Some(())181}182183pub fn withdraw_approve<T: Config>(184 collection: &CollectionHandle<T>,185 who: &T::AccountId,186 item_id: &TokenId,187) -> Option<()> {188 // sponsor timeout189 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;190 let limit = collection.limits.sponsor_approve_timeout();191192 let last_tx_block = match collection.mode {193 CollectionMode::NFT => <NftApproveBasket<T>>::get(collection.id, item_id),194 CollectionMode::Fungible(_) => <FungibleApproveBasket<T>>::get(collection.id, who),195 CollectionMode::ReFungible => {196 <RefungibleApproveBasket<T>>::get((collection.id, item_id, who))197 }198 };199200 if let Some(last_tx_block) = last_tx_block {201 let timeout = last_tx_block + limit.into();202 if block_number < timeout {203 return None;204 }205 }206207 match collection.mode {208 CollectionMode::NFT => <NftApproveBasket<T>>::insert(collection.id, item_id, block_number),209 CollectionMode::Fungible(_) => {210 <FungibleApproveBasket<T>>::insert(collection.id, who, block_number)211 }212 CollectionMode::ReFungible => {213 <RefungibleApproveBasket<T>>::insert((collection.id, item_id, who), block_number)214 }215 };216217 Some(())218}219220fn load<T: UniqueConfig>(id: CollectionId) -> Option<(T::AccountId, CollectionHandle<T>)> {221 let collection = CollectionHandle::new(id)?;222 let sponsor = collection.sponsorship.sponsor().cloned()?;223 Some((sponsor, collection))224}225226pub struct UniqueSponsorshipHandler<T>(PhantomData<T>);227impl<T, C> SponsorshipHandler<T::AccountId, C> for UniqueSponsorshipHandler<T>228where229 T: Config,230 C: IsSubType<UniqueCall<T>>,231{232 fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {233 match IsSubType::<UniqueCall<T>>::is_sub_type(call)? {234 UniqueCall::set_token_properties {235 collection_id,236 token_id,237 properties,238 ..239 } => {240 let (sponsor, collection) = load::<T>(*collection_id)?;241 withdraw_set_token_property(242 &collection,243 &T::CrossAccountId::from_sub(who.clone()),244 &token_id,245 // No overflow may happen, as data larger than usize can't reach here246 properties.iter().map(|p| p.key.len() + p.value.len()).sum(),247 )248 .map(|()| sponsor)249 }250 UniqueCall::create_item {251 collection_id,252 data,253 ..254 } => {255 let (sponsor, collection) = load(*collection_id)?;256 withdraw_create_item::<T>(257 &collection,258 &T::CrossAccountId::from_sub(who.clone()),259 data,260 )261 .map(|()| sponsor)262 }263 UniqueCall::transfer {264 collection_id,265 item_id,266 ..267 } => {268 let (sponsor, collection) = load(*collection_id)?;269 withdraw_transfer::<T>(270 &collection,271 &T::CrossAccountId::from_sub(who.clone()),272 item_id,273 )274 .map(|()| sponsor)275 }276 UniqueCall::transfer_from {277 collection_id,278 item_id,279 from,280 ..281 } => {282 let (sponsor, collection) = load(*collection_id)?;283 withdraw_transfer::<T>(&collection, from, item_id).map(|()| sponsor)284 }285 UniqueCall::approve {286 collection_id,287 item_id,288 ..289 } => {290 let (sponsor, collection) = load(*collection_id)?;291 withdraw_approve::<T>(&collection, who, item_id).map(|()| sponsor)292 }293 _ => None,294 }295 }296}297298pub trait SponsorshipPredict<T: Config> {299 fn predict(collection: CollectionId, account: T::CrossAccountId, token: TokenId) -> Option<u64>300 where301 u64: From<<T as frame_system::Config>::BlockNumber>;302}303304pub struct UniqueSponsorshipPredict<T>(PhantomData<T>);305306impl<T: Config> SponsorshipPredict<T> for UniqueSponsorshipPredict<T> {307 fn predict(collection_id: CollectionId, who: T::CrossAccountId, token: TokenId) -> Option<u64>308 where309 u64: From<<T as frame_system::Config>::BlockNumber>,310 {311 let collection = <CollectionHandle<T>>::try_get(collection_id).ok()?;312 let _ = collection.sponsorship.sponsor()?;313314 // sponsor timeout315 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;316 let limit = collection317 .limits318 .sponsor_transfer_timeout(match collection.mode {319 CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,320 CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,321 CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,322 });323324 let last_tx_block = match collection.mode {325 CollectionMode::NFT => <NftTransferBasket<T>>::get(collection.id, token),326 CollectionMode::Fungible(_) => {327 <FungibleTransferBasket<T>>::get(collection.id, who.as_sub())328 }329 CollectionMode::ReFungible => {330 <ReFungibleTransferBasket<T>>::get((collection.id, token, who.as_sub()))331 }332 };333334 if let Some(last_tx_block) = last_tx_block {335 return Some(336 last_tx_block337 .saturating_add(limit.into())338 .saturating_sub(block_number)339 .into(),340 );341 }342343 let token_exists = match collection.mode {344 CollectionMode::NFT => {345 <pallet_nonfungible::TokenData<T>>::contains_key((collection.id, token))346 }347 CollectionMode::Fungible(_) => token == TokenId::default(),348 CollectionMode::ReFungible => {349 <pallet_refungible::TotalSupply<T>>::contains_key((collection.id, token))350 }351 };352353 if token_exists {354 Some(0)355 } else {356 None357 }358 }359}runtime/opal/Cargo.tomldiffbeforeafterboth--- a/runtime/opal/Cargo.toml
+++ b/runtime/opal/Cargo.toml
@@ -431,7 +431,7 @@
pallet-proxy-rmrk-equip = { default-features = false, path = "../../pallets/proxy-rmrk-equip", package = "pallet-rmrk-equip" }
pallet-unique-scheduler = { path = '../../pallets/scheduler', default-features = false }
# pallet-contract-helpers = { path = '../pallets/contract-helpers', default-features = false, version = '0.1.0' }
-pallet-charge-transaction = { git = "https://github.com/uniquenetwork/pallet-sponsoring", rev="9ee7d6e57e03a2575cbab79431774b56f170018e", package = "pallet-template-transaction-payment", default-features = false, version = "3.0.0" }
+pallet-charge-transaction = { git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27", package = "pallet-template-transaction-payment", default-features = false, version = "3.0.0" }
pallet-evm-migration = { path = '../../pallets/evm-migration', default-features = false }
pallet-evm-contract-helpers = { path = '../../pallets/evm-contract-helpers', default-features = false }
pallet-evm-transaction-payment = { path = '../../pallets/evm-transaction-payment', default-features = false }
@@ -442,7 +442,7 @@
fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", rev = "89a37c5a489f426cc7a42d7b94019974093a052d" }
fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", rev = "89a37c5a489f426cc7a42d7b94019974093a052d" }
evm-coder = { default-features = false, path = '../../crates/evm-coder' }
-up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", rev="9ee7d6e57e03a2575cbab79431774b56f170018e" }
+up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" }
################################################################################
# Build Dependencies
runtime/quartz/Cargo.tomldiffbeforeafterboth--- a/runtime/quartz/Cargo.toml
+++ b/runtime/quartz/Cargo.toml
@@ -432,7 +432,7 @@
pallet-proxy-rmrk-equip = { default-features = false, path = "../../pallets/proxy-rmrk-equip", package = "pallet-rmrk-equip" }
pallet-unique-scheduler = { path = '../../pallets/scheduler', default-features = false }
# pallet-contract-helpers = { path = '../pallets/contract-helpers', default-features = false, version = '0.1.0' }
-pallet-charge-transaction = { git = "https://github.com/uniquenetwork/pallet-sponsoring", rev="9ee7d6e57e03a2575cbab79431774b56f170018e", package = "pallet-template-transaction-payment", default-features = false, version = "3.0.0" }
+pallet-charge-transaction = { git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27", package = "pallet-template-transaction-payment", default-features = false, version = "3.0.0" }
pallet-evm-migration = { path = '../../pallets/evm-migration', default-features = false }
pallet-evm-contract-helpers = { path = '../../pallets/evm-contract-helpers', default-features = false }
pallet-evm-transaction-payment = { path = '../../pallets/evm-transaction-payment', default-features = false }
@@ -443,7 +443,7 @@
fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", rev = "89a37c5a489f426cc7a42d7b94019974093a052d" }
fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", rev = "89a37c5a489f426cc7a42d7b94019974093a052d" }
evm-coder = { default-features = false, path = '../../crates/evm-coder' }
-up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", rev="9ee7d6e57e03a2575cbab79431774b56f170018e" }
+up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" }
################################################################################
# Build Dependencies
runtime/tests/Cargo.tomldiffbeforeafterboth--- a/runtime/tests/Cargo.toml
+++ b/runtime/tests/Cargo.toml
@@ -43,4 +43,4 @@
scale-info = "*"
evm-coder = { default-features = false, path = '../../crates/evm-coder' }
-up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", rev="9ee7d6e57e03a2575cbab79431774b56f170018e" }
+up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" }
runtime/unique/Cargo.tomldiffbeforeafterboth--- a/runtime/unique/Cargo.toml
+++ b/runtime/unique/Cargo.toml
@@ -425,7 +425,7 @@
pallet-proxy-rmrk-equip = { default-features = false, path = "../../pallets/proxy-rmrk-equip", package = "pallet-rmrk-equip" }
pallet-unique-scheduler = { path = '../../pallets/scheduler', default-features = false }
# pallet-contract-helpers = { path = '../pallets/contract-helpers', default-features = false, version = '0.1.0' }
-pallet-charge-transaction = { git = "https://github.com/uniquenetwork/pallet-sponsoring", rev="9ee7d6e57e03a2575cbab79431774b56f170018e", package = "pallet-template-transaction-payment", default-features = false, version = "3.0.0" }
+pallet-charge-transaction = { git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27", package = "pallet-template-transaction-payment", default-features = false, version = "3.0.0" }
pallet-evm-migration = { path = '../../pallets/evm-migration', default-features = false }
pallet-evm-contract-helpers = { path = '../../pallets/evm-contract-helpers', default-features = false }
pallet-evm-transaction-payment = { path = '../../pallets/evm-transaction-payment', default-features = false }
@@ -437,7 +437,7 @@
fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", rev = "89a37c5a489f426cc7a42d7b94019974093a052d" }
fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", rev = "89a37c5a489f426cc7a42d7b94019974093a052d" }
evm-coder = { default-features = false, path = '../../crates/evm-coder' }
-up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", rev="9ee7d6e57e03a2575cbab79431774b56f170018e" }
+up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" }
################################################################################
# Build Dependencies