Skip to content

How to write anytoken wrapper contract to support Multichain Bridge Router

jowenshaw edited this page Sep 9, 2022 · 5 revisions

How to write anytoken/wrapper contract to support Multichain Bridge/Router

IBridge interface

For a token to support Multichain Bridge, we should support the following interface

interface IBridge {
    function Swapin(bytes32 txhash, address account, uint256 amount) external returns (bool);
    function Swapout(uint256 amount, address bindaddr) external returns (bool);

    event LogSwapin(bytes32 indexed txhash, address indexed account, uint256 amount);
    event LogSwapout(address indexed account, address indexed bindaddr, uint256 amount);
}

IRouter interface

For a token to support Multichain Router, we should support the following interface

interface IRouter {
    function mint(address to, uint256 amount) external returns (bool);
    function burn(address from, uint256 amount) external returns (bool);
}

Other required interfaces for Router supporting

Theorectically we only need to implement the above IRouter interface to support Multichain Router.

But For the frontend interaction, we must distinguish the following three things:

  1. call which swapout method of the Router contract

    function anySwapOut(address token, address to, uint amount, uint toChainID) external
    function anySwapOutUnderlying(address token, address to, uint amount, uint toChainID) external
    function anySwapOutNative(address token, address to, uint toChainID) external payable
  2. how to approve token spending

    • no need to approve
    • need approve to the router contract
    • need approve to the anytoken/wrapper contract
  3. should we provide liquidity methods (deposit/withdraw)


To distinguish these, we have the following two processing logics.

if anytoken/wrapper contract has accessable underlying method, then use the underlying logic

1. use underlying logic

function underlying() external view returns (address);
function underlyingIsMinted() external view returns (bool);
  • if underlying is the zero address, then

    1. call anySwapOut
    2. no need to approve
    3. no need to provide liquidity
  • if underlying is non-zero address and underlyingIsMinted is true, then

    1. call anySwapOut
    2. need approve to the anytoken contract
    3. no need to provide liquidity
  • if underlying is non-zero address and underlyingIsMinted is false, then

    1. call anySwapOutNative if the underlying is the wNative address, otherwise call anySwapOutUnderlying
    2. need approve to the router contract
    3. need provide liquidity

Examples:

AnyswapV6ERC20.sol

AnyswapV6ERC20-comint.sol

2. use wrapper logic

function tokenType() external view returns (uint8);
function token() external view returns (address);

the following is the knowable TokenType enumerables (value start from 0):

  • MintBurnAny (0)
    1. token should support mint and burn(from, amount)
    2. no need to approve
    3. no need to provide liquidity
  • MintBurnFrom (1)
    1. token should support mint and burnFrom(from, amount)
    2. need approve to the wrapper contract
    3. no need to provide liquidity
  • MintBurnSelf (2)
    1. token should support mint and burn(amount), called transferFrom
    2. need approve to the wrapper contract
    3. no need to provide liquidity
  • Transfer (3)
    1. use token transfer and transferFrom
    2. need approve to the wrapper contract
    3. no need to provide liquidity
  • TransferDeposit (4)
    1. use token transfer and transferFrom
    2. need approve to the wrapper contract
    3. need to provide liquidity (block when lack of liquidity)
  • TransferDeposit2 (5)
    1. use token transfer and transferFrom
    2. need approve to the wrapper contract
    3. no need to provide liquidity (when lack of liquidity, don't block and borrow or swap from other party)

Examples:

MintBurnWrapper.sol

AnyswapV6ERC20-Ontology.sol