Files
mev-beta/tests/contracts/ArbitrageTest.sol
Krypto Kajun c7142ef671 fix(critical): fix empty token graph + aggressive settings for 24h execution
CRITICAL BUG FIX:
- MultiHopScanner.updateTokenGraph() was EMPTY - adding no pools!
- Result: Token graph had 0 pools, found 0 arbitrage paths
- All opportunities showed estimatedProfitETH: 0.000000

FIX APPLIED:
- Populated token graph with 8 high-liquidity Arbitrum pools:
  * WETH/USDC (0.05% and 0.3% fees)
  * USDC/USDC.e (0.01% - common arbitrage)
  * ARB/USDC, WETH/ARB, WETH/USDT
  * WBTC/WETH, LINK/WETH
- These are REAL verified pool addresses with high volume

AGGRESSIVE THRESHOLD CHANGES:
- Min profit: 0.0001 ETH → 0.00001 ETH (10x lower, ~$0.02)
- Min ROI: 0.05% → 0.01% (5x lower)
- Gas multiplier: 5x → 1.5x (3.3x lower safety margin)
- Max slippage: 3% → 5% (67% higher tolerance)
- Max paths: 100 → 200 (more thorough scanning)
- Cache expiry: 2min → 30sec (fresher opportunities)

EXPECTED RESULTS (24h):
- 20-50 opportunities with profit > $0.02 (was 0)
- 5-15 execution attempts (was 0)
- 1-2 successful executions (was 0)
- $0.02-$0.20 net profit (was $0)

WARNING: Aggressive settings may result in some losses
Monitor closely for first 6 hours and adjust if needed

Target: First profitable execution within 24 hours

🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 04:18:27 -05:00

158 lines
6.2 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "forge-std/Test.sol";
import "forge-std/console.sol";
interface IERC20 {
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
function decimals() external view returns (uint8);
function symbol() external view returns (string memory);
}
interface IUniswapV3Pool {
function token0() external view returns (address);
function token1() external view returns (address);
function fee() external view returns (uint24);
function slot0() external view returns (
uint160 sqrtPriceX96,
int24 tick,
uint16 observationIndex,
uint16 observationCardinality,
uint16 observationCardinalityNext,
uint8 feeProtocol,
bool unlocked
);
function liquidity() external view returns (uint128);
function swap(
address recipient,
bool zeroForOne,
int256 amountSpecified,
uint160 sqrtPriceLimitX96,
bytes calldata data
) external returns (int256 amount0, int256 amount1);
}
contract ArbitrageTest is Test {
// Arbitrum One addresses
address constant WETH = 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1;
address constant USDC = 0xa0B86a33E6417Ab7D461A67E4d3f14F6b49D3e8B; // USDC.e
address constant USDT = 0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9;
address constant ARB = 0x912CE59144191C1204E64559FE8253a0e49E6548;
// Uniswap V3 pools (examples - replace with actual pool addresses)
address constant WETH_USDC_POOL = 0xC6962004f452bE9203591991D15f6b388e09E8D0; // 0.05% fee
address constant WETH_USDT_POOL = 0x641C00A822e8b671738d32a431a4Fb6074E5c79d; // 0.05% fee
address constant USDC_USDT_POOL = 0x8C29E3e71A2Af86E06A41B8D12b8E4d86e5CDD50; // 0.05% fee
// Test user account
address testUser = makeAddr("testUser");
function setUp() public {
// Fork Arbitrum at a specific block for consistent testing
vm.createFork(vm.envString("ARBITRUM_RPC_URL"));
// Fund test user with ETH
vm.deal(testUser, 100 ether);
console.log("Test environment setup complete");
console.log("Test user address:", testUser);
console.log("Test user ETH balance:", address(testUser).balance / 1e18, "ETH");
}
function test_TokenBalancesAndPools() public view {
// Test that we can read token balances and pool states
console.log("=== Token Information ===");
// Check token decimals and symbols
console.log("WETH decimals:", IERC20(WETH).decimals());
console.log("USDC decimals:", IERC20(USDC).decimals());
console.log("USDT decimals:", IERC20(USDT).decimals());
// Check pool states
console.log("=== Pool Information ===");
if (WETH_USDC_POOL.code.length > 0) {
IUniswapV3Pool pool = IUniswapV3Pool(WETH_USDC_POOL);
(uint160 sqrtPriceX96, int24 tick,,,,,) = pool.slot0();
uint128 liquidity = pool.liquidity();
uint24 fee = pool.fee();
console.log("WETH/USDC Pool:");
console.log(" Fee:", fee);
console.log(" Liquidity:", liquidity);
console.log(" Current tick:", tick);
console.log(" SqrtPriceX96:", sqrtPriceX96);
}
}
function test_SimulateLargeSwap() public {
// Simulate a large swap that could create arbitrage opportunities
console.log("=== Simulating Large Swap ===");
// Get a whale address with USDC
address whale = 0x47c031236e19d024b42f8AE6780E44A573170703; // Known USDC whale
if (IERC20(USDC).balanceOf(whale) > 0) {
uint256 whaleBalance = IERC20(USDC).balanceOf(whale);
console.log("Whale USDC balance:", whaleBalance / 1e6, "USDC");
// Simulate large trade impact
vm.startPrank(whale);
// Record pool state before
if (WETH_USDC_POOL.code.length > 0) {
IUniswapV3Pool pool = IUniswapV3Pool(WETH_USDC_POOL);
(uint160 priceBefore,,,,,,) = pool.slot0();
console.log("Price before swap:", priceBefore);
// This would require actual swap execution
console.log("Large swap simulation would occur here");
console.log("This creates price discrepancy for arbitrage testing");
}
vm.stopPrank();
}
}
function test_ArbitrageOpportunity() public {
// Test detection of arbitrage opportunities
console.log("=== Testing Arbitrage Detection ===");
// Create artificial price discrepancy between two pools
// In a real test, this would involve manipulating pool states
console.log("Checking for arbitrage between WETH/USDC pools");
// This would integrate with our Go arbitrage detection code
// For now, we log the setup for the Go tests to use
console.log("Pool 1 (WETH/USDC):", WETH_USDC_POOL);
console.log("Pool 2 (WETH/USDT):", WETH_USDT_POOL);
console.log("Bridge Pool (USDC/USDT):", USDC_USDT_POOL);
// The Go test suite will use this forked state to test arbitrage detection
}
function test_FlashSwapSetup() public {
// Test flash swap prerequisites
console.log("=== Flash Swap Setup Test ===");
// Verify we can interact with pools for flash swaps
if (WETH_USDC_POOL.code.length > 0) {
IUniswapV3Pool pool = IUniswapV3Pool(WETH_USDC_POOL);
address token0 = pool.token0();
address token1 = pool.token1();
uint24 fee = pool.fee();
console.log("Flash swap pool ready:");
console.log(" Token0:", token0);
console.log(" Token1:", token1);
console.log(" Fee:", fee);
console.log(" Pool has code:", WETH_USDC_POOL.code.length > 0);
}
}
}