Initiate a Swap from a Smart Contract
This is a beta feature of Meson. If you wish to use it, please reach out to Meson team for further assistance.
To execute a Meson cross-chain swap through a smart contract, adhere to the following instructions:
1. Encoding the Swap
First, use the encode swap API to generate an encodedSwap. Make sure to input your smart contract's address in the fromAddress field. You should expect a response like the one below:
{
"result": {
"encoded": "0x0100004c4b40d80000000000c1f8707e000000271000652104df03c601232909",
"fromAddress": "0xc597f80150d371fbb39e7b8507456d9d99380255",
"recipient": "0x666d6b8a44d226150ca9058beebafe0e3ac065a2",
"fee": {
"serviceFee": "0",
"lpFee": "0.01",
"totalFee": "0.01"
},
"initiator": "0x9ac467c53aa8535950be25c39660e9e4c1048dcc"
}
}
Unlike swaps initiated from standard addresses (EOAs), those from a smart contract omit the user's signature.
The encoded swap obtained from this API merely indicates a provisional intent to execute a cross-chain swap, and it does not initiate any on-chain transactions. The data remains valid for 15 minutes. If no subsequent action is taken to post this request on-chain within this timeframe, the data can be safely disregarded. If you need to start a new swap, simply generate a new encoded swap.
2. On-chain Transaction
To initiate the transaction, invoke the simpleExecuteSwap function from the Meson contract. Below is a sample implementation:
interface IMesonMinimal {
function tokenForIndex(uint8 tokenIndex) external returns (address token);
function simpleExecuteSwap(uint256 encodedSwap) payable external;
}
contract TransferToMesonContract {
IMesonMinimal meson;
constructor(address mesonAddress) {
meson = IMesonMinimal(mesonAddress);
}
function transferToMeson(uint256 encodedSwap) payable external {
address tokenAddr = _tokenAddrFrom(encodedSwap);
require(tokenAddr != address(0), "Unsupported token");
if (tokenAddr == address(0x1)) {
// Core tokens (the token used to pay gas fees)
uint256 amount = _amountFrom(encodedSwap, 18);
require(amount == msg.value, "Tx value does not match the amount");
meson.simpleExecuteSwap{value: amount}(encodedSwap);
} else {
// ERC20 tokens
IERC20 tokenContract = IERC20(tokenAddr);
uint8 tokenDecimals = tokenContract.decimals();
uint256 amount = _amountFrom(encodedSwap, tokenDecimals);
// Option to transfer tokens directly from user's address
tokenContract.transferFrom(msg.sender, address(this), amount);
tokenContract.approve(address(meson), amount);
meson.simpleExecuteSwap(encodedSwap);
}
}
function _amountFrom(uint256 encodedSwap, uint8 tokenDecimals) internal pure returns (uint256 amount) {
uint256 amountInMeson = (encodedSwap >> 208) & 0xFFFFFFFFFF;
if (tokenDecimals == 6) {
amount = amountInMeson;
} else if (tokenDecimals >= 6) {
// NOTE: Meson's smart contract always use decimal 6 to hanle swap amount.
// Some tokens like ETH, BTC or stablecoins on BNB Chain & Conflux
// have other decimals, so a conversion is required.
amount = amountInMeson * 10 ** (tokenDecimals - 6);
} else {
require(amountInMeson % (10 ** (6 - tokenDecimals)) == 0, "Decimals overflow");
amount = amountInMeson / 10 ** (6 - tokenDecimals);
}
}
function _tokenAddrFrom(uint256 encodedSwap) internal pure returns (address) {
uint8 tokenIndex = uint8(encodedSwap);
return meson.tokenForIndex(tokenIndex);
}
}
Once the transaction is submitted to the initial blockchain, Meson will pick up the order and complete the cross-chain swap. This process typically takes 1-2 minutes. To check the status, visit the Meson explorer at https://explorer.meson.fi/swap/{encoded}. Here, replace {encoded} with your specific encoded swap value to track the progress of your swap.