🔬
InterSwap Docs
  • Welcome
  • Protocol Level
    • Liquidity Pools
      • Weighted Pools
      • Stable Pools
      • Dynamic Weights
      • Gas Tokens Index(GTI)
    • Add/Remove Liquidity
      • New Pool Creation
      • Add Liquidity
      • Remove Liquidity
    • Swap
  • Integration Level
    • You Integrate us
    • We Integrate you
    • Cross-Chain Smart Routing
  • Supported networks
  • How To
    • Setting Up a Wallet
      • Creating a New Wallet
      • Adding Networks to Metamask
      • Connecting Your Wallet
    • Swap
    • Add Liquidity
    • Remove Liquidity
  • Security
    • Audits
    • Bug Bounty
    • Deployed Contracts
  • TOKENOMICS & GOVERNANCE
    • Allocation & Lockups
    • Token Value Accrual
    • Fees
    • Governance Model
    • Proposals & Voting
  • Information
    • FAQ
Powered by GitBook
On this page
  1. Integration Level

You Integrate us

InterSwap creates an easy permissionless integration level to enable cross-chain liquidity flow for existing applications. So any existing multichain AMM or DEX, Aggregator can become a cross-chain application, just by deploying one smart contract. Cross-chain Lending protocol can integrate InterSwap for enabling cross-chain features.

We are providing “out-of-the-box” examples for Uniswap and 1inch Liquidity protocols.

UniswapV2CrossRouter.sol example

pragma solidity ^0.8.11;
import "../../interfaces/IInterswapCallee.sol"; 
import "../../interfaces/IInterswapCommunicator.sol"; 
import "../../interfaces/IERC20.sol"; 
import "./interfaces/IUniswapV2Router.sol"; 
import "../../libraries/TransferHelper.sol";

contract UniswapV2CrossRouter is IInterswapCallee, IMessageObj, ILzGasObj { address public immutable interswapCommunicator; address public immutable uniswapV2Router;
struct PostSwap {
    bytes[] path;
    bytes receiver;
    uint256 amountOutMin;
}

struct PreSwap {
    uint256 amountIn;
    address[] path;
    uint256 deadline;
}

constructor(address _interswapCommunicator, address _uniswapV2Router) {
    interswapCommunicator = _interswapCommunicator;
    uniswapV2Router = _uniswapV2Router;
}

function interswapCall(
    address token,
    uint256 amount,
    bytes calldata data
) external {
    PostSwap memory postSwap = abi.decode(data, (PostSwap));
    TransferHelper.safeApprove(token, uniswapV2Router, amount);

    // convert bytes to native address format
    address[] memory path = new address[](postSwap.path.length);
    address receiver = bytesToAddress(postSwap.receiver);
    for (uint256 i; i < postSwap.path.length; ++i) {
        path[i] = bytesToAddress(postSwap.path[i]);
    }
    
    // do post swap and send final token to receiver
    try IUniswapV2Router(uniswapV2Router).swapExactTokensForTokens(
        amount,
        postSwap.amountOutMin, // here we are checking amountOutMin finally, if it fails - we will send "token" as result
        path,
        receiver,
        block.timestamp * 2 // deadline is 
    ) {
        // do nothing
    } catch {
        // sending "token" as a result
        TransferHelper.safeTransfer(token, receiver, amount);
    }
}

function swapExactTokensForTokens(
    messageObj memory _messageObj,
    lzGasObj memory _lzGasObj,
    PreSwap calldata preSwap,
    PostSwap calldata postSwap
) external payable {
    address srcCrossTokenAddress = bytesToAddress(_messageObj.tokenA);
    if (preSwap.path.length != 0) {
        require(preSwap.path[preSwap.path.length - 1] == srcCrossTokenAddress, "invalid preSwap src token address");
        TransferHelper.safeTransferFrom(
            preSwap.path[0],
            msg.sender,
            address(this),
            preSwap.amountIn
        );
        TransferHelper.safeApprove(preSwap.path[0], uniswapV2Router, preSwap.amountIn);

        uint256 srcCrossAmountBefore = IERC20(srcCrossTokenAddress).balanceOf(
            address(this)
        );
        IUniswapV2Router(uniswapV2Router).swapExactTokensForTokens(
            preSwap.amountIn,
            0,
            preSwap.path,
            address(this),
            preSwap.deadline
        );
        _messageObj.amountA =
            IERC20(srcCrossTokenAddress).balanceOf(address(this)) -
            srcCrossAmountBefore; // change amountIn after preSwap
        TransferHelper.safeApprove(
            srcCrossTokenAddress,
            interswapCommunicator,
            _messageObj.amountA
        );
    }

    if (postSwap.path.length != 0) {
        // need to do additional post swap using uniswapV2Router on destination chain
        require(
            keccak256(_messageObj.tokenB) == keccak256(postSwap.path[0]) || postSwap.path.length == 1,
            "invalid postSwap path"
        );
        _messageObj.data = abi.encode(postSwap);
        _messageObj.amountB = 0;

        IInterswapCommunicator(interswapCommunicator).swap(_messageObj, _lzGasObj);
    } else {
        // no need to do any post swap
        _messageObj.data = bytes("");
        IInterswapCommunicator(interswapCommunicator).swap(_messageObj, _lzGasObj);
    }
}

function bytesToAddress(bytes memory bys)
    internal
    pure
    returns (address addr)
{
    assembly {
        addr := mload(add(bys, 20))
    }
}
PreviousIntegration LevelNextWe Integrate you

Last updated 2 years ago