Swap tokens cross-chain
Learn how to use the Balanced contracts to swap a non-native token for another asset on supported blockchains.
You can interact with the Balanced smart contracts to swap tokens between blockchains. In this guide, you’ll learn how to query contract data, calculate the swap amounts, and encode the payload to swap USD from Base for AVAX on Avalanche.
For more details and advanced configurations, view the source code, documentation, and examples in the Balanced Examples repository.
Prerequisites
To use this guide, you’ll need a basic understanding of Solidity, smart contract interactions, and cross-chain transaction formats.
Here are the values you’ll need to swap USDC on Base AVAX on Avalanche:
Item | Value |
---|---|
xCall contract address on Base | 0x7fdde482956770D148E055f9d2893f84a1B6B00B |
xCall Manager contract address on Base | 0xbcbd42Ab3c9d219b9c992Cc984DD2a77AfD95EF3 |
asset Manager contract address on Base | 0xDccd213951D8214fBACa720728474E2cEf9d247B |
Balanced Router contract address on ICON | cx21e94c08c03daee80c25d8ee3ea22a20786ec231 |
Pool ID for USDC/bnUSD pool | 0x44 |
Pool ID for AVAX/bnUSD pool | 0x46 |
Network ID for Avalanche | 0xa86a.avax |
Network ID for Base | 0x2105.base |
Network ID for Base | 0x1.icon |
You’ll also need the ABI for these contracts:
1. Query the contract data
-
Call the
getProtocols()
method on the xCall Manager contract on the source chain (Base). -
Call the
getFee(string _net, bool _rollback, string[] _sources)
method on the xCall contract on the source chain (Base).
_net
is the network label of the destination chain_rollback
is a boolean that indicates if the transaction should roll back if it fails_sources
is the array list obtained from thegetProtocols()
method
2. Calculate the swap amounts
We can now calculate the required amount of USDC to send (swap amount + fee):
-
Call the
getPoolStats(string id)
method on the DEX contract to get the pool information for USDC/bnUSD and AVAX/bnUSD. Learn how to query a liquidity pool. -
Use the pool prices to calculate the amount of AVAX to receive after slippage:
- AVAX amount =
(USDC amount x USDC/bnUSD price) ÷ (AVAX/bnUSD price)
- AVAX to receive =
AVAX amount - (AVAX amount x slippage)
3. Encode the payload
It’s time to encode the payload for the transaction. The payload is a list of values encoded with RLP that uses this format:
[
"_swap", // operation identifier for Balanced
NETWORK_ADDRESS_OF_RECEIVER,
MIN_AMOUNT_TO_RECEIVE,
[ 2, SMART_CONTRACT_OF_BNUSD_TOKEN ],
[ 1, SMART_CONTRACT_OF_AVAX_TOKEN ],
]
-
NETWORK_ADDRESS_OF_RECEIVER
is the recipient wallet address. Use theNETWORK_ID/WALLET_ADDRESS
format, e.g.0xa86a.avax/0xf963B069aDCbc094cFe2500a668C1399aeC8F803
. -
MIN_AMOUNT_TO_RECEIVE
is the minimum amount of AVAX to receive after the swap, calculated in the previous step. -
The
[ #, SMART_CONTRACT_OF_TOKEN ]
variables are the path for the swap. Our USDC > AVAX example will swap USDC for bnUSD, then bnUSD for AVAX.Each step in the swap path is an array with two values. The first value is an identifier that indicates whether to swap from the liquidity pool (
1
) or the Stability Fund on ICON (2
). (2
is only necessary for swaps that involve a stablecoin other than bnUSD, like this one.) The second value is the smart contract address of the token on ICON.
Here’s an example of the payload before RLP encoding:
[
'_swap',
'0xa86a.avax/0xf963B069aDCbc094cFe2500a668C1399aeC8F803',
34120090037249480,
[ 2, 'cx88fd7df7ddff82f7cc735c871dc519838cb235bb' ],
[ 1, 'cx66a031cc3bd305c76371fb586e93801b948254f0' ]
]
The encoded payload is added to the data
field of the transaction. The value
field should be set to the amount of USDC to swap.