Abstract
This ERC defines a standard for binding structured accounting metadata β equivalent to a traditional invoice or fiscal receipt β to on-chain payment transactions, without modifying existing token contracts or transfer semantics. It specifies (1) a canonical EIP-712 typed data schema (Invoice) covering fiscal identity, tax breakdown, foreign exchange context, line items, and jurisdictional extensions; (2) a singleton registrar contract (InvoiceCommitmentRegistry) deterministically deployable across EVM chains via CREATE2; and (3) a companion ERC-7730 clear-signing descriptor for hardware-wallet verification.
The invoice content lives off-chain by default; only its hash and an optional URI are committed on-chain. An opt-in mode allows the encrypted payload to be carried on-chain when off-chain coordination is impractical. The design preserves commercial confidentiality, keeps gas overhead negligible, and requires no changes to existing ERC-20 tokens.
Motivation
Stablecoin payments have reached commercial maturity: the USβMexico corridor alone moved more than $6.5B in stablecoin remittance flows in 2024 (Bitso disclosure), Stripe and Tempo launched the Machine Payments Protocol (MPP) in March 2026 for agentic commerce, and institutional rails such as Chainlink CCIP/ACE have integrated ISO 20022 messaging with major financial institutions throughout 2025. Yet the accounting layer that traditionally accompanies a payment β the invoice β has no canonical representation in EVM ecosystems. Reconciliation between a transaction hash and the invoice it satisfies remains a private off-chain concern, fragmenting audit trails and preventing independent verification by tax authorities, auditors, and counterparties.
Existing standards address adjacent problems. ERC-7699 introduces an opaque bytes reference field but deliberately leaves its semantic structure undefined. ERC-7943 (uRWA) defines compliance hooks for tokenized real-world assets without carrying accounting metadata. The bytes data extensions of ERC-223, ERC-777, and ERC-1363 permit arbitrary payload attachment but do not standardize its semantic structure. ERC-681 and ERC-7856 define pre-transaction payment-request URIs whose metadata does not persist on-chain. LSP4 / LSP2 on LUKSO provide flexible key-value metadata on tokens but define no canonical keys for fiscal identifiers or invoice line items.
In parallel, the international standards community has framed the problem at higher levels. ITU-T Recommendation F.751.4 (March 2022) defines a general framework for DLT-based invoices including the lifecycle from issuance to tax clearance, but does not specify an EVM-native realization. The W3C Traceability Vocabulary defines a CommercialInvoice Verifiable Credential with linked-data semantics and DID-anchored issuers, but uses JSON-LD rather than EIP-712 and has no on-chain commitment mechanism. Academic work has explored related domains: Fabrizio et al. (Frontiers in Blockchain, 2019) propose a permissioned-blockchain invoice discounting system with attribute-based access control; the present ERC offers a public, cryptographic-economic alternative on EVM.
The Verifiable Invoice Commitment standard fills the remaining gap by defining a canonical, extensible, and privacy-preserving binding between commercial invoices and on-chain payments. It does not replace any existing token standard; it composes on top of them.
Specification
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.
1. EIP-712 Typed Data Schema
Conforming implementations MUST sign invoices using the following EIP-712 domain and type definitions.
1.1 Domain Separator
EIP712Domain {
string name; // "VerifiableInvoiceCommitment"
string version; // "1"
uint256 chainId;
address verifyingContract; // the InvoiceCommitmentRegistry instance
}1.2 Primary Type: Invoice
Invoice {
string invoiceId;
uint256 issueDate;
uint256 dueDate;
string paymentTerms;
string purchaseOrderRef;
address issuer;
TaxIdentity issuerTaxId;
address recipient;
TaxIdentity recipientTaxId;
address paymentToken;
uint256 paymentAmount;
string fiatCurrency;
uint256 fiatAmountMilliUnits;
uint256 fxRateScaled;
address fxOracle;
uint256 fxTimestamp;
TaxEntry[] taxes;
LineItem[] lineItems;
string jurisdiction;
bytes regulatoryData;
uint256 nonce;
}1.3 Subtypes
TaxIdentity {
string scheme; // e.g. "AR-CUIT", "MX-RFC", "EU-VAT", "US-EIN", "OTHER"
string id; // the identifier value in the scheme's format
}TaxEntry {
string taxType; // "VAT" | "IVA" | "SALES" | "WITHHOLDING" | "EXCISE" | "OTHER"
string taxScheme; // jurisdiction + category, e.g. "AR-IVA-21", "MX-IVA-16"
uint256 rateBps; // tax rate in basis points (2100 == 21.00%)
uint256 baseAmountMilliUnits;
uint256 taxAmountMilliUnits;
}LineItem {
string description;
uint256 quantityScaled; // quantity Γ 10^3 to support fractional units
string unit; // UN/CEFACT code: "EA", "HR", "KG", "L", ...
uint256 unitPriceMilliUnits;
uint256 lineTotalMilliUnits;
uint256 taxRefIndex; // index into the parent Invoice.taxes array
}1.4 Field Semantics
invoiceId: MUST be unique within the scope ofissuer. Format is issuer-defined but SHOULD be stable and human-readable.issueDate,dueDate: UNIX timestamps in UTC seconds.dueDateMAY be0to indicate not applicable.paymentTerms: Free-form string describing commercial terms ("Net 30", "50% upfront", "EOM +60"). MAY be empty.purchaseOrderRef: Reference to a buyer-issued purchase order. MAY be empty.issuer,recipient: Ethereum addresses.issuerMUST match theecrecoverresult of the EIP-712 signature.issuerTaxId,recipientTaxId: Fiscal identity in a declared scheme. Forscheme == "OTHER",idformat is jurisdiction-specific and SHOULD be documented in a companion extension ERC.paymentToken: Address of the ERC-20 token used for settlement. For native ETH, implementations MAY use the sentinel0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE.paymentAmount: Token amount in the token's smallest unit.fiatCurrency: ISO 4217 three-letter code.fiatAmountMilliUnits: Invoice total in fiat, in milli-units (1 milli-unit = 0.001 fiat units).fxRateScaled: Exchange rate as(fiat units per 1 token unit) Γ 10^8, matching Chainlink convention. MAY be0if the payment token is itself denominated infiatCurrency.fxOracle: Address of the oracle consulted. MAY be the zero address if not applicable.fxTimestamp: UNIX timestamp at which the FX rate was observed.taxes: Array of tax entries. MAY be empty for tax-exempt transactions.lineItems: Array of line items. MAY be empty. When non-empty,sum(lineTotalMilliUnits) + sum(taxAmountMilliUnits)MUST equalfiatAmountMilliUnits.jurisdiction: ISO 3166-1 alpha-2 country code identifying the fiscal jurisdiction of the issuer.regulatoryData: Opaque bytes whose structure is defined by jurisdiction-specific companion ERCs. MAY be empty.nonce: Arbitrary uint256, unique per issuer. Prevents replay.
2. The Invoice Hash
invoiceHash = keccak256(
"\x19\x01" ||
domainSeparator ||
keccak256(encodeType(Invoice) || encodeData(invoice))
)This value is the canonical commitment identifier of the invoice.
3. Registrar Contract Interface
Conforming registrars MUST implement the following interface:
interface IInvoiceCommitmentRegistry {
enum PayloadMode {
OffChain,
EncryptedOnChain
}
event InvoiceCommitted(
bytes32 indexed invoiceHash,
address indexed issuer,
address indexed recipient,
bytes32 paymentTxRef,
PayloadMode payloadMode,
string uri,
bytes encryptedPayload,
bytes issuerSignature
);
function commitInvoice(
Invoice calldata invoice,
bytes32 paymentTxRef,
PayloadMode payloadMode,
string calldata uri,
bytes calldata encryptedPayload,
bytes calldata issuerSignature
) external returns (bytes32 invoiceHash);
function isNonceUsed(address issuer, uint256 nonce) external view returns (bool);
function getCommitment(bytes32 invoiceHash) external view returns (
address issuer,
address recipient,
bytes32 paymentTxRef
);
}4. Binding to the Payment Transaction
The paymentTxRef field binds the invoice to its payment. Two binding modes are defined:
Mode A β Same-transaction binding. The commitment call is performed in the same transaction as the payment. paymentTxRef MAY be bytes32(0) and the binding is implicit through transaction inclusion.
Mode B β Post-payment binding. The payment is executed first, and the commitment is submitted in a subsequent transaction referencing the payment's transaction hash. paymentTxRef MUST be the transaction hash of the payment.
Implementations MUST emit InvoiceCommitted regardless of binding mode.
5. Verification Procedure
To verify a committed invoice, a verifier MUST:
- Retrieve the invoice JSON (from URI, out-of-band, or by decrypting
encryptedPayload). - Compute the invoice hash per Section 2.
- Verify that the computed hash matches
invoiceHashin the event. - Verify the
issuerSignaturerecovers to the declaredissuer. - Verify that
paymentTxRef(or, in Mode A, the containing transaction) transferredpaymentAmountofpaymentTokenfromrecipienttoissuer. - If
taxesandlineItemsare non-empty, verify the structural invariant from Section 1.4.
6. ERC-7730 Clear Signing
Conforming implementations SHOULD publish a companion ERC-7730 descriptor referencing the EIP-712 Invoice type, enabling hardware wallets to render the invoice in human-readable form during signing. A reference descriptor is provided in the assets directory.
Rationale
Why a signed off-chain document + on-chain commitment rather than full on-chain metadata? Commercial invoices contain competitively sensitive information that enterprises will not publish on a public ledger. A commitment-based design preserves privacy by default while retaining cryptographic integrity and auditability. An encrypted on-chain variant is provided for flows where off-chain coordination is infeasible.
Why EIP-712 rather than a raw JSON signature? EIP-712 provides canonical encoding, replay protection via domain separators, and compatibility with existing wallet infrastructure including hardware wallets. The ERC-7730 ecosystem already exists to render EIP-712 messages clearly.
Why a singleton registrar rather than per-token extensions? Existing stablecoins (USDC, USDT, PYUSD) will not adopt new transfer semantics. A separate registrar works with any existing ERC-20 and composes naturally with intent-based execution (ERC-7683) and account abstraction (ERC-4337).
Why opaque regulatoryData rather than jurisdiction-specific fields in the core? Fiscal regulations evolve at legislation pace, not EIP pace. Argentina's CAE, Mexico's UUID/PAC, Italy's Codice Destinatario have little structural overlap. Encoding them all in the core would produce a brittle spec unlikely to achieve consensus. Deferring jurisdictional detail to companion ERCs enables independent iteration.
Why milli-units for fiat amounts? Fiat currencies have varying decimal conventions (2 for USD, 0 for JPY, 3 for KWD). Milli-units provide uniform integer precision sufficient for all ISO 4217 currencies without floating-point ambiguity.
Why rateBps for tax rates? Basis points (1/10,000) match tax regulator conventions globally and avoid precision loss.
Why is lineItems in the core? Compliance with virtually all fiscal regimes requires line-level itemization for tax discrimination. Permitting empty arrays retains simple-case ergonomics. The gas cost of an empty array is negligible.
Why "Commitment" rather than "Anchor"? The term anchor is heavily overloaded: Anchor Protocol (Terra/Luna) had a 2022 collapse leaving negative associations; Stellar uses "anchor" for fiat gateways; Anchor is a fintech billing platform name. Commitment is precise cryptographically: a binding, hiding scheme that commits to a value while optionally concealing it. The name accurately describes the construction.
Backwards Compatibility
This ERC does not modify any existing token standard and introduces no changes to ERC-20, ERC-721, ERC-1155, or any transfer semantic. Existing tokens, wallets, and indexers continue to operate unchanged. Integration is opt-in.
This ERC is composable with:
- ERC-7699: the
invoiceHashMAY be placed in itsreferencefield. - ERC-3009: the
invoiceHashMAY serve asnonceintransferWithAuthorization. - ERC-4337: commitment calls MAY be bundled with payment operations via
UserOperation. - ERC-7943: commitment MAY be invoked from
canTransferhooks for RWA transfers. - ERC-7730: clear signing of the
Invoicetyped data is the recommended UX path. - MPP (Stripe/Tempo, March 2026): the
invoiceHashMAY be referenced in MPPPayment-Receiptheaders.
Reference Implementation
A reference implementation of the registrar, EIP-712 signing utilities, an ERC-7730 descriptor, and a full end-to-end signing and verification example is included alongside this specification.
Security Considerations
Signature replay across chains or contracts. The EIP-712 domain separator binds signatures to a specific chainId and verifyingContract.
Replay of the same invoice. The nonce field combined with the isNonceUsed check prevents the same signed invoice from being committed twice. Issuers MUST ensure nonce uniqueness within their scope.
Impersonation. The registrar validates the EIP-712 signature against the declared issuer. Verifiers MUST independently confirm that the issuer address is associated with the expected legal entity (via ENS, attestations, ERC-8004 agent identity, or off-chain KYC).
Payment-invoice mismatch. The registrar does not enforce that paymentTxRef actually transferred the declared paymentAmount. Verifiers MUST perform this check independently per Section 5.
Encrypted payload confidentiality. In EncryptedOnChain mode, the encryption scheme is implementation-defined. Implementations SHOULD use ECIES with the recipient's secp256k1 public key. Long-term confidentiality of on-chain ciphertext cannot be guaranteed against future cryptanalytic advances.
Loss of decryption key. In EncryptedOnChain mode, loss of the recipient's private key renders the invoice permanently unrecoverable. Recipients SHOULD maintain out-of-band backups.
Off-chain availability. In OffChain mode, the invoice JSON lives at the discretion of the issuer. Recipients SHOULD retrieve and store their own copy upon receipt.
Tax calculation integrity. The structural invariant is a data-integrity check. It does not validate legal correctness of tax rates or classifications.
On-chain observability. The commitment event publicly discloses issuer, recipient, and paymentTxRef. Counterparty privacy techniques (stealth addresses per ERC-5564, privacy pools) operate orthogonally.
GDPR and right-to-erasure. In OffChain mode, fiscal identifiers do not appear on-chain; the commitment is only a hash. Erasure of the off-chain document renders the hash a dangling commitment without recoverable preimage, which a reasonable interpretation of GDPR Article 17 treats as equivalent to erasure.
Correlation attacks via nonce monotonicity. Implementations SHOULD use arbitrary uint256 nonces (not monotonic counters) to avoid revealing issuance volume to chain observers.
Copyright
Copyright and related rights waived via CC0.
