Save on fees, lose your tokens

Using the Feeless library exposes you to new attacks

Trying to save on transaction fees can leave you with empty hands. (Photo by Jeremy Yap on Unsplash)

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.

The Attack

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 msg.sender with msgSender:

Token Code for feeless ERC827 token.

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:

The feeless modifier as implemented in the library.

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:

The attacker code which approves itself 100 tokens.

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.