文件 2 的 3:keeparb.sol
pragma solidity >=0.6.6;
pragma experimental ABIEncoderV2;
import './lib/SafeMath.sol';
import './interfaces/v3pool.sol';
interface IERC20 {
function balanceOf(address owner) external view returns (uint);
function transfer(address recipient, uint256 amount) external returns (bool);
function approve(address spender, uint value) external returns (bool);
}
interface IWETH{
function deposit() external payable;
function withdraw(uint wad) external;
}
interface v2pool{
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
}
interface vendingmachine{
function conversionToT(uint256 amount)
external
returns (uint256 tAmount, uint256 wrappedRemainder);
function conversionFromT(uint256 amount)
external
returns (uint256 wrappedAmount, uint256 tRemainder);
function wrap(uint256 amount) external;
function unwrap(uint256 amount) external;
}
interface v3quoter{
function quoteExactInputSingle(
address tokenIn,
address tokenOut,
uint24 fee,
uint256 amountIn,
uint160 sqrtPriceLimitX96
) external returns (uint256 amountOut);
}
interface curvepool{
function get_dy(uint256 i , uint256 j, uint256 dx) external view returns (uint256 dy);
function exchange(uint256 i, uint256 j, uint256 dx, uint256 min_dy) external payable returns (uint256 dy);
}
contract keeptarb {
using SafeMath for uint;
address payable public owner;
address quoter_addr = address(0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6);
v3quoter quoter = v3quoter(quoter_addr);
constructor() public {
owner = msg.sender;
IERC20(address(0x85Eee30c52B0b379b046Fb0F85F4f3Dc3009aFEC)).approve(address(0xE47c80e8c23f6B4A1aE41c34837a0599D5D16bb0), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
IERC20(address(0xCdF7028ceAB81fA0C6971208e83fa7872994beE5)).approve(address(0xE47c80e8c23f6B4A1aE41c34837a0599D5D16bb0), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
IERC20(address(0xCdF7028ceAB81fA0C6971208e83fa7872994beE5)).approve(address(0x752eBeb79963cf0732E9c0fec72a49FD1DEfAEAC), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
IERC20(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)).approve(address(0x752eBeb79963cf0732E9c0fec72a49FD1DEfAEAC), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
}
modifier onlyowner{
require(msg.sender == owner);
_;
}
receive() external payable {}
function deposit() payable external{
}
function _safeTransfer(address token, address to, uint value) private {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(bytes4(keccak256(bytes('transfer(address,uint256)'))), to, value));
}
function withdrawtoken(address tokenaddr, uint amount) external onlyowner{
_safeTransfer(tokenaddr, owner, amount);
}
function withdrawethamount(uint amount) external onlyowner {
msg.sender.transfer(amount);
}
function approvetoken(address token, address target) external onlyowner{
IERC20(token).approve(target, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
}
function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata _data
) external {
(uint256 flag) = abi.decode(_data, (uint256));
if(flag == 0){
_safeTransfer(0xCdF7028ceAB81fA0C6971208e83fa7872994beE5, msg.sender, uint256(amount1Delta));
}else{
vendingmachine(address(0xE47c80e8c23f6B4A1aE41c34837a0599D5D16bb0)).unwrap(uint256(-amount1Delta));
_safeTransfer(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2), msg.sender, uint256(amount0Delta));
}
}
function uniswapV2Call(address _sender, uint _amount0, uint _amount1, bytes calldata _data) external {
(uint256 sellpath, bool direct, uint256 bestin, uint256 v2out, uint256 v3amount) = abi.decode(_data, (uint256, bool, uint256, uint256, uint256));
if(sellpath == 0){
if(direct){
vendingmachine(address(0xE47c80e8c23f6B4A1aE41c34837a0599D5D16bb0)).wrap(v2out);
v3pool(address(0x286EB8405231A2201FCb75b6e33098A546216C86)).swap(address(this), false, int256(v3amount), 1461446703485210103287273052203988822378723970342 - 1, abi.encode(0));
_safeTransfer(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2), msg.sender, bestin);
}else{
v3pool(address(0x286EB8405231A2201FCb75b6e33098A546216C86)).swap(address(this), true, int256(bestin), 4295128739 + 1, abi.encode(1));
_safeTransfer(address(0x85Eee30c52B0b379b046Fb0F85F4f3Dc3009aFEC), msg.sender, v3amount);
}
}
if(sellpath == 1){
if(direct){
vendingmachine(address(0xE47c80e8c23f6B4A1aE41c34837a0599D5D16bb0)).wrap(v2out);
curvepool(address(0x752eBeb79963cf0732E9c0fec72a49FD1DEfAEAC)).exchange(1, 0 , v3amount, 0);
_safeTransfer(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2), msg.sender, bestin);
}else{
uint256 tamount = curvepool(address(0x752eBeb79963cf0732E9c0fec72a49FD1DEfAEAC)).exchange(0, 1 , bestin, 0);
vendingmachine(address(0xE47c80e8c23f6B4A1aE41c34837a0599D5D16bb0)).unwrap(tamount);
_safeTransfer(address(0x85Eee30c52B0b379b046Fb0F85F4f3Dc3009aFEC), msg.sender, v3amount);
}
}
}
function keepv3arb(bool direct, uint256 bestin, uint256 v2out, uint256 amount) public payable{
require(block.number <= msg.value, "fuck");
uint256 gasstart = gasleft();
if(direct){
bytes memory data = abi.encode(0, direct, bestin, v2out, amount);
v2pool(address(0xE6f19dAb7d43317344282F803f8E8d240708174a)).swap(v2out, 0, address(this), data);
}else{
bytes memory data = abi.encode(0, direct, bestin, 0, amount);
v2pool(address(0xE6f19dAb7d43317344282F803f8E8d240708174a)).swap(0, v2out, address(this), data);
}
uint256 weth_balance = IERC20(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)).balanceOf(address(this));
require(weth_balance > tx.gasprice * (gasstart - gasleft()), "i");
IERC20(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)).transfer(msg.sender, weth_balance - 1);
}
function keepcurvearb(bool direct, uint256 bestin, uint256 v2out, uint256 amount) public payable{
require(block.number <= msg.value, "fuck");
uint256 gasstart = gasleft();
if(direct){
bytes memory data = abi.encode(1, direct, bestin, v2out, amount);
v2pool(address(0xE6f19dAb7d43317344282F803f8E8d240708174a)).swap(v2out, 0, address(this), data);
}else{
bytes memory data = abi.encode(1, direct, bestin, 0, amount);
v2pool(address(0xE6f19dAb7d43317344282F803f8E8d240708174a)).swap(0, v2out, address(this), data);
}
uint256 weth_balance = IERC20(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)).balanceOf(address(this));
require(weth_balance > tx.gasprice * (gasstart - gasleft()), "i");
IERC20(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)).transfer(msg.sender, weth_balance - 1);
}
function v3out(address tokenIn, address tokenOut, uint24 fee, uint256 amountIn) private returns (uint256 amountOut) {
amountOut = quoter.quoteExactInputSingle(tokenIn, tokenOut, fee, amountIn, 0);
}
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) {
uint amountInWithFee = amountIn.mul(997);
uint numerator = amountInWithFee.mul(reserveOut);
uint denominator = reserveIn.mul(1000).add(amountInWithFee);
amountOut = numerator / denominator;
}
function detectarbv3(uint256 lowerbound, uint256 higherbound , uint256 step) public returns(uint256 bestin, uint256 bestprofit, uint256 best_keep_out, uint256 tout, uint256 bestin2, uint256 bestprofit2, uint256 bestv2wethout, uint256 keeprepay){
bytes memory returnData;
(, returnData) = address(0xE6f19dAb7d43317344282F803f8E8d240708174a).staticcall(abi.encodeWithSelector(0x0902f1ac));
(uint r0, uint r1, ) = abi.decode(returnData, (uint,uint,uint));
uint256 weth_in = lowerbound;
while(weth_in < higherbound){
uint256 keep_out = getAmountOut(weth_in, r1, r0);
(uint256 t_out, ) = vendingmachine(address(0xE47c80e8c23f6B4A1aE41c34837a0599D5D16bb0)).conversionToT(keep_out);
uint256 v3_weth_out = v3out(address(0xCdF7028ceAB81fA0C6971208e83fa7872994beE5), address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2), 10000, t_out);
if(v3_weth_out < weth_in){
break;
}
if(v3_weth_out - weth_in < bestprofit){
break;
}else{
bestprofit = v3_weth_out - weth_in;
bestin = weth_in;
tout = t_out;
best_keep_out = keep_out;
weth_in = weth_in + step;
}
}
weth_in = lowerbound;
while(weth_in < higherbound){
uint256 t_out = v3out(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2), address(0xCdF7028ceAB81fA0C6971208e83fa7872994beE5), 10000, weth_in);
(uint256 keep_out, ) = vendingmachine(address(0xE47c80e8c23f6B4A1aE41c34837a0599D5D16bb0)).conversionFromT(t_out);
uint256 v2_weth_out = getAmountOut(keep_out, r0, r1);
if(v2_weth_out < weth_in){
break;
}
if(v2_weth_out - weth_in < bestprofit2){
break;
}else{
bestprofit2 = v2_weth_out - weth_in;
bestin2 = weth_in;
bestv2wethout = v2_weth_out;
keeprepay = keep_out;
weth_in = weth_in + step;
}
}
}
function detectarbcurve(uint256 lowerbound, uint256 higherbound , uint256 step) public returns(uint256 bestin, uint256 bestprofit, uint256 best_keep_out, uint256 tout, uint256 bestin2, uint256 bestprofit2, uint256 bestv2wethout, uint256 keeprepay){
bytes memory returnData;
(, returnData) = address(0xE6f19dAb7d43317344282F803f8E8d240708174a).staticcall(abi.encodeWithSelector(0x0902f1ac));
(uint r0, uint r1, ) = abi.decode(returnData, (uint,uint,uint));
uint256 weth_in = lowerbound;
while(weth_in < higherbound){
uint256 keep_out = getAmountOut(weth_in, r1, r0);
(uint256 t_out, ) = vendingmachine(address(0xE47c80e8c23f6B4A1aE41c34837a0599D5D16bb0)).conversionToT(keep_out);
uint256 curve_eth_out = curvepool(address(0x752eBeb79963cf0732E9c0fec72a49FD1DEfAEAC)).get_dy(1, 0 , t_out);
if(curve_eth_out < weth_in){
break;
}
if(curve_eth_out - weth_in < bestprofit){
break;
}else{
bestprofit = curve_eth_out - weth_in;
bestin = weth_in;
tout = t_out;
best_keep_out = keep_out;
weth_in = weth_in + step;
}
}
weth_in = lowerbound;
while(weth_in < higherbound){
uint256 t_out = curvepool(address(0x752eBeb79963cf0732E9c0fec72a49FD1DEfAEAC)).get_dy(0, 1 , weth_in);
(uint256 keep_out, ) = vendingmachine(address(0xE47c80e8c23f6B4A1aE41c34837a0599D5D16bb0)).conversionFromT(t_out);
uint256 v2_weth_out = getAmountOut(keep_out, r0, r1);
if(v2_weth_out < weth_in){
break;
}
if(v2_weth_out - weth_in < bestprofit2){
break;
}else{
bestprofit2 = v2_weth_out - weth_in;
bestin2 = weth_in;
bestv2wethout = v2_weth_out;
keeprepay = keep_out;
weth_in = weth_in + step;
}
}
}
}