ERC-5646 Token state fingerprint

Final · Tokens · created 2022-09-11

A standard that summarizes the current state of a token whose state can change into a single 32-byte fingerprint. External protocols can check whether the state has changed without knowing the token's internal implementation.

Why it is needed

Some tokens, such as liquidity positions, have internal state that keeps changing. For a protocol to handle such tokens, it currently has to know implementation details, including which state values the token has, in order to identify the token correctly. As a result, a bottleneck arises where a protocol has to do separate support work for each new token. Trust is the bigger problem. For example, suppose a buy offer is placed on a token. If the owner can secretly change the token's state just before the offer is accepted, the offerer receives a different token from the one they expected. Without a common way to reliably detect state changes from outside, it is hard to trade such mutable tokens with confidence.

What to implement

In depth

The interface is a single function

The ERC5646 interface consists of one function, getStateFingerprint(uint256 tokenId), and inherits ERC165. It is a view function and returns bytes32. All it does is return the current state fingerprint of the token the token id refers to, and there is no function that exposes the state values themselves. This is because the goal is not to reveal the contents of the state but to let outside parties determine only whether the state has changed.

Rules the fingerprint must follow

getStateFingerprint MUST return a different value when the token state changes, and MUST NOT return a different value when the state is the same. It also MUST include in the fingerprint calculation every state property that can change over the token's lifecycle, that is, all properties that are not immutable. Only when these three rules are followed does the fingerprint serve as an unambiguous identifier of the state.

Computed values and metadata can also be included

The fingerprint MAY include computed values that depend on the current timestamp. The original text gives expiration and maturity as examples. For example, if whether the maturity has passed is included in the fingerprint, the fingerprint changes at the moment time passes the maturity, even though the stored values stay the same. The token metadata URI MAY also be included.

ERC-165 support declaration

An implementing contract MUST return true for a call to supportsInterface(0xf5112315). External protocols can use this call to first check whether a token implements the state fingerprint standard, and then use getStateFingerprint.

Immutable properties can be left out of the fingerprint

Properties that never change after deployment are safely identified by the token id alone, so they do not need to be included in the fingerprint calculation. A protocol can use the fingerprint as part of the token identifier and support mutable tokens without knowing any implementation details of the state. However, this standard is not suited to uses that need to know the content of the state properties themselves. The original text states that such cases cannot avoid the bottleneck of token-specific support.

Reference implementation: LP token example

The reference implementation LPToken implements ERC721 and ERC5646 and stores asset1, asset2, amount1, amount2, fee, operator, and expiration in a per-token State struct. getStateFingerprint builds the fingerprint with keccak256(abi.encode(...)). It excludes the immutable fee and operator from the calculation, and for expiration it includes whether the maturity has passed, as block.timestamp >= state.expiration, instead of the value itself. supportsInterface additionally recognizes type(ERC5646).interfaceId.

Things to watch out for

Original ERC · ← ERCs