[Proposal] ERC20 transfers through XCM for Moonriver and Moonbeam

I’m Eloïs, a member of the PureStake development team working on Moonbeam and Moonriver. I’m excited to introduce a new proposal that will make it easier to transfer ERC20 tokens across the broader blockchain ecosystem.

Summary

This is a proposal to enable transfer of ERC20 tokens through XCM directly in Moonriver and Moonbeam.
The main idea is that all ERC20 tokens become sendables to others parachains through xtokens pallet/precompile (and receivable as well).

Abstract

Moonbeam is focused on bringing the best of both the Polkadot ecosystem and the EVM worlds to its users.
One of the main added value of the Polkadot ecosystem is of course XCM and the decentralized cross-chain interactions it provides.
In the EVM world, ERC20 tokens are a fundamental building block of the decentralized finance (DeFi) ecosystem, and enabling the transfer of ERC20 tokens across different blockchains is crucial to ensure the continued growth of the DeFi ecosystem that relies on them.

So allowing transfer of ERC20 tokens via XCM seems evident, but it raises many technical challenges that have taken time to mature and required some compromises.

Where are we now?

Currently it is not possible to transfer “real ERC20” assets through XCM. You have to create an XC20-asset (technically called “local asset”) through governance. This is restrictive but was easier to implement, and allows more security and lower costs because the asset is managed directly by the protocol.
These kind of assets expose an ERC20 API through precompiles, but they are not real evm contracts, the ERC20 api is “simulated” by the protocol.
Besides the fact that it needs to go through governance to be created, these XC20-assets are limited in functionality, they propose to define an owner who can mint/burn/freeze, but it is much more limited than what an EVM contract allows.

Why didn’t you allow transfers of ERC20 tokens through XCM from the beginning?

Relying on the implementation of a contract is risky and requires a lot of investigation time to ensure that the protocol remains secure, It was much easier to use assets managed by the protocol, so we started there first.
This is also due to the way XCM is designed. The XCM design poses two problems in particular:

  1. XCM is designed in such a way that assets should be burned/mint to be transferred, which is not covered by the ERC20 standards. Depending on the contract, mint/burn may not be possible, or may be allowed only by an owner/team, or may be managed by a DAO or anything else. It took time and ideas to work around/mitigate this problem.
  2. Each XCM instruction costs a certain weight which has to be determined before the execution of the XCM message, and if all the pre-calculated weight is not actually used there is no mechanism to refund the surplus. This is incompatible with the dynamic gas-cost paradigm of EVM.

Overall picture after this change

With the proposed implementation, any ERC20 token will be able to be sent or received through XCM without requiring any registration on the Moonriver/Moonbeam side (a registration will still be necessary on each destination parachain).
The sending will take place through the pallet/precompile xtokens, with a new variant Erc20 { contract_address } on CurrencyId enum. If you use the precompile, it will be enough to provide directly the address of the ERC20 contract as a “currency id”. If you want to fill in the multilocation directly, it will be of the form PalletId(Erc20Xcm)/AccountKey20(contractAddress, Network::Any).

For each asset that can be transferred via XCM, a unique ‘reserve chain’ is required, and in this case it must be Moonriver/Moonbeam. This is necessary in order to avoid the need to burn/mint the tokens, but it does come at a cost.

If we want to support in the future the transfer of ERC20 tokens through XCM with a reserve chain other than Moonriver/Moonbeam we will have to add constraints to the contracts (ask them to expose mint/burn methods callable by a protocol hardcoded address), which will then imply a registration/whitelist process managed by the governance.

As the reserve chain is Moonriver/Moonbeam, when a user sends ERC20 tokens to another chain, from the point of view of the ERC20 contract the tokens will be transferred to the sovereign account of the destination chain on Moonriver/Moonbeam. So we can follow how many tokens have been transferred on each chain.

When a user sends back ERC20 tokens from another chain to Moonriver/Moonbeam, this corresponds from the point of view of the ERC20 contract to a transfer from the sovereign account of the concerned chain to the user account.

There is a limitation on the amount of gas that can be used to perform the ERC20 transfer, since XCM does not support dynamic cost, we have to encode a gas limit in the protocol, and charge the full amount of this gas limit whatever the contract actually consumes. For the moment we propose to set the gas limit to 80’000 gas, which seems to be enough to support most ERC20 token transfers without being “too” expensive. In parallel we are discussing with Parity on making the design of XCM evolve, in order to better manage this point, but it’s a long work.

Security considerations

Security considerations for ERC20 contract developers

If the implementation of the transfer function returns true when the transfer has not really been done, it allows to duplicate tokens.

Indeed, in the case of sending tokens to another chain, they must be transferred to the sovereign account of the destination chain.
If the contract returns true, the XCM protocol will consider that the tokens have been transferred to the sovereign account of the destination chain and will then send the tokens on the destination chain.

We consider it to be the responsibility of each ERC20 contract to handle error cases correctly, and to return true only if the transfer really went well.

Next steps

After a few days of collecting feedback from the Community and if there are arguments against/or new suggestions, a 7 days voting session will take place. Otherwise this idea will be implemented and proposed to be included in one of the following Runtime Upgrades.

If you have any questions or comments, feel free to reply in the comment section below.

10 Likes

Thank you very much for opening the discussion, this is really something beneficial for everyone, but seems like is not the better course for now

So there is a risk that a bad configuration of the smart contract in moonbeam could end up in double tokens.

I know it depends on the DEV of the smart contract, but doesn’t this put other parachains at risk? because they can repeat this vulnerability, affecting the economy of the other parachains

If the other parachains can select which xc-20 tokens can be accepted in their chain, then it corresponds to a joint effort of both the parachain team and the Smart contract. Which would make more sense, is it really so?

we should try to mitigate these actions, is there a template for these calls? (I’m not a dev, I’m asking from my ignorance, sorry)

1 Like

Sorry I wasn’t precise enough, in reality there is no risk of doubling the token from the point of view of the contract, the tokens are technically never mint nor burn, instead they are transferred to the “sovereign account of destination parachain” (on moonbeam).

If a contract returns true even though it did not actually perform the transfer, the tokens will remain on the user’s account while being sent to the destination parachain, which will give users the impression that they have been duplicated, even if this is not technically the case.

This is of course still a problem, but no more so with XCM than with all the other interactions between contracts (plenty in DEFI).

If an erc20 contract returns true without actually performing the transfer, this remains a problematic and even blocking security hole for any integration into a DEX or bridge or any other defi protocol.

Each parachain should only support as remote token seriously managed tokens, just as each defi protocol (dex or others) does not integrate any new token without verifications.

Yes it is the case with XCM, by default all tokens are refused on the receiving side, each token must be explicitly whitelisted on each parachain that wishes to be able to receive it.

For which kind of calls?

For sending from moonriver/moonbeam it goes through the xtokens pallet/precompile.
For the reception from another parachain, it depends on each parachain, there is no standard to my knowledge. Same for the “whitelisting/registration” on each parachain.

4 Likes

Hey, Eloïs, thank you for your hard work on this proposal.

I completely agree with your proposal and believe that it opens up more opportunities for interaction between the parachains. enabling the transfer of ERC20 tokens via XCM is a crucial step in achieving true compatibility and ensuring the continued growth of the Moonbeam / Moonriver DeFi ecosystems.

I’m particularly impressed by the proposal’s ability to allow any ERC20 token to be sent or received via XCM without requiring any registration on the Moonriver / Moonbeam side. this makes it much easier for users to participate in the ecosystem

3 Likes

Many thanks for this proposal, this will allow developers to design their ERC20 smart contracts to be cross-chain inside of Polkadot.

I’m curious to see the DEFI integrations that will prompt with this feature, it’s also worth to mention that we will have a native bridge for any token we develop.

Would this proposal be something that could also serve as a basis to be able to transfer non-fungible/ERC721 tokens via XCM in the future?

2 Likes

Not this particular proposal, but it’s something I’ve already started thinking about and I think we can indeed do something similar for ERC721 and ERC1155 in the future. It still requires a lot of investigation and probably some improvements on the XCM side, but I hope that the support of ERC20 is just one more step in the long road of XCM integration.

2 Likes

It all looks pretty logical. On the whole, there’s probably nothing better than a shorter route, right? :slightly_smiling_face:

Thank you Elois for the proposal, I think it is very interesting to enable the ERC20 transfers through XCM. I have one question, when you successfully send the ERC20 token to the moonbeam/moonriver, will the ERC20 token on ETH be burnt? if so, how would that happen? For example, we have USDC asset in Moonbeam, and there might be USDC in ETH, are we able to send the USDC from ETH to Moonbeam in this case without any issue?

As I explained in the 1st post, at first only Moonriver/Moonbeam will be supported as a “XCM reserve chain” for ERC20s:

For each asset that can be transferred via XCM, a unique ‘reserve chain’ is required, and in this case it must be Moonriver/Moonbeam. This is necessary in order to avoid the need to burn/mint the tokens, but it does come at a cost.

The cost, I did not specify it because it is inherent to the XCM design of “reserve based transfers”, is that the token is “real” only on the reserve chain, on the other chains it is only an “XCM derivative”.

In other words, this new feature only supports local ERC20 tokens, native to Moonbeam/Moonriver.

The goal is only to replace the existing “Mintable XC-20s” by real ERC20 contracts with a fully customizable implementation according to each project needs.


As for a bridge with ETH via XCM, it is not yet possible, but when it will be, it will go through the “External XC-20s”.

2 Likes