Expand description
Β§π« pallet-feeless: Feeless Transactions with Rate Limiting for Substrate π«
Welcome to pallet-feeless β a plug-and-play solution to enable fully feeless transactions in any Substrate-based blockchain! β¨
Instead of charging transaction fees, this pallet uses a rate-limiting system to ensure fair usage and network security. Itβs perfect for applications where user experience, accessibility, and cost-efficiency are top priorities.
Β§π§© Introduction
Most blockchains rely on transaction fees to prevent spam and incentivize validators. While effective, this system can create friction, especially for:
- Microtransactions πΈ
- New users π§βπ»
- Developers building free-to-use apps π
This pallet removes transaction fees altogetherβeven during congestionβby using a rate-limiting extrinsic extension. This makes your blockchain:
- π« Free from fees
- π Predictable for users
- π‘οΈ Secure against spam
Β§π‘ How It Works
Instead of fees, each account is subject to a rate limit:
- β±οΈ Max Transactions per Period: The number of transactions allowed per account in a set block window.
- π¦ Max Size per Period: The total size of allowed transactions during that window.
This is enforced via a custom extrinsic extension (CheckRate) that plugs into Substrateβs transaction validation pipeline alongside checks like:
CheckNonceCheckWeightCheckEra- β¦
All validation and accounting are performed before and after dispatch, with minimal storage access to preserve performance and security.
Β§βοΈ Runtime Integration
Β§1. Define AccountData in frame_system
type AccountData = pallet_feeless::AccountData<Balance, BlockNumber>;This custom account type stores balance, last block, and rate data per account.
Β§2. Set Up AccountStore in pallet_balances
type AccountStore = Account;Required to track the accountβs storage location and enable rate tracking.
Β§3. Configure pallet_feeless
Add your custom settings in the runtime:
impl pallet_feeless::Config for Runtime {
type MaxTxByPeriod = ConstU32<128>; // Max transactions per period
type MaxSizeByPeriod = ConstU32<1>; // Max size in bytes per period
type Period = ConstU32<5>; // Length of the rate-limiting window (in blocks)
type RuntimeEvent = RuntimeEvent;
type WeightInfo = (); // Do not forget to generate and reference the weight after benchmarking
}Β§4. Update Your Transaction Extensions
Extend the runtime transaction validation to include CheckRate:
pub type TxExtension = (
frame_system::CheckNonZeroSender<Runtime>,
frame_system::CheckSpecVersion<Runtime>,
frame_system::CheckTxVersion<Runtime>,
frame_system::CheckGenesis<Runtime>,
frame_system::CheckEra<Runtime>,
frame_system::CheckNonce<Runtime>,
pallet_feeless::CheckRate<Runtime>, // π Rate limit extension
frame_system::CheckWeight<Runtime>,
pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
);Β§5. Benchmarking and Payload Setup
In benchmarking.rs or similar:
let tx_ext: runtime::TxExtension = (
frame_system::CheckNonZeroSender::<runtime::Runtime>::new(),
frame_system::CheckSpecVersion::<runtime::Runtime>::new(),
frame_system::CheckTxVersion::<runtime::Runtime>::new(),
frame_system::CheckGenesis::<runtime::Runtime>::new(),
frame_system::CheckEra::<runtime::Runtime>::from(sp_runtime::generic::Era::mortal(
period,
best_block.saturated_into(),
)),
frame_system::CheckNonce::<runtime::Runtime>::from(nonce),
pallet_feeless::CheckRate::<runtime::Runtime>::new(), // π Add this
frame_system::CheckWeight::<runtime::Runtime>::new(),
pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from(0),
frame_metadata_hash_extension::CheckMetadataHash::<runtime::Runtime>::new(false),
);
let raw_payload = runtime::SignedPayload::from_raw(
call.clone(),
tx_ext.clone(),
(
(),
runtime::VERSION.spec_version,
runtime::VERSION.transaction_version,
genesis_hash,
best_hash,
(),
(), // π Add this
(),
(),
None,
),
);Β§β Benefits
-
π« No Transaction Fees
Users never worry about price fluctuations. -
βοΈ Built-in Fairness
Every account gets a rate limit, ensuring equal access. -
π οΈ Developer Friendly
Build dApps without forcing users to hold or buy tokens. -
π Accessible UX
Lower onboarding friction and support for micro-use cases.
Β§β οΈ Considerations
While this system improves user experience, keep in mind:
- βοΈ Fine-tuning required: Limits must strike a balance between usability and protection.
- π― No validator fees: Block rewards or other models must be used to incentivize validators.
- π‘οΈ Spam resistance: Rate limits must be sufficient to deter Sybil attacks or multi-account spamming.
Β§π¦ Want to Try It?
Just include this pallet in your Substrate runtime and configure the limits to your needs. No additional infrastructure or fee logic is required!
Β§π License
MIT β open-source and ready to use in your blockchain projects.
Re-exportsΒ§
pub use pallet::*;pub use weights::*;pub use types::*;pub use extensions::*;
ModulesΒ§
- extensions
- pallet
- The
palletmodule in each FRAME pallet hosts the most important items needed to construct this pallet. - types
- weights
- Autogenerated weights for
pallet_feeless