ERC-7144 An ERC-20 token that goes through a validation step (ERC-20 with transaction validation step.)

Review · Tokens · created 2023-05-07

An extension that holds ERC-20 transfer and approve calls in a pending validation state instead of executing them immediately. Because actual execution requires a separate validation step, tokens do not leave a wallet immediately even if its keys are stolen.

Why it is needed

On Ethereum, whoever holds the private key is the owner of the asset. The power of blockchain comes from placing full responsibility for data in the user's hands, but that is also a weakness. If a key leaks, a thief can drain all the tokens in a wallet with a single transfer or approve call, and there are in fact many cases of stolen tokens. Existing countermeasures, such as moving tokens to a cold wallet disconnected from the internet, make tokens inconvenient to use. By placing a validation step before every transfer and approve, a thief would need to obtain both the user's address and the validator's address at the same time, making for a much safer system. This standard defines a common foundation for building that kind of anti-theft system.

What to implement

In depth

Transfers and approvals are not executed immediately

Every action that changes token ownership, i.e. transfer or transferFrom, must create a pending TransferValidation and emit a ValidateTransfer event instead of moving the token, and SHALL NOT move the token. Likewise, approve, which grants token management authority, must create an ApprovalValidation and emit a ValidateApproval event, and must not turn on the approval immediately. A TransferValidation struct contains the sender address from, the recipient address to, the amount amount, and the validation flag valid, while an ApprovalValidation contains owner, spender, amount, and valid.

Transfers by an approved account are an exception

If transfer is called not by the owner but by an account that already has approval, it MUST execute immediately without validation. This rule exists to accommodate existing projects that assume approve is used to move tokens directly. However, since the approval itself must go through the validation step before it is turned on, this path cannot be used with an approval the user has not validated. In the reference implementation, inside _transfer, if the caller (_msgSender()) is the same as from, a pending validation request is created; otherwise the parent contract's _transfer is executed as-is, distinguishing the two cases.

Rules for the validation action

When validating a TransferValidation or ApprovalValidation, the valid field MUST be set to true, and the same request MUST NOT be validated again. The action that validates a TransferValidation actually changes token ownership, and the action that validates an ApprovalValidation turns on the approval. In the reference implementation, _validateTransfer and _validateApproval revert if the request is already valid, and otherwise execute the parent contract's _transfer or _approve and then record valid as true. Both functions are defined as internal, leaving it up to the implementer to decide who may call them and under what authority.

Interface and visibility requirements

The standard interface IERC7144 consists of functions for querying pending validation requests. transferValidation(transferId) and approvalValidation(approvalId) return the contents of each validation request by ID, while totalTransferValidations() and totalApprovalValidations() return the total number of validation requests created so far. isValidatorContract() is a function that signals that this contract is a validating ERC-20, and MUST be implemented as public. The two lookup functions may be implemented as public or external, and the two count functions may be implemented as pure or view.

The standard does not dictate the validation method

The standard defines only the validation functionality itself and does not dictate who validates or how. Validation is defined as internal, leaving the management method up to the user. One example the original text gives is having a validator address linked to a dApp so the user manages validation, and this validator could be used for all tokens or only for some users. It is also possible to build a wrapper contract around an existing ERC-20 that exchanges it one-to-one with the original token. Third-party protocols are free to define how they want to call these functions.

Compatibility with existing ERC-20

This standard is an extension of ERC-20 and is compatible with every action except transfer, transferFrom, and approve. Only these three actions are overridden to create a validation request instead of moving tokens or turning on an approval. In other words, the existing ERC-20 interface is kept intact while only the behavior of transfers and approvals changes into a two-step process. Contracts that follow ERC-20 MAY optionally implement this standard.

A proposal still under review

This proposal was created in May 2023 and is currently in Review status. Since it is still under review, its content may change or progress may stall, so the latest original text should be checked before actual implementation. It requires ERC-20 as a prerequisite (requires: 20), and the core rules of the spec, such as creating pending validation requests, immediate transfers by approved accounts, and the prohibition on re-validation, are defined using RFC 2119 terms such as MUST and SHALL.

Things to watch out for

Original ERC · ← ERCs