Wrapped asset bridge allows bridging ERC20
tokens and native gas tokens (e.g. ETH
) from existing EVM chains (e.g. Ethereum, Avalanche, BSC, etc.) to subnets or brand new EVM chains where those assets do not exist natively. It supports mapping the same wrapped token to multiple tokens on other chains. E.g. moving native USDC from Ethereum or Avalanche to NewChainX will result in the same wrapped asset on NewChainX.
- Clone the repository
- run
yarn
yarn test
Run the full suite of unit tests.
yarn coverage
Get the coverage report.
- Deploy
OriginalTokenBridge.sol
on existing EVM chains. - Deploy
WrappedTokenBridge.sol
on the new EVM chain. - Call
setTrustedRemoteAddress
inWrappedTokenBridge
contract and in eachOriginalTokenBridge
contract. - For each token you want to bridge (e.g.,
USDC
,WETH
, etc), deployWrappedERC20
contract on the new EVM chain. Make sure to setdecimals
in theWrappedERC20
to the number of decimals used in the original token you want to bridge (e.g.,6
decimals forUSDC
,18
decimals forWETH
). If you want to add an additional functionality to the wrapped token, inherit it fromWrappedERC20
and add a custom logic to the derived contract. - For each token you want to bridge, call
registerToken(address token, uint8 sharedDecimals)
function inOriginalTokenBridge
andregisterToken(address localToken, uint16 remoteChainId, address remoteToken)
function inWrappedTokenBridge
. Each wrapped token can be mapped to multiple original tokens on different chains (e.g.USDC
on the new chain is mapped toUSDC
on Ethereum andUSDC
on Avalanche).
- Call
estimateBridgeFee(bool useZro, bytes calldata adapterParams)
inOriginalTokenBridge
contract. - Call
bridge(address token, uint amountLD, address to, LzLib.CallParams calldata callParams, bytes memory adapterParams)
inOriginalTokenBridge
contract to bridgeERC20
tokens passingnativeFee
obtained earlier as a value. This will lockERC20
tokens inOriginalTokenBridge
contract and send a LayerZero message to theWrappedTokenBridge
on another chain to mint wrapped tokens. To bridgeETH
usebridgeNative(uint amountLD, address to, LzLib.CallParams calldata callParams, bytes memory adapterParams)
function and pass a sum ofnativeFee
and amount as a value.
- Call
estimateBridgeFee(uint16 remoteChainId, bool useZro, bytes calldata adapterParams)
inWrappedTokenBridge
. - Call
bridge(address localToken, uint16 remoteChainId, uint amount, address to, bool unwrapWeth, LzLib.CallParams calldata callParams, bytes memory adapterParams)
supplyingnativeFee
obtained earlier as a value. This will burn wrapped tokens and send a LayerZero message toOriginalTokenBridge
contract on another chain to unlock original tokens.
To deploy fresh contracts plese delete the contents of the deployments
folder.
Populate the env MNENOIC in the env file and run the following commands in order.
npx hardhat deployBridges --original-networks "polygon,gnosis" --wrapped-network "fuse"
Now populate the Bridge address on Fuse in the env file and proceed.
npx hardhat deployTokens --original-networks "fuse"
npx hardhat setTrustedRemote --original-networks "gnosis" --wrapped-network "fuse"
npx hardhat registerTokens --original-networks "gnosis" --wrapped-network "fuse" --tokens "USDC,USDT,WETH"
New tokens can be added by adding them in constants and updating the list in deploy/WrappedERC20.js
To see the whole process of deploying a bridge, please check the scrips/deployments
folders
OriginalTokenBridge: 0x8f5D6332eD11338D2dA4fAAC6675e9A6757BeC8b
- locks erc20 from Polygon to Fuse
WrappedTokenBridge: 0xe453d6649643F1F460C371dC3D1da98F7922fe51
- mints and burns Fuse tokens
OriginalTokenBridge: 0xb0F9cE8598c623Ff42e52388F9b452B7CDc409a1
- locks erc20 from Arbitrum to Fuse
WrappedTokenBridge: 0x4014115fB4816Bc8343d8e69d2708Fa738dCaa15
- mints and burns Fuse tokens
OriginalTokenBridge: 0x081dF5af5d022D4A4a4520D4D0D336B8432fDBBb
- locks erc20 from Optimism to Fuse
WrappedTokenBridge: 0xEEd9154F63f6F0044E6b00dDdEFD895b5B4ED580
- mints and burns Fuse tokens
OriginalTokenBridge: 0x081dF5af5d022D4A4a4520D4D0D336B8432fDBBb
- locks erc20 from Arbitrum to Fuse
WrappedTokenBridge: 0xEEd9154F63f6F0044E6b00dDdEFD895b5B4ED580
- mints and burns Fuse tokens
OriginalTokenBridge: 0x081dF5af5d022D4A4a4520D4D0D336B8432fDBBb
- locks erc20 from BSC to Fuse
WrappedTokenBridge: 0xADef29442A11ad9308aC5D012965c887Cf2A53D3
- mints and burns Fuse tokens
OriginalTokenBridge(to Polygon): 0x36207130CF22d8C54842569A32a0Cd5D711f3580
- Fuse (holds WUFSE)
OriginalTokenBridge(to Gnosis): 0xc465107230c21f154627e017b6727A3C18984B02
- Fuse (holds WUFSE)
OriginalTokenBridge(to Optimism): 0xeC3FD32cd5389FbC581427A648d6dc1bc5cfFE3B
- Fuse (holds WUFSE)
OriginalTokenBridge(to Arbitrum): 0x56dF61E9f39C75e2d84C05753557bEBB9841Eb5B
- Fuse (holds WUFSE)
OriginalTokenBridge(to BSC): 0x6bd341B6C7d6123D28d3DDee6A65d441DbAC1E90
- Fuse (holds WUFSE)
WrappedTokenBridge: 0x353af4878d7452e974538706273887F7ED90Da47
- mints and burns erc20 from all the networks
WrappedTokenBridge: 0x6C460c18459907c5b743188eeA35896BAFe9fd74
OriginalTokenBridge(to BSC): 0xd616e2825dC094460cfEfc3d54ed75A6d34a7065