Experimenting Payment Of Transaction Gaz Fees In Token
I. How transactions work on Ethereum
(If you already know how it works, go straight to II.)
A transaction (tx) is a message signed off with a private key and published on the network using an Ethereum node.
A message contains :
- The address of the receiver
- The value in Ether the sender wants to send to the receiver
- The data sent to the receiver
- The gas the sender wants to pay for the transaction to happen
- The gas price for your transaction
- The nonce
Once the message is signed, it’s published on the network and the tx will go from node to node until a miner gets it and adds it to a block, earning a reward in the process.
A transaction contains information on:
- the receiver (the person you want to send the transaction),
- the value (the smallest unit of ether, names wei)
- the data (the information the receiver needs to act upon receiving the transaction.
- To transfer Nexium tokens to someone, smart contracts (ERC20, a piece of code) will do the job (not the ethereum protocol itself).
It means you won’t send a tx directly to the person you want to transfer nexiums to. You’ll transact with the Nexium smart contract itself and it will look like this:
- Receiver : 0x45e42D659D9f9466cD5DF622506033145a9b89Bc (Nexium smart contract address)
- Value : 0 (you won’t send any ether)
- Data : The fact that you want to transfer Nexiums + The person you want to transfer nexiums to + the amount of nexiums you want to send
Sign off using your private key and publish it on the network but… what if someone took this signed information from the network and publish it again making you spend even more nexiums in the process?
It’s impossible thanks to the nonce system.
A nonce is an index, a tx counter. The first tx you’ll make will have a nonce set to 1, the second to 2 etc. When the network receives a signed tx with a nonce already used, the network doesn’t add it to a block, the sender won’t pay extra fees.
The Nexium smart contract (ERC20) is fairly simple, making it easy for the network to compute the results but it’s still heavier than sending ethers so someone. And other smart contracts are more complex than the Nexium’s. Why pay the same fee as someone using a lot more of computational power and storage resources than you? Gas exist for this reason.
To publish a transaction, one has to provide some “gas”. It will be used to fuel the network for the computation of the transaction. If the transaction is not finished and there is no gas left, it will fail and all your gas will be used up anyway. The more complex your tx is, the more gas you’ll need.
For each unit of gas used for your transaction, you’ll pay fees. Gas price is most of the time low, 1/100 000 000 of ether. A transaction costs a minimum of 21 000 gas, and for an ERC20 token, the transaction will cost roughly 70 000 gas.
If the gas price is 1/100 000 000 ether, it will cost 0.0007 ether.
At the time of writing, it’s about 0.28€. Not so low after all. Here’s how ethereum fees are calculated:
II. Getting Around Transaction Gaz Fee
Besides the transaction cost, the Blockchain technology has many frictions in terms of user experience. Poor usability and lack of education in the matter is a big issue hindering the mass adoption.
Any player wanting to purchase one of our game asset would have to own wallet with ethereum and use the latter to buy nexium tokens and also pay transaction fees.
So, if the back-end is stored on a smart contract, transaction fees must be paid in ether to interact with it. There is no way around it.
We tried a series of attempts to go around it.
- Refund in ether the user what was paid for the transaction
- Pay directly the miner in ether when mining transactions and ask the user to not provide any transaction fee.
Making a tx on behalf of your user seems a good idea.
However, in a decentralised world, it’s not so easy.
First of all, you are exposed to spammers and leads to multiple issues. For example, without the user’s private key, you can’t make transactions on his behalf. Like in any ERC20, the contract the user will interact with needs to be called in from their private key.
To rule out any fraudulent use, we usually use an available variable, called “msg.sender”. It contains the entity address calling your smart contract. It can be an user as well as another smart contract. It can be used to compare the address of the expected user. If you interact with the function “transfer” of an ERC20, the contract will move the balance of the “msg.sender” directly. So if you are not your user, you’ll never be able to move his tokens.
Basically, in the current state of ERC20 and ethereum ecosystem, users will have to pay the fees in ether.
III. Signed Messages
The network knows the author of a transaction is genuine by demanding the private key signature. In solidity, you can also verify these signed messages. With a signature and a message, one can retrieve information on the author of the transaction.
So instead of relying on the entity that calls in the smart contract (the “msg.sender”), it’s possible to make a smart contract accept a signed message and rely on the person who signed it.
Your user can then sign a message, give it to you and you are the one publishing it from your private key to the contract. And it works.
This system has been thought by many. It’s been implemented for example in BokkyPooBahsTokenTeleportationService. The smart contract allows user A to sign a message while the transaction is made by user B. The latter gets a refund for the fee paid in ether, taken from the token transferred by A.
We kept the use of a nonce inside this process : if the contract didn’t store an index, it wouldn’t be able to avoid a simple copy paste of the signed message.
The only blockchain transactions without using ether is by using tokens. It means it’s not possible to deploy a smart contract and pay the fee in tokens.
It’s also not possible to move tokens and pay the fee with other tokens.
Signing off a message outside of the blockchain and making a smart contract decode the signature was the solution we went for.
IV. Why Not A Wallet?
Instead of implementing this feature on each smart contract we deploy, we use a smart contract as a wallet. The owner of the wallet will sign transactions and give it to someone else that will publish it.
The contract is an intermediary between a user and the blockchain. It receives a meta transaction signed off by its’ owner and process the real transaction on the network. Note that you’ll have to stop using your user’s address to interact with him. You’ll have to interact with his wallet address instead.
The wallet takes a transaction from anyone, check if the owner signed off the message that is put in parameters and make the transaction on behalf of the user. This contract is unique for each user. The contract can own other tokens, can publish smart contract, can be the owner of another smart contract etc.
V. The downsides
It’s more expensive
In a normal use case you pay only the gas for the transaction. Here, you’ll need to call one more smart contract. It comes with extra fees.
If the transaction cost continues to increase on ethereum, this issue will be critical.
It’s not compliant with some standards
With ERC223 for example, the contract cancels any token transactions going to other smart contracts (if a fallback function“tokenFallback” is not embedded). Every standard looking like ERC223 (using ERC165) might be inconsistent with the wallet.
You must publish a new contract for each user
What we like about this is, the user doesn’t need any ether as long as he has tokens on his wallet.
To create his own wallet he should have ether, and we are stuck. Except if you gracefully pay for them. It works as long as devs use a good anti spam for account transaction in their system. Transaction fees are de facto the anti spam.
In a fully decentralised ecosystem, it’s a difficult question.
Another solution would be for the user to get some nexium on the contract before it’s published (sounds impossible but it’s actually possible) and add a fee in the constructor.
We will create the contract once the user spent some money in our system.
Meta transactions must find the user publishing the tx
In normal transactions, transactions relay on ethereum node and the network will pass it to the miner. Either we must recode a whole peer to peer protocol, or find a new solution. We’re currently looking into the 0x protocol.
For businesses working with users not yet familiar with the blockchain, a good approach is making them pay transaction fees in tokens in a very seamless UX/UI.