Security issues that may arise with ERC777 and arbitrary contract calls

Recently, while working with one of our clients, we discovered an interesting vulnerability that could serve as an attack vector for some DeFi projects. This vulnerability is particularly related to the popular ERC777 token standard. Furthermore, it is not just a simple reentrancy issue commonly seen in well-known hacks.

This article provides a comprehensive explanation of ERC777, covering all the necessary details. There are few resources that delve into the specific details of ERC777 tokens, making this article a valuable detailed guide for those interested in a deeper understanding of ERC777 tokens.

In the final section of the article, our recent discovery will be explained.

Brief Description of Attack Vector

This vulnerability exploits the feature of ERC777 to set a Hook receive function. By leveraging the ability to make arbitrary calls within the target contract, a malicious caller can call the ERC777 registry contract and assign a specific Hook address for the target contract. Therefore, whenever the target contract receives ERC777 tokens in the future, the attacker’s Hook contract will be triggered. This Hook can be exploited in various ways: either for reentrancy attacks to steal tokens, or simply for a fallback transaction, thereby preventing the target contract from sending or receiving ERC777 tokens.

ERC777 and Its Hooks

What is ERC777

ERC777 is one of the token standards with transfer Hooks. Here is the EIP description: https://eips.ethereum.org/EIPS/eip-777, and here is an ERC777 implementation [4].

The main motivation for implementing ERC777 tokens is to mimic the behavior of native token transfers. By triggering a smart contract upon token reception, developers can execute specific logic to enhance functionality and create more dynamic token interactions.

However, these extra calls during the transfer process make ERC777 different from ERC20 tokens. These Hooks introduce a new attack vector that may impact smart contracts that did not consider handling extra calls during token transfers at design time. This unexpected behavior introduces security risks to these contracts.

Here is a list of some ERC777 tokens with some liquidity on the Ethereum mainnet:

When the Hook Occurs

ERC20 tokens simply update balances during the transfer process. But ERC777 tokens do this differently:

1. Call the address of the token issuer via Hook

2. Update the balance

3. Call the address of the token recipient via Hook

These are well explained in the VRA token:

Source code: https://etherscan.io/address/0xf411903cbc70a74d22900a5de66a2dda66507255

Now let’s take a look at the code for these calls:

As you can see:

  1. This function reads a contract called _ERC1820_REGISTRY, which is referred to as the “implementer”

  2. If this function finds an implementer, it will be called.

Let’s take a look at the registry and implementers to see what they are.

Registry and Implementers

All ERC777 tokens are associated with the Registry contract: https://etherscan.io/address/0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24.

This address is used by ERC777 tokens to store set Hook receivers. These Hook receivers are called “interface implementers”.

This means that Alice can choose Bob as her interface implementer. If Alice receives or sends an ERC777 token, Bob will receive the Hook.

Alice can manage different types of Hooks. So when Alice sends tokens, she can choose Bob as the interface implementer, and when Alice receives tokens, she chooses Tom as the implementer.

In most cases, she can also choose different interface implementers for different tokens.

These preferences are stored in the registry in this mapping:

_interfaceHash is the identifier Alice uses to choose an interface implementer for an event.

And anyone can read Alice’s interface implementer with this function:

As you can see, this is the function we encountered earlier in the VRA code.

The variable _TOKENS_SENDER_INTERFACE_HASH is used as _interfaceHash, and it can be any byte. But VRA tokens use these bytes to identify this type of Hook:

Receiving Hook

Set up a Hook receiver function, where Alice simply calls the function on the registry and inputs Bob’s address as the _implementer parameter.

She also needs to specify an _interfaceHash. She can get this from the VRA token code as _TOKENS_SENDER_INTERFACE_HASH.

There is an important detail to note.

After setting the implementer for the VRA above, Alice will realize that even if other ERC777 tokens are transferred, Bob will receive the call. For example, imBTC [5], which has the same _interfaceHash on the tokens it sends.

This is because all ERC777 tokens share the same registry contract to store Hook preferences. But this depends on ERC777 tokens naming their Hooks in a similar way, which is not always the case.

Finding ERC777 Tokens

Calling the registry is a feature that all ERC777 tokens have. Therefore, we can try dune.com [6] to call all smart contracts that call the registry.

We can use this SQL script. In fact, we should filter out token addresses separately, but at least we have a perfect starting point, with 78 addresses as the result.

Translator’s note: the dune traces table [7] will record transaction internal call records.

Is this registry the only one possible?

In theory, no one can guarantee that some tokens will use this 0x1820 contract as their registry. But we can check with dune.com [8].

It returns these addresses

0x1820a4b7618bde71dce8cdc73aab6c95905fad240xc0ce3461c92d95b4e1d3abeb5c9d378b1e4180300x820c4597fc3e4193282576750ea4fcfe34ddf0a7

We have checked that 0x1820 is the only registry with valuable ERC777 tokens. Other registry tokens are not as valuable.

General Case of Hookable Tokens

ERC777 is not the only standard with Hooks. There are also ERC223, ERC995, or ERC667. They are not that rare. You must have heard of the LINK token [9] which implements ERC667.

Using Any Caller Attack Vector

This is an attack vector recently discovered for our customers.

Researchers usually assume that ERC777 tokens will call the initiator and receiver. However, in reality, the initiator and receiver can choose any “Bob” as the hook receiver.

So imagine what happens when combined with contracts that can make arbitrary calls to any address with any data?

Contracts with arbitrary call capabilities can widely exist in DEX aggregators, wallets, and multicall contracts.

Translator’s Note: Arbitrary call capability refers to a function in a contract that looks like this:

function execute(address target, uint value, string memory signature, bytes memory data, uint eta) public Blockingyable;

It can call any other method.

Attack method:

  1. The attacker finds a target contract (Target) that allows arbitrary calls

  2. The attacker calls on the target (Target):

  3. registy1820.setInterfaceImplementer(Target, hookHash, Attacker)

  4. Now, our Attacker is the implementer of Target

  5. Attacker will be invoked with the hookHash used in the ERC777 token.

  6. Whenever the target contract ( Target ) receives an ERC777 token, Attacker receives a Hook call.

  7. The following attack depends on the Target code:

  • Attacker can perform re-entry when some users execute functions in the target contract.

  • Attacker can directly refund, so the user’s transaction is directly reversed.

If the DEX aggregator calculates the best exchange path through a DEX trading pair with an ERC777 token, there may be a problem.

Protection

After hours of discussion with the client, we found a solution that won’t break any arbitrary call.

The project is best served by limiting the use of Registry1820 as the arbitrary call address. Thus, no attacker can leverage arbitrary calls to set the interface implementer.

Words of Experience

Projects and auditors should be aware of the Hook behavior described in ERC777. These tokens not only call the receiver and initiator, but also call some other Hook receivers.

In this sense, projects that allow arbitrary calls must be particularly careful and consider another attack vector of ERC777.

Like what you're reading? Subscribe to our top stories.

We will continue to update Gambling Chain; if you have any questions or suggestions, please contact us!

Follow us on Twitter, Facebook, YouTube, and TikTok.

Share:

Was this article helpful?

93 out of 132 found this helpful

Gambling Chain Logo
Industry
Digital Asset Investment
Location
Real world, Metaverse and Network.
Goals
Build Daos that bring Decentralized finance to more and more persons Who love Web3.
Type
Website and other Media Daos

Products used

GC Wallet

Send targeted currencies to the right people at the right time.