You don't Need Ether to Transfer Tokens
You don’t Need Ether to Transfer Tokens
This article introduces a new token (standard) which doesn’t require token holders to hold Ether to manage their tokens. We have recently launched such a token at the crypto-startup DreamTeam, the first esports and gaming recruitment and management network.
If you think that ERC20 tokens are something new and terrible, think again. Our world is already full of tokens:
- Currencies of different countries are tokens. In order to buy something, say, in Ukraine, you need Ukrainian Hryvnias. When you buy something in Ukraine with your dollar credit card, you are charged in dollars, but a bank exchanges it into Hryvnia behind the scenes.
- You then exchange those “tokens” for another type of “tokens”, which, for example, may grant you access to a public transit or your favorite cinema.
- Any form of discount can be considered tokens. You can use discounts in particular places and trade them for other “tokens”.
- Any item, like stamps or fridge magnets, can be considered tokens!
Of course, the more tokens we have, the harder it is to manage all of them. But eventually, everything will always be compared to the most stable token (as it is today for USD or EUR).
As far as you probably know, in order to transfer common ERC20 tokens, token owners must have Ether on their balances. This introduces quite a big inconvenience for users: in addition to the tokens they want, they also need to get Ether somewhere. Imagine spending dollars and then being asked to also hand over some Hryvnias.
Managing two crypto assets instead of one creates more problems both for users (they have to manage two assets instead of one) and application owners (as each little complication drastically drops the number of users).
The Need of Ether
The need of Ether to transfer tokens is not just about how Ethereum was made. To keep any decentralized network (today’s blockchains) running smoothly, it requires support and that doesn’t come free. The payment usually comes in the form of some kind of currency fee or computing power. If everyone made transactions without paying network fees, the network would be spammed with millions of transactions and, eventually, reach its peak capacity.
In Ethereum, you must pay fee in Ether for any network state change, thus rewarding miners for including your transaction into the block. Fees in Ether are paid for each transaction, including transferring Ether, deploying smart contracts and executing smart contract functions.
Taking into account that current Ethereum is made of nearly 90% different ICOs and transactions that utilize ERC20 tokens, an inconvenience about holding Ether makes those projects highly narrowed only to those users who are experienced enough in terms of Ethereum, and not useable at all for the masses.
In the ideal decentralized web3 world, every individual has their private key (secret), which they use to interact with the network on their behalf. No one can ever transact on the network on someone’s behalf if they don’t know their private key. In terms of Ethereum and other crypto-platforms, your wallet (Metamask, Exodus, Trezor, etc) holds this private key for you and thus only you are able to do transactions on behalf of your account (public address) on this network.
The public address, or your account’s address is generated by hashing the private key. It is impossible to know the private key from the public address, which is one of the great properties of the hashing function. This means that you are safe to share your public address. To prove that you own the private key, you can simply put your digital signature on any requested data.
In Ethereum, when you are about to do a transaction, say, send some Ether or tokens, you have to sign the transaction data and submit both the data and corresponding signature to the network. As only the private key owner can make a valid signature, it is guaranteed that no one else will be able to forge the signature nor change the signed data and transact on the network on behalf of your public address.
There is a problem with Ether-free transfers. In Ethereum, by design, the transaction fee is subtracted from the account which makes the signature. Theoretically, we can set this fee to 0, by setting the gas price to 0. But practically, today, the transaction fee is the only motivation for miners to include your transaction into the next block, so you have to set it to a reasonable amount. Or, alternatively, you have to contact the top miners directly and ask them to always include your transaction into their blocks (which is not even an option).
However, think about it this way: we always have to pay transaction fees in Ether. However, does it really matter who pays this fee? For instance, we can write such a smart contract that will perform certain actions, no matter which account made the transaction. Moreover, we can utilize public key cryptography in the smart contract itself, which opens wide possibilities for asset management.
ERC20-Compatible Token that can be Transferred without Ether on the Sender’s Balance
By having an ability to cryptographically prove that you are an account (address) owner, let’s design an ERC20-compatible token smart contract, which will allow the transfer of someone’s tokens by having their valid signature on the transfer data (arguments of transfer function). In this scenario, the Token Sender doesn’t need Ether, as the transaction will be published by the Transaction Publisher. However, we still need some confirmation from the Token Sender about their intent to send tokens, so we have to prompt the Token Sender for their signature, which is a free operation.
Here’s how this works:
- The Token Sender signs the arguments to the transfer function (recipient, amount). There are plenty of ways the Token Sender can create a signature, more on this below. For now, assume that signing is just a pop-up window, where the Token Sender clicks “Sign”.
- The Token Sender gives their signature with the corresponding signed data to a Transaction Publisher, an account that has some Ether and is able to do transactions on the Ethereum network.
- The Transaction Publisher executes a special function in the contract, named, say, transferViaSignature. This function takes the transfer data along with the Token Sender’s signature.
- The smart contract validates whether the signature is valid and does the token transfer.
Great, we’ve just made the Token Sender happy! Now, they don’t need to go to an exchange and buy Ether. However, this design doesn’t include the following problems:
- The Transaction Publisher always spends Ether and never gets rewarded for his job.
- Nothing prevents the Transaction Publisher from using the same signature multiple times.
- There’s no control for the Token Sender over when the signature expires nor options to destroy the signature.
- When the Transaction Publisher sends the transaction to the network, everyone sees the signature. This way, anyone can submit the same transaction with a higher gas price, for example. Thus, the transaction will be published from another Transaction Publisher.
We can simply fix the first problem by motivating Transaction Publishers in some way. Transaction Publishers can ask for some kind of fee in order to compensate for spent Ether. Taking into account that in many cases the Token Sender only has one type of token, so it’s rational to give the reward to the Transaction Publisher in that token so as to not need Ether .
To make the signature unique and solve problem #2, the Token Sender also has to sign some sort of “signature identifier” in addition to the transfer function parameters. The Smart contract code then can store the signature identifier and check whether the same signature has already been used. Alternatively, we can remember used signatures and not allow the use of the same signature twice.
To give the Token Sender more control over when and how the signature can be used and solve problem #3, we can introduce one more parameter which the Token Sender has to sign, a deadline. This parameter will be validated by a smart contract and guarantee that the signature expires at some point in the future.
And finally, to solve problem #4, when a transaction can be mined by another Transaction Publisher, we also have to include the Transaction Publisher’s address to the Token Sender’s signature. Or, more elegantly, let’s call it fee recipient. No matter who has submitted the transaction, the transaction fee goes to the given address.
Regarding points #2 and #3 (the signature identifier and deadline), this is a design which we have implemented at DreamTeam, but there are a couple of other options available about which data to sign and validate. For example, in the ERC865 proposal, which originally inspired me to do our own implementation, there’s no deadline, and instead of a signature identifier an unsigned integer nonce is used.
I’ve also seen some implementations where people use nonce for signatures in the way Ethereum uses nonce for transactions: each following transaction (via signature) requires a higher nonce set than the previous one. While such implementation saves some gas (starting from the second transaction via signature), it requires a more strict workflow and dApp maintenance, because of two reasons:
1. In the case the Token Sender makes multiple signatures at once, the application must ensure that the Transaction Publisher submits transactions to the network in sequential order, ensuring that the nonce conflict doesn’t happen.
2. Without the relatively cheap deadline parameter, there’s no other option for the Token Sender to expire the signature other than to manually do a transaction on the network spending even more Ether (to mark nonce in the signature as used).
So far, we have been discussing simple token transfers via signature. But the ERC20 standard also features two more functions: approve and transferFrom. These functions can be implemented by analogy, paying a small fee in tokens to the Transaction Publisher. In the case of transferFrom, it makes sense to take the fee directly from the allowed amount, as, almost, the only use case is when this function is used “by the signature” is for token withdrawals to a personal account.
Now, let’s talk about something more complicated: signature standards.
At the time of writing this article, there isn’t a single signature standard established by the community, and this is a problem. In order to verify signatures on a smart contract, we need to, for sure, know the algorithm of how the signature was created. Currently, as far as I know, there are at least 4 different signature standards supported by different clients (wallets):
- eth.sign, which signs the data as-is. Supported by Metamask with a deprecation warning.
- eth.personal.sign, originally implemented in Geth, which prepends “x19Ethereum Signed Message:n” prefix and a data bytes length in ASCII. Supported by Metamask, Mist and some other wallets such as Trust.
- “Fixed” eth.personal.sign, which prepends “x19Ethereum Signed Message:n” prefix and a data bytes length in HEX. Implemented in Trezor and Ledger (and possibly in other software/hardware wallets).
- SignTypedData, originally proposed in EIP712 by Leonid Logvinov of 0x. Supported by Metamask.
Let me show you a quick example. When using the most widely adopted eth.personal.sign, in a pop-up of your wallet, you are presented with some unreadable gibberish, which is very bad from a UX point of view:
Even though this gibberish could be a readable HEX string, it is still not obvious to users what they are putting their signature on. The SignTypedData signature standard solves this and makes the signature pop-up more readable for users while maintaining the same level of security:
While the best available option from the options above is obviously to go with SignTypedData, it is not widely adopted yet, and still, is a subject to potential (UX) improvements. However, as you may have noticed from the screenshot, the amount to transfer and the fee is displayed in decimals, which is a signature standard limitation. Our token has 6 decimals. Imagine how much more difficult it would be for users to check the amount in the case of 18 decimals.
In our DREAM token, we managed to implement all existing standards, at the time of development (and writing this article). We did a separate function in a smart contract that performs a signature validation, along with validating signature expiration timestamp. You are free to look over our implementation ideas and discuss what can be added or improved.
Some statistics on gas consumption using transfers via the signature standard:
- eth.personal.sign: ~79.5k gas (94.5k gas on the first transfer)
- eth.personal.sign on the HEX string: ~123k gas (~138.3 on the first transfer)
- signTypedData: ~79.8k gas (~94.8k gas on the first transfer)
- simple token transfer that uses Ether: ~36.8k gas (~51.8k gas on the first transfer)
As you can see, transferring tokens via a signature consumes around 2 times more gas than simply transferring tokens with Ether. Nevertheless, enabling such great features in token smart contracts is worth it.
To launch a successful application today, you have to make its user interface as easy and straightforward as possible. Modern corporations and startups spend millions on designing easy to use interfaces and perfecting the user experience. When it comes to Ethereum applications that use standard ERC20 tokens, UX can drastically go bad and make the application unprofitable, all because the need to pay fees in Ether.
The proposed solution in this article eliminates the need for users to pay fees in Ether while maintaining the same level of security. In a combination with well-designed application, it can eliminate the need for users to care about the underlying Ethereum platform all together.
While the proposed solution requires writing ERC20-compatible token smart contracts that support some actions via signature, one can adopt the solution to existing ERC20 tokens, by utilizing a similar strategy as multi-signature wallets do: to deploy a dedicated (tiny) smart contract for each account that won’t hold Ether. In general, the only difference here would be the initial deployment cost for each new account.
Thank you for reading! Follow me on Medium for more interesting stories about cryptoplatforms, programming and useful things!