Save on fees, lose your tokens
Using the Feeless library exposes you to new attacks
Last month, Anton Bukov introduced the
Feeless library, a very interesting approach to pay Ethereum transaction fees in tokens: https://medium.com/bitclave/do-not-pay-transaction-fees-in-ethereum-21a9dccaaf63
While I recommend reading Anton’s article, I will give my personal summary here: Instead of sending a transaction, which incurs transaction fees, the token holder produces a specific signature that allows others to execute the transaction. Others can send the transaction and pay the fees, potentially receiving tokens in return. The transaction result should be identical to the regular execution.
As Anton and Roland Kofler asked for feedback, we are happy to provide our view on the security. Like Anton, we will also use a token for our demonstration, however, for reasons that will become clear later, it is an ERC827 token.
We think that library’s design is likely to lead to unforeseen attacks that would not have been possible in the original implementation. We therefore, advise not to use
Feeless in its current state or only after performing a qualified security audit.
Our example is analogous to Anton’s original example. Using the library, we modify the
approveAndCall function, as intended, by adding the
feeless modifier and replacing
As we can see above, the ERC827 Token will notify the token receiver about the transfer in line 28. An attacker can use this functionality to construct a reentrancy attack against an implementation with
Feeless that would otherwise not be feasible. Why? Because the implementation of the
feeless modifier which is added to the relevant functions is not protected against reentrancy:
As we can see above,
msgSender is not reset in case of a reentrancy. Therefore, in case of an ERC827 token transfer the receiver can reenter the
approveAndCall function and perform a higher token approval in the name of the sender.
In short, the receiver can steal additional tokens from the sender.
In our GitHub repository we provide the code for the complete example. You can execute the attack by running the test case. The test case uses the following attacker code, which is required for performing the reentrancy:
Finally, please note that there might be additional issues with the design or implementation of
Feeless or related approaches. We have not performed a full audit. In case this article sparked your interest in our services, feel free to visit us at https://chainsecurity.com
Our research-based solutions can automatically identify these security issues. The upcoming full release of Securify will enable these checks. Stay tuned.