文件 2 的 3:sohmarb.sol
pragma solidity =0.6.6;
pragma experimental ABIEncoderV2;
import './interfaces/v3pool.sol';
import './lib/SafeMath.sol';
interface IWETH {
function withdraw(uint) external;
}
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 v3quoter{
function quoteExactInputSingle(
address tokenIn,
address tokenOut,
uint24 fee,
uint256 amountIn,
uint160 sqrtPriceLimitX96
) external returns (uint256 amountOut);
}
interface v2pool{
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
}
interface olystaking{
function unstake( uint _amount, bool _trigger ) external;
function stake( uint _amount, address _recipient ) external returns ( bool );
function claim ( address _recipient ) external;
}
contract ohmarb {
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(0x383518188C0C6d7730D91b2c03a03C837814a899)).approve(address(0xFd31c7d00Ca47653c6Ce64Af53c1571f9C36566a),
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
IERC20(address(0x04F2694C8fcee23e8Fd0dfEA1d4f5Bb8c352111F)).approve(address(0xFd31c7d00Ca47653c6Ce64Af53c1571f9C36566a),
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 withdrawtokenall(address tokenaddr) external onlyowner{
_safeTransfer(tokenaddr, owner, IERC20(tokenaddr).balanceOf(address(this)));
}
function withdrawethamount(uint amount) external onlyowner {
msg.sender.transfer(amount);
}
function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata _data
) external {
require(tx.origin == address(0x295CCeE94016D96b81b28e4913Aa16d5a260D2a8), "shit");
(uint256 flag) = abi.decode(_data, (uint256));
if(flag == 0){
bytes memory returnData;
(, returnData) = address(0xC3D03e4F041Fd4cD388c549Ee2A29a9E5075882f).staticcall(abi.encodeWithSelector(0x0902f1ac));
(uint reserve0,uint reserve1, ) = abi.decode(returnData, (uint,uint,uint));
(, returnData) = address(0x34d7d7Aaf50AD4944B70B320aCB24C95fa2def7c).staticcall(abi.encodeWithSelector(0x0902f1ac));
(uint reserve2,uint reserve3, ) = abi.decode(returnData, (uint,uint,uint));
uint256 dai_in = getAmountIn(uint256(amount0Delta), reserve3, reserve2);
uint256 eth_in = getAmountIn(uint256(dai_in), reserve1, reserve0);
IERC20(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)).transfer(address(0xC3D03e4F041Fd4cD388c549Ee2A29a9E5075882f), eth_in);
v2pool(address(0xC3D03e4F041Fd4cD388c549Ee2A29a9E5075882f)).swap(dai_in, 0, address(0x34d7d7Aaf50AD4944B70B320aCB24C95fa2def7c), new bytes(0));
v2pool(address(0x34d7d7Aaf50AD4944B70B320aCB24C95fa2def7c)).swap(uint256(amount0Delta), 0, address(this), new bytes(0));
olystaking(address(0xFd31c7d00Ca47653c6Ce64Af53c1571f9C36566a)).stake(uint256(amount0Delta), address(this));
olystaking(address(0xFd31c7d00Ca47653c6Ce64Af53c1571f9C36566a)).claim(address(this));
IERC20(address(0x04F2694C8fcee23e8Fd0dfEA1d4f5Bb8c352111F)).transfer(msg.sender, uint256(amount0Delta));
}else{
bytes memory returnData;
(, returnData) = address(0xC3D03e4F041Fd4cD388c549Ee2A29a9E5075882f).staticcall(abi.encodeWithSelector(0x0902f1ac));
(uint reserve0,uint reserve1, ) = abi.decode(returnData, (uint,uint,uint));
(, returnData) = address(0x34d7d7Aaf50AD4944B70B320aCB24C95fa2def7c).staticcall(abi.encodeWithSelector(0x0902f1ac));
(uint reserve2,uint reserve3, ) = abi.decode(returnData, (uint,uint,uint));
uint256 dai_out = getAmountOut(uint256(-amount0Delta), reserve2, reserve3);
uint256 eth_out = getAmountOut(uint256(dai_out), reserve0, reserve1);
olystaking(address(0xFd31c7d00Ca47653c6Ce64Af53c1571f9C36566a)).unstake(uint256(-amount0Delta), false);
IERC20(address(0x383518188C0C6d7730D91b2c03a03C837814a899)).transfer(address(0x34d7d7Aaf50AD4944B70B320aCB24C95fa2def7c), uint256(-amount0Delta));
v2pool(address(0x34d7d7Aaf50AD4944B70B320aCB24C95fa2def7c)).swap(0, dai_out, address(0xC3D03e4F041Fd4cD388c549Ee2A29a9E5075882f), new bytes(0));
v2pool(address(0xC3D03e4F041Fd4cD388c549Ee2A29a9E5075882f)).swap(0, eth_out, address(this), new bytes(0));
IERC20(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)).transfer(msg.sender, uint256(amount1Delta));
}
}
function stake_arb(uint256 weth_out) public payable{
if(block.number > msg.value){
return;
}
uint256 gasstart = gasleft();
bytes memory data = abi.encode(0);
v3pool(address(0x0bb5FD9b4E16607D32C4E5aC625AC5381c605920)).swap(address(this), true, int256(-weth_out),
4295128739 + 1, 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);
}
function unstake_arb(uint256 sohm_out) public payable{
if(block.number > msg.value){
return;
}
uint256 gasstart = gasleft();
bytes memory data = abi.encode(1);
v3pool(address(0x0bb5FD9b4E16607D32C4E5aC625AC5381c605920)).swap(address(this), false, int256(-sohm_out),
1461446703485210103287273052203988822378723970342 - 1, 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);
}
function stake_arb_mem(uint256 weth_out, uint256 minweth) public {
uint256 check = IERC20(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)).balanceOf(address(0x0bb5FD9b4E16607D32C4E5aC625AC5381c605920));
require(check >= minweth, "s");
bytes memory data = abi.encode(0);
v3pool(address(0x0bb5FD9b4E16607D32C4E5aC625AC5381c605920)).swap(address(this), true, int256(-weth_out),
4295128739 + 1, data);
uint256 weth_balance = IERC20(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)).balanceOf(address(this));
require(weth_balance > 0, "i");
IERC20(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)).transfer(msg.sender, weth_balance);
}
function unstake_arb_mem(uint256 sohm_out, uint256 sohmamount) public{
uint256 check = IERC20(address(0x04F2694C8fcee23e8Fd0dfEA1d4f5Bb8c352111F)).balanceOf(address(0x0bb5FD9b4E16607D32C4E5aC625AC5381c605920));
require(check >= sohmamount, "s");
bytes memory data = abi.encode(1);
v3pool(address(0x0bb5FD9b4E16607D32C4E5aC625AC5381c605920)).swap(address(this), false, int256(-sohm_out),
1461446703485210103287273052203988822378723970342 - 1, data);
uint256 weth_balance = IERC20(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)).balanceOf(address(this));
require(weth_balance > 0, "i");
IERC20(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)).transfer(msg.sender, weth_balance);
}
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) internal pure returns (uint amountIn) {
uint numerator = reserveIn.mul(amountOut).mul(1000);
uint denominator = reserveOut.sub(amountOut).mul(997);
amountIn = (numerator / denominator).add(1);
}
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 v3out(address tokenIn, address tokenOut, uint24 fee, uint256 amountIn) private returns (uint256 amountOut) {
amountOut = quoter.quoteExactInputSingle(tokenIn, tokenOut, fee, amountIn, 0);
}
function stake_best(uint256 lowerbound, uint256 higherbound , uint256 step) public returns(uint256 bestprofit, uint256 bestin){
uint256 amountin;
uint256 v2_dai_out;
uint256 v2_ohm_out;
uint256 v3_eth_out;
bytes memory returnData;
(, returnData) = address(0xC3D03e4F041Fd4cD388c549Ee2A29a9E5075882f).staticcall(abi.encodeWithSelector(0x0902f1ac));
(uint reserve0,uint reserve1, ) = abi.decode(returnData, (uint,uint,uint));
(, returnData) = address(0x34d7d7Aaf50AD4944B70B320aCB24C95fa2def7c).staticcall(abi.encodeWithSelector(0x0902f1ac));
(uint reserve2,uint reserve3, ) = abi.decode(returnData, (uint,uint,uint));
while(lowerbound < higherbound){
amountin = lowerbound;
v2_dai_out = getAmountOut(amountin, reserve1, reserve0);
v2_ohm_out = getAmountOut(v2_dai_out, reserve3, reserve2);
v3_eth_out = v3out(address(0x04F2694C8fcee23e8Fd0dfEA1d4f5Bb8c352111F), address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2), 10000, v2_ohm_out);
if(v3_eth_out < amountin){
break;
}
if((v3_eth_out - amountin) > bestprofit){
bestprofit = v3_eth_out - amountin;
bestin = amountin;
lowerbound = lowerbound + step;
}else{
break;
}
}
}
function unstake_best(uint256 lowerbound, uint256 higherbound , uint256 step) public returns(uint256 bestprofit, uint256 bestin, uint256 sohmout){
uint256 amountin;
uint256 v2_dai_out;
uint256 v2_eth_out;
uint256 v3_sohm_out;
bytes memory returnData;
(, returnData) = address(0xC3D03e4F041Fd4cD388c549Ee2A29a9E5075882f).staticcall(abi.encodeWithSelector(0x0902f1ac));
(uint reserve0,uint reserve1, ) = abi.decode(returnData, (uint,uint,uint));
(, returnData) = address(0x34d7d7Aaf50AD4944B70B320aCB24C95fa2def7c).staticcall(abi.encodeWithSelector(0x0902f1ac));
(uint reserve2,uint reserve3, ) = abi.decode(returnData, (uint,uint,uint));
while(lowerbound < higherbound){
amountin = lowerbound;
v3_sohm_out = v3out(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2), address(0x04F2694C8fcee23e8Fd0dfEA1d4f5Bb8c352111F), 10000, amountin);
v2_dai_out = getAmountOut(v3_sohm_out, reserve2, reserve3);
v2_eth_out = getAmountOut(v2_dai_out, reserve0, reserve1);
if(v2_eth_out < amountin){
break;
}
if((v2_eth_out - amountin) > bestprofit){
bestprofit = v2_eth_out - amountin;
bestin = amountin;
sohmout = v3_sohm_out;
lowerbound = lowerbound + step;
}else{
break;
}
}
}
}