# Meta transaction pallet

**URL:** <https://forum.polkadot.network/t/meta-transaction-pallet/2302>\
**Category:** Ecosystem\
**Tags:** frame\
**Created:** [March 13, 2023, 9:18am UTC](https://forum.polkadot.network/t/meta-transaction-pallet/2302 "2023-03-13T09:18:42Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![shunsukew](https://dub1.discourse-cdn.com/flex005/user_avatar/forum.polkadot.network/shunsukew/32/1396_2.png) [@shunsukew](https://forum.polkadot.network/u/shunsukew)\
**Post date:** [March 13, 2023, 9:18am UTC](https://forum.polkadot.network/t/meta-transaction-pallet/2302/1 "2023-03-13T09:18:42Z")

</div>

Substrate/Polkadot can have meta-transaction pallet so users can execute calls without paying extrinsic fees.

Idea discussion link in the Substrate repository

> **[Meta transaction pallet · paritytech/substrate · Discussion #13588](https://github.com/paritytech/substrate/discussions/13588)**
>
> Substrate can have meta-transaction pallet so users can execute calls without paying extrinsic fees. What is meta transaction Meta transactions are a way of processing transactions on blockchains w...

**What is meta transaction**  
Meta transactions are a way of processing transactions on blockchains without requiring the user to pay gas fees. Instead, a third party, such as a relayer, pays the gas fees on behalf of users. In other words, separating transaction signer and payer(sender) of the actual cost needed for processing transactions. This can be useful in scenarios where users may not have enough tokens to cover the cost of gas fees or where gas prices are high. This also can improve UX for new users with no funds to use Dapps on blockchains since it can omit processes for them to purchase or get tokens in some ways and brings easy onboarding.

**Terminologies definition in this discussion thread**

- Signer: Signer of the signature who wants to execute `RuntimeCall` without paying extrinsic fee.
- Sender: Actual users’ accounts who receive signed data and signature from signer, and execute the call (cover extrinsic fee).

**Design**  
This is just an idea for initiating discussion.

```auto
pub fn meta_call(
    origin: OriginFor<T>,
    signer: T::AccountId,
    signature: Vec<u8>,
    #[pallet::compact] nonce: T::Index,
    call: Box<<T as Config>::RuntimeCall>,
) -> DispatchResultWithPostInfo

```

(and also `chain_id`?)

1. Signer signs to Call and nonce tuple `(nonce, RuntimeCall)`
2. Signer sends request data (nonce, RuntimeCall) together with signature he/she gets at the step 1 to Sender (Relayer service).
3. Sender executes `meta_call` Extrinsic.
4. Validate signature and nonce on the pallet.
5. Dispatch Call with `Origin::Signed(signer)` (not sender) after validation.

In generic smart contract blockchains, this can be done by using contracts.  
But using a pallet has advantages

- All substrate based blockchains (without frontier/evm pallets or pallet-contracts) can use it.
- Multiple signature schemes are available (`ecdsa`, `sr25519`, `ed25519`) while contracts are not.
- In smart contract context, Caller AccountId of the objective contract signers wants to call is always signers’ AccountId. In the contracts approach, because we need Forwarder contract in-between, caller AccountId of that is Forwarder contract AccountId. This requires workarounds/adjustments for contracts developers, in Ethereum case, such as ERC20-permit, ERC721-permit, [EIP 2771](https://eips.ethereum.org/EIPS/eip-2771)

But still, to be used widely, we need relayer service which receives requests from signers and send extrinsics on behalf of them outside of Substrate nodes.

---

<div class="post-metadata">

**Author:** ![shunsukew](https://dub1.discourse-cdn.com/flex005/user_avatar/forum.polkadot.network/shunsukew/32/1396_2.png) [@shunsukew](https://forum.polkadot.network/u/shunsukew)\
**Post date:** [March 13, 2023, 10:21am UTC](https://forum.polkadot.network/t/meta-transaction-pallet/2302/2 "2023-03-13T10:21:44Z")

</div>

Seems like Github Issue is already there

> <https://github.com/paritytech/substrate/issues/11988>
>
> We need a way to support meta transaction to enable many useful scenarios. Howev…er meta transaction is can be very hard to implement correctly and securely.
> 
> TLDR; I don't know how to store nonce for accounts without any tokens without introducing new attack vector.
> 
> \## Scope
> 
> Firstly we need to define a scope. Here are a list of the potential use cases that I can think of and we need to decide what do we want to support and what is out of the scope. Support all of the use cases may result the solution be too complicated.
> 
> \### 1. Pay for transaction fee
> 
> Allow relayer to pay transaction fee for a user. This allows user account does not hold any fee token can still able to interact with the chain.
> 
> \#### Use cases
> 
> \- dApp onboard new users by allowing them to interact with the dApp contracts without paying transaction fee
> \- Create a better proxy account patten. Main account create limited proxy account A, send small fund on fee payment account B. Account A never holds any funds and can be rotated easily without need to move tx fee funds. All the transaction from A are broadcasted by B and B pays all the tx fee.
> \- Support any token to be tx fee token. User can craft \`batch(\[sendCustomToken(relayerAddr, amount), doTheActualWork()\])\`. And if it is profitable to pay tx fee for getting \`amount\` of custom token, relayer submit the tx to make the trade. It is up to the relayer to ensure the sendCustomToken step are expected to be successful.
> 
> \#### Flow
> 
> There are two possible flow to achieve the desired goal.
> 
> \- User sign tx
> \- Send tx payload and signature to relayer
> \- Relayer sign the transaction and broadcast it
> \- Blockchain charges relayer for tx fee, validates the user signature, and dispatch the payload tx from user origin
> 
> OR
> 
> \- User generate tx payload
> \- Relayer sign the tx payload
> \- User sign the tx payload with relayer signature and broadcast it
> \- Blockchain validates relayer signature, charges relayer for tx fee, and dispatch payload from user origin
> 
> \### 2. Atomic multi origin tx
> 
> Allow atomically dispatch a transaction mixed from different origins. It can only be successfully executed IFF all the origins signs the whole payload.
> 
> \#### Use cases
> 
> \- Atomic exchange of assets between multiple users
> - e.g. \`batch\_all(\[as\_user(alice, transfer(10 DOT, bob)), as\_user(bob, transfer(100 aUSD, alice))\])\`
> \- Perform a sequence of actions from multiple users at once without revealing it to avoid front running
> - e.g. \`batch(\[create\_swap\_pool(aUSD, DOT), as\_user(alice, add\_liquidity(100 aUSD, 10 DOT)), as\_user(bob, add\_liquidity(100 aUSD, 10 DOT))\])\` so that no one can make a trade between Alice add liquidity and Bob add liquidity
> 
> \#### Flow
> 
> \- Generate a transaction payload
> \- All party sign the transaction payload
> \- Relayer sign the transaction and broadcast it
> \- Blockchain charges relayer for tx fee, execute the payload. When encountered a \`as\_user\` call, ensure a valid signature is included.
> 
> \### 3. Attest messages delivered via XCM
> 
> One issue about XCM is that it cannot blindly trust all the messages from the source. SPREE is the solution but it will not be available anytime soon. We can verify the message are indeed authorize by a user by having the user attest the message with a signature. The signing payload should cover the whole XCM so it cannot be placed under a different context.
> 
> \#### Use cases
> 
> \- User from Astar make one transaction to send ASTR to Acala to swap to GLMR and send GLMR to Moonbeam to invoke a smart contract with origin from the user account
> \- Moonbeam user can send one transaction to transfer DOT from Moonbeam to Acala to mint aUSD and send aUSD to Moonbeam and buy more DOT on a dex
> 
> \#### Flow
> 
> \- User generate XCM payload, sign the payload and fill-in the signature and dispatch the XCM
> \- Receiving parachain receives XCM and verify the signature and grant the permission to dispatch the message from user origin
> 
> \## Security considerations
> 
> Here are some common security considerations I came up with. Please comment below if you have anything more to add
> 
> \- Single chain replay attack prevention
> - Need some mechanism to prevent replay of signatures on a same chain
> - Usually are done with nonce
> \- Multichain replay attack prevention
> - Need some mechanism to prevent replay of signatures on different chains
> - Usually are done by including the genesis hash into the payload
> \- Signature Invalidation
> - In some cases, the signature are hand off to other party for broadcasting and the other party may choose to not broadcast the message for whatever reason. In the case, the signature signer need to have the ability to invalidate the signature
> \- Context aware validation
> - The signature must be validated with a known context. e.g. A XCM to invoke a smart contract on Moonbeam cannot be copied and send to Astar to invoke the smart contract on Astar
> 
> The default signed extensions from Substrate provides a very good starting point on what needs to included in the signature payload to keep it secure and the signature validation mechanism should just reuse it if possible.
> 
> \## Implementation considerations
> 
> The common way to implement replay attack prevention mechanism is by having a sequence number / nonce that increments for each new message.
> 
> However, this is incompatible on the default storage model of Substrate. The nonce have to be stored onchain and all the onchain storages must be covered with a deposit (ED). For some use cases, the signing account will not hold any balances at all and therefore shouldn't really be able to cover the storage deposit for nonce storage.
> 
> Another point to keep in mind is that nonce can be reused on chain with ED. An account can purposefully reset's its account data to reset nonce and able to replay some transactions.
> 
> One solution is have the fee payer to give user enough balance to cover ED. But ED value can be relatively high (1 DOT on Polkadot) and therefore this solution is not universally suitable to all the chains.
> 
> Another potential solution is to expire the signature after certain amount of time so we can purge nonce data periodically but it is only suitable until we can do O(1) purge of storages with a common prefix.
