git.delta.rocks / unique-network / refs/commits / 144732746abe

difftreelog

Finished smart contract sponsoring

Greg Zaitsev2020-11-05parent: #31c3cec.patch.diff
in: master

3 files changed

modifiedpallets/nft/src/default_weights.rsdiffbeforeafterboth
92 .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}
96101
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
11 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};
2826
29use 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;
4240
43#[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}
209208
210pub 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;
261260
262 // Sponsorship261 // Contract Sponsorship and Ownership
263 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 }
1117
1118 /// Enable smart contract self-sponsoring.
1119 ///
1120 /// # Permissions
1121 ///
1122 /// * Contract Owner
1123 ///
1124 /// # Arguments
1125 ///
1126 /// * contract address
1127 /// * enable flag
1128 ///
1129 #[weight = 0]
1130 pub fn enable_contract_sponsoring(
1131 origin,
1132 contract_address: T::AccountId,
1133 enable: bool
1134 ) -> 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");
1142
1143 <ContractSelfSponsoring<T>>::insert(contract_address, enable);
1144 Ok(())
1145 }
1146
1118 }1147 }
1119}1148}
17581787
1759impl<T: Trait + Send + Sync> ChargeTransactionPayment<T>1788impl<T: Trait + Send + Sync> ChargeTransactionPayment<T>
1760where1789where
1761 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.
17971826
1798 // Determine who is paying transaction fee based on ecnomic model1827 // Determine who is paying transaction fee based on ecnomic model
1799 // Parse call to extract collection ID and access collection sponsor1828 // Parse call to extract collection ID and access collection sponsor
1800 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).sponsor
1803 }1832 }
1863 }1892 }
1864 }1893 }
18651894
1866 // Some(pallet_contracts::Call::call(_dest, _value, _gas_limit, _data)) => {
1867 // Some(pallet_contracts::Call::call(..)) => {
1868 // T::AccountId::default()
1869 // }
1870
1871 _ => T::AccountId::default(),1895 _ => T::AccountId::default(),
1872 };1896 };
18731897
1898 // Sponsor smart contracts
1899 sponsor = match IsSubType::<pallet_contracts::Call<T>>::is_sub_type(call) {
1900
1901 // On instantiation: set the contract owner
1902 Some(pallet_contracts::Call::instantiate(_endowment, _gas_limit, code_hash, data)) => {
1903
1904 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());
1910
1911 T::AccountId::default()
1912 },
1913
1914 // When the contract is called, check if the sponsoring is enabled and pay fees from contract endowment if it is
1915 Some(pallet_contracts::Call::call(dest, _value, _gas_limit, _data)) => {
1916
1917 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 }
1924
1925 sp
1926 },
1927
1928 _ => sponsor,
1929 };
1930
1874 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>
1903where1960where
1904 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 }
19211977
1922 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)?;
1930
1931 print("====== validate");
1932
1933 Ok(ValidTransaction::default())1985 Ok(ValidTransaction::default())
1934 }1986 }
19351987
1940 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> {
1943
1944 print("========= PreDispatch");1995 let (fee, imbalance) = self.withdraw_fee(who, call, info, len)?;
1945
1946 // let (fee, imbalance) = self.withdraw_fee(who, call, info, len)?;
1947
1948 // debug::info!("Fee: {:?}", fee);1996 Ok((self.0, who.clone(), imbalance, fee))
1949
1950 // Ok((self.0, who.clone(), imbalance, fee))
1951 Ok(())
1952 }1997 }
19531998
1954 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 payment
1980 // // 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}
1991
1992/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1993
1994
1995#[derive(Encode, Decode, Clone, Eq, PartialEq)]
1996pub struct ChargeContractTransactionPayment<T: Trait + Send + Sync>(
1997 #[codec(compact)] BalanceOf<T>
1998);
1999
2000impl<T: Trait + Send + Sync> sp_std::fmt::Debug
2001 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}
2012
2013// impl<T: Trait + Send + Sync> ChargeContractTransactionPayment<T>
2014// where
2015// // 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// // }
2023
2024// pub fn traditional_fee(
2025// len: usize,
2026// info: &DispatchInfoOf<T::Call>,
2027// tip: BalanceOf<T>,
2028// ) -> BalanceOf<T>
2029// where
2030// T::Call: Dispatchable<Info = DispatchInfo>,
2031// {
2032// <transaction_payment::Module<T>>::compute_fee(len as u32, info, tip)
2033// }
2034
2035// 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;
2043
2044// let mut fee = Self::traditional_fee(len, info, tip);
2045
2046// // Determine who is paying transaction fee based on ecnomic model
2047// // Parse call to extract collection ID and access collection sponsor
2048// // 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();
2057
2058// let mut who_pays_fee: T::AccountId = sponsor.clone();
2059// if sponsor == T::AccountId::default() {
2060// who_pays_fee = who.clone();
2061// }
2062
2063// // Only mess with balances if fee is not zero.
2064// if fee.is_zero() {
2065// return Ok((fee, None));
2066// }
2067
2068// 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::Tip
2075// },
2076// ExistenceRequirement::KeepAlive,
2077// ) {
2078// Ok(imbalance) => Ok((fee, Some(imbalance))),
2079// Err(_) => Err(InvalidTransaction::Payment.into()),
2080// }
2081// }
2082// }
2083
2084
2085
2086impl<T: Trait + Send + Sync> SignedExtension
2087 for ChargeContractTransactionPayment<T>
2088where
2089 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 = ();
2098
2099 // 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 }
2108
2109 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)?;
2117
2118 print("====== Contracts validate");
2119
2120 Ok(ValidTransaction::default())
2121 }
2122
2123 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))
2132
2133 print("====== Contracts pre-dispatch");
2134 // debug::info!("Fee: {:?}", fee);
2135
2136 Ok(())
2137 }
2138
2139 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 payment
2165 // // 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}
2176
21772036
2178// #endregion2037// #endregion
modifiedruntime/src/lib.rsdiffbeforeafterboth
352 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>;