difftreelog
Finished smart contract sponsoring
in: master
3 files changed
pallets/nft/src/default_weights.rsdiffbeforeafterboth92 .saturating_add(DbWeight::get().reads(2 as Weight))92 .saturating_add(DbWeight::get().reads(2 as Weight))93 .saturating_add(DbWeight::get().writes(1 as Weight))93 .saturating_add(DbWeight::get().writes(1 as Weight))94 }94 }95 // fn enable_contract_sponsoring() -> Weight {96 // (0 as Weight)97 // .saturating_add(DbWeight::get().reads(1 as Weight))98 // .saturating_add(DbWeight::get().writes(1 as Weight))99 // }95}100}96101pallets/nft/src/lib.rsdiffbeforeafterboth11 construct_runtime, decl_event, decl_module, decl_storage,11 construct_runtime, decl_event, decl_module, decl_storage,12 dispatch::DispatchResult,12 dispatch::DispatchResult,13 ensure, parameter_types,13 ensure, parameter_types,14 debug,15 traits::{14 traits::{16 Currency, ExistenceRequirement, Get, Imbalance, KeyOwnerProofSystem, OnUnbalanced,15 Currency, ExistenceRequirement, Get, Imbalance, KeyOwnerProofSystem, OnUnbalanced,17 Randomness, WithdrawReason,16 Randomness, WithdrawReason,23 },22 },24 IsSubType, StorageValue,23 IsSubType, StorageValue,25};24};26use sp_runtime::print;27// use frame_support::weights::{Weight, constants::RocksDbWeight as DbWeight};25// use frame_support::weights::{Weight, constants::RocksDbWeight as DbWeight};282629use frame_system::{self as system, ensure_signed, ensure_root};27use frame_system::{self as system, ensure_signed, ensure_root};30use sp_runtime::sp_std::prelude::Vec;28use sp_runtime::sp_std::prelude::Vec;31use sp_runtime::{29use sp_runtime::{32 traits::{30 traits::{33 DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SaturatedConversion, Saturating,31 DispatchInfoOf, Dispatchable, PostDispatchInfoOf, Saturating, SignedExtension, Zero,34 SignedExtension, Zero,35 },32 },36 transaction_validity::{33 transaction_validity::{37 InvalidTransaction, TransactionPriority, TransactionValidity, TransactionValidityError,34 InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction,38 ValidTransaction,39 },35 },40 FixedPointOperand, FixedU128,36 FixedPointOperand, FixedU128,41};37};38use pallet_contracts::ContractAddressFor;39use sp_runtime::traits::StaticLookup;424043#[cfg(test)]41#[cfg(test)]44mod mock;42mod mock;205 fn approve() -> Weight;203 fn approve() -> Weight;206 fn transfer_from() -> Weight;204 fn transfer_from() -> Weight;207 fn set_offchain_schema() -> Weight;205 fn set_offchain_schema() -> Weight;206 // fn enable_contract_sponsoring() -> Weight;208}207}209208210pub trait Trait: system::Trait + Sized + transaction_payment::Trait + pallet_contracts::Trait {209pub trait Trait: system::Trait + Sized + transaction_payment::Trait + pallet_contracts::Trait {259 pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => Vec<BasketItem<T::AccountId, T::BlockNumber>>;258 pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => Vec<BasketItem<T::AccountId, T::BlockNumber>>;260 pub ReFungibleTransferBasket get(fn refungible_transfer_basket): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => T::BlockNumber;259 pub ReFungibleTransferBasket get(fn refungible_transfer_basket): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => T::BlockNumber;261260262 // Sponsorship261 // Contract Sponsorship and Ownership263 pub ContractSponsor get(fn contract_sponsor): map hasher(identity) T::AccountId => T::AccountId;262 pub ContractOwner get(fn contract_owner): map hasher(identity) T::AccountId => T::AccountId;264 pub UnconfirmedContractSponsor get(fn unconfirmed_contract_sponsor): map hasher(identity) T::AccountId => T::AccountId;263 pub ContractSelfSponsoring get(fn contract_self_sponsoring): map hasher(identity) T::AccountId => bool;265 }264 }266 add_extra_genesis {265 add_extra_genesis {267 build(|config: &GenesisConfig<T>| {266 build(|config: &GenesisConfig<T>| {1114 ensure_root(origin)?;1113 ensure_root(origin)?;1115 <ChainLimit>::put(limits);1114 <ChainLimit>::put(limits);1116 Ok(())1115 Ok(())1117 } 1116 }11171118 /// Enable smart contract self-sponsoring.1119 /// 1120 /// # Permissions1121 /// 1122 /// * Contract Owner1123 /// 1124 /// # Arguments1125 /// 1126 /// * contract address1127 /// * enable flag1128 /// 1129 #[weight = 0]1130 pub fn enable_contract_sponsoring(1131 origin,1132 contract_address: T::AccountId,1133 enable: bool1134 ) -> DispatchResult {1135 let sender = ensure_signed(origin)?;1136 let mut is_owner = false;1137 if <ContractOwner<T>>::contains_key(contract_address.clone()) {1138 let owner = <ContractOwner<T>>::get(&contract_address);1139 is_owner = sender == owner;1140 }1141 ensure!(is_owner, "Only contract owner may call this method");11421143 <ContractSelfSponsoring<T>>::insert(contract_address, enable);1144 Ok(())1145 }11461118 }1147 }1119}1148}175817871759impl<T: Trait + Send + Sync> ChargeTransactionPayment<T>1788impl<T: Trait + Send + Sync> ChargeTransactionPayment<T>1760where1789where1761 T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType<Call<T>>,1790 T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType<Call<T>> + IsSubType<pallet_contracts::Call<T>>,1762 BalanceOf<T>: Send + Sync + FixedPointOperand,1791 BalanceOf<T>: Send + Sync + FixedPointOperand,1763{1792{1764 /// utility constructor. Used only in client/factory code.1793 /// utility constructor. Used only in client/factory code.179718261798 // Determine who is paying transaction fee based on ecnomic model1827 // Determine who is paying transaction fee based on ecnomic model1799 // Parse call to extract collection ID and access collection sponsor1828 // Parse call to extract collection ID and access collection sponsor1800 let sponsor: T::AccountId = match call.is_sub_type() {1829 let mut sponsor: T::AccountId = match IsSubType::<Call<T>>::is_sub_type(call) {1801 Some(Call::create_item(collection_id, _properties, _owner)) => {1830 Some(Call::create_item(collection_id, _properties, _owner)) => {1802 <Collection<T>>::get(collection_id).sponsor1831 <Collection<T>>::get(collection_id).sponsor1803 }1832 }1863 }1892 }1864 }1893 }186518941866 // Some(pallet_contracts::Call::call(_dest, _value, _gas_limit, _data)) => {1867 // Some(pallet_contracts::Call::call(..)) => {1868 // T::AccountId::default()1869 // }18701871 _ => T::AccountId::default(),1895 _ => T::AccountId::default(),1872 };1896 };187318971898 // Sponsor smart contracts1899 sponsor = match IsSubType::<pallet_contracts::Call<T>>::is_sub_type(call) {19001901 // On instantiation: set the contract owner1902 Some(pallet_contracts::Call::instantiate(_endowment, _gas_limit, code_hash, data)) => {19031904 let new_contract_address = <T as pallet_contracts::Trait>::DetermineContractAddress::contract_address_for(1905 code_hash,1906 &data,1907 &who,1908 );1909 <ContractOwner<T>>::insert(new_contract_address.clone(), who.clone());19101911 T::AccountId::default()1912 },19131914 // When the contract is called, check if the sponsoring is enabled and pay fees from contract endowment if it is1915 Some(pallet_contracts::Call::call(dest, _value, _gas_limit, _data)) => {19161917 let mut sp = T::AccountId::default();1918 let called_contract: T::AccountId = T::Lookup::lookup((*dest).clone()).unwrap_or(T::AccountId::default());1919 if <ContractSelfSponsoring<T>>::contains_key(called_contract.clone()) {1920 if <ContractSelfSponsoring<T>>::get(called_contract.clone()) {1921 sp = called_contract;1922 }1923 }19241925 sp1926 },19271928 _ => sponsor,1929 };19301874 let mut who_pays_fee: T::AccountId = sponsor.clone();1931 let mut who_pays_fee: T::AccountId = sponsor.clone();1875 if sponsor == T::AccountId::default() {1932 if sponsor == T::AccountId::default() {1876 who_pays_fee = who.clone();1933 who_pays_fee = who.clone();1902 for ChargeTransactionPayment<T>1959 for ChargeTransactionPayment<T>1903where1960where1904 BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,1961 BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,1905 T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType<Call<T>>,1962 T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType<Call<T>> + IsSubType<pallet_contracts::Call<T>>,1906{1963{1907 const IDENTIFIER: &'static str = "ChargeTransactionPayment";1964 const IDENTIFIER: &'static str = "ChargeTransactionPayment";1908 type AccountId = T::AccountId;1965 type AccountId = T::AccountId;1909 type Call = T::Call;1966 type Call = T::Call;1910 type AdditionalSigned = ();1967 type AdditionalSigned = ();1911 type Pre = ();1968 type Pre = (1912 // type Pre = (1969 BalanceOf<T>,1913 // BalanceOf<T>,1914 // Self::AccountId,1970 Self::AccountId,1915 // Option<NegativeImbalanceOf<T>>,1971 Option<NegativeImbalanceOf<T>>,1916 // BalanceOf<T>,1972 BalanceOf<T>,1917 // );1973 );1918 fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> {1974 fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> {1919 Ok(())1975 Ok(())1920 }1976 }192119771922 fn validate(1978 fn validate(1923 &self,1979 &self,1924 who: &Self::AccountId,1980 _who: &Self::AccountId,1925 call: &Self::Call,1981 _call: &Self::Call,1926 info: &DispatchInfoOf<Self::Call>,1982 _info: &DispatchInfoOf<Self::Call>,1927 len: usize,1983 _len: usize,1928 ) -> TransactionValidity {1984 ) -> TransactionValidity {1929 let (fee, _) = self.withdraw_fee(who, call, info, len)?;19301931 print("====== validate");19321933 Ok(ValidTransaction::default())1985 Ok(ValidTransaction::default())1934 }1986 }193519871940 info: &DispatchInfoOf<Self::Call>,1992 info: &DispatchInfoOf<Self::Call>,1941 len: usize,1993 len: usize,1942 ) -> Result<Self::Pre, TransactionValidityError> {1994 ) -> Result<Self::Pre, TransactionValidityError> {19431944 print("========= PreDispatch");1995 let (fee, imbalance) = self.withdraw_fee(who, call, info, len)?;19451946 // let (fee, imbalance) = self.withdraw_fee(who, call, info, len)?;19471948 // debug::info!("Fee: {:?}", fee);1996 Ok((self.0, who.clone(), imbalance, fee))19491950 // Ok((self.0, who.clone(), imbalance, fee))1951 Ok(())1952 }1997 }195319981954 fn post_dispatch(1999 fn post_dispatch(1958 len: usize,2003 len: usize,1959 _result: &DispatchResult,2004 _result: &DispatchResult,1960 ) -> Result<(), TransactionValidityError> {2005 ) -> Result<(), TransactionValidityError> {1961 // let (tip, who, imbalance, fee) = pre;2006 let (tip, who, imbalance, fee) = pre;1962 // if let Some(payed) = imbalance {2007 if let Some(payed) = imbalance {1963 // let actual_fee = <transaction_payment::Module<T>>::compute_actual_fee(2008 let actual_fee = <transaction_payment::Module<T>>::compute_actual_fee(1964 // len as u32, info, post_info, tip,2009 len as u32, info, post_info, tip,1965 // );2010 );1966 // let refund = fee.saturating_sub(actual_fee);2011 let refund = fee.saturating_sub(actual_fee);1967 // let actual_payment =2012 let actual_payment =1968 // match <T as transaction_payment::Trait>::Currency::deposit_into_existing(2013 match <T as transaction_payment::Trait>::Currency::deposit_into_existing(1969 // &who, refund,2014 &who, refund,1970 // ) {2015 ) {1971 // Ok(refund_imbalance) => {2016 Ok(refund_imbalance) => {1972 // // The refund cannot be larger than the up front payed max weight.2017 // The refund cannot be larger than the up front payed max weight.1973 // // `PostDispatchInfo::calc_unspent` guards against such a case.2018 // `PostDispatchInfo::calc_unspent` guards against such a case.1974 // match payed.offset(refund_imbalance) {2019 match payed.offset(refund_imbalance) {1975 // Ok(actual_payment) => actual_payment,2020 Ok(actual_payment) => actual_payment,1976 // Err(_) => return Err(InvalidTransaction::Payment.into()),2021 Err(_) => return Err(InvalidTransaction::Payment.into()),1977 // }2022 }1978 // }2023 }1979 // // We do not recreate the account using the refund. The up front payment2024 // We do not recreate the account using the refund. The up front payment1980 // // is gone in that case.2025 // is gone in that case.1981 // Err(_) => payed,2026 Err(_) => payed,1982 // };2027 };1983 // let imbalances = actual_payment.split(tip);2028 let imbalances = actual_payment.split(tip);1984 // <T as transaction_payment::Trait>::OnTransactionPayment::on_unbalanceds(2029 <T as transaction_payment::Trait>::OnTransactionPayment::on_unbalanceds(1985 // Some(imbalances.0).into_iter().chain(Some(imbalances.1)),2030 Some(imbalances.0).into_iter().chain(Some(imbalances.1)),1986 // );2031 );1987 // }2032 }1988 Ok(())2033 Ok(())1989 }2034 }1990}2035}19911992/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////199319941995#[derive(Encode, Decode, Clone, Eq, PartialEq)]1996pub struct ChargeContractTransactionPayment<T: Trait + Send + Sync>(1997 #[codec(compact)] BalanceOf<T>1998);19992000impl<T: Trait + Send + Sync> sp_std::fmt::Debug2001 for ChargeContractTransactionPayment<T>2002{2003 #[cfg(feature = "std")]2004 fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {2005 write!(f, "ChargeContractTransactionPayment<{:?}>", self.0)2006 }2007 #[cfg(not(feature = "std"))]2008 fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {2009 Ok(())2010 }2011}20122013// impl<T: Trait + Send + Sync> ChargeContractTransactionPayment<T>2014// where2015// // T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,2016// T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType<pallet_contracts::Call<T>>,2017// BalanceOf<T>: Send + Sync + FixedPointOperand,2018// {2019// // /// utility constructor. Used only in client/factory code.2020// // pub fn from(fee: BalanceOf<T>) -> Self {2021// // Self(fee)2022// // }20232024// pub fn traditional_fee(2025// len: usize,2026// info: &DispatchInfoOf<T::Call>,2027// tip: BalanceOf<T>,2028// ) -> BalanceOf<T>2029// where2030// T::Call: Dispatchable<Info = DispatchInfo>,2031// {2032// <transaction_payment::Module<T>>::compute_fee(len as u32, info, tip)2033// }20342035// fn withdraw_fee(2036// &self,2037// who: &T::AccountId,2038// call: &T::Call,2039// info: &DispatchInfoOf<T::Call>,2040// len: usize,2041// ) -> Result<(BalanceOf<T>, Option<NegativeImbalanceOf<T>>), TransactionValidityError> {2042// let tip = self.0;20432044// let mut fee = Self::traditional_fee(len, info, tip);20452046// // Determine who is paying transaction fee based on ecnomic model2047// // Parse call to extract collection ID and access collection sponsor2048// // let sponsor: T::AccountId = match call.is_sub_type() {2049// // // Some(pallet_contracts::Call::call(_dest, _value, _gas_limit, _data)) => {2050// // Some(pallet_contracts::Call::call(..)) => {2051// // // fee = <BalanceOf<T>>::from(0);2052// // T::AccountId::default()2053// // }2054// // _ => T::AccountId::default(),2055// // };2056// let sponsor = T::AccountId::default();20572058// let mut who_pays_fee: T::AccountId = sponsor.clone();2059// if sponsor == T::AccountId::default() {2060// who_pays_fee = who.clone();2061// }20622063// // Only mess with balances if fee is not zero.2064// if fee.is_zero() {2065// return Ok((fee, None));2066// }20672068// match <T as transaction_payment::Trait>::Currency::withdraw(2069// &who_pays_fee,2070// fee,2071// if tip.is_zero() {2072// WithdrawReason::TransactionPayment.into()2073// } else {2074// WithdrawReason::TransactionPayment | WithdrawReason::Tip2075// },2076// ExistenceRequirement::KeepAlive,2077// ) {2078// Ok(imbalance) => Ok((fee, Some(imbalance))),2079// Err(_) => Err(InvalidTransaction::Payment.into()),2080// }2081// }2082// }2083208420852086impl<T: Trait + Send + Sync> SignedExtension2087 for ChargeContractTransactionPayment<T>2088where2089 BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,2090 // T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,2091 T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType<pallet_contracts::Call<T>>,2092{2093 const IDENTIFIER: &'static str = "ChargeContractTransactionPayment";2094 type AccountId = T::AccountId;2095 type Call = T::Call;2096 type AdditionalSigned = ();2097 type Pre = ();20982099 // type Pre = (2100 // BalanceOf<T>,2101 // Self::AccountId,2102 // Option<NegativeImbalanceOf<T>>,2103 // BalanceOf<T>,2104 // );2105 fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> {2106 Ok(())2107 }21082109 fn validate(2110 &self,2111 who: &Self::AccountId,2112 call: &Self::Call,2113 info: &DispatchInfoOf<Self::Call>,2114 len: usize,2115 ) -> TransactionValidity {2116 // let (fee, _) = self.withdraw_fee(who, call, info, len)?;21172118 print("====== Contracts validate");21192120 Ok(ValidTransaction::default())2121 }21222123 fn pre_dispatch(2124 self,2125 who: &Self::AccountId,2126 call: &Self::Call,2127 info: &DispatchInfoOf<Self::Call>,2128 len: usize,2129 ) -> Result<Self::Pre, TransactionValidityError> {2130 // let (fee, imbalance) = self.withdraw_fee(who, call, info, len)?;2131 // Ok((self.0, who.clone(), imbalance, fee))21322133 print("====== Contracts pre-dispatch");2134 // debug::info!("Fee: {:?}", fee);21352136 Ok(())2137 }21382139 fn post_dispatch(2140 pre: Self::Pre,2141 info: &DispatchInfoOf<Self::Call>,2142 post_info: &PostDispatchInfoOf<Self::Call>,2143 len: usize,2144 _result: &DispatchResult,2145 ) -> Result<(), TransactionValidityError> {2146 // let (tip, who, imbalance, fee) = pre;2147 // if let Some(payed) = imbalance {2148 // let actual_fee = <transaction_payment::Module<T>>::compute_actual_fee(2149 // len as u32, info, post_info, tip,2150 // );2151 // let refund = fee.saturating_sub(actual_fee);2152 // let actual_payment =2153 // match <T as transaction_payment::Trait>::Currency::deposit_into_existing(2154 // &who, refund,2155 // ) {2156 // Ok(refund_imbalance) => {2157 // // The refund cannot be larger than the up front payed max weight.2158 // // `PostDispatchInfo::calc_unspent` guards against such a case.2159 // match payed.offset(refund_imbalance) {2160 // Ok(actual_payment) => actual_payment,2161 // Err(_) => return Err(InvalidTransaction::Payment.into()),2162 // }2163 // }2164 // // We do not recreate the account using the refund. The up front payment2165 // // is gone in that case.2166 // Err(_) => payed,2167 // };2168 // let imbalances = actual_payment.split(tip);2169 // <T as transaction_payment::Trait>::OnTransactionPayment::on_unbalanceds(2170 // Some(imbalances.0).into_iter().chain(Some(imbalances.1)),2171 // );2172 // }2173 Ok(())2174 }2175}2176217720362178// #endregion2037// #endregionruntime/src/lib.rsdiffbeforeafterboth352 system::CheckNonce<Runtime>,352 system::CheckNonce<Runtime>,353 system::CheckWeight<Runtime>,353 system::CheckWeight<Runtime>,354 pallet_nft::ChargeTransactionPayment<Runtime>,354 pallet_nft::ChargeTransactionPayment<Runtime>,355 pallet_nft::ChargeContractTransactionPayment<Runtime>,356);355);357/// Unchecked extrinsic type as expected by this runtime.356/// Unchecked extrinsic type as expected by this runtime.358pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;357pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;