Add typst
and tinymist
to shell
Start writing notes Notes on Uniswap V2's optimum Fix error in formula Test `computeAmountInt` using various deltas Add `concurrency` to the default configuration file Remove unused imports Correctly propagate error Allow dead code Make the priority queue a real FIFO Refactor: remove priority queue as stream and use channels Increase buffer size New `flashArbitrage` function Comment with some ideas Add pragma version Refactor: decrease the amount of calls Remove unused code Re-enable tests Remove comment Process known pairs when started Avoid re-allocating a new provider every time Ignore `nixos.qcow2` file created by the VM Add support for `aarch64-linux` Add NixOS module and VM configuration Add `itertools` Add arbitrage opportunity detection Implement `fallback` method for non standard callbacks Add more logs Fix sign error in optimum formula Add deployment scripts and `agenix-shell` secrets Bump cargo packages Fix typo Print out an error if processing a pair goes wrong Add `actionlint` to formatters Fix typo Add TODO comment Remove not relevant anymore comment Big refactor - process actions always in the correct order avoiding corner cases - avoid using semaphores New API key Add `age` to dev shell Used by Emacs' `agenix-mode` on my system Fix parametric deploy scripts Add `run-forge-tests` flake app Remove fork URL from Solidity source Remove `pairDir` argument Add link to `ArbitrageManager`'s ABI WIP
This commit is contained in:
parent
7a1e03ee7a
commit
fb378c4931
17 changed files with 1222 additions and 441 deletions
|
@ -16,7 +16,6 @@ contract ArbitrageTest is Test {
|
|||
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();
|
||||
|
@ -34,12 +33,13 @@ contract ArbitrageTest is Test {
|
|||
n = 115792089237316195423570985008687907853269984665640564039457584007913129639935;
|
||||
assertEq(340282366920938463463374607431768211456 - 1, arbitrageManager.sqrt(n)); // +-1 is an acceptable rounding error
|
||||
}
|
||||
|
||||
function test_computeAmountIn() public {
|
||||
|
||||
function test_swapUsingOptimum() 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("Sushiswap pair reserves", X_B, Y_B);
|
||||
console.log("Uniswap pair ratio", Y_A/X_A);
|
||||
console.log("Sushiswap pair ratio", Y_B/X_B);
|
||||
|
||||
|
@ -53,6 +53,7 @@ contract ArbitrageTest is Test {
|
|||
(X_A, Y_A, ) = uniswapPair.getReserves();
|
||||
(X_B, Y_B, ) = sushiswapPair.getReserves();
|
||||
console.log("Uniswap pair reserves", X_A, Y_A);
|
||||
console.log("Sushiswap pair reserves", X_B, Y_B);
|
||||
console.log("Uniswap pair ratio", Y_A/X_A);
|
||||
console.log("Sushiswap pair ratio", Y_B/X_B);
|
||||
|
||||
|
@ -74,4 +75,47 @@ contract ArbitrageTest is Test {
|
|||
console.log("Uniswap pair ratio", Y_A/X_A);
|
||||
console.log("Sushiswap pair ratio", Y_B/X_B);
|
||||
}
|
||||
|
||||
function computeGain(uint256 X_A, uint256 Y_A, uint256 X_B, uint256 Y_B, int256 delta)
|
||||
internal view returns(uint256)
|
||||
{
|
||||
uint256 optimum = (delta > 0) ?
|
||||
arbitrageManager.optimalIn(X_A, Y_A, X_B, Y_B) + uint256(delta)
|
||||
: arbitrageManager.optimalIn(X_A, Y_A, X_B, Y_B) - uint256(-delta);
|
||||
uint256 amountOut = arbitrageManager.getAmountOut(optimum, Y_A, X_A);
|
||||
amountOut = arbitrageManager.getAmountOut(amountOut, X_B, Y_B);
|
||||
return amountOut - optimum;
|
||||
}
|
||||
|
||||
function test_computeOptimum() public view {
|
||||
(uint256 X_A, uint256 Y_A, ) = uniswapPair.getReserves(); // (USDT, WETH)
|
||||
(uint256 X_B, uint256 Y_B, ) = sushiswapPair.getReserves(); // (USDT, WETH)
|
||||
Y_A -= Y_A / 5; // unbalancing the pair
|
||||
|
||||
// Using delta too low (~< 10**8) seems to produce a better gain,
|
||||
// I *believe this has to do to some rounding, it should be neglibile
|
||||
uint256[4] memory deltas = [uint256(0), uint256(10**8), uint256(10**9), uint256(10**10)];
|
||||
|
||||
uint256 gain = computeGain(X_A, Y_A, X_B, Y_B, 0);
|
||||
|
||||
for (uint256 i; i < deltas.length; i++) {
|
||||
assertGe(gain, computeGain(X_A, Y_A, X_B, Y_B, int256(deltas[i])), "Computed optimum isnt't really optimal");
|
||||
assertGe(gain, computeGain(X_A, Y_A, X_B, Y_B, -int256(deltas[i])), "Computed optimum isnt't really optimal");
|
||||
}
|
||||
}
|
||||
|
||||
function test_flashArbitrage () public {
|
||||
uint256 initialWethBalance = weth.balanceOf(address(this));
|
||||
|
||||
console.log("initial weth balance", initialWethBalance);
|
||||
(, uint256 Y_A, ) = uniswapPair.getReserves(); // (USDT, WETH)
|
||||
uint256 unbalance = Y_A / 5;
|
||||
vm.prank(address(uniswapPair)); // it works only for the next call
|
||||
weth.transfer(address(0), unbalance);
|
||||
uniswapPair.sync();
|
||||
|
||||
uint256 profit = arbitrageManager.flashArbitrage(address(uniswapPair), address(sushiswapPair), false);
|
||||
console.log("profit", profit);
|
||||
assertEq(initialWethBalance + profit, weth.balanceOf(address(this)), "There was no profit");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue