Multichain
Search…
Bridge funds and anyCall
You're able to utilize Multichain's vast liquidity to bridge funds and execute the destination contract in one tx. This is only live on testnets at the time of writing

Introduction

This feature would be implemented in Router V7. (At the time of writing, Router V6 is live) This would combine our token router and anyCall which allows dapps to bridge funds and execute destination contracts with flexibility.
This allows the transfer of monetary values and data information cross-chain in one transaction.
The method is called anySwapOutAndCall .

Applications include:

  • Cross-chain atomic swaps
  • Cross-chain staking
  • Cross-chain lending

Testnet Information

Quick Start

GitHub - bscethbot/BridgeFundsAndAnyCallExample
GitHub
Please fork the above hardhat repo and follow the readme. This repo will do the following:
  1. 1.
    Aquire some test token A for bridging on chain A.
  2. 2.
    Bridge funds and swap to other tokens on chain B.

anySwapOutAndCall workflow

Make sure you're familiar with the basics of anyCall before reading on as this method combines anyCall and bridge functions.
The anySwapOutAndCall function exists on our router contracts. This function would bridge tokens and call your receiver contract on the destination chain.
DAPPS need to deploy a receiver Exec/Anycallproxy Contract which would handle the bridged funds. On the receiver contract, a function named exec needs to be present and it will be called.
A sender contract is optional. You can deploy a sender contract that calls
anySwapOutAndCall if you want to implement additional features like extra fees, swap on source chain.
The general flow is specified below:
DAPPS -> anySwapOutAndCall(Chain A) -> SMPC Network -> anySwapInAndExec(Chain B) ->AnycallExecutor-> exec by DAPP receiver contract(Chain B)
DAPPS call anySwapOutAndCall on Chain A. Then the SMPC network will relay this event and invoke anySwapInAndExec on Chain B which will send the tokens to the DAPP receiver contract.
Then use AnycallExecutortor as a sandbox to call the exec function on the DAPP receiver contract. Hence a function named exec needs to be present in the DAPP receiver contract.
If the exec function execution failed on Chain B, your Exec Contract would handle the fail case.

Interfaces

anySwapOutAndCall (Called by Dapps)

function anySwapOutAndCall( address token, string to, uint256 amount, uint256 toChainID, string anycallProxy, bytes data )

Parameters

Param
Type
Description
token
address
The token you want to bridge.
to
string
The address of the final receiver of bridged token.
amount
uint256
Amount of tokens bridged
toChainID
uint256
The target chain id to interact with
anycallProxy
string
Your destination contract to process the bridge tokens.
data
calldata
The bytes calldata to pass into your destination contract anycallProxy.

Requirements to be compatible with anyCall interfaces:

  1. 1.
    Receiver Contract: A method named execneeds to exist on your anycallProxy contract address. This is needed because the destination router will call execon your receiver contract.
The exec function below is an example of implementation to allow cross-chain swap.
function exec(
address token,
address receiver,
uint256 amount,
bytes calldata data
) external onlyAuth returns (bool success, bytes memory result) {
AnycallInfo memory anycallInfo = decode_anycall_info(data);
require(
anycallInfo.deadline >= block.timestamp,
"SushiSwapAnycallProxy: EXPIRED"
);
address[] memory path = anycallInfo.path;
require(path.length >= 2, "SushiSwapAnycallProxy: invalid path length");
require(
path[0] == token,
"SushiSwapAnycallProxy: source token mismatch"
);
require(
anycallInfo.amountInMax <= amount,
"SushiSwapAnycallProxy:EXCESSIVE_INPUT_AMOUNT"
);
uint256[] memory amounts;
if (anycallInfo.amountOut == 0) {
amounts = swapExactTokensForTokens(anycallInfo);
} else {
amounts = swapTokensForExactTokens(anycallInfo);
}
IERC20(path[0]).safeTransfer(
SushiswapV2Library.pairFor(sushiFactory, path[0], path[1]),
amounts[0]
);
address recvToken;
uint256 recvAmount;
if (anycallInfo.toNative) {
require(
path[path.length - 1] == wNATIVE,
"SushiSwapAnycallProxy:INVALID_PATH"
);
(recvToken, recvAmount) = _swap(
amounts,
path,
address(this)
);
IwNATIVE(wNATIVE).withdraw(recvAmount);
Address.sendValue(payable(receiver), recvAmount);
recvToken = address(0);
} else {
(recvToken, recvAmount) = _swap(
amounts,
path,
receiver
);
}
emit TokenSwap(recvToken, receiver, recvAmount);
if (amount.sub(amounts[0]) > 0) {
IERC20(path[0]).safeTransfer(
receiver,
amount.sub(amounts[0])
);
emit TokenBack(token, receiver, amount.sub(amounts[0]));
}
return (
true,
abi.encode(recvToken, recvAmount)
);
}
2. Whitelist: Your anycallProxy contract needs to be whitelisted by our team. Please contact us on telegram. A proxy contract can be whitelisted on testnet to ease development.
3. If your anycallProxy contract needs role control, use the AnycallExecutor listed in the above table. It will be the sandbox executing the contract. Refer to the role control below.
modifier onlyAuth() {
require(supportedCaller[msg.sender], "SushiSwapAnycallProxy: only auth");
_;
}

Examples

Please read through our example contracts to see how to design a anycallproxy contract. This contract swaps the users funds via Sushiswap to other tokens after receiving the bridged tokens on destination chain.
Polygon mumbai
BNB Testnet

How to test?

This example is for swapping tokens from bnb testnet to rinkeby
  1. 1.
    Request some test multichain tokens for bridging and request for whitelist
2. Call anySwapOutAndCall ( address token, string memory to, uint256 amount, uint256 toChainID, string memory anycallProxy, bytes calldata data ) on polygon mumbai
Param
Value
Description
token
0x53098A3656de0c1ee8DCF004e6a0e886B2968a2F
The token you want to bridge.
to
0xCD54aBE307ccea40Bd24F1892Db4Bde9526D9A11
Your destination contract to process the bridge tokens.
amount
5000000000000000000
Amount of tokens bridged
toChainID
97
The target chain id to interact with
anycallProxy
0xCD54aBE307ccea40Bd24F1892Db4Bde9526D9A11
Your destination contract to process the bridge tokens.
data
abi.encode(0,
0,
1000000000000000000,[0x651FCf3Cf2b52b632185b1175475aE07F320d008,0xA2f5Ab36a1dDd3d64CF07319a84Af8061d38bb9C],Your address,
115792089237316195423570985008687907853269984665640564039457584007913129639935,
false)
{ uint256 amountOut;
uint256 amountOutMin;
uint256 amountInMax;
address[] path;
address receiver;
uint256 deadline;
bool toNative; }
Copy link
On this page
Introduction
Applications include:
Testnet Information
Quick Start
anySwapOutAndCall workflow
Interfaces
Requirements to be compatible with anyCall interfaces:
Examples
How to test?