diff --git a/Cargo.lock b/Cargo.lock index 08e5102d3402a..c1ea4a479c0ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4006,7 +4006,6 @@ dependencies = [ "pallet-contracts-primitives", "pallet-randomness-collective-flip", "pallet-timestamp", - "pallet-transaction-payment", "parity-scale-codec", "parity-wasm 0.41.0", "pretty_assertions", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index cf1b0de8f7922..5acaafcab424f 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -581,6 +581,7 @@ parameter_types! { impl pallet_contracts::Trait for Runtime { type Time = Timestamp; type Randomness = RandomnessCollectiveFlip; + type Currency = Balances; type Call = Call; type Event = Event; type DetermineContractAddress = pallet_contracts::SimpleAddressDeterminer; @@ -594,6 +595,7 @@ impl pallet_contracts::Trait for Runtime { type SurchargeReward = SurchargeReward; type MaxDepth = pallet_contracts::DefaultMaxDepth; type MaxValueSize = pallet_contracts::DefaultMaxValueSize; + type WeightPrice = pallet_transaction_payment::Module; } impl pallet_sudo::Trait for Runtime { diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml index 57c278a3fb2a9..2dee486fcf681 100644 --- a/frame/contracts/Cargo.toml +++ b/frame/contracts/Cargo.toml @@ -25,7 +25,6 @@ sp-sandbox = { version = "0.8.0-rc3", default-features = false, path = "../../pr frame-support = { version = "2.0.0-rc3", default-features = false, path = "../support" } frame-system = { version = "2.0.0-rc3", default-features = false, path = "../system" } pallet-contracts-primitives = { version = "2.0.0-rc3", default-features = false, path = "common" } -pallet-transaction-payment = { version = "2.0.0-rc3", default-features = false, path = "../transaction-payment" } [dev-dependencies] wabt = "0.9.2" @@ -52,5 +51,4 @@ std = [ "pwasm-utils/std", "wasmi-validation/std", "pallet-contracts-primitives/std", - "pallet-transaction-payment/std", ] diff --git a/frame/contracts/src/exec.rs b/frame/contracts/src/exec.rs index ff0d4d9dc0de1..ba3619195d0c5 100644 --- a/frame/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -21,10 +21,11 @@ use crate::rent; use crate::storage; use sp_std::prelude::*; -use sp_runtime::traits::{Bounded, Zero}; +use sp_runtime::traits::{Bounded, Zero, Convert}; use frame_support::{ storage::unhashed, dispatch::DispatchError, traits::{ExistenceRequirement, Currency, Time, Randomness}, + weights::Weight, }; pub type AccountIdOf = ::AccountId; @@ -216,8 +217,8 @@ pub trait Ext { /// Returns `None` if the value doesn't exist. fn get_runtime_storage(&self, key: &[u8]) -> Option>; - /// Returns the price of one weight unit. - fn get_weight_price(&self) -> BalanceOf; + /// Returns the price for the specified amount of weight. + fn get_weight_price(&self, weight: Weight) -> BalanceOf; } /// Loader is a companion of the `Vm` trait. It loads an appropriate abstract @@ -874,11 +875,8 @@ where unhashed::get_raw(&key) } - fn get_weight_price(&self) -> BalanceOf { - use pallet_transaction_payment::Module as Payment; - use sp_runtime::SaturatedConversion; - let price = Payment::::weight_to_fee_with_adjustment::(1); - price.saturated_into() + fn get_weight_price(&self, weight: Weight) -> BalanceOf { + T::WeightPrice::convert(weight) } } diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index c12029a856c9d..63de1ee164bb5 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -102,7 +102,7 @@ use sp_std::{prelude::*, marker::PhantomData, fmt::Debug}; use codec::{Codec, Encode, Decode}; use sp_runtime::{ traits::{ - Hash, StaticLookup, Zero, MaybeSerializeDeserialize, Member, + Hash, StaticLookup, Zero, MaybeSerializeDeserialize, Member, Convert, }, RuntimeDebug, }; @@ -117,6 +117,7 @@ use frame_support::traits::{OnUnbalanced, Currency, Get, Time, Randomness}; use frame_support::weights::GetDispatchInfo; use frame_system::{self as system, ensure_signed, RawOrigin, ensure_root}; use pallet_contracts_primitives::{RentProjection, ContractAccessError}; +use frame_support::weights::Weight; pub type CodeHash = ::Hash; pub type TrieId = Vec; @@ -289,9 +290,10 @@ where } } -pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +pub type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; pub type NegativeImbalanceOf = - <::Currency as Currency<::AccountId>>::NegativeImbalance; + <::Currency as Currency<::AccountId>>::NegativeImbalance; parameter_types! { /// A reasonable default value for [`Trait::SignedClaimedHandicap`]. @@ -312,10 +314,13 @@ parameter_types! { pub const DefaultMaxValueSize: u32 = 16_384; } -pub trait Trait: frame_system::Trait + pallet_transaction_payment::Trait { +pub trait Trait: frame_system::Trait { type Time: Time; type Randomness: Randomness; + /// The currency in which fees are paid and contract balances are held. + type Currency: Currency; + /// The outer call dispatch type. type Call: Parameter + @@ -371,6 +376,10 @@ pub trait Trait: frame_system::Trait + pallet_transaction_payment::Trait { /// The maximum size of a storage value in bytes. type MaxValueSize: Get; + + /// Used to answer contracts's queries regarding the current weight price. This is **not** + /// used to calculate the actual fee and is only for informational purposes. + type WeightPrice: Convert>; } /// Simple contract address determiner. diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index df6afa8ac51e0..ae81a83be727c 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -30,7 +30,7 @@ use frame_support::{ assert_ok, assert_err_ignore_postinfo, impl_outer_dispatch, impl_outer_event, impl_outer_origin, parameter_types, StorageMap, StorageValue, traits::{Currency, Get}, - weights::{Weight, PostDispatchInfo, IdentityFee}, + weights::{Weight, PostDispatchInfo}, }; use std::cell::RefCell; use frame_system::{self as system, EventRecord, Phase}; @@ -169,17 +169,10 @@ impl Convert> for Test { } } -impl pallet_transaction_payment::Trait for Test { - type Currency = Balances; - type OnTransactionPayment = (); - type TransactionByteFee = TransactionByteFee; - type WeightToFee = IdentityFee>; - type FeeMultiplierUpdate = (); -} - impl Trait for Test { type Time = Timestamp; type Randomness = Randomness; + type Currency = Balances; type Call = Call; type DetermineContractAddress = DummyContractAddressFor; type Event = MetaEvent; @@ -193,6 +186,7 @@ impl Trait for Test { type SurchargeReward = SurchargeReward; type MaxDepth = MaxDepth; type MaxValueSize = MaxValueSize; + type WeightPrice = Self; } type Balances = pallet_balances::Module; diff --git a/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs index 890915a793d46..a4814a1b22f43 100644 --- a/frame/contracts/src/wasm/mod.rs +++ b/frame/contracts/src/wasm/mod.rs @@ -162,6 +162,7 @@ mod tests { use hex_literal::hex; use assert_matches::assert_matches; use sp_runtime::DispatchError; + use frame_support::weights::Weight; const GAS_LIMIT: Gas = 10_000_000_000; @@ -373,8 +374,8 @@ mod tests { ) ) } - fn get_weight_price(&self) -> BalanceOf { - 1312_u32.into() + fn get_weight_price(&self, weight: Weight) -> BalanceOf { + BalanceOf::::from(1312_u32).saturating_mul(weight.into()) } } @@ -479,8 +480,8 @@ mod tests { fn get_runtime_storage(&self, key: &[u8]) -> Option> { (**self).get_runtime_storage(key) } - fn get_weight_price(&self) -> BalanceOf { - (**self).get_weight_price() + fn get_weight_price(&self, weight: Weight) -> BalanceOf { + (**self).get_weight_price(weight) } } @@ -1056,7 +1057,7 @@ mod tests { const CODE_GAS_PRICE: &str = r#" (module - (import "env" "ext_gas_price" (func $ext_gas_price)) + (import "env" "ext_gas_price" (func $ext_gas_price (param i64))) (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) (import "env" "memory" (memory 1 1)) @@ -1072,7 +1073,7 @@ mod tests { (func (export "call") ;; This stores the gas price in the scratch buffer - (call $ext_gas_price) + (call $ext_gas_price (i64.const 1)) ;; assert $ext_scratch_size == 8 (call $assert diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs index b393898835ba3..8c4d1bfb99a56 100644 --- a/frame/contracts/src/wasm/runtime.rs +++ b/frame/contracts/src/wasm/runtime.rs @@ -696,12 +696,14 @@ define_env!(Env, , Ok(()) }, - // Stores the gas price for the current transaction into the scratch buffer. + // Stores the price for the specified amount of gas in scratch buffer. // // The data is encoded as T::Balance. The current contents of the scratch buffer are overwritten. - ext_gas_price(ctx) => { + // It is recommended to avoid specifying very small values for `gas` as the prices for a single + // gas can be smaller than one. + ext_gas_price(ctx, gas: u64) => { ctx.scratch_buf.clear(); - ctx.ext.get_weight_price().encode_to(&mut ctx.scratch_buf); + ctx.ext.get_weight_price(gas).encode_to(&mut ctx.scratch_buf); Ok(()) }, diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index 4d920f8ec53b8..b993a85da3df3 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -51,7 +51,7 @@ use sp_runtime::{ }, traits::{ Zero, Saturating, SignedExtension, SaturatedConversion, Convert, Dispatchable, - DispatchInfoOf, PostDispatchInfoOf, UniqueSaturatedFrom, UniqueSaturatedInto, + DispatchInfoOf, PostDispatchInfoOf, }, }; use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo; @@ -340,23 +340,6 @@ impl Module where tip } } -} - -impl Module { - /// Compute the fee for the specified weight. - /// - /// This fee is already adjusted by the per block fee adjustment factor and is therefore the - /// share that the weight contributes to the overall fee of a transaction. - /// - /// This function is generic in order to supply the contracts module with a way to calculate the - /// gas price. The contracts module is not able to put the necessary `BalanceOf` constraints - /// on its trait. This function is not to be used by this module. - pub fn weight_to_fee_with_adjustment(weight: Weight) -> Balance where - Balance: UniqueSaturatedFrom - { - let fee: u128 = Self::weight_to_fee(weight).unique_saturated_into(); - Balance::unique_saturated_from(NextFeeMultiplier::get().saturating_mul_acc_int(fee)) - } fn weight_to_fee(weight: Weight) -> BalanceOf { // cap the weight to the maximum defined in runtime, otherwise it will be the @@ -366,6 +349,20 @@ impl Module { } } +impl Convert> for Module where + T: Trait, + BalanceOf: FixedPointOperand, +{ + /// Compute the fee for the specified weight. + /// + /// This fee is already adjusted by the per block fee adjustment factor and is therefore the + /// share that the weight contributes to the overall fee of a transaction. It is mainly + /// for informational purposes and not used in the actual fee calculation. + fn convert(weight: Weight) -> BalanceOf { + NextFeeMultiplier::get().saturating_mul_int(Self::weight_to_fee(weight)) + } +} + /// Require the transactor pay for themselves and maybe include a tip to gain additional priority /// in the queue. #[derive(Encode, Decode, Clone, Eq, PartialEq)]