Fuel Tanks
This document outlines how to interact and modify a fuel tank.
A fuel tank is a pool of funds that can be used by multiple accounts to dispatch calls. It is created with the
create_fuel_tank
extrinsic, and it can have various settings and rules based on which fuel tank would pay for transaction fees and provide storage deposits. Calls are dispatched with the dispatch
extrinsic. A fuel tank's settings can be modified by using the mutate_fuel_tank
extrinsic.Fuel tanks require a user to have an account registered with the fuel tank before they can dispatch calls. The fuel tank owner can decide if they want users to create their own accounts by modifying the
user_account_management
field, and accounts can even be created at the same time as dispatching by using the dispatch_and_touch
extrinsic.
Accounts are added with the
add_account
or batch_add_account
extrinsics. They are removed with the remove_account
or batch_remove_account
extrinsics.When a call is dispatched, it must be dispatched through a rule set. Each rule set can contain multiple rules that determine if the call is valid or not. A fuel tank can contain multiple rule sets.

Rules can be added when the fuel tank is created. They can also be modified by using the
insert_rule_set
or remove_rule_set
extrinsics. A rule cannot be removed if it is storing user data because this would lead to orphaned data. The user data must be removed from all accounts first, using the remove_account_rule_data
extrinsic.Each rule set can contain any combination of the following rules:
- 1.Whitelisted callers
Accounts allowed to dispatch. Any other accounts that dispatch will fail.

- 2.Whitelisted collections
Collection ids that dispatch is allowed to call. If other collections are called through dispatch, it will fail.

- 3.Max fuel burn per transaction
Maximum fuel that can be consumed in a single transaction

- 4.User fuel budget
Fuel budget for a user. Includes consumption in all rule sets.

- 5.Tank fuel budget
Fuel budget for a tank. Includes consumption in all rule sets.

- 5.Require token
Require the caller to have a token. If they don’t have it, the call will fail.

- 5.Permitted calls
Calls that are permitted for this rule set. Other calls will fail.

- 5.Permitted extrinsics
Extrinsics that are permitted for this rule set, all other extrinsics will fail. While setting this rule, note that the params passed to the extrinsic does not matter, only the function name matters. For example, in the below image, the
multiTokens->transfer
call is permitted, no matter what parameters are passed.
Some changes on the fuel tank require the fuel tank or a rule set to be frozen. While a fuel tank or rule set is frozen, no dispatches are allowed. To apply a freeze, call
schedule_mutate_freeze_state
with the
is_frozen
parameter set to true
.Then call any extrinsics to make any changes you want. Then call
schedule_mutate_freeze_state
again with is_frozen
set to false
.You can either freeze the entire fuel tank, or you can freeze an individual rule set. It is recommended to only freeze the rule set you need to modify if possible. Some mutations, like removing an account, require the entire fuel tank to be frozen.

Descriptor
is the list of all the data used to create a fuel tank. It contains, name, account_management_rules, rule_sets and other configuration information related to the fuel tank.A fuel tank can be created by anyone using the
create_fuel_tank
extrinsic function, once the fuel tank is created, the owner can add funds to it and subsidise transactions that are permitted by the fuel tank. The primary function of a fuel tank is to allow a user to interact with the efinity parachain without paying transaction fees (called gas fees in Ethereum).Having transaction fees is necessary to ensure parachain security. But often this ends up being a barrier for adoption since a user cannot use a parachain without first acquiring some tokens to pay for transaction fees. A fuel tank will subsidise (pay a portion of) or completely cover transaction cost for the user subject to rules set by the fuel tank creator.

This guide uses a Custom PolkadotJS explorer pages, which are available at https://console.enjin.io/, and Fuel Tanks page is located in
Network
tab.Create a new fuel tank by providing a
descriptor
. Extrinsic generates a discrete AccountId
for the fuel tank based on passed in parameters, it takes a storage deposit and emits FuelTankCreated
event in the success case. Creation of already existing fuel tank will result in FuelTankAlreadyExists
error, while duplicate rule kinds within a rule set will result in DuplicateRuleKinds
To create a new fuel tank using the explorer, head to
Network
-> Fuel tanks
-> Create fuel tank
. This page allows you to create a new fuel tank by specifying the following options:- Name: Name for the fuel tank
- User Account Management: (Optional) Allows setting the permission level to add new accounts to the fuel tank
- Provides Deposit: boolean -> Allows specifying if Fuel Tank is providing a storage deposit for operations that require it
- Account Rules: (Optional) Allows specifying rules that are evaluated before an account is added to the fuel tank
- Dispatch Rules: (Optional) Allows specifying rules that are evaluated before an extrinsic is executed via the fuel tank
Even though the account rules and dispatch rules are optional, it is recommended to have some rules setup for your fuel tank, a fuel tank without any rules is open to anyone without limits.
This image shows how to create a fuel tank, with some basic rules, in the following fuel tank configuration only the account Alice (test account) can join the fuel tank and only Alice can dispatch operations via the fuel tank.

To mutate or modify a fuel tank, the caller must be the owner of the fuel tank, otherwise call will result in
NoPermission
error. Tank must be frozen in order to mutate it, otherwise call will result in RequiresFrozenTankOrRuleset
error. Duplicate rule kinds within a rule set will result in DuplicateRuleKinds
. In success case emits FuelTankMutated
eventTo mutate a fuel tank using the explorer, head to
Network
-> Fuel tanks
. Mutating a fuel tank involves three steps 1. Freeze the fuel tank 2. Mutate the fuel tank 3. Unfreeze the fuel tank- 1.To Freeze the fuel tank, head to
Network
->Fuel tanks
, this will present a list of all fuel tanks, select the fuel tank you wish to mutate and select freeze/unfreeze. In the next dialog box, setis_frozen
to true and execute the transaction

- 2.To mutate the fuel tank, head to
Network
->Fuel Tanks
-> under specific fuel tank ->Mutate
In the modal, select the Account (the owner of the fuel tank) and select the fuel tank id (you can get this from the fuel tanks page in the previous step) and add any modifications to the fuel tank.
In this image, we are changing the providesDeposit to
true


- 3.To unfreeze the fuel tank, head to
Network
->Fuel tanks
, and perform the same step but select theis_frozen
to false

Adds a new fuel tank user account, which not only allows using fuel tank, but also stores user consumption and rule set data. An account can be created only if account rules are successfully validated. An account is required to dispatch calls. A storage deposit is required, and may be paid by the user or the fuel tank, depending on the settings. Could fail with
NoPermission
if caller is not the owner and user management settings dont allow users to create accounts on their own. Creation of already existing account withing a tank will result in AccountAlreadyExists
error. In case some of account rules cannot validate the caller, rule specific error will be returned. In success case emits AccountAdded
event- Select the fuel tank and click add account
- Select account to be added.
- On success you should see an AccountAdded event
Removes a user account from a fuel tank and returns the storage deposits. Fuel tank must be frozen for operation to succeed, otherwise call will result in
RequiresFrozenTank
error. Account must not contain any rule data, otherwise call will result in AccountContainsRuleData
error. In success case emits AccountRemoved
eventTo remove an account from a fuel tank using the explorer, head to
Network
-> Fuel tanks
, and follow similar instructions to remove an account- select the fuel tank and click remove account

As part of enforcing the budget and max spending limits of the fuel tank, the fuel tank stores data for every account. The remove_account_rule_data allows to remove a user account rule data if it exists. Requires the fuel tank or the rule set to be frozen, otherwise will result in
RequiresFrozenTankOrRuleset
error. Only callable by the fuel tank's owner, otherwise will result in NoPermission
error. In success case emits AccountRuleDataRemoved
event.Similar to the process of mutating a Fuel Tank, the Fuel Tank must be frozen for the operation to succeed, otherwise the call will result in an error.
To remove an account rule data, head to
Developer
-> Extrinsic
-> fuelTanks
-> removeAccountRuleData
, and select the tankId, accountId to remove and the rule set and rule type to remove data from.In this example, we are removing
Bob
account data from the fuel budget
Dispatch a call through the fuel tank, where the tank would pay for transaction fees and, if configured, provide a storage deposit. All calls are subject to rule set evaluation and would result in rule specific errors in case of failure. In case the inner call fails, the
DispatchFailed
event will be emitted with wrapped dispatch error inside. In success case emits Dispatched
event.To dispatch a transaction using a fuel tank, head to
Network
-> Fuel tanks
, select the fuel tank you wish to use and select Dispatch
.Inside the dialog box that opens, select
- The extrinsic you want to call via the fuel tank,
- The rule set id you wish to apply to the transaction
- The extrinsic to execute
- If willing to pay for transaction fees that execeed the fuel tank budget threshold
In this example, Bob is using the fuel tank to transfer 1 EFI to Alice

On success, you should see the
CallDispatched
event
Lets say you are a game developer, and you have used the efinity multitokens pallet to represent some in-game assets. You want to subsidise players that want to acquire these in-game assets. Your best option is to create a fuel tank but lets set some baseline rules
- 1.You only want to subsidise transactions that are connected to your game
- 2.You want to put an upper limit on how much fee to subside for a single transaction to prevent abuse
- 3.You want to encourage more players to try out the fuel tank, so you also need a rolling budget to ensure your fuel tank is not depleted by a few heavy hitters initially.
There are many ways to structure the fuel tank rules to get this setup working, but lets use the WhitelistedCollections rule as the basis for our fuel tank rules.
- 1.Now lets assume that you have a lot of in-game assets (tokens) all grouped under a single collection_id. We are going to create a fuel tank that allows transactions that deal with these collection_id only, any other transactions will be rejected. This takes care of rule 1
- 2.We will use the MaxFuelBurnPerTransaction rule to set the max fuel burn in a single transaction to 1 EFI
- 3.We will set the TankFuelBudget rule to 2 EFI and allow it to reset every 5 blocks so that it is possible to only deplete 2 EFI every 5 block interval.
The create fuel tank transaction, will look like this:


Our fuel tank is now created, before we can test it, we have to add some funds to it, to fund the fuel tank, head to
Network
-> My fuel tanks
, select the appropriate fuel tank and select Fund

Now that our fuel tank is funded, lets test to make sure that the rules are working as intended:
Lets use a new account, to try to dispatch a balance transfer transaction via the fuel tank We use the Ferdie account to transfer 1 EFI to Alice, this should be rejected by our fuel tank since we have setup the rules to only allow transactions that deal with our collection_id.

As expected, the transaction is rejected with InvalidTransaction error

Lets try to do an expected transaction, here we create a dispatch call for a transaction that sets the atttibutes for a token withint the collection_id permitted. We will see that the transaction suceeds this time

create_fuel_tank
Create a new fuel tank by providing a
descriptor
. Extrinsic generates a discrete AccountId
for the fuel tank based on passed in parameters, it takes a storage deposit and emits FuelTankCreated
event in the success case. Creation of already existing fuel tank will result in FuelTankAlreadyExists
error, while duplicate rule kinds within a rule set will result in DuplicateRuleKinds
mutate_fuel_tank
Applies provided
mutation
to the fuel tank. Caller must be the owner of the fuel tank, otherwise call will result in NoPermission
error. Tank must be frozen in order to mutate it, otherwise call will result in RequiresFrozenTankOrRuleset
error. Duplicate rule kinds within a rule set will result in DuplicateRuleKinds
. In success case emits FuelTankMutated
eventadd_account
Adds a new fuel tank user account, which not only allows using fuel tank, but also stores user consumption and rule set data. An account can be created only if account rules are successfully validated. An account is required to dispatch calls. A storage deposit is required, and may be paid by the user or the fuel tank, depending on the settings. Could fail with
NoPermission
if caller is not the owner and user management settings dont allow users to create accounts on their own. Creation of already existing account withing a tank will result in AccountAlreadyExists
error. In case some of account rules cannot validate the caller, rule specific error will be returned. In success case emits AccountAdded
eventremove_account
Removes a user account from a fuel tank and returns the storage deposits. Fuel tank must be frozen for operation to succeed, otherwise call will result in
RequiresFrozenTank
error. Account must not contain any rule data, otherwise call will result in AccountContainsRuleData
error. In success case emits AccountRemoved
eventremove_account_rule_data
Remove account rule data if it exists. Requires the fuel tank or the rule set to be frozen, otherwise will result in
RequiresFrozenTankOrRuleset
error. Only callable by the fuel tank's owner, otherwise will result in NoPermission
error. In success case emits AccountRuleDataRemoved
eventdispatch
Dispatch a call through the fuel tank, where the tank would pay for transaction fees and, if configured, provide a storage deposit. All calls are subject to rule set evaluation and would result in rule specific errors in case of failure. In case the inner call fails, the
DispatchFailed
event will be emitted with wrapped dispatch error inside. In success case emits Dispatched
eventdispatch_and_touch
Same as dispatch, but also does create an account for a caller with
add_account
operation if it doesnt exist. Fuel tank's user_account_management
settings must allow self-service account creation, otherwise call will result in NoPermission
error.schedule_mutate_freeze_state
Schedule mutating of fuel tank or rule set
is_frozen
state for on_finalize
to execute with help of process_freeze_queue
helper function. Additional 1 read and 1 write are added to account for on_finalize
storage operations. Only callable by the fuel tank's owner, otherwise will result in NoPermission
error. In case queue already has maximum number of items, will result in FreezeQueueFull
error. In success case emits MutateFreezeStateScheduled
eventinsert_rule_set
Insert a new rule set into a fuel tank. It can be a new rule set or it can replace an existing one. If it is replacing a rule set, a rule that is storing data on any accounts cannot be removed and will result in
CannotRemoveRuleThatIsStoringAccountData
error. Use remove_account_rule_data
to remove the data first. If a rule is being replaced, it will be mutated with the new parameters, and it will maintain any persistent data it already has. Fuel tank or rule set must be frozen, otherwise will result in RequiresFrozenTankOrRuleset
error. If fuel tank already has maximum number of rule sets, will result in MaxRuleSetsExceeded
error. Duplicate rule kinds within a rule set will result in DuplicateRuleKinds
. In success case emits RuleSetInserted
eventremove_rule_set
Remove rule set from a fuel tank. A rule that is storing data on any accounts cannot be removed and will result in
CannotRemoveRuleThatIsStoringAccountData
error. Use remove_account_rule_data
to remove the data first. This is only callable by the fuel tank's owner, otherwise will result in NoPermission
error. Fuel tank or rule set must be frozen, otherwise will result in RequiresFrozenTankOrRuleset
error. In success case emits RuleSetRemoved
eventbatch_add_account
Same as
add_account
but takes a list of AccountId
s to add into a fuel tankbatch_remove_account
Same as
remove_account
but takes a list of AccountId
s to remove from a fuel tankforce_set_consumption
Force set the fuel tank consumption. If
user_id
is Some
, it sets the consumption for that account. If it is None
, it sets the consumption on the fuel tank directly. Currently only callable by fuel tank owner and sudo account, otherwise will result in NoPermission
errordestroy_fuel_tank
Destroy the fuel tank. Only callable by owner, otherwise will result in
NoPermission
error. The fuel tank must be frozen, otherwise will result in DestroyUnfrozenTank
error. Can only be destroyed if all accounts are removed, otherwise will result in DestroyWithExistingAccounts
error. Returns the storage deposit and remaining balance to the fuel tank owner. In success case emits FuelTankDestroyed
eventLast modified 24d ago