Abstract
This ERC defines a standard interface for representing physical reserves on-chain so they can be allocated as backing for reserve-backed tokens and other real-world asset (RWA) instruments.
A physical reserve may represent a gold bar, precious-metal batch, custody record, or another real-world reserve object. The standard defines a common observable model for reserve identity, asset type, quantity, state, endorsements, and reserve metadata.
This ERC does not prescribe how reserves are originated, deposited, audited, held, or managed. Implementations may use custodians, banks, regulators, auditors, or oracle feeds. The purpose of this ERC is to expose the minimum reserve accounting surface that tokens, auditors, explorers, and protocols require.
The primary intended use is to support issuance and redemption of reserve-backed fungible tokens. A separate ERC-20 extension may rely on this registry to ensure that token supply does not exceed the reserve quantity allocated to that token contract.
Optional extensions support endorsement records, reserve metadata, and ERC-721 reserve receipt mappings.
Motivation
Reserve-backed real-world asset systems often rely on reserve records that are operationally important but not exposed through a common on-chain interface. A project may maintain bank confirmations, audit reports, or regulatory attestations, but external systems usually cannot query a standardized contract interface to determine:
- what physical reserves exist;
- how much reserve quantity is active, allocated to a token contract, or consumed;
- which authorities, custodians, auditors, or other parties have endorsed a reserve.
Existing RWA-related standards address adjacent concerns such as permissioned transfers, compliance checks, or NFT redemption metadata. They do not define a reusable physical reserve-accounting layer that can be shared by reserve-backed tokens, auditors, explorers, and protocols.
This ERC introduces the reserve accounting layer. It allows implementations to keep their own operational and legal workflows while exposing a common observable model for reserve status and reserve allocation.
The core interface behaves similarly to a traditional custody or inventory reserve ledger: it records what reserve exists, what asset it represents, what quantity is available, and what quantity has been assigned to an instrument. Optional extensions add additional features such as endorsements, metadata references, and ERC-721 reserve receipt mappings.
The standard is not intended to replace bank records, audit procedures, or legal documentation. Instead, it provides a regulation-agnostic, machine-readable on-chain interface that can mirror or reference those processes.
A reserve-backed fungible token can use this registry to query the quantity allocated to it and enforce its own supply constraints. For example, a later reserve-backed ERC-20 token extension may require:
totalSupply() <= allocatedQuantity(assetId, address(this))In that example, totalSupply() refers to the outstanding supply of the reserve-backed ERC-20 token that uses the registry as its reserve source.
Implementations may also maintain an operational margin, such as:
totalSupply() + safetyMargin <= allocatedQuantity(assetId, address(this))This allows platforms to handle operational delays, redemptions, substitutions, and reconciliation without requiring every user-facing event to immediately update the reserve registry, provided the token remains sufficiently backed.
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 and RFC 8174.
Terms
Reserve
A real-world physical reserve object or reserve entry, such as a gold bar, precious-metal batch, vault lot, custody record, warehouse receipt, commodity inventory entry, or other physical asset record.
Reserve Registry
A smart contract that exposes standardized reserve state and reserve accounting through this ERC.
Reserve ID
A unique bytes32 identifier for a reserve. The identifier may be derived from a serial number, vault record, document hash, oracle reference, or implementation-specific source.
Asset ID
A bytes32 identifier representing the type of physical asset. A registry MAY support multiple assetId values. One assetId MAY be associated with many reserves. Each reserveId MUST be associated with exactly one assetId. Examples may include:
keccak256("XAU")
keccak256("PLATINUM")
keccak256("GOLD_9999")This ERC does not define a global asset namespace. Implementations MUST document the meaning and unit convention of each assetId.
Quantity
A non-negative integer amount of the physical asset, expressed in implementation-defined smallest units.
For precious metals, the quantity SHOULD represent the economically relevant backing quantity. For example, in a gold implementation, quantity may represent fine gold content rather than gross physical weight. Gross weight, fineness, assay, product type, and other descriptive fields may be exposed through the optional metadata extension.
Implementations MUST document the unit used for each assetId.
Instrument
A contract or address to which the reserve quantity is allocated. An instrument may be an ERC-20 token, ERC-721 contract, ERC-1155 contract, vault, structured product, redemption module, custodial account, or another contract or account that uses reserve backing.
Allocation
The assignment of reserve quantity to an instrument. Allocation means that the allocated quantity is no longer generally available for other instruments, but it is not consumed. Allocation does not imply that any token has been minted.
Release
The cancellation of an allocation without consuming the reserve. Released quantity may return to available quantity if the reserve is active.
Consumption
The final removal of reserve quantity from future backing. Consumption may occur after physical redemption, physical delivery, withdrawal from custody, replacement, or another implementation-defined event that makes the reserve quantity unavailable for future backing.
Consumption does not mean token issuance. Token issuance is handled by the instrument using the allocation.
Design Principles
This ERC standardizes the observable reserve model, not the complete business workflow.
Implementations MAY use any internal process to register, verify, deposit, endorse, audit, activate, suspend, allocate, release, or consume reserves. Examples include:
- role-based enterprise workflows;
- Safe multisig approvals;
- bank or vault confirmations;
- auditor attestations;
- off-chain legal and operational procedures.
A compliant implementation MUST expose the required view functions and MUST emit the required events for future state and accounting changes after it adopts this standard.
This ERC is designed to be compatible with real custody and inventory practices. Where applicable, implementers may align metadata and documentation with existing precious-metal or commodity custody practices, such as bar lists, vault records, custody statements, and other recognized inventory documents. This ERC does not normatively require any specific external custody standard.
Reserve State
enum ReserveState {
NONE,
PENDING,
ACTIVE,
SUSPENDED,
CONSUMED,
CANCELLED
}The states have the following meanings:
NONE: The reserve does not exist or is unknown to the registry.PENDING: The reserve exists but is not eligible to back instruments.ACTIVE: The reserve is eligible to be allocated as backing.SUSPENDED: The reserve exists but is temporarily ineligible for new allocation or reserve use due to risk, dispute, legal, operational, verification, or policy reasons.CONSUMED: The reserve has been fully consumed and MUST NOT be used for future allocation.CANCELLED: The reserve registration was canceled, rejected, invalidated, withdrawn, or otherwise made permanently ineligible before or outside normal consumption.
PENDING and SUSPENDED are intentionally separate. PENDING describes a reserve that has not yet become eligible to back instruments. SUSPENDED describes a reserve that is known to the registry but temporarily cannot be used, typically because of a later issue, dispute, restriction, or review.
CONSUMED and CANCELLED are also intentionally separate. CONSUMED means the reserve quantity was removed from future backing after use, redemption, settlement, withdrawal, or another finalization event. CANCELLED means the reserve registration was invalidated or made ineligible without being consumed as backing.
Implementations with richer internal workflows SHOULD map their internal states to these common states. For example:
Registered -> Deposited -> Audited -> LegalApprovedmay be exposed as:
PENDING -> ACTIVEThis ERC intentionally does not define states such as TOKENIZED, ALLOCATED, or ISSUED. A reserve may be active, partly allocated, partly available, and partly consumed at the same time. These conditions are represented through accounting quantities rather than a single enum state.
Core Interface
All compliant reserve registries MUST implement IERCPhysicalReserveRegistry.
interface IERCPhysicalReserveRegistry {
enum ReserveState {
NONE,
PENDING,
ACTIVE,
SUSPENDED,
CONSUMED,
CANCELLED
}
struct Reserve {
bytes32 reserveId;
bytes32 assetId;
uint256 quantity;
uint256 availableQuantity;
uint256 consumedQuantity;
ReserveState state;
}
event ReserveRegistered(bytes32 indexed reserveId, bytes32 indexed assetId, uint256 quantity);
event ReserveStateChanged(bytes32 indexed reserveId, ReserveState previousState, ReserveState newState);
event ReserveQuantityUpdated(bytes32 indexed reserveId, uint256 previousQuantity, uint256 newQuantity);
function reserveOf(bytes32 reserveId) external view returns (Reserve memory reserve);
function stateOf(bytes32 reserveId) external view returns (ReserveState state);
function assetIdOf(bytes32 reserveId) external view returns (bytes32 assetId);
function quantityOf(bytes32 reserveId) external view returns (uint256 quantity);
function availableQuantityOf(bytes32 reserveId) external view returns (uint256 quantity);
function consumedQuantityOf(bytes32 reserveId) external view returns (uint256 quantity);
function activeQuantity(bytes32 assetId) external view returns (uint256 quantity);
function availableQuantity(bytes32 assetId) external view returns (uint256 quantity);
function consumedQuantity(bytes32 assetId) external view returns (uint256 quantity);
}Core Interface Clarification
reserveOf(bytes32 reserveId) returns the standard summary view of a reserve. It is intended as the primary read function for wallets, explorers, auditors, tokens, and external protocols.
reserveOf returns only the core accounting fields: reserve identifier, asset identifier, total quantity, available quantity, consumed quantity, and reserve state. Metadata, documents, endorsements, and receipt NFTs are exposed through OPTIONAL extensions.
For an unknown reserveId, implementations SHOULD return a default reserve object with state = NONE and zero quantities rather than reverting.
Core Accounting Requirements
For each reserveId, the following relationship MUST hold:
quantityOf(reserveId) >= availableQuantityOf(reserveId) + consumedQuantityOf(reserveId)If the registry implements allocation, the stronger relationship MUST hold:
quantityOf(reserveId) >=
availableQuantityOf(reserveId)
+ totalAllocatedQuantityOf(reserveId)
+ consumedQuantityOf(reserveId)For each assetId:
activeQuantity(assetId)
=
sum of available quantity plus allocated but unconsumed quantity for ACTIVE reserves of assetIdavailableQuantity(assetId)
=
sum of unallocated active quantity for ACTIVE reserves of assetIdconsumedQuantity(assetId)
=
sum of consumed quantity for reserves of assetIdImplementations MUST NOT include CONSUMED or CANCELLED reserves in activeQuantity(assetId).
Implementations MUST NOT include SUSPENDED reserves in availableQuantity(assetId) for new allocation.
Implementations MUST include allocated but unconsumed quantity in activeQuantity(assetId) while the reserve remains ACTIVE, because such quantity may still be backing outstanding instruments.
Optional Allocation Extension
The allocation extension is OPTIONAL for generic reserve registries. A registry that supports reserve-backed instruments SHOULD implement IERCPhysicalReserveAllocator.
A reserve-backed ERC-20 extension that relies on this ERC MUST reference a registry implementing this allocation extension.
interface IERCPhysicalReserveAllocator {
event ReserveAllocated(bytes32 indexed reserveId, address indexed instrument, uint256 quantity);
event ReserveReleased(bytes32 indexed reserveId, address indexed instrument, uint256 quantity);
event ReserveConsumed(bytes32 indexed reserveId, address indexed instrument, uint256 quantity);
function allocatedQuantityOf(bytes32 reserveId, address instrument) external view returns (uint256 quantity);
function allocatedQuantity(bytes32 assetId, address instrument) external view returns (uint256 quantity);
function totalAllocatedQuantityOf(bytes32 reserveId) external view returns (uint256 quantity);
function totalAllocatedQuantity(bytes32 assetId) external view returns (uint256 quantity);
function allocateReserve(
bytes32 reserveId,
address instrument,
uint256 quantity,
bytes calldata data
) external;
function releaseReserve(
bytes32 reserveId,
address instrument,
uint256 quantity,
bytes calldata data
) external;
function consumeReserve(
bytes32 reserveId,
address instrument,
uint256 quantity,
bytes calldata data
) external;
}Allocation Requirements
allocateReserve assigns active reserve quantity to an instrument.
allocateReserve MUST NOT allocate from a reserve unless the reserve state is ACTIVE.
allocateReserve MUST NOT allocate more than availableQuantityOf(reserveId).
After successful allocation:
availableQuantityOf(reserveId) decreases by quantity
allocatedQuantityOf(reserveId, instrument) increases by quantityAllocation does not mean token issuance. It only means that a reserve quantity has been assigned to an instrument. The instrument is responsible for its own issuance logic.
releaseReserve releases previously allocated but unconsumed quantity back to the active available quantity of the reserve, if the reserve is currently ACTIVE.
releaseReserve MUST NOT release more than the quantity allocated to instrument.
After successful release:
allocatedQuantityOf(reserveId, instrument) decreases by quantity
availableQuantityOf(reserveId) increases by quantity if the reserve is ACTIVEIf the reserve is SUSPENDED, an implementation MAY reduce allocation without increasing quantity available for new allocation until the reserve becomes ACTIVE again.
consumeReserve consumes previously allocated quantity.
consumeReserve MUST NOT consume more than the quantity allocated to instrument.
After successful consumption:
allocatedQuantityOf(reserveId, instrument) decreases by quantity
consumedQuantityOf(reserveId) increases by quantityIf the consumed quantity equals the reserve's total quantity, the reserve state SHOULD become CONSUMED.
consumeReserve MUST NOT be interpreted as token minting. It represents the final removal of the physical reserve quantity from future backing.
Examples of consumption include:
- physical redemption or delivery completed;
- reserve withdrawn from custody;
- reserve replaced, retired, or destroyed from backing.
Non-Normative Reserve-Backed Token Example
A reserve-backed ERC-20 token may use this registry as follows:
- Reserve registry exposes an
ACTIVEreserve. - Issuer allocates 10,000 grams of gold reserve to
GoldToken. GoldTokenobservesallocatedQuantity(XAU, address(GoldToken)) = 10,000.GoldTokenmay mint token units according to its own token logic. For example, 10,000 or 100,000 units.- The registry does not track how many ERC-20 tokens were minted.
A token-side invariant may be:
totalSupply() <= allocatedQuantity(assetId, address(this))A token or platform may maintain an additional margin:
totalSupply() + safetyMargin <= allocatedQuantity(assetId, address(this))This ERC does not define the token-side invariant. It is expected to be defined in a separate reserve-backed ERC-20 extension.
Non-Normative Redemption Note
This ERC does not define user-facing redemption. Redemption is expected to be handled by the instrument, such as an ERC-20 token, a redemption module, an issuer platform, or another contract.
When redemption reduces token supply but the physical reserve remains in custody and remains eligible to back future issuance, an implementation MAY use releaseReserve.
When redemption or settlement removes physical reserve quantity from future backing, an implementation SHOULD use consumeReserve.
If token supply remains safely below allocated reserve quantity, including any margin required by the implementation, no immediate action may be necessary by the Reserve Registry contract. Implementations should define their own reconciliation policy.
Optional Endorsement Extension
A registry MAY implement IERCPhysicalReserveEndorsement to expose endorsements, audit attestations, insurance confirmations, regulatory approvals, or other validations.
The extension supports multiple endorsements by multiple authorities on a single reserve.
interface IERCPhysicalReserveEndorsement {
event ReserveEndorsed(
bytes32 indexed reserveId,
address indexed endorser,
bytes32 indexed endorsementType,
bytes32 endorsementHash
);
event ReserveEndorsementRevoked(
bytes32 indexed reserveId,
address indexed endorser,
bytes32 indexed endorsementType
);
function endorsementCount(bytes32 reserveId, bytes32 endorsementType) external view returns (uint256 count);
function isEndorsedBy(bytes32 reserveId, address endorser, bytes32 endorsementType) external view returns (bool);
function latestEndorsementHash(bytes32 reserveId, address endorser, bytes32 endorsementType) external view returns (bytes32 endorsementHash);
function canEndorse(bytes32 reserveId, address endorser, bytes32 endorsementType) external view returns (bool);
function endorsementThreshold(bytes32 reserveId, bytes32 endorsementType) external view returns (uint256 threshold);
function endorsementPolicyURI(bytes32 reserveId) external view returns (string memory uri);
function endorseReserve(
bytes32 reserveId,
bytes32 endorsementType,
bytes32 endorsementHash,
bytes calldata data
) external;
function revokeEndorsement(
bytes32 reserveId,
bytes32 endorsementType,
bytes calldata data
) external;
}endorsementThreshold(reserveId, endorsementType) returns the number of valid unique endorsements required by the implementation's policy for the given reserve and endorsement type. A threshold of zero means that no threshold is defined or required by the registry for that type.
endorsementPolicyURI(reserveId) MAY return a document describing which authorities are allowed to endorse the reserve, which endorsement types are required, and how endorsements are evaluated before activation.
Examples of endorsementType include:
keccak256("CUSTODY_CONFIRMATION")
keccak256("AUDIT_REPORT")
keccak256("INSURANCE_CONFIRMATION")Implementations MAY restrict endorsement functions to specific authorized addresses.
For example, an implementation may require:
CUSTODY_CONFIRMATION: only the custodian Safe
AUDIT_REPORT: at least two approved auditors
INSURANCE_CONFIRMATION: only insurance verifier
REGULATORY_APPROVAL: only trustee or regulator addressImplementations SHOULD prevent the same address from being counted more than once for the same reserveId and endorsementType.
This ERC does not define the legal validity of endorsements. It only standardizes how endorsement data is exposed.
A registry MAY require certain endorsement thresholds before changing a reserve state to ACTIVE, but this policy is implementation-specific.
Optional Reserve Metadata Extension
A registry MAY implement IERCPhysicalReserveMetadata to expose metadata and document references associated with reserves.
This extension is intended to support references to custody records, vault statements, audit reports, insurance confirmations, regulatory documents, or other off-chain documents.
interface IERCPhysicalReserveMetadata {
event ReserveMetadataURIUpdated(bytes32 indexed reserveId, string metadataURI);
event ReserveDocumentUpdated(
bytes32 indexed reserveId,
bytes32 indexed documentType,
bytes32 documentHash,
string documentURI
);
function reserveMetadataURI(bytes32 reserveId) external view returns (string memory uri);
function reserveDocument(
bytes32 reserveId,
bytes32 documentType
) external view returns (bytes32 documentHash, string memory documentURI);
}The metadata URI MAY point to JSON, CSV, PDF, IPFS, or another implementation-defined document location.
A non-normative metadata JSON object may include fields such as:
{
"assetId": "XAU",
"unit": "fine_gram",
"quantity": "100000",
"serialNumber": "ABC12345",
"brandOrRefiner": "Example Refiner",
"fineness": "999.9",
"grossWeight": "100.02",
"fineWeight": "100.00",
"custodian": "Example Custodian",
"vaultLocation": "Example Vault",
"inventoryDate": "2026-06-02",
"sourceDocumentHash": "0x..."
}This ERC does not require any specific metadata schema. Implementations SHOULD document their metadata schema.
Examples of documentType include:
keccak256("CUSTODY_RECORD")
keccak256("AUDIT_REPORT")
keccak256("INSURANCE_DOCUMENT")
keccak256("LEGAL_TERMS")Optional ERC-721 Reserve Receipt Extension
A registry MAY represent or link each reserve to an ERC-721 reserve receipt NFT.
The reserve receipt NFT may represent:
- evidence of a physical reserve;
- a custody or warehouse receipt;
- a redemption right;
- a non-transferable administrative receipt.
This ERC does not require that receipt NFTs be transferable.
interface IERCPhysicalReserveReceipt721 {
event ReserveReceiptLinked(bytes32 indexed reserveId, address indexed receiptContract, uint256 indexed tokenId);
event ReserveReceiptUnlinked(bytes32 indexed reserveId, address indexed receiptContract, uint256 indexed tokenId);
function receiptOf(bytes32 reserveId) external view returns (address receiptContract, uint256 tokenId);
function reserveIdOf(address receiptContract, uint256 tokenId) external view returns (bytes32 reserveId);
}A registry implementing this extension SHOULD ensure:
Each reserveId maps to at most one active ERC-721 receipt.
Each active ERC-721 receipt maps to exactly one reserveId.The receipt NFT MAY be:
- issued by the registry itself or by a separate ERC-721 contract;
- held by the issuer, custodian, a Safe multisig, or the registry contract;
- burned or locked after full reserve consumption.
If the receipt NFT represents a physical asset with redemption or legal metadata, the receipt contract SHOULD consider ERC-7578 compatibility.
If the receipt NFT is intended to be non-transferable, the implementation MAY use a soulbound ERC-721 extension.
Receipt NFTs are not required for ERC-20 token minting. A reserve-backed ERC-20 token should rely on allocated reserve quantity, not on ownership of reserve receipt NFTs.
ERC-165 Interface Detection
Compliant contracts MUST implement ERC-165.
A registry implementing the core interface MUST return true for:
type(IERCPhysicalReserveRegistry).interfaceIdA registry implementing optional extensions MUST return true for the corresponding extension interface IDs.
The exact interface identifiers should be finalized after the function signatures in this proposal are stable.
Rationale
Why this ERC standardizes reserve accounting instead of reserve operations
Physical reserve workflows depend on asset type, jurisdiction, legal structure, audit policy, and operational design. A standard that mandated one registration, audit, or redemption workflow would exclude many legitimate implementations.
This ERC therefore standardizes the observable accounting model: reserve identity, state, asset type, quantity, allocation, release, consumption, endorsement, and optional metadata.
Why allocation is the bridge to token issuance
A reserve-backed token should not simply check the global active reserve. If two instruments read the same active reserve without allocation, both may claim the same backing.
Allocation prevents double-backing by assigning a reserve quantity to a specific instrument. Therefore, a reserve-backed ERC-20 extension should enforce supply against:
allocatedQuantity(assetId, tokenAddress)not merely against:
activeQuantity(assetId)Why this ERC does not track the minted token supply
This ERC treats the reserve registry as a certification and allocation layer. It confirms that a physical reserve exists, that it is eligible to back instruments, and that a specified quantity has been allocated to an instrument. It does not need to know whether the instrument minted ERC-20 tokens, issued ERC-721 claims, created ERC-1155 certificates, or used the reserve in another structure. Token supply, token burning, redemption requests, and user balances belong to the instrument using the allocation.
Why consumeReserve is not used for minting
Minting tokens does not remove the physical reserve from custody or from backing. It only creates a token supply against the allocated reserve. consumeReserve is used for the final removal of reserve quantity from future backing, usually after physical delivery, redemption, withdrawal, or another finalization event.
Why the state enum stays minimal
A reserve can be simultaneously active, partly available, partly allocated, and partly consumed. A single enum cannot cleanly represent all these combinations.
The enum, therefore, represents broad eligibility. Exact usage is represented through accounting quantities.
Why metadata is optional
Reserve metadata can vary widely across commodities, custodians, asset types, legal systems, and inventory practices. Gold bars, silver bars, warehouse receipts, and other physical reserves may require different fields. A required universal metadata schema would either be too narrow or too complex. This ERC therefore provides a metadata URI and document hash interface without requiring a specific schema.
Why ERC-721 receipt NFTs are optional
Reserve receipt NFTs are useful for Web3-native representation, wallet visibility, legal metadata, and physical redemption. However, forcing all reserve registries to issue ERC-721 tokens would reduce adoption. Some institutions may prefer non-transferable identifiers. Some registries may already exist off-chain and only expose an adapter. Some legal structures may not allow transferable receipt NFTs. The optional ERC-721 receipt extension allows NFT-oriented implementations without forcing all implementers into an NFT architecture.
Why endorsements are optional
Different assets and jurisdictions require different validation models. A precious metal reserve may require vault confirmations. A warehouse receipt may require operator confirmation. The endorsement extension provides a common interface for multiple authorities to endorse a reserve, while leaving authorization and threshold rules to implementations.
Backwards Compatibility
This ERC does not modify ERC-20, ERC-721, ERC-1155, ERC-3643, ERC-7578, ERC-7943, or any existing standard.
Existing reserve-backed projects can adopt this ERC by deploying an adapter contract that maps their internal reserve database to the interfaces defined here.
Existing ERC-721 reserve receipt NFTs can be linked through the optional receipt extension without changing the NFT contract, provided the registry can expose the receiptOf and reserveIdOf relationships.
Existing ERC-20 tokens can reference a compatible registry from a separate wrapper or extension contract. Strict reserve-backed token supply enforcement requires integration at the token contract or token controller level.
Test Cases
Implementations should include tests covering at least the following:
- A
PENDINGreserve cannot be allocated. - An
ACTIVEreserve can be allocated up to available quantity. - Allocation decreases the reserve-level and asset-level available quantity.
- Allocation increases the reserve-level and asset-level allocated quantity.
- Two instruments cannot allocate the same reserve quantity twice.
- Releasing allocation restores available quantity when the reserve is
ACTIVE. - Consumption is only possible from the allocated quantity.
- Consumption decreases the allocated quantity and increases the consumed quantity.
- Full consumption changes the reserve state to
CONSUMED. CONSUMEDandCANCELLEDreserves are not counted in active quantity.SUSPENDEDreserves are not available for new allocation.- Multiple authorities can endorse the same reserve under different endorsement types.
- Optional ERC-721 receipt links correctly map
reserveIdto(receiptContract, tokenId)and back. - Fractional consumption of a reserve does not require burning the reserve receipt NFT.
- Whole-reserve consumption may burn, transfer, lock, or mark the reserve receipt NFT according to the implementation policy.
Security Considerations
Off-chain truth
This ERC cannot prove that a physical reserve exists. It standardizes how a registry exposes reserve data on-chain. Implementations rely on custodians, auditors, issuers, legal agreements, or other off-chain mechanisms to ensure that on-chain reserve data corresponds to real-world facts.
Over-allocation
Implementations MUST ensure that a reserve cannot be allocated more than its available quantity. Failure to enforce allocation accounting can allow multiple instruments to claim the same reserve.
Over-minting by instruments
This ERC does not itself prevent token over-minting. A token or instrument using this registry must enforce its own invariant against the allocated reserve quantity.
For a reserve-backed ERC-20 token, a typical invariant is:
totalSupply() <= allocatedQuantity(assetId, address(this))Implementations may use an additional margin:
totalSupply() + safetyMargin <= allocatedQuantity(assetId, address(this))Consumption errors
Implementations MUST ensure that consumeReserve cannot consume more than the quantity allocated to the specified instrument.
Suspended reserves
A reserve in SUSPENDED state is not eligible for new allocation. Implementations must define how suspension affects existing allocations. Dependent instruments should monitor state changes and define whether suspension triggers mint pauses, replacement backing, redemption restrictions, or emergency governance.
Quantity units and precision
This ERC does not define a global unit system. Implementations MUST document the unit used for each assetId. Integrators should not assume that two registries use the same unit convention for the same apparent asset.
Metadata integrity
A metadata URI may point to an external file that can change, disappear, or become unavailable. Implementations SHOULD use document hashes, content-addressed storage, signed statements, or other integrity mechanisms when metadata affects trust or reserve valuation.
Multisig and role risk
Custodians, issuers, endorsers, and registry operators may use multisig wallets such as Safe. Implementations should consider signer rotation, compromised keys, timelocks, emergency pauses, and governance procedures.
Copyright
Copyright and related rights waived via CC0.
