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.
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
:
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.