ETH Price: $3,669.19 (+0.89%)

Contract Diff Checker

Contract Name:
LQTYWBTCArb

Contract Source Code:

File 1 of 1 : LQTYWBTCArb

// based on https://etherscan.io/address/0xf9a0e641c98f964b1c732661fab9d5b96af28d49#code
pragma solidity ^0.8.14;

interface IUniswapReserve {
    function swap(
        address recipient,
        bool zeroForOne,
        int256 amountSpecified,
        uint160 sqrtPriceLimitX96,
        bytes calldata data
    ) external returns (int256 amount0, int256 amount1);
}

//import "forge-std/console.sol"; // TODO

interface ICurvePool {
    function get_dy(uint i, uint j, uint dx) external view returns(uint);
    function get_dy_underlying(int128 i, int128 j, uint dx) external view returns(uint);
    function exchange(uint i, uint j, uint dx, uint minDy, bool useEth) external payable;
    function exchange_underlying(int128 i, int128 j, uint dx, uint minDy) external returns(uint);
}

interface IGemSeller {
    function getSwapGemAmount(uint lusdQty) external view returns(uint gemAmount, uint feeLusdAmount);
    function swap(uint lusdAmount, uint minGemReturn, address payable dest) external returns(uint);
    function fetchGem2EthPrice() external view returns(uint);
    function fetchEthPrice() external view returns(uint);
    function gemToUSD(uint gemQty, uint gem2EthPrice, uint eth2UsdPrice) external pure returns(uint);
    function USDToGem(uint lusdQty, uint gem2EthPrice, uint eth2UsdPrice) external pure returns(uint);
    function getReturn(uint xQty, uint xBalance, uint yBalance, uint A) external pure returns(uint);
    function compensateForLusdDeviation(uint gemAmount) external view returns(uint newGemAmount);
}

interface ERC20Like {
    function approve(address spender, uint value) external returns(bool);
    function transfer(address to, uint value) external returns(bool);
    function balanceOf(address a) external view returns(uint);
}

interface IUSDT {
    function approve(address spender, uint amount) external;
}

contract LQTYWBTCArb {
    address constant LQTY = 0x6DEA81C8171D0bA574754EF6F8b412F2Ed88c54D;
    address constant WBTC = 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599;
    address constant USDT = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
    address constant LUSD = 0x5f98805A4E8be255a32880FDeC7F6728C6568bA0;

    IGemSeller immutable gemSeller;

    IUniswapReserve constant WBTCLQTY = IUniswapReserve(0xeFd784093dDD12e24231Fa6B792c09d03A4F7B7E);
    uint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;
    uint160 constant MIN_SQRT_RATIO = 4295128739;

    ICurvePool constant threeCrypto = ICurvePool(0xD51a44d3FaE010294C616388b506AcdA1bfAAE46);
    ICurvePool constant lusdCrv = ICurvePool(0xEd279fDD11cA84bEef15AF5D39BB4d4bEE23F0cA);

    constructor(address _gemSellerAddress) {
        gemSeller = IGemSeller(_gemSellerAddress);
        ERC20Like(WBTC).approve(address(threeCrypto), type(uint256).max);
        IUSDT(USDT).approve(address(lusdCrv), type(uint256).max);
        ERC20Like(LUSD).approve(address(gemSeller), type(uint256).max);
    }

    function getSwapAmount(uint wbtcAmount) public view returns(uint lqtyAmount) {
        // wbtc => usdt => lusd => lqty
        uint usdtAmount = threeCrypto.get_dy(1, 0, wbtcAmount);
        uint lusdAmount = lusdCrv.get_dy_underlying(3, 0, usdtAmount);
        (lqtyAmount,) = gemSeller.getSwapGemAmount(lusdAmount);
    }

    function swap(uint lqtyQty, address lqtyDest, uint minLqtyProfit) external payable returns(uint) {
        WBTCLQTY.swap(address(this), false, int256(lqtyQty), MAX_SQRT_RATIO - 1, new bytes(0));

        uint retVal = ERC20Like(LQTY).balanceOf(address(this));
        require(retVal >= minLqtyProfit, "insufficient arb profit");
        ERC20Like(LQTY).transfer(lqtyDest, retVal);

        return retVal;
     }

    function _uniswapWBTCLQTYCallback(
        int256 /* amount0Delta */,
        int256 amount1Delta,
        bytes calldata /* data */
    ) internal {
        // swap WBTC to LQTY
        //uint wbtcAmount = uint(-1 * amount1Delta);
        uint totalWbtcBal = ERC20Like(WBTC).balanceOf(address(this));

        // wbtc => usdt => lusd => lqty
        threeCrypto.exchange(1, 0, totalWbtcBal, 1, false);
        uint usdtBalance = ERC20Like(USDT).balanceOf(address(this));
        uint lusdBalance = lusdCrv.exchange_underlying(3, 0, usdtBalance, 1);

        require(gemSeller.swap(lusdBalance, 1, payable(this)) > 0, "Nothing swapped in GemSeller");

        if(amount1Delta > 0) {
            ERC20Like(LQTY).transfer(msg.sender, uint(amount1Delta));
        }
    }

    function uniswapV3SwapCallback(
        int256 amount0Delta,
        int256 amount1Delta,
        bytes calldata data
    ) external {
        if (msg.sender == address(WBTCLQTY)) {
            _uniswapWBTCLQTYCallback(amount0Delta, amount1Delta, data);
        } else {
            revert("uniswapV3SwapCallback: invalid sender");
        }
    }

    receive() external payable {}
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):