ERC-4931: Generic Token Upgrade Standard

Create a standard interface for upgrading ERC20 token contracts.


Metadata
Status: StagnantStandards Track: ERCCreated: 2021-11-02
Authors
John Peterson (@John-peterson-coinbase), Roberto Bayardo (@roberto-bayardo), David Núñez (@cygnusv)
Requires

Abstract


The following standard allows for the implementation of a standard API for ERC-20 token upgrades. This standard specifies an interface that supports the conversion of tokens from one contract (called the "source token") to those from another (called the "destination token"), as well as several helper methods to provide basic information about the token upgrade (i.e. the address of the source and destination token contracts, the ratio that source will be upgraded to destination, etc.).

Motivation


Token contract upgrades typically require each asset holder to exchange their old tokens for new ones using a bespoke interface provided by the developers. This standard interface will allow asset holders as well as centralized and decentralized exchanges to conduct token upgrades more efficiently since token contract upgrade scripts will be essentially reusable. Standardization will reduce the security overhead involved in verifying the functionality of the upgrade contracts. It will also provide asset issuers clear guidance on how to effectively implement a token upgrade.

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.

Please Note: Methods marked with (Optional Ext.) are a part of the optional extension for downgrade functionality and may remain unimplemented if downgrade functionality is not required.

Token Upgrade Interface Contract


Methods

upgradeSource

Returns the address of the original (source) token that will be upgraded.


upgradeDestination

Returns the address of the token contract that is being upgraded to.


isUpgradeActive

Returns the current status of the upgrade functionality. Status MUST return true when the upgrade contract is functional and serving upgrades. It MUST return false when the upgrade contract is not currently serving upgrades.


isDowngradeActive

Returns the current status of the downgrade functionality. Status MUST return true when the upgrade contract is functional and serving downgrades. It MUST return false when the upgrade contract is not currently serving downgrades. When the downgrade Optional Ext. is not implemented, this method will always return false to signify downgrades are not available.


ratio

Returns the ratio of destination token to source token, expressed as a 2-tuple, that the upgrade will use. E.g. (3, 1) means the upgrade will provide 3 destination tokens for every 1 source token being upgraded.


totalUpgraded

Returns the total number of tokens that have been upgraded from source to destination. If the downgrade Optional Ext. is implemented, calls to downgrade will reduce the totalUpgraded return value making it possible for the value to decrease between calls. The return value will be strictly increasing if downgrades are not implemented.


computeUpgrade

Computes the destinationAmount of destination tokens that correspond to a given sourceAmount of source tokens, according to the predefined conversion ratio, as well as the sourceRemainder amount of source tokens that can't be upgraded. For example, let's consider a (3, 2) ratio, which means that 3 destination tokens are provided for every 2 source tokens; then, for a source amount of 5 tokens, computeUpgrade(5) must return (6, 1), meaning that 6 destination tokens are expected (in this case, from 4 source tokens) and 1 source token is left as remainder.


computeDowngrade (Optional Ext.)

Computes the sourceAmount of source tokens that correspond to a given destinationAmount of destination tokens, according to the predefined conversion ratio, as well as the destinationRemainder amount of destination tokens that can't be downgraded. For example, let's consider a (3, 2) ratio, which means that 3 destination tokens are provided for every 2 source tokens; for a destination amount of 13 tokens, computeDowngrade(13) must return (4, 1), meaning that 4 source tokens are expected (in this case, from 12 destination tokens) and 1 destination token is left as remainder.


upgrade

Upgrades the amount of source token to the destination token in the specified ratio. The destination tokens will be sent to the _to address. The function MUST lock the source tokens in the upgrade contract or burn them. If the downgrade Optional Ext. is implemented, the source tokens MUST be locked instead of burning. The function MUST throw if the caller's address does not have enough source token to upgrade or if isUpgradeActive is returning false. The function MUST also fire the Upgrade event. approve MUST be called first on the source contract.


downgrade (Optional Ext.)

Downgrades the amount of destination token to the source token in the specified ratio. The source tokens will be sent to the _to address. The function MUST unwrap the destination tokens back to the source tokens. The function MUST throw if the caller's address does not have enough destination token to downgrade or if isDowngradeActive is returning false. The function MUST also fire the Downgrade event. approve MUST be called first on the destination contract.


Events

Upgrade

MUST trigger when tokens are upgraded.


Downgrade (Optional Ext.)

MUST trigger when tokens are downgraded.


Rationale


There have been several notable ERC20 upgrades (Ex. Golem: GNT -> GLM) where the upgrade functionality is written directly into the token contracts. We view this as a suboptimal approach to upgrades since it tightly couples the upgrade with the existing tokens. This EIP promotes the use of a third contract to facilitate the token upgrade to decouple the functionality of the upgrade from the functionality of the token contracts. Standardizing the upgrade functionality will allow asset holders and exchanges to write simplified reusable scripts to conduct upgrades which will reduce the overhead of conducting upgrades in the future. The interface aims to be intentionally broad leaving much of the specifics of the upgrade to the implementer, so that the token contract implementations do not interfere with the upgrade process. Finally, we hope to create a greater sense of security and validity for token upgrades by enforcing strict means of disposing of the source tokens during the upgrade. This is achieved by the specification of the upgrade method. The agreed upon norm is that burnable tokens shall be burned. Otherwise, tokens shall be effectively burned by being sent to the 0x00 address. When downgrade Optional Ext. is implemented, the default is instead to lock source tokens in the upgrade contract to avoid a series of consecutive calls to upgrade and downgrade from artificially inflating the supply of either token (source or destination).

Backwards Compatibility


There are no breaking backwards compatibility issues. There are previously implemented token upgrades that likely do not adhere to this standard. In these cases, it may be relevant for the asset issuers to communicate that their upgrade is not EIP-4931 compliant.

Reference Implementation



Security Considerations


The main security consideration is ensuring the implementation of the interface handles the source tokens during the upgrade in such a way that they are no longer accessible. Without careful handling, the validity of the upgrade may come into question since source tokens could potentially be upgraded multiple times. This is why EIP-4931 will strictly enforce the use of burn for source tokens that are burnable. For non-burnable tokens, the accepted method is to send the source tokens to the 0x00 address. When the downgrade Optional Ext. is implemented, the constraint will be relaxed, so that the source tokens can be held by the upgrade contract.

Copyright


Copyright and related rights waived via CC0.