HomeEIPs
EIPsERC-5791
ERC-5791

Physical Backed Tokens

Minimal interface for linking ownership of ERC-721 NFTs to a physical chip
DraftStandards Track: ERC
Created: 2022-10-17
Requires: EIP-191, EIP-721
2pmflow (@2pmflow), locationtba (@locationtba), Cameron Robertson (@ccamrobertson), cygaar (@cygaar), Brian Weick (@bweick)
DiscussionsOriginal linkEdit
1 min read

The ERC-5791 proposal suggests a system for creating non-fungible tokens (NFTs) that are tied to physical assets. The proposal builds on the existing EIP-721 NFT standard and includes a user management mechanism that does not affect token ownership. The physical asset generates a random Ethereum address that only the asset knows, preventing identity theft and proving the asset's authenticity. Only the asset manufacturer should be able to create the associated token, and assets should reconstruct their secrets from non-sensitive information to avoid storing secrets. The proposal also suggests a secure key exchange protocol based on elliptic curves but allows for coexistence with other key exchange methods. The proposal does not address the security of the physical chip, which is outside its scope.

Video
Anyone may contribute to propose contents.
Go propose
Original

Abstract

This standard is an extension of ERC-721. It proposes a minimal interface for a ERC-721 NFT to be "physically backed" and owned by whoever owns the NFT's physical counterpart.

Motivation

NFT collectors enjoy collecting digital assets and sharing them with others online. However, there is currently no such standard for showcasing physical assets as NFTs with verified authenticity and ownership. Existing solutions are fragmented and tend to be susceptible to at least one of the following:

  • The ownership of the physical item and the ownership of the NFT are decoupled.

  • Verifying the authenticity of the physical item requires action from a trusted 3rd party (e.g. StockX).

Specification

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.

Requirements

This approach requires that the physical item must have a chip attached to it that fulfills the following requirements:

  • The chip can securely generate and store an ECDSA secp256k1 asymmetric key pair;
  • The chip can sign messages using the private key of the previously-generated asymmetric key pair;
  • The chip exposes the public key; and
  • The private key cannot be extracted

The approach also requires that the contract uses an account-bound implementation of ERC-721 (where all ERC-721 functions that transfer must throw, e.g. the "read only NFT registry" implementation referenced in ERC-721). This ensures that ownership of the physical item is required to initiate transfers and manage ownership of the NFT, through a new function introduced in this interface described below.

Approach

Each NFT is conceptually linked to a physical chip.

When the NFT is minted, it must also emit an event that includes the corresponding chip address (20-byte address derived from the chip's public key). This lets downstream indexers know which chip addresses are mapped to which tokens for the NFT collection. The NFT cannot be minted without its token id being linked to a specific chip.

The interface includes a function called transferTokenWithChip that transfers the NFT to the function caller if a valid signature signed by the chip is passed in. A valid signature must follow the schemes set forth in ERC-191 and EIP-2 (s-value restrictions), where the data to sign consists of the target recipient address (the function caller) and a recent blockhash (the level of recency is up to the implementation).

The interface also includes other functions that let anyone validate whether the chip in the physical item is backing an existing NFT in the collection.

Interface

interface IERC5791 { /// @notice Returns the token id for a given chip address. /// @dev Throws if there is no existing token for the chip in the collection. /// @param chipAddress The address for the chip embedded in the physical item (computed from the chip's public key). /// @return The token id for the passed in chip address. function tokenIdFor(address chipAddress) external view returns (uint256); /// @notice Returns true if the chip for the specified token id is the signer of the signature of the payload. /// @dev Throws if tokenId does not exist in the collection. /// @param tokenId The token id. /// @param payload Arbitrary data that is signed by the chip to produce the signature param. /// @param signature Chip's signature of the passed-in payload. /// @return Whether the signature of the payload was signed by the chip linked to the token id. function isChipSignatureForToken(uint256 tokenId, bytes calldata payload, bytes calldata signature) external view returns (bool); /// @notice Transfers the token into the message sender's wallet. /// @param signatureFromChip An EIP-191 signature of (msgSender, blockhash), where blockhash is the block hash for blockNumberUsedInSig. /// @param blockNumberUsedInSig The block number linked to the blockhash signed in signatureFromChip. Should be a recent block number. /// @param useSafeTransferFrom Whether EIP-721's safeTransferFrom should be used in the implementation, instead of transferFrom. /// /// @dev The implementation should check that block number be reasonably recent to avoid replay attacks of stale signatures. /// The implementation should also verify that the address signed in the signature matches msgSender. /// If the address recovered from the signature matches a chip address that's bound to an existing token, the token should be transferred to msgSender. /// If there is no existing token linked to the chip, the function should error. function transferTokenWithChip( bytes calldata signatureFromChip, uint256 blockNumberUsedInSig, bool useSafeTransferFrom ) external; /// @notice Calls transferTokenWithChip as defined above, with useSafeTransferFrom set to false. function transferTokenWithChip(bytes calldata signatureFromChip, uint256 blockNumberUsedInSig) external; /// @notice Emitted when a token is minted event PBTMint(uint256 indexed tokenId, address indexed chipAddress); /// @notice Emitted when a token is mapped to a different chip. /// Chip replacements may be useful in certain scenarios (e.g. chip defect). event PBTChipRemapping(uint256 indexed tokenId, address indexed oldChipAddress, address indexed newChipAddress); }

To aid recognition that an ERC-721 token implements physical binding via this EIP: upon calling ERC-165’s function supportsInterface(bytes4 interfaceID) external view returns (bool) with interfaceID=0x4901df9f, a contract implementing this EIP must return true.

The mint interface is up to the implementation. The minted NFT's owner should be the owner of the physical chip (this authentication could be implemented using the signature scheme defined for transferTokenWithChip).

Rationale

This solution's intent is to be the simplest possible path towards linking physical items to digital NFTs without a centralized authority.

The interface includes a transferTokenWithChip function that's opinionated with respect to the signature scheme, in order to enable a downstream aggregator-like product that supports transfers of any NFTs that implement this EIP in the future.

Out of Scope

The following are some peripheral problems that are intentionally not within the scope of this EIP:

  • trusting that a specific NFT collection's chip addresses actually map to physical chips embedded in items, instead of arbitrary EOAs
  • ensuring that the chip does not deterioriate or get damaged
  • ensuring that the chip stays attached to the physical item
  • etc.

Work is being done on these challenges in parallel.

Mapping token ids to chip addresses is also out of scope. This can be done in multiple ways, e.g. by having the contract owner preset this mapping pre-mint, or by having a (tokenId, chipAddress) tuple passed into a mint function that's pre-signed by an address trusted by the contract, or by doing a lookup in a trusted registry, or by assigning token ids at mint time first come first served, etc.

Additionally, it's possible for the owner of the physical item to transfer the NFT to a wallet owned by somebody else (by sending a chip signature to that other person for use). We still consider the NFT physical backed, as ownership management is tied to the physical item. This can be interpreted as the item's owner temporarily lending the item to somebody else, since (1) the item's owner must be involved for this to happen as the one signing with the chip, and (2) the item's owner can reclaim ownership of the NFT at any time.

Backwards Compatibility

This proposal is backward compatible with ERC-721 on an API level. As mentioned above, for the token to be physical-backed, the contract must use a account-bound implementation of ERC-721 (all ERC-721 functions that transfer must throw) so that transfers go through the new function introduced here, which requires a chip signature.

Reference Implementation

The following is a snippet on how to recover a chip address from a signature.

import '@openzeppelin/contracts/utils/cryptography/ECDSA.sol'; function getChipAddressFromChipSignature( bytes calldata signatureFromChip, uint256 blockNumberUsedInSig ) internal returns (TokenData memory) { if (block.number <= blockNumberUsedInSig) { revert InvalidBlockNumber(); } unchecked { if (block.number - blockNumberUsedInSig > getMaxBlockhashValidWindow()) { revert BlockNumberTooOld(); } } bytes32 blockHash = blockhash(blockNumberUsedInSig); bytes32 signedHash = keccak256(abi.encodePacked(_msgSender(), blockHash)) .toEthSignedMessageHash(); address chipAddr = signedHash.recover(signatureFromChip); }

Security Considerations

The ERC-191 signature passed to transferTokenWithChip requires the function caller's address in its signed data so that the signature cannot be used in a replay attack. It also requires a recent blockhash so that a malicious chip owner cannot pre-generate signatures to use after a short time window (e.g. after the owner of the physical item changes).

Additionally, the level of trust that one has for whether the token is physically-backed is dependent on the security of the physical chip, which is out of scope for this EIP as mentioned above.

Copyright and related rights waived via CC0.

Further reading
Anyone may contribute to propose contents.
Go propose
Adopted by projects
Anyone may contribute to propose contents.
Go propose

Not miss a beat of EIPs' update?

Subscribe EIPs Fun to receive the latest updates of EIPs Good for Buidlers to follow up.

View all
Serve EIP builders, scale Ethereum.
Resources
GitHub
Supported by