ERC-4931: Generic Token Upgrade Standard
Create a standard interface for upgrading ERC20 token contracts.
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.