arbi/onchain/test/ArbitrageManager.t.sol
Andrea Ciceri 7a1e03ee7a
Incomplete prototype
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
2025-05-10 10:02:36 +02:00

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);
}
}