This standard allows integrating physical and digital ASSETS without signing capabilities into dApps/web3 by extending ERC-721.
An ASSET, for example a physical object, is marked with a uniquely identifiable ANCHOR. The ANCHOR is bound in a secure and inseparable manner 1:1 to an NFT on-chain - over the complete life cycle of the ASSET.
Through an ATTESTATION, an ORACLE testifies that a particular ASSET associated with an ANCHOR has been CONTROLLED when defining the to-address for certain operations (mint, transfer, burn, approve, ...). The ORACLE signs the ATTESTATION off-chain. The operations are authorized through verifying on-chain that ATTESTATION has been signed by a trusted ORACLE. Note that authorization is solely provided through the ATTESTATION, or in other words, through PROOF-OF-CONTROL over the ASSET. The controller of the ASSET is guaranteed to be the controller of the Asset-Bound NFT.
The proposed ATTESTATION-authorized operations such as transferAnchor(attestation) are permissionless, meaning neither the current owner (from-address) nor the receiver (to-address) need to sign.
Figure 1 shows the data flow of an ASSET-BOUND NFT transfer. The simplified system is utilizing a smartphone as user-device to interact with a physical ASSET and specify the to-address.
The well-known ERC-721 establishes that NFTs may represent "ownership over physical properties [...] as well as digital collectables and even more abstract things such as responsibilities" - in a broader sense, we will refer to all those things as ASSETS, which typically have value to people.
ERC-721 outlines that "NFTs can represent ownership over digital or physical assets". ERC-721 excels in this task when used to represent ownership over digital, on-chain assets, that is when the asset is "holding a token of a specific contract" or the asset is an NFT's metadata. Today, people commonly treat an NFT's metadata (images, traits, ...) as asset-class, with their rarity often directly defining the value of an individual NFT.
However, we see integrity issues not solvable with ERC-721, primarily when NFTS are used to represent off-chain ASSETS ("ownership over physical products", "digital collectables", "in-game assets", "responsibilities", ...). Over an ASSET's lifecycle, the ASSET's ownership and possession state changes multiple, sometimes thousands, of times. Each of those state changes may result in shifting obligations and privileges for the involved parties. Therefore tokenization of an ASSET without enforcably anchoring the ASSET's associated obligation and properties to the token is not complete. Nowadays, off-chain ASSETs are often "anchored" through adding an ASSET-identifier to a NFT's metadata.
NFT-ASSET integrity: Contrary to a popular belief among NFT-investors, metadata is data that is, more often than not, mutable and off-chain. Therefore the link between an ASSET through an asset-identifier stored in mutable metadata, which is only linked to the NFT through tokenURI, can be considered weak at best.
Approaches to ensure integrity between metadata (=reference to ASSET) and a token exist. This is most commonly achieved by storing metadata-hashes onchain. Additional problems arise through hashing; For many applications, metadata (besides the asset-identifier) should be update-able. Therefore making metadata immutable through storing a hash is problematic. Further the offchain metadata-resource specified via tokenURI must be made available until eternity, which has historically been subject to failure (IPFS bucket disappears, central tokenURI-provider has downtimes, ...)
Off-chain-on-chain-integrity: There are approaches where off-chain ASSET ownership is enforced or conditioned through having ownership over the on-chain representation. A common approach is to burn tokens in order to get the (physical) ASSET, as the integrity cannot be maintained. However, there are no approaches known, where on-chain ownership is enforced through having off-chain ownership of the ASSET. Especially when the current owner of an NFT is incooperative or incapacitated, integrity typically fail due to lack of signing-power from the current NFT owner.
Metadata is off-chain. The majority of implementations completely neglect that metadata is mutable. More serious implementations strive to preserve integrity by for example hashing metadata and storing the hash mapped to the tokenId on-chain. However, this approach does not allow for use-case, where metadata besides the asset-identifier, for example traits, "hours played", ... shall be mutable or evolvable.
In this standard we propose to
As 2. and 3. indicate, the control/ownership/possession of the ASSET should be the single source of truth, not the possession of an NFT. Hence, we propose an ASSET-BOUND NFT, where off-chain CONTROL over the ASSET enforces on-chain CONTROL over the anchored NFT. Also the proposed ASSET-BOUND NFTs allow to anchor digital metadata inseperably to the ASSET. When the ASSET is a physical asset, this allows to design "phygitals" in their purest form, namely creating a "phygital" asset with a physical and digital component that are inseparable. Note that metadata itself can still change, for instance for "Evolvable NFT".
We propose to complement the existing transfer control mechanisms of a token according to ERC-721 by another mechanism; ATTESTATION. An ATTESTATION is signed off-chain by the ORACLE and must only be issued when the ORACLE verified that whoever specifies the to address or beneficiary address has simultaneously been in control over the ASSET. The to address of an attestation may be used for Transfers as well as for approvals and other authorizations.
Transactions authorized via ATTESTATION shall not require signature or approval from neither the from (donor, owner, sender) nor to (beneficiary, receiver) account, namely making transfers permissionless. Ideally, transaction are signed independent from the ORACLE as well, allowing different scenarios in terms of gas-fees.
Lastly we want to mention two major side-benefits of using the proposed standard, which drastically lowers hurdles in onboarding web2 users and increase their security;
0xaa...aa (Fig.1), can use gasless wallets, hence participate in Web3/dApps/DeFi and mint+transfer tokens without ever owning crypto currency. Gas-fees may be paid through a third-party account 0x..gasPayer (Fig.1). The gas is typically covered by the ASSET issuer, who signs transferAnchor() transactionstransferAnchor() transaction based on proofing control over the ASSET, namely the physical object.We primarily aim to onboard physical or digital ASSETS into dApps, which do not signing-capabilities of their own (contrary to other proposals relying on crypto-chips). Note that we do not see any restrictions preventing to use such solutions in combination with this standard, as the address of the crypto-chip qualifies as an ANCHOR.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.
ANCHOR uniquely identifies the off-chain ASSET, whether it is physical or digital.
ANCHOR-TECHNOLOGY MUST ensure that
ASSET refers to the "thing", being it physical or digital, which is represented through NFTs according to the proposed standard. Typically, an ASSET does not have signing capabilities.
ATTESTATION is the confirmation that PROOF OF CONTROL was established when specifying the to (receiver, beneficiary) address.
PROOF-OF-CONTROL over the ASSET means owning or otherwise controlling an ASSET. How Proof of Control is established depends on the ASSET and may be implemented using technical, legal or other means. For physical ASSETS, CONTROL is typically verified by proofing physical proximity between a physical ASSET and an input device (for example a smartphone) used to specify the to address.
An ORACLE has signing capabilities. MUST be able to sign ATTESTATIONS off-chain in a way such that signatures can be verified on-chain.
Every contract compliant to this standard MUST implement the the proposed standard interface, ERC-721 and ERC-165 interfaces and is subject to Caveats below:
MUST implement ERC-721 and ERC-165
MUST have bidirectional mapping tokenByAnchor(anchor) and anchorByToken(tokenId). This implies that a maximum of one token per ANCHOR exists.
MUST have a mechanism to determine whether an ANCHOR is valid for the contract. RECOMMENDED to implement the proposed ValidAnchors-Interface
MUST implement decodeAttestationIfValid(attestation, data) to validate and decode ATTESTATIONS as specified in the ORACLE-Section
attestation.to, attestation.anchor, attestation.attestationHash.attestationUsagesLeft(attestation.to) <= 0validAnchor() != true.validAnchor(attestation.to, abi.decode('bytes32[]',data)), meaning the first abi-encoded value in the data parameter corresponds to proof.MUST have a ANCHOR-RELEASED mechanism, indicating whether the anchored NFT is released/transferable.
MUST extend any ERC-721 token transfer mechanism by:
ANCHOR is not released.AnchorTransfer(from, to, anchorByToken[tokenId], tokenId)MUST implement attestationsUsedByAnchor(anchor), returning how many attestations have already been used for a specific anchor.
MUST implement the state-changing transferAnchor(..), burnAnchor(..), approveAnchor(..) and OPTIONAL MAY implement additional state-changing operations which
decodeAttestationIfValid() to determine to, anchor and attestationHashattestationHashattestationsUsedByAnchor[anchor]AttestationUsedtransferAnchor(attestation) MUST behave and emit events like ERC-721.safeTransferFrom(ownerOf[tokenByAnchor(attestation.anchor)], attestation.to, tokenByAnchor(attestation.anchor), ..) and mint an NFT if tokenByAnchor(anchor)==0.RECOMMENDED to implement tokenURI(tokenId) to return an anchorBased-URI, namely baseURI/anchor. This anchoring metadata to ASSET. Before an anchor is not used for the first time, the ANCHOR's mapping to tokenId is unknown. Hence, using the anchor in instead of the tokenId is preferred.
to address of a transfer has been specified under the pre-condition of PROOF-OF-CONTROL associated with the particular ANCHOR being transferred to to.to, MUST be address, specifying the beneficiary, for example the to-address, approved account etc.attestationTime, UTC seconds, time when attestation was signed by ORACLE,validStartTime UTC seconds, start time of the ATTESTATION's validity timespanvalidEndTime, UTC seconds, end time of the ATTESTATION's validity timespansignature, ETH-signature (65 bytes). Output of an ORACLE signing the attestationHash = keccak256([to, anchor, attestationTime, validStartTime, validEndTime]).A Minimal Typescript sample to generate an ATTESTATION is available in the Reference Implementation section of this proposal.
Every contract compliant to this standard MAY implement the proposed AttestationLimited interface and is subject to Caveats below:
attestationLimitPolicy()
attestationLimitPolicy() != FIXED)attestationLimit(anchor), specifying how often an ANCHOR can be transferred in total. Changes in the return value MUST reflect the AttestationLimit-Policy.attestationUsagesLeft(anchor), returning the number of usages left (namely attestationLimit(anchor)-attestationsUsedByAnchor[anchor]) for a particular anchorEvery contract compliant to this extension MAY implement the proposed Floatable interface and is subject to Caveats below:
If floating(anchor) returns true, the token identified by tokenByAnchor(anchor) MUST be transferable without attestation, typically authorized via ERC721.isApprovedOrOwner(msg.sender, tokenId)
Every contract compliant to this extension MAY implement the proposed ValidAnchors interface and is subject to Caveats below:
validAnchor(anchor, proof) which returns true when anchor is valid, namely MerkleProof is correct, false otherwise.Why do you use an anchor<>tokenId mapping and not simply use tokenIds directly? Especially for collectable use-cases, special or sequential tokenIds (for example low numbers), have value. Holders may be proud to have claimed tokenId=1 respectively the off-chain ASSET with tokenId=1 may increase in value, because it was the first ever claimed. Or an Issuer may want to address the first 100 owners who claimed their ASSET-BOUND NFT. While these use-cases technically can certainly be covered by observing the blockchain state-changes, we consider reflecting the order in the tokenIds to be the user-friendly way. Please refer Security considerations on why sequential anchors shall be avoided.
Why is tokenId=0 and anchor=0x0 invalid? For gas efficiency. This allows to omit checks and state-variables for the existence of a token or anchor, since mappings of a non-existent key return 0 and cannot be easily distinguished from anchor=0 or tokenId=0.
ASSETS are often batch-produced with the goal of identical properties, for example a batch of automotive spare parts. Why should do you extend ERC-721 and not Multi-Token standards? Even if a (physical) ASSET is mass produced with fungible characteristics, each ASSET has an individual property/ownership graph and thus shall be represented in a non-fungible way. Hence this EIP follows the design decision that ASSET (represented via a unique asset identifier called ANCHOR) and token are always mapped 1-1 and not 1-N, so that a token represents the individual property graph of the ASSET.
Why is there a burnAnchor() and approveAnchor()? Due to the permissionless nature ASSET-BOUND NFTs can even be transferred to or from any address. This includes arbitrary and randomly generated accounts (where the private key is unknown) and smart-contracts which would traditionally not support ERC-721 NFTs. Following that owning the ASSET must be equivalent to owning the NFT, this means that we also need to support ERC-721 operations like approval and burning in such instances through authorizing the operations with an attestation.
Implementation alternatives considered Soulbound burn+mint combination, for example through Consensual Soulbound Tokens (ERC-5484). Disregarded because appearance is highly dubious, when the same asset is represented through multiple tokens over time. An predecessor of this EIP has used this approach and can be found deployed to Mumbai Testnet under address 0xd04c443913f9ddcfea72c38fed2d128a3ecd719e.
When should I implement AttestationLimited-Interface Naturally, when your use-case requires each ASSET being transferable only a limited number of times. But also for security reasons, see Security Considerations
Why is there the IERC6956Floatable.FloatState enum? In order to allow gas-efficient implementation of floatAll(), which can be overruled by anchor-based floatability in all combinations. (See rationale for tokenId=0 above).
Why is there no floating(tokenId) function?
This would behave identically to an isTransferable(tokenId,...) mechanism proposed in many other EIPs (refer e.g. ERC-6454). Further, the proposed floating(anchorByToken(tokenId)) can be used.
Why are there different FloatingAuthorizations for start and stop? Depending on the use-case, different roles should be able to start or stop floating. Note that for many applications the ISSUER may want to have control over the floatability of the collection.
Possession based use cases are covered by the standard interface IERC6956: The holder of ASSET is in possession of ASSET. Possession is an important social and economical tool: In many sports games possession of ASSET, commonly referred to as "the ball", is of essence. Possession can come with certain obligations and privileges. Ownership over an ASSET can come with rights and benefits as well as being burdened with liens and obligations. For example, an owned ASSET can be used for collateral, can be rented or can even yield a return. Example use-cases are
Possession based token gating: Club guest in possession of limited T-Shirt (ASSET) gets a token which allows him to open the door to the VIP lounge.
Possession based digital twin: A gamer is in possession of a pair of physical sneakers (ASSET), and gets a digital twin (NFT) to wear them in metaverse.
Scarce possession based digital twin: The producer of the sneakers (ASSET) decided that the product includes a limit of 5 digital twins (NFTs), to create scarcity.
Lendable digital twin: The gamer can lend his sneaker-tokens (NFT) to a friend in the metaverse, so that the friend can run faster.
Securing ownership from theft: If ASSET is owned off-chain, the owner wants to secure the anchored NFT, namely not allow transfers to prevent theft or recover the NFT easily through the ASSET.
Selling a house with a mortgage: The owner holds NFT as proof of ownership. The DeFi-Bank finances the house and puts a lock on the transfer of NFT. Allow Transfers of the NFT require the mortgage to be paid off. Selling the ASSET (house) off-chain will be impossible, as it's no longer possible to finance the house.
Selling a house with a lease: A lease contract puts a lien on an ASSET's anchored NFT. The old owner removes the lock, the new owner buys and refinances the house. Transfer of NFT will also transfer the obligations and benefits of the lien to the new owner.
Buying a brand new car with downpayment: A buyer configures a car and provides a downpayment, for a car that will have an ANCHOR. As long as the car is not produced, the NFT can float and be traded on NFT market places. The owner of the NFT at time of delivery of the ASSET has the permission to pick up the car and the obligation to pay full price.
Buying a barrel of oil by forward transaction: A buyer buys an oil option on a forward contract for one barrel of oil (ASSET). On maturity date the buyer has the obligation to pick up the oil.
The use case matrix below shows which extensions and settings must (additionally to IERC6956!) be implemented for the example use-cases together with relevant configurations.
Note that for Lockable listed in the table below, the proposed EIP can be extended with any Lock- or Lien-Mechanism known to extend for ERC-721, for example ERC-5192 or ERC-6982. We recommend to verify whether a token is locked in the _beforeTokenTransfer()-hook, as this is called from safeTransferFrom() as well as transferAnchor(), hence suitable to block "standard" ERC-721 transfers as well as the proposed attestation-based transfers.
| Use Case | approveAuthorization | burnAuthorization | IERC6956Floatable | IERC6956AttestationLimited | Lockable |
|---|---|---|---|---|---|
| Managing Possession | |||||
| Token gating | ASSET | ANY | incompatible | - | - |
| Digital twin | ASSET | ANY | incompatible | - | - |
| Scarce digital twin | ASSET | ANY | incompatible | required | - |
| Lendable digital twin | OWNER_AND_ASSET | ASSET | required | - | - |
| Managing Ownership | |||||
| Securing ownership from theft | OWNER or OWNER_AND_ASSET | ANY | optional | - | required |
| Selling an house with a mortgage | ASSET or OWNER_AND_ASSET | ANY | optional | optional | required |
| Selling a house with a lease | ASSET or OWNER_AND_ASSET | ANY | optional | optional | required |
| Buying a brand new car with downpayment | ASSET or OWNER_AND_ASSET | ANY | optional | optional | required |
| Buying a barrel of oil by forward transaction | ASSET or OWNER_AND_ASSET | ANY | optional | optional | required |
Legend:
No backward compatibility issues found.
This EIP is fully compatible with ERC-721 and (when extended with the IERC6956Floatable-interface) corresponds to the well-known ERC-721 behavior with an additional authorization-mechanism via attestations. Therefore we recommend - especially for physical assets - to use the present EIP instead of ERC-721 and amend it with extensions designed for ERC-721.
However, it is RECOMMENDED to extend implementations of the proposed standard with an interface indicating transferability of NFTs for market places. Examples include ERC-6454 and ERC-5484.
Many ERC-721 extensions suggest to add additional throw-conditions to transfer methods. This standard is fully compatible, as
_beforeTokenTransfer() hook must be called for all transfers including attestation-authorized transfers._beforeAnchorUse() hook is suggested in the reference implementation, which only is called when using attestation as authorization.Test cases are available:
If the asset is stolen, does this mean the thief has control over the NFT? Yes.The standard aims to anchor an NFT to the asset inseperably and unconditionally. This includes reflecting theft, as the ORACLE will testify that PROOF-OF-CONTROL over the ASSET is established. The ORACLE does not testify whether the controller is the legitimate owner, Note that this may even be a benefit. If the thief (or somebody receiving the asset from the thief) should interact with the anchor, an on-chain address of somebody connected to the crime (directly or another victim) becomes known. This can be a valuable starting point for investigation. Also note that the proposed standard can be combined with any lock-mechanism, which could lock attestation-based action temporarily or permanently (after mint).
How to use AttestationLimits to avoid fund-draining A central security mechanism in blockchain applications are gas fees. Gas fees ensure that executing a high number of transactions get penalized, hence all DoS or other large-scale attacks are discouraged. Due to the permissionless nature of attestation-authorized operations, many use-cases will arise, where the issuer of the ASSET (which normally is also the issuer of the ASSET-BOUND NFT) will pay for all transactions - contrary to the well-known ERC-721 behavior, where either from- or to-address are paying. So a user with malicious intent may just let the ORACLE approve PROOF-OF-CONTROL multiple times with specifying alternating account addresses. These ATTESTATIONS will be handed to the central gas-payer, who will execute them in a permissionless way, paying gas-fees for each transactions. This effectively drains the funds from the gas-payer, making the system unusable as soon as the gas-payer can no longer pay for transactions.
Why do you recommend hashing serial numbers over using them plain? Using any sequential identifier allows to at least conclude of the number between the lowest and highest ever used serial number. This therefore provides good indication over the total number of assets on the market. While a limited number of assets is often desirable for collectables, publishing exact production numbers of assets is undesirable for most industries, as it equals to publishing sales/revenue numbers per product group, which is often considered confidential. Within supply chains, serial numbers are often mandatory due to their range-based processing capability. The simplest approach to allow using physical serial numbers and still obfuscating the actual number of assets is through hashing/encryption of the serial number.
Why is anchor-validation needed, why not simply trust the oracle to attest only valid anchors? The oracle testifies PROOF-OF-CONTROL. As the ORACLE has to know the merkle-tree of valid anchors, it could also modify the merkle-tree with malicious intent. Therefore, having an on-chain verification, whether the original merkle-tree has been used, is needed. Even if the oracle gets compromised, it should not have the power to introduce new anchors. This is achieved by requiring that the oracle knows the merkle-tree, but updateValidAnchors() can only be called by a maintainer. Note that the oracle must not be the maintainer. As a consequence, care shall be taken off-chain, in order to ensure that compromising one system-part not automatically compromises oracle and maintainer accounts.
Why do you use merkle-trees for anchor-validation? For security- and gas-reasons. Except for limited collections, anchors will typically be added over time, e.g. when a new batch of the asset is produced or issued. While it is already ineffective to store all available anchors on-chain gas-wise, publishing all anchors would also expose the total number of assets. When using the data from anchor-updates one could even deduce the production capabilities of that asset, which is usually considered confidential information.
Assume you have N anchors. If all anchored NFTs are minted, what use is a merkle-tree? If all anchored NFTs are minted this implies that all anchors have been published and could be gathered on-chain. Consequently, the merkle-tree can be reconstructed. While this may not be an issue for many use cases (all supported anchors are minted anyway), we still recommend to add one "salt-leave" to the merkle-tree, characterized in that the ORACLE will never issue an attestation for an ANCHOR matching that salt-leave. Therefore, even if all N anchors are
In case the ASSET is a physical object, good or property, the following ADDITIONAL specifications MUST be satisfied:
to address and a particular physical ANCHOR and it's associated physical object. Typical acceptable proximity is ranges between some millimeters to several meters.to address has malicious intent and to acquire false ATTESTATION, without currently or ever having access to the physical object comprising the physical ANCHOR.Copyright and related rights waived via CC0.