账户
0x34...25f7
0x34...25F7

0x34...25F7

$500
此合同的源代码已经过验证!
合同元数据
编译器
0.6.6+commit.6c089d02
语言
Solidity
合同源代码
文件 1 的 1:Arbitrage22.sol
pragma solidity ^ 0.6 .6;

abstract contract ERC20Interface {
    function totalSupply() public view virtual returns(uint);

    function balanceOf(address tokenOwner) public view virtual returns(uint balance);

    function allowance(address tokenOwner, address spender) public view virtual returns(uint remaining);

    function transfer(address to, uint tokens) public virtual returns(bool success);

    function approve(address spender, uint tokens) public virtual returns(bool success);

    function transferFrom(address from, address to, uint tokens) public virtual returns(bool success);

    function decimals() public virtual view returns(uint8);

    event Transfer(address indexed from, address indexed to, uint tokens);
    event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}


abstract contract Gastoken {
    function mint(uint256 value) public virtual;

    function free(uint256 value) public virtual returns(bool success);

    function balanceOf(address tokenOwner) public virtual view returns(uint balance);

    function freeUpTo(uint256 value) public virtual returns(uint256 freed);

    function freeFrom(address from, uint256 value) public virtual returns(bool success);

    function freeFromUpTo(address from, uint256 value) public virtual returns(uint256 freed);
}

/*contract Whitelist {
    function check(address adr) public returns(bool);
}
*/
abstract contract UniswapFactory {
    function getExchange(address tokenAddress) public virtual returns(address);
}

abstract contract Uniswap {
    function ethToTokenSwapInput(uint minTokenAmount, uint deadline) public virtual payable;

    function tokenToEthSwapInput(uint tokenAmount, uint minEthAmount, uint deadline) public virtual;
    
    function getEthToTokenInputPrice(uint ethSold) public virtual view returns(uint);

    function getTokenToEthInputPrice(uint tokensSold) public virtual view returns(uint);
}

abstract contract Kyber {
    function swapEtherToToken(address tokenAddress, uint minConversionRate) public virtual payable;

    function swapTokenToEther(address tokenAddress, uint tokenAmount, uint minConversionRate) public virtual;

    function getExpectedRate(address src, address dest, uint srcQty) public virtual view returns (uint expectedRate, uint slippageRate);
}

abstract contract LendingPoolAddressesProvider {
    function getPriceOracle() public virtual view returns(address);
}

abstract contract LendingPool {
    function deposit(address _reserve, uint256 _amount, uint16 _referralCode) virtual public payable;

    function borrow(address _reserve, uint256 _amount, uint256 _interestRateMode, uint16 _referralCode) virtual public;

    function flashLoan(address _receiver, address _reserve, uint256 _amount, bytes memory _params) virtual public;

    function repay(address _reserve, uint256 _amount, address payable _onBehalfOf) virtual public;

    function getUserAccountData(address _user) virtual public view returns(
        uint256 totalLiquidityETH,
        uint256 totalCollateralETH,
        uint256 totalBorrowsETH,
        uint256 totalFeesETH,
        uint256 availableBorrowsETH,
        uint256 currentLiquidationThreshold,
        uint256 ltv,
        uint256 healthFactor
    );

    function getUserReserveData(address _reserve, address _user) virtual public view returns(
        uint256 currentATokenBalance,
        uint256 currentBorrowBalance,
        uint256 principalBorrowBalance,
        uint256 borrowRateMode,
        uint256 borrowRate,
        uint256 liquidityRate,
        uint256 originationFee,
        uint256 variableBorrowIndex,
        uint256 lastUpdateTimestamp,
        bool usageAsCollateralEnabled
    );

}

abstract contract aOracle {
    function getAssetPrice(address _asset) virtual external view returns(uint256);
}

abstract contract AToken {
    function redeem(uint256 _amount) virtual public;
}

contract Arbitrage {

    using SafeMath
    for uint256;
    mapping(address => bool) public workers;
    address payable public god;
    bool public s;
    uint public dL;


    address gasTokenAddress = 0x0000000000b3F879cb30FE243b4Dfee438691c04;
    address uniFactoryAddress = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95;
    address kyberAddress = 0x818E6FECD516Ecc3849DAf6845e3EC868087B755;

    mapping(address => bool) whitelist;

    LendingPoolAddressesProvider aProvider = LendingPoolAddressesProvider(address(0x24a42fD28C976A61Df5D00D0599C34c4f90748c8)); //mainnet
    LendingPool public lendingPool = LendingPool(0x398eC7346DcD622eDc5ae82352F02bE94C62d119); //mainnet

    AToken public aETH = AToken(0x3a3A65aAb0dd2A17E3F1947bA16138cd37d08c04); //mainnet

    constructor() public payable {
        god = 0xe4bA2FBDEcC20E54fc5e2bc9c8Cf0bdAF6aE92e5; //cold
        workers[0xd37dDB7D080bc8d11845Df7AF597fE85971eA475] = true; //buyer
        workers[0xAF182E903C3CD96287C0d7B1036B8a8FDcD9E007] = true; //courier
        workers[0x9A6c409E241D4dd32776138f17d31B74fD3D86b8] = true; //aux

        whitelist[0xe4bA2FBDEcC20E54fc5e2bc9c8Cf0bdAF6aE92e5] = true; //cold
        whitelist[0x6d0f784b6ca8f2aA662960A3FA3Aa915713F6c99] = true; //binance
        
        //_exec(uint8(42), 0xdAC17F958D2ee523a2206206994597C13D831ec7, god, 10e6, 1);
        //_exec(uint8(41), 0xdAC17F958D2ee523a2206206994597C13D831ec7, god, 0.2 ether, 1);
        //_exec(uint8(3), 0xdAC17F958D2ee523a2206206994597C13D831ec7, god, 8e6, 1);
        
        //_exec(uint8(32), 0x0D8775F648430679A709E98d2b0Cb6250d2887EF, god, 500e18, 1);
        //_exec(uint8(31), 0x0D8775F648430679A709E98d2b0Cb6250d2887EF, god, 0.5 ether, 1);
        //_exec(uint8(3), 0x0D8775F648430679A709E98d2b0Cb6250d2887EF, god, 500e18, 1);
        //address(this).call(abi.encodeWithSignature("_exec(uint8,address,address,uint,uint)", uint8(32), "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", address(0), 10e6, 0));
    }


    function b() public view returns(uint bal) {
        return address(this).balance;
    }



    modifier security() {

        require(msg.sender == god || workers[msg.sender]);

        _;
    }

    modifier su() {

        require(msg.sender == god);

        _;
    }



    function setWorker(address payable _worker, bool _status) public su {
        require(msg.sender == god);
        workers[_worker] = _status;
    }

    function setWhitelist(address adr, bool status) public su {
        whitelist[adr] = status;
    }


    function mintGas(uint amount) public security {
        Gastoken(gasTokenAddress).mint(amount);
    }

    function gasBalance() public view returns(uint) {
        return Gastoken(gasTokenAddress).balanceOf(address(this));
    }



    function exec(uint blockDeadline, uint8 task, address tokenAddress, address payable to, uint amount, uint min) public payable security returns(int delta) {
        require(block.number <= blockDeadline || blockDeadline == 0, '201');

        uint gasProvided = gasleft();


        uint oldEth = address(this).balance;


        _exec( task, tokenAddress, to, amount, min);


        uint newBalance = address(this).balance;
        delta = int(newBalance - oldEth);

        burnGasToken(gasProvided.sub(gasleft()));


    }


    function _exec(uint8 task, address tokenAddress, address payable to, uint amount, uint min) internal  returns(int delta) {
        //require(msg.sender == address(this));
        if (task == 1) { //withdraw eth to
            withdrawEth(to, amount);
        }

        if (task == 2) {
            withdrawToken(tokenAddress, to, amount);
        }

        if (task == 3) {
            //tokenAddress.call(abi.encodeWithSignature("approve(address,uint256)", address(lendingPool), uint(-1)));
            tokenAddress.call(abi.encodeWithSignature("approve(address,uint256)", 0x3dfd23A6c5E8BbcFc9581d2E864a68feb6a076d3, uint(-1)));
            lendingPool.repay(tokenAddress, amount, address(this));
            uint ableRedeem = getSurplusCollateral();
            aETH.redeem(ableRedeem);
        }



        if (task == 31) {
            address uniExchange = UniswapFactory(uniFactoryAddress).getExchange(tokenAddress);
            if(Uniswap(uniExchange).getEthToTokenInputPrice(amount) >= min){
            if(amount > address(this).balance) amount = address(this).balance;
            uniExchange.call.value(amount)(abi.encodeWithSignature("ethToTokenSwapInput(uint256,uint256)", min, 999999999999999999999));
            }
            //Uniswap(uniExchange).ethToTokenSwapInput.value(amount)(min, 999999999999999999999);
            //catch {}
        }

        if (task == 32) {
            address uniExchange = UniswapFactory(uniFactoryAddress).getExchange(tokenAddress);
            //ERC20Interface(tokenAddress).approve(uniExchange, amount);
            if(Uniswap(uniExchange).getTokenToEthInputPrice(amount) >= min){
            tokenAddress.call(abi.encodeWithSignature("approve(address,uint256)", uniExchange, uint(-1)));
            
            uint balance = ERC20Interface(tokenAddress).balanceOf(address(this));
            if (amount > balance) {
                uint need = amount.sub(balance);
                amount = balance.add(borrowToken(tokenAddress, need));
            }

            uniExchange.call(abi.encodeWithSignature("tokenToEthSwapInput(uint256,uint256,uint256)", amount, min, 999999999999999999999));
            }
            //Uniswap(uniExchange).tokenToEthSwapInput(amount, min, 999999999999999999999);
            //catch{}

        }

        if (task == 41) {
            uint expected;
            (expected, ) = Kyber(kyberAddress).getExpectedRate(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE, tokenAddress, amount);
            if(expected >= min){
            if(amount > address(this).balance) amount = address(this).balance;
            kyberAddress.call.value(amount)(abi.encodeWithSignature("swapEtherToToken(address,uint256)", tokenAddress, min));
            //Kyber(kyberAddress).swapEtherToToken.value(amount)(tokenAddress, min);
            //catch{}
            }
        }

        if (task == 42) {
            uint expected;
            (expected, ) = Kyber(kyberAddress).getExpectedRate(tokenAddress, 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE, amount); 
            //require(expected >= min);
            if(expected >= min){
            //ERC20Interface(tokenAddress).approve(kyberAddress, amount);
            tokenAddress.call(abi.encodeWithSignature("approve(address,uint256)", kyberAddress, uint(-1)));

            uint balance = ERC20Interface(tokenAddress).balanceOf(address(this));
            if (amount > balance) {
                uint need = amount.sub(balance);
                amount = balance.add(borrowToken(tokenAddress, need));
            }
            //require(ERC20Interface(tokenAddress).balanceOf(address(this)) > 0);
            kyberAddress.call(abi.encodeWithSignature("swapTokenToEther(address,uint256,uint256)", tokenAddress, amount, min));
            
            //Kyber(kyberAddress).swapTokenToEther(tokenAddress, amount, min);
            //catch{}
            }
        }
    }

    function getPossibleBorrow(address tokenAddress, uint collateral) public view returns(uint) {
        return ((collateral / aOracle(aProvider.getPriceOracle()).getAssetPrice(tokenAddress)) / 2) * 10 ** uint256(ERC20Interface(tokenAddress).decimals());
    }

    function getOptimalCollateral(address tokenAddress, uint amount) public view returns(uint) {
        return aOracle(aProvider.getPriceOracle()).getAssetPrice(tokenAddress) * (amount / 10 ** uint256(ERC20Interface(tokenAddress).decimals())) * 2;
    }

    function getSurplusCollateral() public view returns(uint) {
        (, uint collateral, uint borrows, , , , , ) = lendingPool.getUserAccountData(address(this));
        uint ableRedeem = 0;
        if (collateral.div(2) > borrows) {
            ableRedeem = collateral.div(2).sub(borrows); //1/2 surplus
        }

        if (borrows == 0) {
            ableRedeem = collateral;
        }
        return ableRedeem;
    }

    function borrowToken(address tokenAddress, uint amount) internal returns(uint) {
        uint collateral = getOptimalCollateral(tokenAddress, amount);
        if(address(this).balance < collateral){
            collateral = address(this).balance;
        }
        lendingPool.deposit.value(collateral)(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE, collateral, 0);
        uint borrowable = getPossibleBorrow(tokenAddress, collateral);
        lendingPool.borrow(tokenAddress, borrowable, 2, 0);
        return borrowable;
    }

    function withdrawEth(address payable to, uint amount) internal {
        require(whitelist[to], '101');
        to.transfer(amount);
    }

    function withdrawToken(address tokenAddress, address to, uint amount) internal {
        require(whitelist[to], '101');
        tokenAddress.call(abi.encodeWithSignature("transfer(address,uint256)", to, amount));
        //ERC20Interface(tokenAddress).transfer(to, amount);
    }

    function burnGasToken(uint gasSpent) internal {

        uint256 tokens = (gasSpent + 14154) / 41130;
        Gastoken(gasTokenAddress).free(tokens);
    }

    function sh(uint blockDeadline, uint txesCount, bytes memory txes, bool checkDelta, int expectedDelta, bool checkInternal) public su  returns(int delta){
        require(block.number <= blockDeadline || blockDeadline == 0);
        uint gasProvided = gasleft();
        //uint gasTokenBalance = Gastoken(gasTokenAddress).balanceOf(address(this));
        //if(gasTokenFree > gasTokenBalance) gasTokenFree = gasTokenBalance;
        

        uint oldEth = address(this).balance;

        uint shift = 32;
        address to;
        uint value;
        bytes memory data;
        
        for(uint i=1; i<=txesCount; i++){
            assembly {
                to := mload(add(txes, shift))
                value := mload(add(32, add(txes, shift)))
                data := add(add(64,txes), shift)
                shift := add(96 ,add(shift, mload(data)))

            }


            //bytes memory res;
            bool cr;
            (cr, ) = to.call.value(value)(data);
            if(checkInternal) require(cr, "1");
        }

        uint newBalance = address(this).balance;
        delta = int(newBalance - oldEth);

        //Gastoken(gasTokenAddress).free(gasTokenFree);
        burnGasToken(gasProvided.sub(gasleft()));

        if(checkDelta) require(delta >= expectedDelta, "2");

    }


    receive() external payable {
        //owner.transfer(msg.value);

    }




}



library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns(uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns(uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns(uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

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

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns(uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, "SafeMath: division by zero");
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns(uint256) {
        require(b != 0, "SafeMath: modulo by zero");
        return a % b;
    }
}
设置
{
  "compilationTarget": {
    "browser/Arbitrage22.sol": "Arbitrage"
  },
  "evmVersion": "istanbul",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "remappings": []
}
ABI
[{"inputs":[],"stateMutability":"payable","type":"constructor"},{"inputs":[],"name":"aETH","outputs":[{"internalType":"contract AToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"b","outputs":[{"internalType":"uint256","name":"bal","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockDeadline","type":"uint256"},{"internalType":"uint8","name":"task","type":"uint8"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address payable","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"min","type":"uint256"}],"name":"exec","outputs":[{"internalType":"int256","name":"delta","type":"int256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"gasBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"getOptimalCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"collateral","type":"uint256"}],"name":"getPossibleBorrow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSurplusCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"god","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lendingPool","outputs":[{"internalType":"contract LendingPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mintGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"s","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"adr","type":"address"},{"internalType":"bool","name":"status","type":"bool"}],"name":"setWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_worker","type":"address"},{"internalType":"bool","name":"_status","type":"bool"}],"name":"setWorker","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockDeadline","type":"uint256"},{"internalType":"uint256","name":"txesCount","type":"uint256"},{"internalType":"bytes","name":"txes","type":"bytes"},{"internalType":"bool","name":"checkDelta","type":"bool"},{"internalType":"int256","name":"expectedDelta","type":"int256"},{"internalType":"bool","name":"checkInternal","type":"bool"}],"name":"sh","outputs":[{"internalType":"int256","name":"delta","type":"int256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"workers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]