Asset Transaction Payment (#488)

* use new pallet name based genesis config names

* use custom substrate and update polkadot

* add initial asset-tx-payment pallet

* update cargo.toml

* add (failing) tests

* dispatch Calls instead of using Pallet functions

* fix fee-refund split

* add test for transaction payment with tip

* update cargo.lock

* update cargo.lock

* remove mint workaround and use Mutable trait

* extract fee charging logic into OnChargeAssetTransaction trait

* use asset-tx-payment in statemint runtime

* make extrinsics public

* make extrinsics public

* use ChargeAssetIdOf type alias

* update deps

* move back to AssetIdOf

* remove extra rpc_http_threads

* use different substrate branch

* Update pallets/asset-tx-payment/src/payment.rs

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update pallets/asset-tx-payment/src/payment.rs

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* remove overrides

* override substrate deps (again)

* increment spec_version and transaction_version (because we change transaction signing)

* remove direct dependency on pallet-balances from asset-tx-payment

* remove Assets pallet visibility workaround

* add docs and comments

* remove unused imports

* more docs

* add more debug asserts to document assumptions

* add test for tx payment from account with only assets

* add test for missing asset case

* extend test to cover non-sufficient assets

* add a test for Pays::No (refunded transaction)

* add type alias comments

* add more doc comments

* add asset-tx-payment to statemine and westmint

* improve formatting

* update license headers

* add default implementation of HandleCredit for ()

* update doc comments and format imports

* adjust Cargo.toml

* update cargo.lock

* cargo fmt

* cargo fmt

* cargo fmt

* cargo +nightly fmt

* add type alias for OnChargeTransaction

* cargo +nightly fmt

* convert ChargeAssetTxPayment from tuple struct to regular struct

* add more comments

* formatting

* adjust imports and comment

* cargo +nightly fmt

* reformat comment

* use ChargeTransactionPayment's own get_priority + update Substrate

* update Substrate and Polkadot

* cargo fmt

* cargo fmt

* add OperationalFeeMultiplier to asset tx payment tests

* Apply suggestions from code review

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* add doc links

* charge a minimum converted asset fee of 1 if the input fee is greater zero

* cargo +nightly fmt

* bump spec and transaction version

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
Alexander Popiak
2021-10-11 11:57:37 +02:00
committed by GitHub
parent 2647053fd3
commit 3b1446d791
14 changed files with 1268 additions and 24 deletions
@@ -20,6 +20,8 @@ sp-io = { git = 'https://github.com/paritytech/substrate', branch = "master", de
frame-executive = { git = 'https://github.com/paritytech/substrate', branch = "master", default-features = false }
frame-support = { git = 'https://github.com/paritytech/substrate', branch = "master", default-features = false }
frame-system = { git = 'https://github.com/paritytech/substrate', branch = "master", default-features = false }
pallet-assets = { git = 'https://github.com/paritytech/substrate', branch = "master", default-features = false }
pallet-authorship = { git = 'https://github.com/paritytech/substrate', branch = "master", default-features = false }
pallet-balances = { git = 'https://github.com/paritytech/substrate', branch = "master", default-features = false }
sp-runtime = { git = 'https://github.com/paritytech/substrate', branch = "master", default-features = false }
sp-core = { git = 'https://github.com/paritytech/substrate', branch = "master", default-features = false }
@@ -32,6 +34,7 @@ xcm = { git = 'https://github.com/paritytech/polkadot', branch = "master", defau
xcm-executor = { git = 'https://github.com/paritytech/polkadot', branch = "master", default-features = false }
# Local dependencies
pallet-asset-tx-payment = { path = '../../pallets/asset-tx-payment', default-features = false }
pallet-collator-selection = { path = '../../pallets/collator-selection', default-features = false }
[dev-dependencies]
@@ -52,7 +55,10 @@ std = [
'frame-support/std',
'frame-executive/std',
'frame-system/std',
'pallet-asset-tx-payment/std',
'pallet-collator-selection/std',
'pallet-assets/std',
'pallet-authorship/std',
'pallet-balances/std',
'node-primitives/std',
'polkadot-runtime-common/std',
@@ -16,23 +16,31 @@
//! Auxillary struct/enums for parachain runtimes.
//! Taken from polkadot/runtime/common (at a21cd64) and adapted for parachains.
use frame_support::traits::{fungibles, Contains, Currency, Get, Imbalance, OnUnbalanced};
use frame_support::traits::{
fungibles::{self, Balanced, CreditOf},
Contains, Currency, Get, Imbalance, OnUnbalanced,
};
use pallet_asset_tx_payment::HandleCredit;
use sp_runtime::traits::Zero;
use sp_std::marker::PhantomData;
use xcm::latest::{AssetId, Fungibility::Fungible, MultiAsset, MultiLocation};
use xcm_executor::traits::FilterAssetLocation;
/// Type alias to conveniently refer to the `Currency::NegativeImbalance` associated type.
pub type NegativeImbalance<T> = <pallet_balances::Pallet<T> as Currency<
<T as frame_system::Config>::AccountId,
>>::NegativeImbalance;
/// Logic for the author to get a portion of fees.
pub struct ToStakingPot<R>(sp_std::marker::PhantomData<R>);
/// Type alias to conveniently refer to `frame_system`'s `Config::AccountId`.
pub type AccountIdOf<R> = <R as frame_system::Config>::AccountId;
/// Implementation of `OnUnbalanced` that deposits the fees into a staking pot for later payout.
pub struct ToStakingPot<R>(PhantomData<R>);
impl<R> OnUnbalanced<NegativeImbalance<R>> for ToStakingPot<R>
where
R: pallet_balances::Config + pallet_collator_selection::Config,
<R as frame_system::Config>::AccountId: From<polkadot_primitives::v1::AccountId>,
<R as frame_system::Config>::AccountId: Into<polkadot_primitives::v1::AccountId>,
AccountIdOf<R>:
From<polkadot_primitives::v1::AccountId> + Into<polkadot_primitives::v1::AccountId>,
<R as frame_system::Config>::Event: From<pallet_balances::Event<R>>,
{
fn on_nonzero_unbalanced(amount: NegativeImbalance<R>) {
@@ -46,13 +54,14 @@ where
}
}
/// Merge the fees into one item and pass them on to the staking pot.
pub struct DealWithFees<R>(sp_std::marker::PhantomData<R>);
/// Implementation of `OnUnbalanced` that deals with the fees by combining tip and fee and passing
/// the result on to `ToStakingPot`.
pub struct DealWithFees<R>(PhantomData<R>);
impl<R> OnUnbalanced<NegativeImbalance<R>> for DealWithFees<R>
where
R: pallet_balances::Config + pallet_collator_selection::Config,
<R as frame_system::Config>::AccountId: From<polkadot_primitives::v1::AccountId>,
<R as frame_system::Config>::AccountId: Into<polkadot_primitives::v1::AccountId>,
AccountIdOf<R>:
From<polkadot_primitives::v1::AccountId> + Into<polkadot_primitives::v1::AccountId>,
<R as frame_system::Config>::Event: From<pallet_balances::Event<R>>,
{
fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance<R>>) {
@@ -65,6 +74,22 @@ where
}
}
/// A `HandleCredit` implementation that naively transfers the fees to the block author.
/// Will drop and burn the assets in case the transfer fails.
pub struct AssetsToBlockAuthor<R>(PhantomData<R>);
impl<R> HandleCredit<AccountIdOf<R>, pallet_assets::Pallet<R>> for AssetsToBlockAuthor<R>
where
R: pallet_authorship::Config + pallet_assets::Config,
AccountIdOf<R>:
From<polkadot_primitives::v1::AccountId> + Into<polkadot_primitives::v1::AccountId>,
{
fn handle_credit(credit: CreditOf<AccountIdOf<R>, pallet_assets::Pallet<R>>) {
let author = pallet_authorship::Pallet::<R>::author();
// In case of error: Will drop the result triggering the `OnDrop` of the imbalance.
let _ = pallet_assets::Pallet::<R>::resolve(&author, credit);
}
}
/// Allow checking in assets that have issuance > 0.
pub struct NonZeroIssuance<AccountId, Assets>(PhantomData<(AccountId, Assets)>);
impl<AccountId, Assets> Contains<<Assets as fungibles::Inspect<AccountId>>::AssetId>