ERC-7417: Token Converter
Smart-contract service that converts token of one ERC version to another
Abstract
There are multiple token standards on Ethereum chain currently. This EIP introduces a concept of cross-standard interoperability by creating a service that allows ERC-20 tokens to be upgraded to ERC-223 tokens anytime. ERC-223 tokens can be converted back to ERC-20 version without any restrictions to avoid any problems with backwards compatibility and allow different standards to co-exist and become interoperable and interchangeable.
In order to perform the conversion, a user must deposit tokens of one standard to the Converter contract and it will automatically send tokens of another standard back.
Motivation
This proposal introduces a concept of a token standard upgrading procedure driven by a specialized smart-contract which can convert tokens of one standard to another at any time.
Currently some tokens are available on different chains in different standards, for example most exchanges support ERC-20 USDT, TRX USDT, BEP-20 USDT and all this tokens are in fact the same USDT token. This proposal is intended to introduce a concept where there can be a ERC-20 USDT and ERC-223 USDT available on Ethereum mainnet at the same time and these would be freely interchangeable.
The address of the deployed Token Converter must be described here as to solve the trust issues for the token developers and help them figure out a proper way of interacting with the Converter.
As Ethereum already has an established ecosystem of tokens and ERC-20 is the most adopted standard at the moment the lack of defined migration processes can be a bottleneck for newer standards adoption. This proposal addresses the problem of coordinating the upgrading process and addresses the backwards compatibility problems for ERC-20 and ERC-223 tokens.
The Token Converter is supposed to allow anyone to create an alternative version of an existing token implemented in a different standard. This proposal focuses on ERC-20 and ERC-223 standards and takes into account the specifics of this particular token standards. It is assumed that the most common case would be creation of ERC-223 version for an existing ERC-20 token.
The implementation of this service is an alternative to convincing each token developer to choose an alternative standard at the moment of the token deployment or during the development stage of their project. With this service there will be no need to choose one standard and stick with it as every token can be available in both concurrently.
The implementation of this Token Converter service is supposed to be a contract deployed on Ethereum mainnet once and forever. It's address will be provided in the text of this proposal as to avoid any potential trust issues and assure the developers that the service they are interacting with is exactly the one which drives the conversion process of existing tokens.
All the ERC-223 tokens created by the Token Converter will be identical in a way that they all implement the same functions, which return the same values and there is no ambiguity there. This helps to avoid problems where a token deployed during the early stage of a token standard adoption may implement it improperly or there can be an ambiguity in the standard itself that would allow developers to implement tokens of one standard in different ways.
For example it was a common case with ERC-20 where developers could implement custom logic of the transfer
function and mess the return values. The ERC-20 specification declares that a transfer
function MUST return a bool
value, however in practice we have three different types of ERC-20 tokens which are not compatible with each other:
- ERC-20 tokens that return
true
on success and revert on an error. - ERC-20 tokens that return
true
on success andfalse
on an error without reverting the transaction. - ERC-20 tokens that don't have return values and revert on an error.
Technically the third category of tokens is not compatible with ERC-20 standard. However, USDT token deployed on Ethereum mainnet at 0xdac17f958d2ee523a2206206994597c13d831ec7
address does not implement return values and it is one of the most used tokens and it is not an option to deny supporting USDT due to it's improper implementation of the standard.
The Token Converter eliminates the issue where different development teams may implement the standard with slight modifications and result in a situation where we would have different versions of the same standard on the mainnet.
At the same time the Converter enables the concurrent token support in other smart-contracts, such as decentralized exchanges. The Converter can guarantee that a pair of two tokens one of which is a wrapper for another is in fact the same token that can be converted from one standard to another at any time. This enables the creation of liquidity pools where two different tokens are dealt with as if they were one token.
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 Token Converter system comprises two main components:
-
Converter contract.
-
Wrapper contracts. Each original token can have exactly one wrapper of each standard.
Converter contract can deploy new ERC-223 wrapper contracts for any ERC-20 token that does not have a ERC-223 wrapper currently. There MUST be exactly one ERC-223 wrapper for each ERC-20 token.
Converter contract MUST accept deposits of ERC-20 tokens and send ERC-223 tokens to the depositor at 1:1 ratio. Upon depositing 1234 units of ERC20 token_A
the depositor MUST receive exactly 1234 units of ERC223 token_A
. This is done by issuing new ERC-223 tokens at the moment of ERC-20 deposit. The original ERC-20 tokens MUST be frozen in the Converter contract and available for claiming back.
Converter contract MUST accept deposits of ERC-223 tokens and send ERC-20 tokens to the depositor at 1:1 ratio. This is done by releasing the original ERC-20 tokens at the moment of ERC-223 deposit. The deposited ERC-223 tokens must be burned.
Token Converter
Conver contract methods
getERC20WrapperFor
Returns the address of the ERC-20 wrapper for a given token address. Returns 0x0
if there is no ERC-20 version for the provided token address. There can be exactly one wrapper for any given ERC-223 token address created by the Token Converter contract.
getERC223WrapperFor
Returns the address of the ERC-223 wrapper for a given token address. Returns 0x0
if there is no ERC-223 version for the provided token address. There can be exactly one ERC-223 wrapper for any given ERC-20 token address created by the Token Converter contract.
getERC20OriginFor
Returns the address of the original ERC-20 token for the provided ERC-223 wrapper. Returns 0x0
if the provided _erc223Token
is not an address of any ERC-223 wrapper created by the Token Converter contract.
getERC223OriginFor
Returns the address of the original ERC-223 token for the provided ERC-20 wrapper. Returns 0x0
if the provided _erc20Token
is not an address of any wrapper created by the Token Converter contract.
predictWrapperAddress
Wrapper contracts are deployed via CREATE2
opcode and it is possible to predict the address of a wrapper which is not yet deployed. The address of a wrapper contract depends on the bytecode therefore it is necessary to specify if the address of wrapper ERC-20 or wrapper ERC-223 must be predicted.
Providing _token
address and _isERC20 = false
will result in ERC-20 wrapper address being predicted.
Providing _token
address and _isERC20 = true
will result in ERC-223 wrapper address being predicted.
createERC223Wrapper
Creates a new ERC-223 wrapper for a given _erc20Token
if it does not exist yet. Reverts the transaction if the wrapper already exist. Returns the address of the new wrapper token contract on success. Reverts if _erc223Token
is a wrapper created by the Converter.
The deployed contract will be a standard ERC-223 token with approve
and transferFrom
functions implemented for backwards compatibility.
All ERC-223 wrappers deployed by the Converter will have standard() pure returns (bytes32)
function implemented which returns 223
. This serves further token standard introspection as ERC-165 may not be reliable when dealing with identifying the internal logic implemented within transfer
function of a token.
NOTE: This function does not verify the standard of _erc20Token
because there is no reliable method of introspection available which could guarantee that the provided token implements a particular standard. As the result it is possible to create a ERC-223 wrapper for an original ERC-223 token.
createERC20Wrapper
Creates a new ERC-20 wrapper for a given _erc223Token
if it does not exist yet. Reverts the transaction if the wrapper already exist. Returns the address of the new wrapper token contract on success. Reverts if _erc223Token
is a wrapper created by the Converter.
NOTE: This function does not verify the standard of _erc223Token
because there is no reliable method of introspection available which could guarantee that the provided token implements a particular standard. As the result it is possible to create a ERC-20 wrapper for an original ERC-20 token.
wrapERC20toERC223
Withdraws _amount
of ERC-20 tokens from the transaction sender with transferFrom
function. Delivers the _amount
of ERC-223 wrapper tokens to the sender of the transaction. Stores the original tokens at the balance of the Token Converter contract for future claims. Returns true
on success. The Token Converter must keep record of the amount of ERC-20 tokens that were deposited with wrapERC20toERC223
function because it is possible to deposit ERC-20 tokens to any contract by directly sending them with transfer
function.
If there is no ERC-223 wrapper for the _ERC20token
then creates it by calling a createERC223Wrapper(_erc20toke)
function.
There is no special function to unwrap ERC-223 wrappers to ERC-20 origin as this logic is implemented in the tokenReceived
function of the Converter.
unwrapERC20toERC223
Withdraws _amount
of ERC-20 tokens from the transaction sender with transferFrom
function. Delivers the _amount
of ERC-223 wrapper tokens to the sender of the transaction. Stores the original tokens at the balance of the Token Converter contract for future claims. Returns true
on success. The Token Converter must keep record of the amount of ERC-20 tokens that were deposited with wrapERC20toERC223
function because it is possible to deposit ERC-20 tokens to any contract by directly sending them with transfer
function.
If there is no ERC-223 wrapper for the _ERC20token
then creates it by calling a createERC223Wrapper(_erc20toke)
function.
convertERC20
Automatically determines if the provided ERC-20 token is a wrapper or not. If it is a wrapper then executes unwrapERC20toERC223
function. If the provided token is an origin then executes wrapERC20toERC223
function.
This function is implemented to significantly simplify the workflow of services that integrate both versions of one token in the same contract and need to automatically convert tokens through the Converter.
isWrapper
Returns true
if the provided _token
address is an address of a wrapper created by the Converter.
NOTE: This function does not identify the standard of a _token
. There can be exactly one origin for any wrapper created by the Converter. However an original token can have two wrappers, one of each standard.
tokenReceived
This is a standard ERC-223 transaction handler function and it is called by the ERC-223 token contract when _from
is sending _value
of ERC-223 tokens to address(this)
address. In the scope of this function msg.sender
is the address of the ERC-223 token contract and _from
is the sender of the token transfer.
Automatically determines
If msg.sender
is an address of ERC-223 wrapper created by the Token Converter then _value
of ERC-20 original token must be sent to the _from
address.
If msg.sender
is not an address of any ERC-223 wrapper known to the Token Converter then it is considered a ERC-223 origin and _value
amount of ERC-20 wrapper tokens must be sent to the _from
address. If the ERC-20 wrapper for the msg.sender
token does not exist then create it first.
Returns 0x8943ec02
.
extractStuckERC20
This function allows to extract the ERC-20 tokens that were directly deposited to the contract with transfer
function to prevent users who may send tokens by mistake from permanently losing their tokens. Since the Token Converter calculates the amount of tokens that were deposited legitimately with convertERC20toERC223
function it is always possible to calculate the amount of "accidentally deposited tokens" by subtracting the recorded amount from the returned value of the balanceOf( address(this) )
function called on the ERC-20 token contract.
Converting ERC-20 tokens to ERC-223
In order to convert ERC-20 tokens to ERC-223 the token holder should:
- Call the
approve
function of the ERC-20 token and allow Token Converter to withdraw tokens from the token holders address viatransferFrom
function. - Wait for the transaction with
approve
to be submitted to the blockchain. - Call the
convertERC20toERC223
function of the Token Converter contract.
Converting ERC-223 wrapper tokens back to ERC-20
In order to convert ERC-20 tokens to ERC-223 the token holder should:
- Send ERC-223 tokens to the address of the Token Converter contract via
transfer
function of the ERC-223 token contract.
Rationale
Support of ERC-223 original tokens
Two methods of implementing a Token Converter service were considered: (1) a converter that can only create ERC-223 versions of the existing ERC-20 tokens, and (2) a converter that can create both versions (ERC-20 and ERC-223) of any original token.
The first approach would encourage developers to always deploy an original token as ERC-20 and then create it's ERC-223 version in the converter. If it would happen that some developers may consider ERC-223 as their original standard then they would be left with the problem of creating their custom ERC-20 version of the token. In addition, if any third party contracts like liquidity pools are using the proposed Token Converter to ensure that a token can be listed on a DEX with two versions and both can be combined within one pool - then such contract would not be able to recognize any original ERC-223 token and it's ERC-20 version as a valid pair of contracts that represent one token available in two standards.
For that reason it was decided to go with the second approach where the Converter can create ERC-20 wrappers for original ERC-223 tokens.
Support of approve
& transferFrom
functions in the ERC-223 wrapper tokens
This functions are superfluous for a ERC-223 token since the transfer
function can be used to deposit tokens of this standard to contracts. The current ecosystem is built for ERC-20 tokens however and there are plenty of multisig contracts that rely on accepting tokens deposited without any callback with an assumption that it is not necessary for a multisig to count the amount of tokens it stores.
There can be any other contracts and scenarios where it would be necessary to deposit a token to a contract which is relying on an assumption that tokens are deposited without invoking a callback in the recipient. As the result we can expect that any original deployed ERC-223 tokens will support this functions, as token developers strive for backward compatibility with the existing ecosystem. In order to make tokens deployed by the converter a reference implementation for developers that can be used without any modifications it was decided to support this functions in the ERC-223 wrapper contracts.
transferFrom
function does not support error handling and this needs to be taken into account. It is possible to deposit tokens to a contract which is not designed to receive them by approving X tokens to your own address and then calling a transferFrom(self, contract, X)
. The tokens will be deposited regardless of whether the recipient contract is designed to hold/receive tokens or not. The tokens may get permanently stuck if the recipient contract did not implement the extraction functions. The approve
& transferFrom
function is not the default method of token transferring however and it is not directly used by any wallets and any other software that manages tokens. The transfer
function (which is safe) is used instead. The transferFrom
function is supposed to be invoked by a contract to pull tokens from the approver.
As the result, the approve
& transferFrom
transferring method must be avoided with ERC-223 tokens whenever possible.
Modified transfer events of the ERC-223 token
The pure ERC-223 token implementation has the following event emitted on a token transfer: event Transfer(address indexed _from, address indexed _to, uint256 _value, bytes _data)
. This events are different from ones emitted by ERC-20 tokens and may not be properly recognized by existing blockchain explorers, wallets and other services that browse token transfers history.
It was considered that events are not an important part of the standard as these do not affect the logic of the token, it's workflow and it's security. When developing the Converter it was decided to prioritize compatibility with existing ecosystem.
standard()
function usage for the introspection
The main existing method of introspection is currently ERC-165 which inspects the signatures of functions implemented in a contract. It is not possible to differentiate an ERC-20 token from an ERC-223 token by just browsing functions that they implement without digging their internal logic.
Here is a token and it is not possible to identify if it should be dealt with as ERC-20 or ERC-223 because it depends on the actual implemenation of it's transfer
function logic.
In case of this implementation the token will behave as ERC-20:
In case of this implementation the token will behave as ERC-223:
Also, there are plenty of tokens that do not implement ERC-165 introspection at all. As the result it was decided to implement a special standard() returns (uint32)
function in all ERC-223 wrappers created by the Converter and assume that original ERC-223 tokens may explicityly declare themselves as ERC-223 by implementing the same function too. It is assumed that if a token does not implement this function then it is ERC-20.
This method of token standard introspection is more precise than ERC-165.
Backwards Compatibility
This proposal is supposed to eliminate the backwards compatibility concerns for different token standards making them interchangeable and interoperable.
This service is the first of its kind and therefore does not have any backwards compatibility issues as it does not have any predecessors.
Reference Implementation
Security Considerations
- While it is possible to implement a service that converts any token standard to any other standard - it is better to keep different standard convertors separate from one another as different standards may contain specific logic and therefore require different conversion approach. This proposal focuses on ERC-20 and ERC-223 upgradeability.
- ERC-20 tokens can be deposited to any contract directly with
transfer
function. This may result in a permanent loss of tokens because it is not possible to recognize this transaction on the recipients side. Therefore wrapper-ERC-20 tokens are prone to this problem as they are compatible with the ERC-20 standard.rescueERC20
function is implemented to address this problem. - Token Converter relies on ERC-20
approve
&transferFrom
method of depositing assets. Any related issues must be taken into account.approve
andtransferFrom
are two separate transactions so it is required to make sureapproval
was successful before relying ontransferFrom
. - This is a common practice for UI services to prompt a user to issue unlimited
approval
on any contract that may withdraw tokens from the user. This puts users funds at risk and therefore is not recommended. - There is no reliable token standard introspection method available that could guarantee that a token implements a particular token standard. It is possible to artificially construct a token that will pretend it is a ERC-20 token that implements
approve & transferFrom
but at the same time implements ERC-223 logic of transferring viatransfer
function. It can be possible to create a ERC-223 wrapper for this ERC-20-ERC-223 hybrid implementation in the Token Converter. This doesn't pose any threat for the workflow of the Token Converter itself but it must be taken into account that if a token has ERC-223 wrapper in the Token Converter it does not automatically mean the origin is fully compatible with the ERC-20 standard and methods of introspection must be used to determine the origins compatibility with any existing standard. - Token Converter does not verify the standard of a provided token when it is asked to create a wrapper for it due to the lack of reliable standard introspection method. It is possible to call
createERC20Wrapper
function and provide an address of an existing ERC-20 token. The Token Converter will successfully create a ERC-20 wrapper for that ERC-20 original token. It is also possible to create a ERC-223 wrapper for that exact original ERC-20 token. This doesn't pose any threat to the workflow of the Converter but it must be taken into account that any token regardless of it's original standard may have up to two wrappers created by the Converter, one for each standard. Any wrapper token must have exactly one origin. It is not possible to create a wrapper for a wrapper. - The Token Converter only holds the original tokens that were deposited during the conversion process and it assumes that tokens do not decay over time and the token balance of the Converter does not decrease on its own. If some token implements burning logic or decaying supply and it may impact the balance of the Converter then the Converter must not be used to deploy an alternative version of that token as it will not be able to guarantee that there is enough tokens for the conversion at any time.
Copyright
Copyright and related rights waived via CC0.