GitHub Logo HIP-719: Associate and Dissociate Tokens via Facade Contract

Author Luke Lee
Working Group Nana Essilfie-Conduah, Danno Ferrin, Mohammed Shaikjee
Discussions-To https://github.com/hashgraph/hedera-improvement-proposal/discussions/722
Status Accepted
Needs Council Approval Yes
Review period ends Wed, 10 May 2023 07:00:00 +0000
Type Standards Track
Category Service
Created 2023-04-19
Updated 2023-11-01
Requires 206, 218, 376

Abstract

HIP-218 proposed a way to enable treating HTS tokens in an equivalent manner to ERC-20 and ERC-721 tokens by creating a proxy redirect facade contract. This proposal extends this functionality to include the HTS associate dissociate and isAssociated functions.

Motivation

There are some functions that are unique to Hedera HTS tokens that are not part of the ERC standard. A mechanism should be provided to enable developers to call these functions on HTS tokens in a way that is familiar to users of ERC-20 and ERC-721 tokens. Additionally, these token functions should be callable by both EOAs and contracts.

Rationale

By adding associate dissociate and isAssociated functions to the token proxy redirect facade contract, functionality that is only available to HTS tokens can be included to the available capabilities of token contracts.

User stories

  1. As a developer, I want to be able to call the associate dissociate and isAssociated functions on HTS tokens in a way that is similar to calling functions on the IERC20 and IERC721 interfaces.
  2. As a DApp, I want to be able to enable users to call the associate dissociate and isAssociated functions without having to have intermediary contracts.

Specification

The method by which the redirection to proxy contract is currently implemented is that during the execution of an EVM request, the contract address is examined to determine whether it is an HTS token address and if so then the request execution is redirected to the proxy contract.

More specifically the algorithm by which the system gets from (a) the call to the token address to (b) the precompiled contract is as follows:

  1. The EVM encounters a call such as this tokenAddress.<functionName>(<params>);
  2. The EVM calls HederaStackedWorldStateUpdater.get() and loads the code stored on tokenAddress
  3. In HederaStackedWorldStateUpdater.get(), we intercept the loading of the account code, determine if this is actually a contract address, and, if true, we return an instance of HederaEvmWorldStateTokenAccount which wraps the redirect token bytecode
  4. The redirect bytecode is obtained by compiling the following contract, which accepts all the inputs the user provided (including function selector and function arguments), precedes the argument list with the token address, and delegatecalls the HTS precompile:
    // SPDX-License-Identifier: Apache-2.0
    pragma solidity 0.5.5;
    contract Assembly {
     fallback() external {
         address precompileAddress = address(0x167);
         assembly {
             mstore(0, 0xFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE)
             calldatacopy(32, 0, calldatasize())
             let result := delegatecall(gas(), precompileAddress, 8, add(24, calldatasize()), 0, 0)
             let size := returndatasize()
             returndatacopy(0, 0, size)
             switch result
                 case 0 { revert(0, size) }
                 default { return(0, size) }
         }
     }
    }
    
  5. This means that any function can be redirected-to as long as the HTS precompile handles the redirect call.

For this HIP, the mechanism described above will be extended to include handling calls to associate dissociate and isAssociated functions in the HTSPrecompileContract class method which handles the ABI_ID_REDIRECT_FOR_TOKEN function selector.

The following table describes the function selector for the new associate, dissociate and isAssociated functions and the associated function signatures.

Function Selector Function Signature
0x0a754de6 associate()
0x5c9217e0 dissociate()
0x4d8fdd6d isAssociated()

No arguments are necessary because

  • The token address was already determined by looking up the contract address to determine if it is an HTS token address.
  • The address to associate/dissociate will be the caller (i.e. msg.sender)

The solidity interface for IHRC will be the following

interface IHRC {
    function associate() external returns (responseCode);
    function dissociate() external returns (responseCode);
    function isAssociated() external view returns (bool);
}

Once the above functionality has been implemented in services, the end user will be able to call the associate, dissociate and isAssociated functions as follows:

IHRC(tokenAddress).associate()
IHRC(tokenAddress).dissociate()
IHRC(tokenAddress).isAssociated()

A token contract which needs the capability of both ERC-20 or ERC-721 and HTS functionality can implement both the IERC interfaces and IHRC interface.

Backwards Compatibility

This HIP builds on HIP-218 and adds a new way to access existing functionality and thus does not impact backwards compatibility.

Security Implications

By design, the association and dissociation of tokens can only occur from the sender of the transaction which is in line with the existing security model.

How to Teach This

The associate, dissociate and isAssociated functions can be invoked on an HTS tokens just like other functions on the IERC20 and IERC721 interfaces by casting the token with the IHTS interface.

Reference Implementation

Rejected Ideas

Open Issues

References

HIP-218

Copyright/license

This document is licensed under the Apache License, Version 2.0 – see LICENSE or (https://www.apache.org/licenses/LICENSE-2.0)

Citation

Please cite this document as: