difftreelog
Merge pull request #14 from usetech-llc/feature/NFTPAR-109-110_contract_sponsoring
in: master
Feature/nftpar 109 110 contract sponsoring
4 files changed
Cargo.lockdiffbeforeafterboth3737 "frame-support",3737 "frame-support",3738 "frame-system",3738 "frame-system",3739 "log",3739 "log",3740 "pallet-contracts",3740 "pallet-transaction-payment",3741 "pallet-transaction-payment",3741 "parity-scale-codec",3742 "parity-scale-codec",3742 "serde",3743 "serde",pallets/nft/Cargo.tomldiffbeforeafterboth--- a/pallets/nft/Cargo.toml
+++ b/pallets/nft/Cargo.toml
@@ -73,6 +73,13 @@
branch = 'v2.0.0_release'
optional = true
+[dependencies.pallet-contracts]
+default-features = false
+git = 'https://github.com/usetech-llc/substrate.git'
+package = 'pallet-contracts'
+branch = 'v2.0.0_release'
+version = '2.0.0'
+
[features]
default = ['std']
std = [
pallets/nft/src/default_weights.rsdiffbeforeafterboth--- a/pallets/nft/src/default_weights.rs
+++ b/pallets/nft/src/default_weights.rs
@@ -92,4 +92,9 @@
.saturating_add(DbWeight::get().reads(2 as Weight))
.saturating_add(DbWeight::get().writes(1 as Weight))
}
+ // fn enable_contract_sponsoring() -> Weight {
+ // (0 as Weight)
+ // .saturating_add(DbWeight::get().reads(1 as Weight))
+ // .saturating_add(DbWeight::get().writes(1 as Weight))
+ // }
}
pallets/nft/src/lib.rsdiffbeforeafterboth--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -28,15 +28,15 @@
use sp_runtime::sp_std::prelude::Vec;
use sp_runtime::{
traits::{
- DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SaturatedConversion, Saturating,
- SignedExtension, Zero,
+ DispatchInfoOf, Dispatchable, PostDispatchInfoOf, Saturating, SignedExtension, Zero,
},
transaction_validity::{
- InvalidTransaction, TransactionPriority, TransactionValidity, TransactionValidityError,
- ValidTransaction,
+ InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction,
},
FixedPointOperand, FixedU128,
};
+use pallet_contracts::ContractAddressFor;
+use sp_runtime::traits::StaticLookup;
#[cfg(test)]
mod mock;
@@ -203,9 +203,10 @@
fn approve() -> Weight;
fn transfer_from() -> Weight;
fn set_offchain_schema() -> Weight;
+ // fn enable_contract_sponsoring() -> Weight;
}
-pub trait Trait: system::Trait + Sized {
+pub trait Trait: system::Trait + Sized + transaction_payment::Trait + pallet_contracts::Trait {
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
/// Weight information for extrinsics in this pallet.
@@ -257,9 +258,9 @@
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>>;
pub ReFungibleTransferBasket get(fn refungible_transfer_basket): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => T::BlockNumber;
- // Sponsorship
- pub ContractSponsor get(fn contract_sponsor): map hasher(identity) T::AccountId => T::AccountId;
- pub UnconfirmedContractSponsor get(fn unconfirmed_contract_sponsor): map hasher(identity) T::AccountId => T::AccountId;
+ // Contract Sponsorship and Ownership
+ pub ContractOwner get(fn contract_owner): map hasher(identity) T::AccountId => T::AccountId;
+ pub ContractSelfSponsoring get(fn contract_self_sponsoring): map hasher(identity) T::AccountId => bool;
}
add_extra_genesis {
build(|config: &GenesisConfig<T>| {
@@ -1112,7 +1113,37 @@
ensure_root(origin)?;
<ChainLimit>::put(limits);
Ok(())
- }
+ }
+
+ /// Enable smart contract self-sponsoring.
+ ///
+ /// # Permissions
+ ///
+ /// * Contract Owner
+ ///
+ /// # Arguments
+ ///
+ /// * contract address
+ /// * enable flag
+ ///
+ #[weight = 0]
+ pub fn enable_contract_sponsoring(
+ origin,
+ contract_address: T::AccountId,
+ enable: bool
+ ) -> DispatchResult {
+ let sender = ensure_signed(origin)?;
+ let mut is_owner = false;
+ if <ContractOwner<T>>::contains_key(contract_address.clone()) {
+ let owner = <ContractOwner<T>>::get(&contract_address);
+ is_owner = sender == owner;
+ }
+ ensure!(is_owner, "Only contract owner may call this method");
+
+ <ContractSelfSponsoring<T>>::insert(contract_address, enable);
+ Ok(())
+ }
+
}
}
@@ -1737,11 +1768,11 @@
/// Require the transactor pay for themselves and maybe include a tip to gain additional priority
/// in the queue.
#[derive(Encode, Decode, Clone, Eq, PartialEq)]
-pub struct ChargeTransactionPayment<T: transaction_payment::Trait + Send + Sync>(
- #[codec(compact)] BalanceOf<T>,
+pub struct ChargeTransactionPayment<T: Trait + Send + Sync>(
+ #[codec(compact)] BalanceOf<T>
);
-impl<T: Trait + transaction_payment::Trait + Send + Sync> sp_std::fmt::Debug
+impl<T: Trait + Send + Sync> sp_std::fmt::Debug
for ChargeTransactionPayment<T>
{
#[cfg(feature = "std")]
@@ -1754,10 +1785,9 @@
}
}
-impl<T: Trait + transaction_payment::Trait + Send + Sync> ChargeTransactionPayment<T>
+impl<T: Trait + Send + Sync> ChargeTransactionPayment<T>
where
- T::Call:
- Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType<Call<T>>,
+ T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType<Call<T>> + IsSubType<pallet_contracts::Call<T>>,
BalanceOf<T>: Send + Sync + FixedPointOperand,
{
/// utility constructor. Used only in client/factory code.
@@ -1787,15 +1817,16 @@
// Set fee based on call type. Creating collection costs 1 Unique.
// All other transactions have traditional fees so far
- let fee = match call.is_sub_type() {
- Some(Call::create_collection(..)) => <BalanceOf<T>>::from(1_000_000_000),
- _ => Self::traditional_fee(len, info, tip), // Flat fee model, use only for testing purposes
- // _ => <BalanceOf<T>>::from(100)
- };
+ // let fee = match call.is_sub_type() {
+ // Some(Call::create_collection(..)) => <BalanceOf<T>>::from(1_000_000_000),
+ // _ => Self::traditional_fee(len, info, tip), // Flat fee model, use only for testing purposes
+ // // _ => <BalanceOf<T>>::from(100)
+ // };
+ let fee = Self::traditional_fee(len, info, tip);
// Determine who is paying transaction fee based on ecnomic model
// Parse call to extract collection ID and access collection sponsor
- let sponsor: T::AccountId = match call.is_sub_type() {
+ let mut sponsor: T::AccountId = match IsSubType::<Call<T>>::is_sub_type(call) {
Some(Call::create_item(collection_id, _properties, _owner)) => {
<Collection<T>>::get(collection_id).sponsor
}
@@ -1864,6 +1895,39 @@
_ => T::AccountId::default(),
};
+ // Sponsor smart contracts
+ sponsor = match IsSubType::<pallet_contracts::Call<T>>::is_sub_type(call) {
+
+ // On instantiation: set the contract owner
+ Some(pallet_contracts::Call::instantiate(_endowment, _gas_limit, code_hash, data)) => {
+
+ let new_contract_address = <T as pallet_contracts::Trait>::DetermineContractAddress::contract_address_for(
+ code_hash,
+ &data,
+ &who,
+ );
+ <ContractOwner<T>>::insert(new_contract_address.clone(), who.clone());
+
+ T::AccountId::default()
+ },
+
+ // When the contract is called, check if the sponsoring is enabled and pay fees from contract endowment if it is
+ Some(pallet_contracts::Call::call(dest, _value, _gas_limit, _data)) => {
+
+ let mut sp = T::AccountId::default();
+ let called_contract: T::AccountId = T::Lookup::lookup((*dest).clone()).unwrap_or(T::AccountId::default());
+ if <ContractSelfSponsoring<T>>::contains_key(called_contract.clone()) {
+ if <ContractSelfSponsoring<T>>::get(called_contract.clone()) {
+ sp = called_contract;
+ }
+ }
+
+ sp
+ },
+
+ _ => sponsor,
+ };
+
let mut who_pays_fee: T::AccountId = sponsor.clone();
if sponsor == T::AccountId::default() {
who_pays_fee = who.clone();
@@ -1890,11 +1954,12 @@
}
}
-impl<T: Trait + transaction_payment::Trait + Send + Sync> SignedExtension
+
+impl<T: Trait + Send + Sync> SignedExtension
for ChargeTransactionPayment<T>
where
BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,
- T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType<Call<T>>,
+ T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType<Call<T>> + IsSubType<pallet_contracts::Call<T>>,
{
const IDENTIFIER: &'static str = "ChargeTransactionPayment";
type AccountId = T::AccountId;
@@ -1912,18 +1977,12 @@
fn validate(
&self,
- who: &Self::AccountId,
- call: &Self::Call,
- info: &DispatchInfoOf<Self::Call>,
- len: usize,
+ _who: &Self::AccountId,
+ _call: &Self::Call,
+ _info: &DispatchInfoOf<Self::Call>,
+ _len: usize,
) -> TransactionValidity {
- let (fee, _) = self.withdraw_fee(who, call, info, len)?;
-
- let mut r = ValidTransaction::default();
- // NOTE: we probably want to maximize the _fee (of any type) per weight unit_ here, which
- // will be a bit more than setting the priority to tip. For now, this is enough.
- r.priority = fee.saturated_into::<TransactionPriority>();
- Ok(r)
+ Ok(ValidTransaction::default())
}
fn pre_dispatch(
@@ -1974,6 +2033,7 @@
Ok(())
}
}
+
// #endregion