ERC-6093 Common custom error standard for tokens (Custom errors for commonly-used tokens)

Final · Tokens · created 2022-12-06

Defines a common format for the errors that ERC-20, ERC-721, and ERC-1155 tokens use when they fail. Wallets and apps can interpret the cause of a failure as structured data and show it to the user.

Why it is needed

Ethereum apps and wallets have long relied on revert reason strings to show users why a transaction failed. Since Solidity 0.8.4, custom errors have made it possible to interpret the cause by type, but the leading token standards ERC-20, ERC-721, and ERC-1155 were finalized earlier and contain no errors in their specifications. As a result, error names and contents differ from token to token, and it is hard for wallets and test environments to interpret failure causes consistently. Long strings in deployed code also raise deployment costs. This standard organizes the failures that commonly occur in the three token standards into a structured, common list of errors, so that they provide at least the same information as the existing strings in a more consistent and predictable form.

What to implement

In depth

Error name grammar: domain, prefix, subject

Every error name follows the grammar <Domain><ErrorPrefix><Subject>(<Arguments>). Domain is a standard name such as ERC20, ERC721, or ERC1155, and ErrorPrefix indicates the reason for the failure, such as Invalid (a general error) or Insufficient (a shortage of quantity). Subject is the party that failed, such as Sender, Receiver, Balance, Approver, Operator, or Approval. Actions are of two kinds, Transfer and Approval. An action itself is not the subject of an error. An error is built by combining which subject failed during which action.

Why a domain prefix is needed

Error arguments differ by token type. If errors with the same name and different arguments exist, the Solidity compiler fails with a DeclarationError. For example, InsufficientApproval(address spender, uint256 allowance, uint256 needed) and InsufficientApproval(address operator, uint256 tokenId) cannot coexist. So a domain prefix made of the ERC name and number (ERC20InsufficientApproval, ERC721InsufficientApproval) avoids declaration conflicts.

Argument order: who, what, why

Arguments follow a fixed order. First comes the subject of the error (for example, address sender), next what failed (for example, uint256 allowance), and last why it failed as an additional argument (for example, uint256 needed). One argument can overlap several categories, so not all three are always present, but the order must be kept. For tokens that need a tokenId, it is recommended to put it at the end as additional information rather than as the subject. When adding implementation-specific errors such as extensions, this guideline SHOULD also be followed for consistency.

Nature of the usage guidance: whether to revert is up to the implementer

This standard only defines standard errors that can be used in specific situations. It does not decide whether to revert in those situations. Unless the relevant token EIP enforces it, whether to revert is up to the implementer. However, each error has rules that must be followed. For example, ERC20InsufficientBalance requires that balance be less than needed (MUST), and ERC20InvalidSender MUST NOT be used for approval operations or for balance and allowance requirements, in which case ERC20InsufficientBalance or ERC20InsufficientAllowance is used. Argument names MUST be used as defined in the Parameter Glossary (MUST).

Error composition by standard

ERC-20 defines 6 errors in total: 4 for transfers (InsufficientBalance, InvalidSender, InvalidReceiver, InsufficientAllowance) and 2 for approvals (InvalidApprover, InvalidSpender). ERC-721 defines 8 errors centered on ownership. They include InvalidOwner for balance queries, NonexistentToken for unminted or burned tokens, IncorrectOwner for when the sender is not the owner, and InsufficientApproval for missing approval. ERC-1155 defines 7 errors. Balance errors carry a tokenId, and it adds MissingApprovalForAll for the absence of a blanket approval and InvalidArrayLength for mismatched array lengths in batch transfers.

Compatibility with existing deployed tokens

Most already deployed tokens use require with revert strings, and many tokens deployed after Solidity 0.8.4 also inherit string-based implementations. This standard cannot be forced on existing tokens that cannot be upgraded. They use similar conventions with small variations, such as having or lacking a domain, a different prefix, a similar subject, or a different word order. Upgradeable contracts MAY be upgraded to implement this standard. Implementers and dapp developers who support this standard SHOULD also accept the other errors that non-conforming contracts emit and the classic revert strings.

Things to watch out for

Original ERC · ← ERCs