pallet-feeless 0.0.2

A pallet to implement a feeless Substrate blockchain node.
Documentation
# ๐Ÿšซ 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:

- `CheckNonce`
- `CheckWeight`
- `CheckEra`
- ...

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`

```rust ignore
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`

```ignore
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:

```rust ignore
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`:

```rust ignore
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:

```rust ignore
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](./LICENSE) โ€” open-source and ready to use in your blockchain projects.