A fuel tank is a feature that allows users to interact with Efinity, without incurring transaction fees. It is essentially a pool of tokens used by multiple accounts (wallets) to make calls on Efinity. It can have various settings and rules for paying transaction fees and providing storage deposits. Fuel tanks can be modified using the Polkadot.JS interface or by setting specific parameters using the fuel tank pallet.
Similar to a car with gas, all your friends can ride in the car for free and have a happy road trip with you!
A fuel tank's primary purpose is to let users interact and use Efinity without paying transaction fees.
A fuel tank can be created by anyone using the create_fuel_tank extrinsic function. Once the fuel tank is created, it’s possible to add funds to it and subsidize transactions permitted by the fuel tank.
Transaction fees are required to maintain the security of a parachain. However, this frequently becomes a barrier to adoption because users cannot use a parachain without first purchasing some tokens to cover transaction fees, and most users who are new to blockchain would find it extremely difficult to buy tokens and transfer them to a wallet to engage with NFT projects or play games.
A fuel tank will subsidize/completely cover transaction costs for the user subject to rules set by the fuel tank creator.
Accounts: To interact with a fuel tank, users must first register an account with the fuel tank. The owner of the fuel tank has the ability to specify if they want to allow users to create their own accounts by adjusting a specific setting.
When a call is made to a fuel tank, it must be made in accordance with a set of rules. These rules, known as rule sets, can include multiple individual rules that determine the validity of the call. A fuel tank can have multiple rule sets, each of which controls access and permissions to the fuel tank's functionality and resources.
Whitelisted Callers: Whitelisted callers are accounts that are explicitly granted permission to make calls to a fuel tank. Any calls made by accounts not on the whitelist will be rejected and fail.
Whitelisted Collections: Whitelisted collections refer to a list of specific collections allowed to be called by dispatch on a fuel tank. If a dispatch call is made to any collection, not on the whitelist, it will be rejected and fail. This ensures that calls are only made to the specific collections authorized to be accessed.
Max Fuel Burn Per Transaction: It is a setting that limits the amount of fuel that can be consumed in a single transaction. It is a safety measure that helps prevent misuse and overuse of the fuel tank's resources by ensuring that a single transaction doesn't consume too much fuel, which is important to ensure a sustainable network.
User Fuel Budget: A user fuel budget is the total amount of fuel allocated to a specific user across all rule sets of a fuel tank. It sets a limit on the amount of fuel that can be consumed by a user's transactions. Once the user's fuel budget is exhausted, their transactions will fail until more fuel is added to their budget or their overall consumption is lowered , which is meant to avoid the overuse of resources and ensure a sustainable network.
Tank Fuel Budget: A tank fuel budget is the total amount of fuel allocated to a specific fuel tank across all its rule sets. It sets a limit on the amount of fuel that can be consumed by all transactions made through that tank. Once the tank's fuel budget is exhausted, all transactions will fail until more fuel is added to the tank's budget or overall consumption is lowered.
Require Token: The "Require token" setting indicates that a specific token must be held by the caller for their call to be accepted by the fuel tank. If the caller does not possess the required token, their call will be rejected and fail. This feature is intended to ensure that only users who hold the specified token can access the fuel tank's functions and resources.
Permitted Calls: Permitted calls refer to a list of specific function calls that are allowed to be made using this rule set. Any calls made to other functions will be rejected and fail. This ensures that only authorized calls can be made by the users, and also, by setting a boundary to what calls are allowed and what calls are not, it helps to protect the network from unwanted transactions that could impact negatively on the network.
Permitted Extrinsics: Permitted extrinsics refer to a list of specific extrinsics that are allowed to be made using this rule set. Any extrinsics that are not on the list will be rejected and fail. This feature is used to restrict access to specific functionality and resources on the network and ensure that only authorized calls can be made by users. When setting this rule, it's important to note that the parameters passed to the extrinsic do not affect the outcome, only the function name is considered.
Freezing: : "Freezing" is a state where a fuel tank or a rule set is temporarily prevented from accepting calls or making changes. This means that while a fuel tank or rule set is frozen, no dispatches are allowed to occur on it. This is implemented as a safety measure to prevent accidental or malicious changes and to ensure that the fuel tank or rule set remains in a stable state until the freeze is lifted.
Descriptor: A descriptor is a list of all the data needed to create a fuel tank. It includes details such as the fuel tank's name, account management rules, rule sets and other configuration information related to the fuel tank. The descriptor acts as a blueprint that defines how the fuel tank is set up and how it will function. It contains all the information needed to create and configure the fuel tank, and can be used to modify the fuel tank's settings.
Once you have accessed the fuel tanks page, click on the “Create Fuel Tank” button. The page which appears, allows you to set the following parameters:
In the screenshot below, we can see how to create a basic fuel tank with entry-level rules, where only the account Tassio (our test account) can join the fuel tank and dispatch an operation via the fuel tank.
To mutate or modify a fuel tank, the caller must be the owner of the fuel tank; otherwise, the platform will return an error related to permissions. It’s also important to freeze the tank before mutating it, so that it cannot perform any transactions while being mutated.
To mutate a fuel tank using the Efinity Explorer, head to the Network tab and click on “Fuel Tanks”.
From there, you will see your fuel tank, and you can also click on the drop-down arrow to show all available options. Please note that you will be able to interact with fuel tanks created by your account.
Mutating the already existing fuel tank involves 3 simple steps:
1. Freeze the Fuel Tank — Head to Network → Fuel Tanks; this will present a list of all fuel tanks. Select the one you wish to interact with and click on Freeze/Unfreeze. Then, in the following dialogue box, set the is_frozen parameter to true and execute the transaction as shown below.
2. Mutate the Fuel Tank — The process for mutating the fuel tank goes through the same steps as those for freezing one. Head to the Network tab → Fuel Tanks. This will present a list of all fuel tanks. Select the one you wish to interact with and click on Mutate. In the following dialogue box, choose the account of the fuel tank owner and select the fuel tank ID. You can then add any modifications that you may choose.
3. Unfreeze the fuel tank — To unfreeze the fuel tank, head to Network → Fuel Tanks, and perform the same steps, but change the value of is_frozen to false.
This command allows you to add a new fuel tank user account. This allows the use of the fuel tank and storing consumption and ruleset data for the user and the fuel tank. An account can only be created if the rules are validated.
It’s important to note that a storage deposit is required for this, which, depending on the settings, may be paid by the user or the fuel tank itself.
It’s also important to note that this could fail with NoPermission if the caller is not the owner and the user management settings don't allow users to create accounts on their own. Creation of an already existing account within a tank will result in AccountAlreadyExists error. A rule-specific error will be returned if some account rules cannot validate the caller. In success, it emits an AccountAdded event.
Head to Network → Fuel Tanks, select the fuel tank of your choice, click on add account, select the amount to be added and click on Add account, as shown in the screenshot below.
If the process works as expected, you should see an AccountAdded event on the network.
This command allows you to remove a user account from a fuel tank and return the storage deposit to the account which paid for it. To remove an account from the fuel tank, make sure that the fuel tank is frozen, as the operation cannot be executed otherwise. Removing all rule data from that specific account is important to prevent any errors.
Head to Network → Fuel Tanks, select the fuel tank of your choice, click on remove account, select the account to be removed and click on Remove account as shown in the screenshot below.
If the process works as expected, you should see an AccountRemoved event on the network.
To enforce the fuel tank’s budget and max spending limits, the fuel tank stores data for every account. This command allows the removal of user account rule data if it exists. This also requires the fuel tank or the rule set to be frozen to prevent errors. This call is only able to be performed by the Fuel Tank owner.
Head to Developer → Extrinsics → FuelTanks → RemoveAccountRuleData, select the tankID and the accountID to remove as well as the rule set and rule type to remove as shown in the example below.
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. If the inner call fails, the DispatchFailed event will be emitted with a wrapped dispatch error inside. If successful, 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 click on the Dispatch menu.
Inside the dialog box that opens, select
If all the dispatch parameters are correct, it should return a CallDispatched event on the network.
Last but not least, we will go through the process of creating a fuel tank that pays for transactions for your own game/project!
As a game developer building on Efinity, you would have some tokens created by your collection. Having a fuel tank set-up for your collection would allow users to acquire your in-game items by subsidizing their transactions.
As a good set of rules, we have the following suggested guidelines —
There are many ways to structure the fuel tank rules to get this set-up working, but let's use the WhitelistedCollections rule as the basis for our fuel tank rules.
The created fuel tank transaction should look like this —
Now that your fuel tank has been created, we need to add some funds to it. To do this, head to Network → My Fuel Tanks, select the respective fuel tank created by you and click on Fund.
Now that this fuel tank has enough funds, we can run some tests to ensure all the rules are working as expected!
Using a new account, we can try to dispatch a balance transfer via the fuel tank.
In this example, we use the Ferdie account to transfer 1 EFI to Alice. Our fuel tank should reject this since we have set up the rules only to allow transactions that deal with our Collection ID.
As expected, the transaction is rejected with an InvalidTransaction error.
Let's try to do another transaction. Here we create a dispatch call for a transaction that sets the attributes for a token within the permitted collection ID. This should result in a successful transaction.
The screenshot below, shows us what a successful dispatch looks like.
Fuel tanks will be a game changer for adoption with unmatched flexibility to set rules at user level. Efinity brings true disruption to those building on blockchain.
To Efinity and beyond!