Untitled

mail@pastecode.io avatar
unknown
plain_text
5 months ago
3.7 kB
1
Indexable
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

import "@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

struct SwapCoreDescription {
    address tokenIn;
    address tokenOut;
    uint256 sourceChainId;
    uint256 targetChainId;
    address source;
    address target;
    uint256 amountIn;
    uint256 channel;
    string extra;
}

struct SourceSwapDescription {
    SwapCoreDescription core;
    address maker;
    address makerToken;
    address router; // 可能需要改成数组,因为未必只调用一个call就swap成功,比如universalRouter 需要 permit2
    bytes routerCallData;
}

struct TargetSwapDescription {
    SwapCoreDescription core;
    address makerToken;
    uint256 makerTokenAmount;
    address router;
    bytes routerCallData;
}

struct InternalSwapDescription {
    address target;
    address tokenIn;
    address tokenOut;
    uint256 amountIn;
    address router;
    bytes routerCallData;
}

contract OwltoRouter {
    // 原链直接swap到maker
    function swapOnSourceChain(SourceSwapDescription calldata desc)
        external
        payable
        returns (bool)
    {
        receiveToken(desc.core.tokenIn, desc.core.amountIn);

        InternalSwapDescription memory swapDesc = InternalSwapDescription({
            target: desc.maker,
            tokenIn: desc.core.tokenIn,
            tokenOut: desc.makerToken,
            amountIn: desc.core.amountIn,
            router: desc.router,
            routerCallData: desc.routerCallData
        });
        return swap(swapDesc);
    }

    // 目标链先判断是否同链,然后swap到target地址
    function swapOnTargetChain(TargetSwapDescription calldata desc)
        external
        payable
        returns (bool)
    {
        receiveToken(desc.core.tokenIn, desc.core.amountIn);

        address tokenIn = isOnTheSameChain(desc.core)
            ? desc.core.tokenIn
            : desc.makerToken;
        uint256 amountIn = isOnTheSameChain(desc.core)
            ? desc.core.amountIn
            : desc.makerTokenAmount;
        InternalSwapDescription memory swapDesc = InternalSwapDescription({
            target: desc.core.target,
            tokenIn: tokenIn,
            tokenOut: desc.core.tokenOut,
            amountIn: amountIn,
            router: desc.router,
            routerCallData: desc.routerCallData
        });
        return swap(swapDesc);
    }

    function isOnTheSameChain(SwapCoreDescription calldata desc)
        internal
        pure
        returns (bool)
    {
        return desc.sourceChainId == desc.targetChainId;
    }

    function receiveToken(address token, uint256 amount) internal {
        if (token != address(0)) {
            TransferHelper.safeTransferFrom(
                token,
                msg.sender,
                address(this),
                amount
            );
        }
    }

    function swap(InternalSwapDescription memory desc) public returns (bool) {
        if (desc.tokenIn == desc.tokenOut) {
            return send(desc.target, desc.tokenIn, desc.amountIn);
        }

        require(desc.router != address(0), "no router");

        (bool ok, ) = desc.router.call(desc.routerCallData);
        return ok;
    }

    function send(
        address target,
        address token,
        uint256 amount
    ) internal returns (bool) {
        bool ok = true;
        if (token == address(0)) {
            (ok, ) = target.call{value: amount}("");
        } else {
            TransferHelper.safeTransferFrom(
                token,
                address(this),
                target,
                amount
            );
        }
        return ok;
    }
}
Leave a Comment