Things WIP Format Work in progress Work in progres Work in progress Work in progress Work in progress Work in progress Work in progress Work in progress Work in progress Work in progress Work in progress Work in progress Work in progress Work in progress Work in progress
77 lines
3.3 KiB
Solidity
77 lines
3.3 KiB
Solidity
// SPDX-License-Identifier: UNLICENSED
|
|
pragma solidity ^0.8.28;
|
|
|
|
import {Test, console} from "forge-std/Test.sol";
|
|
import {ArbitrageManager} from "../src/ArbitrageManager.sol";
|
|
import {IERC20} from "../src/IERC20.sol";
|
|
import {IUniswapV2Pair} from "../src/IUniswapV2Pair.sol";
|
|
|
|
|
|
contract ArbitrageTest is Test {
|
|
ArbitrageManager public arbitrageManager;
|
|
uint256 mainnetFork;
|
|
address constant vitalik = 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045;
|
|
IERC20 weth = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
|
|
IUniswapV2Pair uniswapPair = IUniswapV2Pair(0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc);
|
|
IUniswapV2Pair sushiswapPair = IUniswapV2Pair(0x397FF1542f962076d0BFE58eA045FfA2d347ACa0);
|
|
|
|
function setUp() public {
|
|
mainnetFork = vm.createFork("https://eth-mainnet.g.alchemy.com/v2/kkDMaLVYpWQA0GsCYNFvAODnAxCCiamv"); // TODO use an env variable
|
|
vm.selectFork(mainnetFork);
|
|
vm.rollFork(22_147_269);
|
|
arbitrageManager = new ArbitrageManager();
|
|
}
|
|
|
|
function test_canSelectFork() public view {
|
|
assertEq(vm.activeFork(), mainnetFork);
|
|
assertEq(block.number, 22_147_269);
|
|
}
|
|
|
|
function test_sqrt() public view {
|
|
uint256 n = 344353442342354234324324324323;
|
|
assertEq(arbitrageManager.sqrt(n**2), n);
|
|
|
|
n = 115792089237316195423570985008687907853269984665640564039457584007913129639935;
|
|
assertEq(340282366920938463463374607431768211456 - 1, arbitrageManager.sqrt(n)); // +-1 is an acceptable rounding error
|
|
}
|
|
|
|
function test_computeAmountIn() public {
|
|
(uint256 X_A, uint256 Y_A, ) = uniswapPair.getReserves(); // (USDT, WETH)
|
|
(uint256 X_B, uint256 Y_B, ) = sushiswapPair.getReserves(); // (USDT, WETH)
|
|
|
|
console.log("Uniswap pair reserves", X_A, Y_A);
|
|
console.log("Uniswap pair ratio", Y_A/X_A);
|
|
console.log("Sushiswap pair ratio", Y_B/X_B);
|
|
|
|
uint256 unbalance = Y_A / 5;
|
|
console.log("Unbalance", unbalance);
|
|
vm.prank(address(uniswapPair)); // it works only for the next call
|
|
weth.transfer(address(0), unbalance);
|
|
uniswapPair.sync();
|
|
console.log("Arbitrage opportunity created");
|
|
|
|
(X_A, Y_A, ) = uniswapPair.getReserves();
|
|
(X_B, Y_B, ) = sushiswapPair.getReserves();
|
|
console.log("Uniswap pair reserves", X_A, Y_A);
|
|
console.log("Uniswap pair ratio", Y_A/X_A);
|
|
console.log("Sushiswap pair ratio", Y_B/X_B);
|
|
|
|
uint256 optimum = arbitrageManager.optimalIn(X_A, Y_A, X_B, Y_B);
|
|
console.log("The optimum is", optimum);
|
|
|
|
vm.prank(address(0)); // it works only for the next call
|
|
weth.transfer(address(uniswapPair), optimum);
|
|
uint256 amountOut = arbitrageManager.getAmountOut(optimum, Y_A, X_A);
|
|
console.log("First swap's amountOut", amountOut);
|
|
uniswapPair.swap(amountOut, 0, address(sushiswapPair), new bytes(0));
|
|
amountOut = arbitrageManager.getAmountOut(amountOut, X_B, Y_B);
|
|
console.log("Second swap's amountOut", amountOut);
|
|
sushiswapPair.swap(0, amountOut, address(this), new bytes(0));
|
|
|
|
(X_A, Y_A, ) = uniswapPair.getReserves();
|
|
(X_B, Y_B, ) = sushiswapPair.getReserves();
|
|
console.log("Uniswap pair reserves", X_A, Y_A);
|
|
console.log("Uniswap pair ratio", Y_A/X_A);
|
|
console.log("Sushiswap pair ratio", Y_B/X_B);
|
|
}
|
|
}
|