Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow set_currency in batch TX #788

Merged
merged 16 commits into from
Mar 19, 2024
Merged
7 changes: 4 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion integration-tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "runtime-integration-tests"
version = "1.19.8"
version = "1.19.9"
description = "Integration tests"
authors = ["GalacticCouncil"]
edition = "2021"
Expand Down
130 changes: 130 additions & 0 deletions integration-tests/src/non_native_fee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,136 @@ fn non_native_fee_payment_works_with_oracle_price_based_on_onchain_route() {
});
}

#[test]
fn set_currency_should_work_in_batch_transaction_when_first_tx() {
TestNet::reset();

// batch
Hydra::execute_with(|| {
let first_inner_call = hydradx_runtime::RuntimeCall::MultiTransactionPayment(
pallet_transaction_multi_payment::Call::set_currency { currency: BTC },
);
let second_inner_call = hydradx_runtime::RuntimeCall::System(frame_system::Call::remark { remark: vec![] });
let call = hydradx_runtime::RuntimeCall::Utility(pallet_utility::Call::batch {
calls: vec![first_inner_call, second_inner_call],
});

let info = DispatchInfo {
weight: Weight::from_parts(106_957_000, 0),
..Default::default()
};
let len: usize = 10;

assert_ok!(
pallet_transaction_payment::ChargeTransactionPayment::<hydradx_runtime::Runtime>::from(0).pre_dispatch(
&AccountId::from(BOB),
&call,
&info,
len,
)
);
let bob_balance = hydradx_runtime::Tokens::free_balance(BTC, &AccountId::from(BOB));
assert_eq!(bob_balance, 999991);
});

TestNet::reset();

// batch_all
Hydra::execute_with(|| {
let first_inner_call = hydradx_runtime::RuntimeCall::MultiTransactionPayment(
pallet_transaction_multi_payment::Call::set_currency { currency: BTC },
);
let second_inner_call = hydradx_runtime::RuntimeCall::System(frame_system::Call::remark { remark: vec![] });
let call = hydradx_runtime::RuntimeCall::Utility(pallet_utility::Call::batch_all {
calls: vec![first_inner_call, second_inner_call],
});

let info = DispatchInfo {
weight: Weight::from_parts(106_957_000, 0),
..Default::default()
};
let len: usize = 10;

assert_ok!(
pallet_transaction_payment::ChargeTransactionPayment::<hydradx_runtime::Runtime>::from(0).pre_dispatch(
&AccountId::from(BOB),
&call,
&info,
len,
)
);
let bob_balance = hydradx_runtime::Tokens::free_balance(BTC, &AccountId::from(BOB));
assert_eq!(bob_balance, 999991);
});
}

#[test]
fn set_currency_should_not_work_in_batch_transaction_when_not_first_tx() {
TestNet::reset();

// batch
Hydra::execute_with(|| {
let first_inner_call = hydradx_runtime::RuntimeCall::System(frame_system::Call::remark { remark: vec![] });
let second_inner_call = hydradx_runtime::RuntimeCall::MultiTransactionPayment(
pallet_transaction_multi_payment::Call::set_currency { currency: BTC },
);
let call = hydradx_runtime::RuntimeCall::Utility(pallet_utility::Call::batch {
calls: vec![first_inner_call, second_inner_call],
});

let info = DispatchInfo {
weight: Weight::from_parts(106_957_000, 0),
..Default::default()
};
let len: usize = 10;

let bob_initial_balance = hydradx_runtime::Tokens::free_balance(BTC, &AccountId::from(BOB));

assert_ok!(
pallet_transaction_payment::ChargeTransactionPayment::<hydradx_runtime::Runtime>::from(0).pre_dispatch(
&AccountId::from(BOB),
&call,
&info,
len,
)
);
let bob_balance = hydradx_runtime::Tokens::free_balance(BTC, &AccountId::from(BOB));
assert_eq!(bob_balance, bob_initial_balance);
});

TestNet::reset();

// batch_all
Hydra::execute_with(|| {
let first_inner_call = hydradx_runtime::RuntimeCall::System(frame_system::Call::remark { remark: vec![] });
let second_inner_call = hydradx_runtime::RuntimeCall::MultiTransactionPayment(
pallet_transaction_multi_payment::Call::set_currency { currency: BTC },
);
let call = hydradx_runtime::RuntimeCall::Utility(pallet_utility::Call::batch_all {
calls: vec![first_inner_call, second_inner_call],
});

let info = DispatchInfo {
weight: Weight::from_parts(106_957_000, 0),
..Default::default()
};
let len: usize = 10;

let bob_initial_balance = hydradx_runtime::Tokens::free_balance(BTC, &AccountId::from(BOB));

assert_ok!(
pallet_transaction_payment::ChargeTransactionPayment::<hydradx_runtime::Runtime>::from(0).pre_dispatch(
&AccountId::from(BOB),
&call,
&info,
len,
)
);
let bob_balance = hydradx_runtime::Tokens::free_balance(BTC, &AccountId::from(BOB));
assert_eq!(bob_balance, bob_initial_balance);
});
}

const HITCHHIKER: [u8; 32] = [42u8; 32];

#[test]
Expand Down
3 changes: 2 additions & 1 deletion pallets/transaction-multi-payment/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pallet-transaction-multi-payment"
version = "9.3.1"
version = "9.4.0"
description = "Transaction multi currency payment support module"
authors = ["GalacticCoucil"]
edition = "2021"
Expand Down Expand Up @@ -30,6 +30,7 @@ sp-core = { workspace = true }
sp-std = { workspace = true }
sp-runtime = { workspace = true }
pallet-transaction-payment = { workspace = true }
pallet-utility = { workspace = true }

pallet-evm = { workspace = true, optional = true }

Expand Down
34 changes: 25 additions & 9 deletions pallets/transaction-multi-payment/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,13 +361,14 @@ pub struct TransferFees<MC, DF, FR>(PhantomData<(MC, DF, FR)>);

impl<T, MC, DF, FR> OnChargeTransaction<T> for TransferFees<MC, DF, FR>
where
T: Config,
T: Config + pallet_utility::Config,
MC: MultiCurrency<<T as frame_system::Config>::AccountId>,
AssetIdOf<T>: Into<MC::CurrencyId>,
MC::Balance: FixedPointOperand,
FR: Get<T::AccountId>,
DF: DepositFee<T::AccountId, MC::CurrencyId, MC::Balance>,
<T as frame_system::Config>::RuntimeCall: IsSubType<Call<T>>,
<T as frame_system::Config>::RuntimeCall: IsSubType<Call<T>> + IsSubType<pallet_utility::pallet::Call<T>>,
<T as pallet_utility::Config>::RuntimeCall: IsSubType<Call<T>>,
BalanceOf<T>: FixedPointOperand,
{
type LiquidityInfo = Option<PaymentInfo<Self::Balance, AssetIdOf<T>, Price>>;
Expand All @@ -378,18 +379,33 @@ where
/// Note: The `fee` already includes the `tip`.
fn withdraw_fee(
who: &T::AccountId,
call: &T::RuntimeCall,
_info: &DispatchInfoOf<T::RuntimeCall>,
call: &<T as frame_system::Config>::RuntimeCall,
_info: &DispatchInfoOf<<T as frame_system::Config>::RuntimeCall>,
fee: Self::Balance,
_tip: Self::Balance,
) -> Result<Self::LiquidityInfo, TransactionValidityError> {
if fee.is_zero() {
return Ok(None);
}

let currency = match call.is_sub_type() {
Some(Call::set_currency { currency }) => *currency,
_ => Pallet::<T>::account_currency(who),
let currency = if let Some(Call::set_currency { currency }) = call.is_sub_type() {
*currency
} else if let Some(pallet_utility::pallet::Call::<T>::batch { calls }) = call.is_sub_type() {
let first_call = &calls[0];
let currency = match first_call.is_sub_type() {
Some(Call::set_currency { currency }) => *currency,
_ => Pallet::<T>::account_currency(who),
};
currency
} else if let Some(pallet_utility::pallet::Call::<T>::batch_all { calls }) = call.is_sub_type() {
let first_call = &calls[0];
let currency = match first_call.is_sub_type() {
Some(Call::set_currency { currency }) => *currency,
_ => Pallet::<T>::account_currency(who),
};
currency
} else {
Pallet::<T>::account_currency(who)
};
mrq1911 marked this conversation as resolved.
Show resolved Hide resolved

let price = Pallet::<T>::get_currency_price(currency)
Expand All @@ -416,8 +432,8 @@ where
/// Note: The `fee` already includes the `tip`.
fn correct_and_deposit_fee(
who: &T::AccountId,
_dispatch_info: &DispatchInfoOf<T::RuntimeCall>,
_post_info: &PostDispatchInfoOf<T::RuntimeCall>,
_dispatch_info: &DispatchInfoOf<<T as frame_system::Config>::RuntimeCall>,
_post_info: &PostDispatchInfoOf<<T as frame_system::Config>::RuntimeCall>,
corrected_fee: Self::Balance,
tip: Self::Balance,
already_withdrawn: Self::LiquidityInfo,
Expand Down
8 changes: 8 additions & 0 deletions pallets/transaction-multi-payment/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ frame_support::construct_runtime!(
Balances: pallet_balances,
Currencies: pallet_currencies,
Tokens: orml_tokens,
Utility: pallet_utility,
}

);
Expand Down Expand Up @@ -261,6 +262,13 @@ impl pallet_currencies::Config for Test {
type WeightInfo = ();
}

impl pallet_utility::Config for Test {
type RuntimeEvent = RuntimeEvent;
type RuntimeCall = RuntimeCall;
type PalletsOrigin = OriginCaller;
type WeightInfo = ();
}

pub struct ExtBuilder {
base_weight: Weight,
native_balances: Vec<(AccountId, Balance)>,
Expand Down
Loading
Loading