16 KiB
eip | title | description | author | discussions-to | status | type | category | created | requires |
---|---|---|---|---|---|---|---|---|---|
6093 | Custom errors for commonly-used tokens | Lists custom errors for common token implementations | Ernesto García (@ernestognw), Francisco Giordano (@frangio), Hadrien Croubois (@Amxx) | https://ethereum-magicians.org/t/eip-6093-custom-errors-for-erc-tokens/12043 | Draft | Standards Track | ERC | 2022-12-06 | 20, 721, 1155 |
Abstract
This EIP defines a standard set of custom errors for commonly-used tokens, which are defined as EIP-20, EIP-721, and EIP-1155 tokens.
Ethereum applications and wallets have historically relied on revert reason strings to display the cause of transaction errors to users. Recent Solidity versions offer rich revert reasons with error-specific decoding (sometimes called "custom errors"). This EIP defines a standard set of errors designed to give at least the same relevant information as revert reason strings, but in a structured and expected way that clients can implement decoding for.
Motivation
Since the introduction of Solidity custom errors in v0.8.4, these have provided a way to show failures in a more expressive and gas efficient manner with dynamic arguments, while reducing deployment costs.
However, EIP-20, EIP-721, EIP-1155 were already finalized when custom errors were released, so no errors are included in their specification.
Standardized errors allow users to expect more consistent error messages across applications or testing environments, while exposing pertinent arguments and overall reducing the need of writing expensive revert strings in the deployment bytecode.
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.
The following errors were designed according to the criteria described in Rationale.
This EIP defines standard errors that may be used by implementations in certain scenarios, but does not specify whether implementations should revert in those scenarios, which remains up to the implementers, unless a revert is mandated by the corresponding EIPs.
The names of the error arguments are defined in the Parameter Glossary, and MUST be used according to those definitions.
EIP-20
ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed)
Indicates an error related to the current balance
of a sender
.
Used in transfers.
- MUST be used when
balance
is less thanneeded
. - MUST NOT be used if
balance
is greater than or equal toneeded
.
ERC20InvalidSender(address sender)
Indicates a failure with the token sender
.
Used in transfers.
- MUST be used for disallowed transfers from the zero address.
- MUST NOT be used for approval operations.
- MUST NOT be used for balance or allowance requirements.
- Use
ERC20InsufficientBalance
orERC20InsufficientAllowance
instead.
- Use
ERC20InvalidReceiver(address receiver)
Indicates a failure with the token receiver
.
Used in transfers.
- MUST be used for disallowed transfers to the zero address.
- MUST be used for disallowed transfers to non-compatible addresses (eg. contract addresses).
- MUST NOT be used for approval operations.
ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed)
Indicates a failure with the spender
's allowance
.
Used in transfers.
- MUST be used when
allowance
is less thanneeded
. - MUST NOT be used if
allowance
is greater than or equal toneeded
.
ERC20InvalidApprover(address approver)
Indicates a failure with the approver
of a token to be approved.
Used in approvals.
- MUST be used for disallowed approvals from the zero address.
- MUST NOT be used for transfer operations.
ERC20InvalidSpender(address spender)
Indicates a failure with the spender
to be approved.
Used in approvals.
- MUST be used for disallowed approvals to the zero address.
- MUST be used for disallowed approvals to the owner itself.
- MUST NOT be used for transfer operations.
- Use
ERC20InsufficientAllowance
instead.
- Use
EIP-721
ERC721InvalidOwner(address sender, uint256 tokenId, address owner)
Indicates an error related to the ownership over a particular token. Used in transfers.
- MUST be used when
sender
is notowner
. - MUST NOT be used for approval operations.
ERC721InvalidSender(address sender)
Indicates a failure with the token sender. Used in transfers.
- MUST be used for disallowed transfers from the zero address.
- MUST NOT be used for approval operations.
- MUST NOT be used for ownership or approval requirements.
- Use
ERC721InvalidOwner
orERC721InsufficientApproval
instead.
- Use
ERC721InvalidReceiver(address receiver)
Indicates a failure with the token receiver. Used in transfers.
- MUST be used for disallowed transfers to the zero address.
- MUST be used for disallowed transfers to non-
ERC721TokenReceiver
contracts or those that reject a transfer. (eg. returning an invalid response inonERC721Received
). - MUST NOT be used for approval operations.
ERC721InsufficientApproval(address operator, uint256 tokenId)
Indicates a failure with the operator
's approval.
Used in transfers.
- MUST be used when operator
isApprovedForAll(owner, operator)
is false. - MUST be used when operator
getApproved(tokenId)
is notoperator
.
ERC721InvalidApprover(address approver)
Indicates a failure with the owner
of a token to be approved.
Used in approvals.
- MUST be used for disallowed approvals from the zero address.
- MUST NOT be used for transfer operations.
ERC721InvalidOperator(address operator)
Indicates a failure with the operator
to be approved.
Used in approvals.
- MUST be used for disallowed approvals to the zero address.
- MUST be used for disallowed approvals to the owner itself.
- MUST NOT be used for transfer operations.
- Use
ERC721InsufficientApproval
instead.
- Use
EIP-1155
ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId)
Indicates an error related to the current balance
of a sender.
Used in transfers.
- MUST be used when
balance
is less thanneeded
for atokenId
. - MUST NOT be used if
balance
is greater than or equal toneeded
for atokenId
.
ERC1155InvalidSender(address sender)
Indicates a failure with the token sender. Used in transfers.
- MUST be used for disallowed transfers from the zero address.
- MUST NOT be used for approval operations.
- MUST NOT be used for balance or allowance requirements.
- Use
ERC1155InsufficientBalance
orERC1155InsufficientApproval
instead.
- Use
ERC1155InvalidReceiver(address receiver)
Indicates a failure with the token receiver. Used in transfers.
- MUST be used for disallowed transfers to the zero address.
- MUST be used for disallowed transfers to non-
ERC1155TokenReceiver
contracts or those that reject a transfer. (eg. returning an invalid response inonERC1155Received
). - MUST NOT be used for approval operations.
ERC1155InsufficientApproval(address operator, uint256 tokenId)
Indicates a failure with the operator
's approval in a transfer.
Used in transfers.
- MUST be used when operator
isApprovedForAll(owner, operator, tokenId)
is false.
ERC1155InvalidApprover(address approver)
Indicates a failure with the approver
of a token to be approved.
Used in approvals.
- MUST be used for disallowed approvals from the zero address.
- MUST NOT be used for transfer operations.
ERC1155InvalidOperator(address operator)
Indicates a failure with the operator
to be approved.
Used in approvals.
- MUST be used for disallowed approvals to the zero address.
- MUST be used for disallowed approvals to the owner itself.
- MUST NOT be used for transfer operations.
- Use
ERC1155InsufficientApproval
instead.
- Use
ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength)
Indicates an array length mismatch between ids
and values
in a safeBatchTransferFrom
operation.
Used in batch transfers.
- MUST be used only if
idsLength
is different fromvaluesLength
Parameter Glossary
Name | Description |
---|---|
sender |
Address whose tokens are being transferred. |
balance |
Current balance for the interacting account. |
needed |
Minimum amount required to perform an action. |
receiver |
Address to which tokens are being transferred. |
spender |
Address that may be allowed to operate on tokens without being their owner. |
allowance |
Amount of tokens a spender is allowed to operate with. |
approver |
Address initiating an approval operation. |
tokenId |
Identifier number of a token. |
owner |
Address of the current owner of a token. |
operator |
Same as spender . |
*Length |
Array length for the prefixed parameter. |
Error additions
Any addition to this EIP or implementation-specific errors (such as extensions) SHOULD follow the guidelines presented in the rationale section to keep consistency.
Rationale
The chosen objectives for a standard for token errors are to provide context about the error, and to make moderate use of meaningful arguments (to maintain the code size benefits with respect to strings).
Considering this, the error names are designed following a basic grammatical structure based on the standard actions that can be performed on each token and the subjects involved.
Actions and subjects
The main actions that can be performed within a token are:
- Transfer: An operation in which a sender moves to a receiver any number of tokens (fungible balance and/or non-fungible token ids).
- Approval: An operation in which an approver grants any form of approval to an operator.
The subjects outlined above are expected to exhaustively represent what can go wrong in a token transaction, deriving a specific error by adding an error prefix.
Note that the action is never seen as the subject of an error. Additionally, the token itself is not seen as the subject of an error but rather the context in which it happens, as identified in the domain.
If a subject is called different on a particular token standard, the error should be consistent with the standard's naming convention.
Error prefixes
An error prefix is added to a subject to derive a concrete error condition. Developers can think about an error prefix as the why an error happened.
A prefix can be Invalid
for general incorrectness, or more specific like Insufficient
for amounts.
Domain
Each error's arguments may vary depending on the token domain. If there are errors with the same name and different arguments, the Solidity compiler currently fails with a DeclarationError
.
An example of this is:
InsufficientApproval(address spender, uint256 allowance, uint256 needed);
InsufficientApproval(address operator, uint256 tokenId);
For that reason, a domain prefix is proposed to avoid declaration clashing, which is the name of the ERC and its corresponding number appended at the beginning.
Example:
ERC20InsufficientApproval(address spender, uint256 allowance, uint256 needed);
ERC721InsufficientApproval(address operator, uint256 tokenId);
Arguments
The selection of arguments depends on the subject involved, and it should follow the order presented below:
- Who is involved with the error (eg.
address sender
) - What failed (eg.
uint256 allowance
) - Why it failed, expressed in additional arguments (eg.
uint256 needed
)
A particular argument may fall into overlapping categories (eg. Who may also be What), so not all of these will be present but the order shouldn't be broken.
Some tokens may need a tokenId
. This is suggested to include at the end as additional information instead of as a subject.
Error grammar rules
Given the above, we can summarize the construction of error names with a grammar that errors will follow:
<Domain><ErrorPrefix><Subject>(<Arguments>);
Where:
- Domain:
ERC20
,ERC721
orERC1155
. Although other token standards may be suggested if not considered in this EIP. - ErrorPrefix:
Invalid
,Insufficient
, or another if it's more appropriate. - Subject:
Sender
,Receiver
,Balance
,Approver
,Operator
,Approval
or another if it's more appropriate, and must make adjustments based on the domain's naming convention. - Arguments: Follow the who, what and why order.
Backwards Compatibility
Tokens already deployed rely mostly on revert strings and make use of require
instead of custom errors. Even most of the newly deployed tokens since Solidity's v0.8.4 release inherit from implementations using revert strings.
This EIP can not be enforced on non-upgradeable already deployed tokens, however, these tokens generally use similar conventions with small variations such as:
- including/removing the domain.
- using different error prefixes.
- including similar subjects.
- changing the grammar order.
Upgradeable contracts MAY be upgraded to implement this EIP.
Implementers and DApp developers that implement special support for tokens that are compliant with this EIP, SHOULD tolerate different errors emitted by non-compliant contracts, as well as classic revert strings.
Reference Implementation
Solidity
pragma solidity ^0.8.4;
/// @title Standard ERC20 Errors
/// @dev See https://eips.ethereum.org/EIPS/eip-20
/// https://eips.ethereum.org/EIPS/eip-6093
interface ERC20Errors {
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
error ERC20InvalidSender(address sender);
error ERC20InvalidReceiver(address receiver);
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
error ERC20InvalidApprover(address approver);
error ERC20InvalidSpender(address spender);
}
/// @title Standard ERC721 Errors
/// @dev See https://eips.ethereum.org/EIPS/eip-721
/// https://eips.ethereum.org/EIPS/eip-6093
interface ERC721Errors {
error ERC721InvalidOwner(address sender, uint256 tokenId, address owner);
error ERC721InvalidSender(address sender);
error ERC721InvalidReceiver(address receiver);
error ERC721InsufficientApproval(address operator, uint256 tokenId);
error ERC721InvalidApprover(address approver);
error ERC721InvalidOperator(address operator);
}
/// @title Standard ERC1155 Errors
/// @dev See https://eips.ethereum.org/EIPS/eip-1155
/// https://eips.ethereum.org/EIPS/eip-6093
interface ERC1155Errors {
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
error ERC1155InvalidSender(address sender);
error ERC1155InvalidReceiver(address receiver);
error ERC1155InsufficientApproval(address operator, uint256 tokenId);
error ERC1155InvalidApprover(address approver);
error ERC1155InvalidOperator(address operator);
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}
Security Considerations
There are no known signature hash collisions for the specified errors.
Tokens upgraded to implement this EIP may break assumptions in other systems relying on revert strings.
Copyright
Copyright and related rights waived via CC0.