Developer Docs

Composability: StargateSwap.sol

The simplest form of composing Stargate
To test Stargate Composability you can mint yourself testnet tokens using the addresses found on the Test Faucet page.


The StargateSwap.sol must use the IStargateRouter.sol to interact with Stargate. This code snippet shows how the contract uses it to swap tokens using Stargate to another chain
Warning: When composing, Do Not swap() real funds to a contract address that does not implement sgReceive() or your *will* lose those funds.
/// @param qty The remote chainId sending the tokens
/// @param bridgeToken The remote Bridge address
/// @param dstChainId The message ordering nonce
/// @param srcPoolId The token contract on the local chain
/// @param dstPoolId The qty of local _token contract tokens
/// @param to The bytes containing the toAddress
/// @param deadline The bytes containing the toAddress
/// @param destStargateComposed The bytes containing the toAddress
function swap(
uint qty,
address bridgeToken,
uint16 dstChainId,
uint16 srcPoolId,
uint16 dstPoolId,
address to,
uint deadline,
address destStargateComposed
) external payable {
require(msg.value > 0, "stargate requires a msg.value to pay crosschain message");
require(qty > 0, 'error: swap() requires qty > 0');
// encode payload data to send to destination contract, which it will handle with sgReceive()
bytes memory data = abi.encode(to);
// this contract calls stargate swap()
IERC20(bridgeToken).transferFrom(msg.sender, address(this), qty);
IERC20(bridgeToken).approve(address(stargateRouter), qty);
// Stargate's Router.swap() function sends the tokens to the destination chain.
dstChainId, // the destination chain id
srcPoolId, // the source Stargate poolId
dstPoolId, // the destination Stargate poolId
payable(msg.sender), // refund adddress. if msg.sender pays too much gas, return extra eth
qty, // total tokens to send to destination chain
0, // min amount allowed out
IStargateRouter.lzTxObj(200000, 0, "0x"), // default lzTxObj
abi.encodePacked(destStargateComposed), // destination address, the sgReceive() implementer
data // bytes payload


StargateSwap.sol implements IStargateReceiver so it can implement the sgReceive function to receive the tokens and payload.
/// @param _chainId The remote chainId sending the tokens
/// @param _srcAddress The remote Bridge address
/// @param _nonce The message ordering nonce
/// @param _token The token contract on the local chain
/// @param amountLD The qty of local _token contract tokens
/// @param _payload The bytes containing the toAddress
function sgReceive(
uint16 _chainId,
bytes memory _srcAddress,
uint _nonce,
address _token,
uint amountLD,
bytes memory _payload
) override external {
msg.sender == address(stargateRouter),
"only stargate router can call sgReceive!"
(address _toAddr) = abi.decode(_payload, (address));
IERC20(_token).transfer(_toAddr, amountLD);
emit ReceivedOnDestination(_token, amountLD);