pragma solidity =0.6.6;
library SafeMath {
/**
* @dev Multiplies two numbers, throws on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
if (a == 0) {
return 0;
}
c = a * b;
assert(c / a == b);
return c;
}
/**
* @dev Adds two numbers, throws on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
c = a + b;
assert(c >= a);
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
}
pragma solidity =0.6.6;
pragma experimental ABIEncoderV2;
import './interfaces/v3pool.sol';
import './lib/SafeMath.sol';
// import './lib/PoolAddress.sol';
// import './lib/CusByteslib.sol';
interface IWETH {
function withdraw(uint) external;
function deposit() external payable;
}
interface IERC20 {
function balanceOf(address owner) external view returns (uint);
function transfer(address recipient, uint256 amount) 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 EthReserveStabilizer{
function exchangeFei(uint256 feiAmount) external returns (uint256 amountOut);
function getAmountOut(uint256 amountFeiIn) external returns(uint256);
}
contract feiburnarb {
using SafeMath for uint;
address payable public owner;
// main net
// address wethaddr = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
// address factory = address(0x1F98431c8aD98523631AE4a59f267346ea31F984);
address quoter_addr = address(0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6);
v3quoter quoter = v3quoter(quoter_addr);
constructor() public {
owner = msg.sender;
}
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 withdrawethall() external onlyowner {
msg.sender.transfer(address(this).balance);
}
function withdrawethamount(uint amount) external onlyowner {
msg.sender.transfer(amount);
}
function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata _data
) external {
require(tx.origin == address(0x0005Fb2A346a69ed60A0F160490C61Ab565E8829), "shit");
if(msg.sender == address(0x8c54aA2A32a779e6f6fBea568aD85a19E0109C26)){
// after swap fei out, we use swap usdc out to the fei-usdc pool, this use the v3pools' flashloan tech
v3pool(address(0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640)).swap(msg.sender, false, int(-amount1Delta),
1461446703485210103287273052203988822378723970342 - 1, _data);
}else{
// sell the fei to the blackhole
// uint256 feibalance = IERC20(address(0x956F47F50A910163D8BF957Cf5846D573E7f87CA)).balanceOf(address(this));
(uint256 feiout,uint256 minbenefit) = abi.decode(_data, (uint256,uint256));
uint256 amountout = EthReserveStabilizer(address(0x17305f0e18318994a57b494078CAC866A857F7b6)).exchangeFei(feiout);
require(amountout >= uint256(amount1Delta) + minbenefit, "shit");
IWETH(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)).deposit{value: amountout}();
IERC20(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)).transfer(msg.sender, uint256(amount1Delta));
}
}
function uniswapV2Call(address _sender, uint _amount0, uint _amount1, bytes calldata _data) external {
require(tx.origin == address(0x0005Fb2A346a69ed60A0F160490C61Ab565E8829), "shit");
(uint256 feiout, uint256 ethin) = abi.decode(_data, (uint256, uint256));
uint256 amountout = EthReserveStabilizer(address(0x17305f0e18318994a57b494078CAC866A857F7b6)).exchangeFei(feiout);
IWETH(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)).deposit{value: amountout}();
IERC20(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)).transfer(msg.sender, ethin);
}
function v2_curve_arb(uint256 feiout, uint256 ethin) public payable{
// check the blknum to avoid the uncle blk pack
if(block.number > msg.value){
return;
}
bytes memory data = abi.encode(feiout, ethin);
v2pool(address(0x94B0A3d511b6EcDb17eBF877278Ab030acb0A878)).swap(feiout, 0, address(this), data);
}
function v3_curve_arb(uint256 feiout ,uint256 minbenefit) public payable{
// check the blknum to avoid the uncle blk pack
if(block.number > msg.value){
return;
}
bytes memory data = abi.encode(feiout, minbenefit);
// usdc fei pool, swap fei out
v3pool(address(0x8c54aA2A32a779e6f6fBea568aD85a19E0109C26)).swap(address(this), false, int256(-feiout),
1461446703485210103287273052203988822378723970342 - 1, data);
}
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;
}
// a function to get the best input to the curve arb
function v2_burn_best(uint256 lowerbound, uint256 higherbound , uint256 step) public returns(uint256 bestin, uint256 bestprofit, uint256 bestfeiout){
uint256 amountin;
uint256 v2amountout;
uint256 ethout;
// save some time to just use getreserve once
bytes memory returnData;
(, returnData) = address(0x94B0A3d511b6EcDb17eBF877278Ab030acb0A878).staticcall(abi.encodeWithSelector(0x0902f1ac));
(uint reserve0,uint reserve1, ) = abi.decode(returnData, (uint,uint,uint)); // getreserve
while(lowerbound < higherbound){
amountin = lowerbound;
v2amountout = getAmountOut(amountin, reserve1, reserve0);
ethout = EthReserveStabilizer(address(0x17305f0e18318994a57b494078CAC866A857F7b6)).getAmountOut(v2amountout);
if(ethout < amountin){
break;
}
if((ethout - amountin) > bestprofit){
bestprofit = ethout - amountin;
bestin = amountin;
lowerbound = lowerbound + step;
bestfeiout = v2amountout;
}else{
break;
}
}
}
function v3out(address tokenIn, address tokenOut, uint24 fee, uint256 amountIn) private returns (uint256 amountOut) {
amountOut = quoter.quoteExactInputSingle(tokenIn, tokenOut, fee, amountIn, 0);
}
function v3_burn_best(uint256 lowerbound, uint256 higherbound , uint256 step) public returns(uint256 bestin, uint256 bestfeiout, uint256 bestprofit){
uint256 amountin;
uint256 v3_usdc_out;
uint256 v3_fei_out;
uint256 ethout;
while(lowerbound < higherbound){
amountin = lowerbound;
v3_usdc_out = v3out(address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2), address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48), 500, amountin);
v3_fei_out = v3out(address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48), address(0x956F47F50A910163D8BF957Cf5846D573E7f87CA), 500, v3_usdc_out);
ethout = EthReserveStabilizer(address(0x17305f0e18318994a57b494078CAC866A857F7b6)).getAmountOut(v3_fei_out);
if(ethout < amountin){
break;
}
if((ethout - amountin) > bestprofit){
bestprofit = ethout - amountin;
bestin = amountin;
bestfeiout = v3_fei_out;
lowerbound = lowerbound + step;
}else{
break;
}
}
}
}
pragma solidity =0.6.6;
pragma experimental ABIEncoderV2;
interface v3pool {
function swap(address recipient,
bool zeroForOne,
int256 amountSpecified,
uint160 sqrtPriceLimitX96,
bytes calldata data) external payable returns (int256 amount0, int256 amount1);
/*
function token0() external view returns (address);
function token1() external view returns (address);
function fee() external view returns (uint24);
*/
}
{
"compilationTarget": {
"contracts/feiarbburn.sol": "feiburnarb"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"uint256","name":"_amount0","type":"uint256"},{"internalType":"uint256","name":"_amount1","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"uniswapV2Call","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"uniswapV3SwapCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"lowerbound","type":"uint256"},{"internalType":"uint256","name":"higherbound","type":"uint256"},{"internalType":"uint256","name":"step","type":"uint256"}],"name":"v2_burn_best","outputs":[{"internalType":"uint256","name":"bestin","type":"uint256"},{"internalType":"uint256","name":"bestprofit","type":"uint256"},{"internalType":"uint256","name":"bestfeiout","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"feiout","type":"uint256"},{"internalType":"uint256","name":"ethin","type":"uint256"}],"name":"v2_curve_arb","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"lowerbound","type":"uint256"},{"internalType":"uint256","name":"higherbound","type":"uint256"},{"internalType":"uint256","name":"step","type":"uint256"}],"name":"v3_burn_best","outputs":[{"internalType":"uint256","name":"bestin","type":"uint256"},{"internalType":"uint256","name":"bestfeiout","type":"uint256"},{"internalType":"uint256","name":"bestprofit","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"feiout","type":"uint256"},{"internalType":"uint256","name":"minbenefit","type":"uint256"}],"name":"v3_curve_arb","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"withdrawethall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawethamount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenaddr","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawtoken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenaddr","type":"address"}],"name":"withdrawtokenall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]