Rust区块链交易支付模块pallet-transaction-payment的使用,Substrate链上交易费用处理与支付功能
Transaction Payment Pallet
这个pallet提供了支付交易被包含所需绝对最低金额的基本逻辑。这包括:
- 权重费用:与交易消耗的权重量成比例的费用。
- 长度费用:与交易编码长度成比例的费用。
- 小费:可选的小费。小费提高交易的优先级,使其有更高机会被交易队列包含。
此外,这个pallet允许配置:
- 通过[
Config::WeightToFee
]配置一个单位权重到一个单位费用的映射。 - 通过基于上一个区块结束时链的最终状态定义乘数,来更新下一个区块的费用。这可以通过[
Config::FeeMultiplierUpdate
]配置。
许可证:Apache-2.0
安装: 运行以下Cargo命令在您的项目目录中:
cargo add pallet-transaction-payment
或在您的Cargo.toml中添加以下行:
pallet-transaction-payment = "42.0.0"
完整示例demo:
// 引入必要的依赖和模块
use frame_support::{pallet_prelude::*, traits::Currency};
use frame_system::pallet_prelude::*;
use sp_runtime::{
traits::{Convert, Saturating, Zero},
FixedPointNumber, FixedU128,
};
// 定义pallet
pub use pallet::*;
#[frame_support::pallet]
pub mod pallet {
use super::*;
// Pallet声明
#[pallet::pallet]
pub struct Pallet<T>(_);
// 配置trait
#[pallet::config]
pub trait Config: frame_system::Config {
/// 运行时事件类型
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
/// 货币类型
type Currency: Currency<Self::AccountId>;
/// 权重到费用的转换器
type WeightToFee: Convert<Weight, BalanceOf<Self>>;
/// 费用乘数更新机制
type FeeMultiplierUpdate: Get<FixedU128>;
}
// 存储项
#[pallet::storage]
#[pallet::getter(fn next_fee_multiplier)]
pub type NextFeeMultiplier<T> = StorageValue<_, FixedU128, ValueQuery>;
// 事件
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// 交易费用已支付
TransactionFeePaid {
who: T::AccountId,
actual_fee: BalanceOf<T>,
tip: BalanceOf<T>,
},
}
// 错误
#[pallet::error]
pub enum Error<T> {
/// 费用计算错误
FeeCalculationFailed,
}
// Pallet实现
#[pallet::call]
impl<T: Config> Pallet<T> {
/// 处理交易支付
#[pallet::call_index(0)]
#[pallet::weight(0)]
pub fn pay_transaction_fee(
origin: OriginFor<T>,
weight: Weight,
tip: BalanceOf<T>,
) -> DispatchResult {
let who = ensure_signed(origin)?;
// 计算权重费用
let weight_fee = T::WeightToFee::convert(weight);
// 计算总费用(权重费用 + 小费)
let total_fee = weight_fee.saturating_add(tip);
// 从账户扣除费用
T::Currency::withdraw(&who, total_fee, WithdrawReasons::FEE, ExistenceRequirement::KeepAlive)?;
// 发出事件
Self::deposit_event(Event::TransactionFeePaid {
who,
actual_fee: weight_fee,
tip,
});
Ok(())
}
}
// 实现交易支付API
impl<T: Config> Pallet<T> {
/// 计算交易费用
pub fn compute_fee(
weight: Weight,
tip: BalanceOf<T>,
) -> Result<BalanceOf<T>, Error<T>> {
let weight_fee = T::WeightToFee::convert(weight);
Ok(weight_fee.saturating_add(tip))
}
/// 更新费用乘数
pub fn update_fee_multiplier() {
let new_multiplier = T::FeeMultiplierUpdate::get();
NextFeeMultiplier::<T>::put(new_multiplier);
}
}
}
// 运行时配置示例
pub struct Runtime;
impl frame_system::Config for Runtime {
type AccountId = u64;
type RuntimeEvent = ();
// 其他必要的关联类型...
}
impl Config for Runtime {
type RuntimeEvent = ();
type Currency = (); // 需要实现具体的Currency类型
type WeightToFee = (); // 需要实现具体的Convert trait
type FeeMultiplierUpdate = (); // 需要实现具体的Get trait
}
1 回复