金色财经

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 518|回复: 0

分享一份闪电贷套利合约

[复制链接]

738

主题

844

帖子

4579

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
4579
QQ
发表于 2023-4-25 17:04:45 | 显示全部楼层 |阅读模式
分享一份闪电贷套利合约
https://twitter.com/0xLmaoevd/status/1650785721643589633?s=20


https://github.com/foolstack-omg ... oduction/Joepeg.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.7;

library SafeMath {
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }
}

interface IWETH {
    function deposit() external payable;

    function transfer(address to, uint256 value) external returns (bool);

    function withdraw(uint256) external;
}

interface IERC20 {
    function transfer(address to, uint256 value) external returns (bool);

    function balanceOf(address owner) external view returns (uint256);

    function approve(address spender, uint256 value) external returns (bool);
}

interface IERC721 {
    function setApprovalForAll(address operator, bool _approved) external;
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

interface ILendingPoolAddressesProvider {
    function getPool() external view returns (address);
}

interface ILendingPool {
    function flashLoanSimple(
        address receiverAddress,
        address asset,
        uint256 amount,
        bytes calldata params,
        uint16 referralCode
    ) external;
}

interface IJoepegExchange {
    function matchAskWithTakerBidUsingAVAXAndWAVAX(
        TakerOrder calldata takerBid,
        MakerOrder calldata makerAsk
    ) external payable;

    function matchAskWithTakerBid(
        TakerOrder calldata takerBid,
        MakerOrder calldata makerAsk
    ) external;

    function matchBidWithTakerAsk(
        TakerOrder calldata takerAsk,
        MakerOrder calldata makerBid
    ) external;
}

struct MakerOrder {
    bool isOrderAsk; // true --> ask / false --> bid
    address signer; // signer of the maker order
    address collection; // collection address
    uint256 price; // price (used as )
    uint256 tokenId; // id of the token
    uint256 amount; // amount of tokens to sell/purchase (must be 1 for ERC721, 1+ for ERC1155)
    address strategy; // strategy for trade execution (e.g., DutchAuction, StandardSaleForFixedPrice)
    address currency; // currency (e.g., WAVAX)
    uint256 nonce; // order nonce (must be unique unless new maker order is meant to override existing one e.g., lower ask price)
    uint256 startTime; // startTime in timestamp
    uint256 endTime; // endTime in timestamp
    uint256 minPercentageToAsk; // slippage protection (9000 --> 90% of the final price must return to ask)
    bytes params; // additional parameters
    uint8 v; // v: parameter (27 or 28)
    bytes32 r; // r: parameter
    bytes32 s; // s: parameter
}

struct TakerOrder {
    bool isOrderAsk; // true --> ask / false --> bid
    address taker; // msg.sender
    uint256 price; // final price for the purchase
    uint256 tokenId;
    uint256 minPercentageToAsk; // // slippage protection (9000 --> 90% of the final price must return to ask)
    bytes params; // other params (e.g., tokenId)
}

contract Joepeg {
    using SafeMath for uint256;
    address private immutable _owner;
    address private constant _joepeg = 0xaE079eDA901F7727D0715aff8f82BA8295719977;
    address private constant _weth = 0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7;
    address private constant _lendingPoolAddressProvider =  0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb;

    constructor() {
        _owner = msg.sender;
        IERC20(_weth).approve(0xaE079eDA901F7727D0715aff8f82BA8295719977, type(uint).max);
    }

    modifier onlyOwner() {
        require(msg.sender == _owner, "only owner.");
        _;
    }

    receive() external payable {}

    function onERC721Received(
        address,
        address,
        uint256,
        bytes memory
    ) public virtual returns (bytes4) {
        return this.onERC721Received.selector;
    }

    function withdraw(address[] calldata erc20s) public onlyOwner {
        for (uint256 i = 0; i < erc20s.length; i++) {
            if (IERC20(erc20s).balanceOf(address(this)) > 0) {
                IERC20(erc20s).transfer(
                    _owner,
                    IERC20(erc20s).balanceOf(address(this))
                );
            }
        }
        uint256 balance = address(this).balance;
        if (balance > 0) {
            payable(_owner).transfer(balance);
        }
    }


    function go(MakerOrder memory order, MakerOrder memory offerOrder, uint code) external onlyOwner {
        ILendingPoolAddressesProvider addressProvider = ILendingPoolAddressesProvider(
                _lendingPoolAddressProvider
            );

        ILendingPool lendingPool = ILendingPool(
            addressProvider.getPool()
        );
        // flashLoan `_debtToCover` amount of `_debtAsset`
        lendingPool.flashLoanSimple(
            address(this),
            _weth,
            order.price,
            abi.encode(order, offerOrder, code),
            uint16(0)
        );

        IERC20(_weth).transfer(_owner, IERC20(_weth).balanceOf(address(this)));
    }

    /**
     * 闪电贷回调
     */
    function executeOperation(
        address asset,
        uint256 amount,
        uint256 premium,
        address initiator,
        bytes calldata params
    ) external returns (bool) {
        require(
            initiator == address(this),
            "flashloan executeOperation failed"
        );

        (MakerOrder memory order, MakerOrder memory offerOrder, uint code) = abi.decode(
            params,
            (MakerOrder, MakerOrder, uint)
        );
        uint256 owed = amount.add(premium);
        //
        // This contract now has the funds requested.
        // Your logic goes here.
        //
        // 1. 购买NFT
        TakerOrder memory takerBid;
        takerBid.isOrderAsk = false;
        takerBid.taker = address(this);
        takerBid.price = order.price;
        takerBid.tokenId = order.tokenId;
        takerBid.minPercentageToAsk = 0;
        takerBid.params = new bytes(0);
        IJoepegExchange(_joepeg).matchAskWithTakerBidUsingAVAXAndWAVAX(takerBid, order);
        // 0x16736b117ab4842C825599db1f1F4B0fd32D3751 JoePeg的ERC721管理器 可能会变化
        IERC721(order.collection).setApprovalForAll(0x16736b117ab4842C825599db1f1F4B0fd32D3751, true);

        // 2. 接受Offer
        TakerOrder memory takerAsk;
        takerAsk.isOrderAsk = true;
        takerAsk.taker = address(this);
        takerAsk.price = offerOrder.price;
        takerAsk.tokenId = offerOrder.tokenId;
        takerAsk.minPercentageToAsk = 0;
        takerAsk.params = new bytes(0);
        IJoepegExchange(_joepeg).matchBidWithTakerAsk(takerAsk, offerOrder);
        // 3. 检查利润是否足以还款
        require(IERC20(_weth).balanceOf(address(this)) >= owed, "LMAO");
        // At the end of your logic above, this contract owes
        // the flashloaned amounts + premiums.
        // Therefore ensure your contract has enough to repay
        // these amounts.

        // Approve the LendingPool contract allowance to *pull* the owed amount
        IERC20(asset).approve(msg.sender, owed);
        return true;
    }
}



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|金色财经

GMT+8, 2026-2-9 04:34 , Processed in 0.016220 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表