Hello! 👋 This section will guide you through the process of setting up your xERC20
token.
Let's begin by getting a comprehensive understanding of the required steps based on your token's current situation.
Determine which of the following categories best describes your token's current state.
- Category A: The token is new and is not deployed anywhere.
- Category B: The token already exists on one chain.
- Category C: The token already exists on multiple chains.
{% hint style="info" %}
If you want to spin up an xERC20
on testnet, the category may be different from your mainnet token. We recommend emulating your mainnet token setup if your goal is to testrun the process on testnet.
For example: on mainnet, your token TKN
is currently only deployed on Ethereum (Category B). Then on testnet, you should deploy a TKN
to Goerli and follow the steps for a Category B token.
{% endhint %}
Based on your token's category:
- Category A: Choose one chain to be the home chain.
- Category B: The chain where your token is currently deployed will be the home chain.
- Category C: Choose one chain (among the ones your token is currently deployed) to be the home chain.
- Category A:
- You will deploy an
xERC20
on each chain you wish to support, including the home chain.
- You will deploy an
- Category B and Category C:
- On each chain with an existing token, you need to figure out if a Lockbox setup is needed (next section).
- On all other chains you wish to support, you will just deploy an
xERC20
.
A Lockbox allows any existing ERC20 to become compatible with the ERC-7281 (xERC20) standard. The Lockbox is just a simple wrapper contract, analogous to Wrapped ETH.
For Category B and Category C, there are tokens that already exist on certain chains. For each of these tokens, follow this flowchart to determine if you need to have a Lockbox setup on that token's chain.
To better understand how a Lockbox setup operates, consider the NEXT
token as a real-world example.
- On Ethereum: Both the
NEXT
token andxNEXT
token are deployed with aLockbox
. - On Arbitrum: Only the
xNEXT
token is deployed.
Bridging from Ethereum to Arbitrum:
- [Ethereum] User deposits
NEXT
into the Lockbox and receivesxNEXT
- [Ethereum] User calls the bridge using
xNEXT
- [Arbitrum] Bridge delivers
xNEXT
to the user
Bridging from Arbitrum to Ethereum:
- [Arbitrum] User calls the bridge using
xNEXT
- [Ethereum] Bridge withdraws
NEXT
from the Lockbox using the bridgedxNEXT
- [Ethereum] Bridge delivers
NEXT
to the user
Now that you have an idea of how your tokens should be set up, let's move on to the actual deployment procedures.
The Wonderland team provides an xERC20 Github repository that contains fully compliant implementations of xERC20
, Lockbox
, and scripts to deploy them. Factory contracts have already been deployed on each chain listed under /broadcast/MultichainDeploy.sol/{chain_id}/run-latest.json
.
We suggest you deploy from a fork of this repo, please see the README
for instructions. You will configure the scripts based on which chains you need to have Lockbox setups.
If you wish to roll your own version of an xERC20, make sure your custom implementation is compliant with the standard.
{% hint style="info" %} The ERC-7281 specification requires compliant tokens to implement ERC-20 along with mint/burn and some additional rate limit interfaces. The absolute minimal interface needed is the ERC-20 interface plus mint/burn:
/**
* @notice Mints tokens for a user
* @dev Can only be called by a bridge
* @param _user The address of the user who needs tokens minted
* @param _amount The amount of tokens being minted
*/
function mint(address _user, uint256 _amount) external;
/**
* @notice Burns tokens for a user
* @dev Can only be called by a bridge
* @param _user The address of the user who needs tokens burned
* @param _amount The amount of tokens being burned
*/
function burn(address _user, uint256 _amount) external;
{% endhint %}
You might have noticed there's a LockBoxAdapter
contract in the diagram above when you have a Lockbox setup. This contract facilitates the unwrapping of xERC20 -> ERC20
on the destination chain and is needed for UIs to do this step automatically for users.
The Connext team has a LockboxAdapter
deployed to all our supported chains (the implementation is available here).
As the token issuer, you have the power to decide which bridges can mint/burn your token and the ability to set rate limits per bridge:
/**
* @notice Updates the limits of any bridge
* @dev Can only be called by the owner
* @param _mintingLimit The updated minting limit we are setting to the bridge
* @param _burningLimit The updated burning limit we are setting to the bridge
* @param _bridge The address of the bridge we are setting the limits too
*/
function setLimits(address _bridge, uint256 _mintingLimit, uint256 _burningLimit) external;
These limits will replenish after_DURATION
(by default the repo deploys xERC20
with a value of 1 day).
Once your token is deployed, you can call setLimits
to grant any bridge the privilege to mint/burn your token on that chain.
If you want Connext to be able to bridge your token (here's our pitch in the next section), please go through the following steps.
- Set rate limits for Connext.
- For each chain where your xERC20 is deployed, call
setLimits
as the owner/governor. Use the appropriate Connext address listed under "Core Contract" here as the_bridge
parameter.
- For each chain where your xERC20 is deployed, call
- Submit a PR to our ChainData mappings.
-
For each chain where your xERC20 is deployed, add an object keyed by its address like this:
"0x4c781E4D22cfaAdA520cAe4aF9097C5ecf9C3A71": { "name": "xDappRadar", "symbol": "xRADAR", "decimals": 18 }
-
- Submit a PR to our allowlisting scripts.
-
Under the
assets
key in the configuration object, add another object to the list like this:{ name: "RADAR", canonical: { domain: "11111", address: "0x202426c15a18a0e0fE3294415E66421891E2EB7C", decimals: 18, }, representations: { /// ETHEREUM "6648936": { local: "0x202426c15a18a0e0fE3294415E66421891E2EB7C", adopted: "0x202426c15a18a0e0fE3294415E66421891E2EB7C", }, /// BSC "6450786": { local: "0x489580eB70a50515296eF31E8179fF3e77E24965", adopted: "0x489580eB70a50515296eF31E8179fF3e77E24965", }, }, },
-
The
canonical
object should always have11111
as thedomain
. Change theaddress
anddecimals
to match your home chain xERC20. For example,RADAR
's home chain is Ethereum. -
For each chain where your xERC20 is deployed (including the home chain), add an entry into the
representations
field keyed on the chain'sdomainId
.- You can look up each chain's domainId here. We encourage commenting the chain name above each entry.
local
andadopted
should both be set to the xERC20 address. These exist as separate fields for non-xERC20 assets.- Note:
domainId
is a Connext-specific identifier per chain that exists for forward compatibility with non-evm chains.
-
{% hint style="info" %} 📌 Please reference the ChainData PR in the allowlisting script PR to expedite the review process! {% endhint %}
Once this is done, the Connext Labs team will review your PRs to sanity check deployment details. Once your PR is approved, your tokens will be whitelisted and transferrable across chains!
The Connext team will take care of listing your token on our Bridge UI and be able to track transfers in the Connext explorer.
At this point, your token should be transferrable across chains with no added fees or slippage. However, because of how Connext’s model works, these transfers will happen in large batches through Ethereum L1 roughly once every 2-3 hours.
{% hint style="info" %} 💡 Learn more about fast and slow path execution here. {% endhint %}
If your usecase requires fast (i.e. <2 minute) transfers across chains, you will need some routers in our network to supply some liquidity to execute transactions immediately on behalf of users.
Please reach out to the Connext team and we can help work through options here with our router partners.