import os import sys import json import time from decimal import Decimal from web3 import Web3 from dotenv import load_dotenv # Add project root to sys.path sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) from clp_abis import NONFUNGIBLE_POSITION_MANAGER_ABI load_dotenv() RPC_URL = os.environ.get("BASE_RPC_URL") if not RPC_URL: print("Error: BASE_RPC_URL not set") sys.exit(1) w3 = Web3(Web3.HTTPProvider(RPC_URL)) private_key = os.environ.get("MAIN_WALLET_PRIVATE_KEY") account = w3.eth.account.from_key(private_key) NPM_ADDRESS = "0x827922686190790b37229fd06084350E74485b72" WETH = "0x4200000000000000000000000000000000000006" USDC = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" # Amounts (Reduced to fit allowance) AMOUNT0 = 10000000000000000 # 0.01 ETH AMOUNT1 = 10000000 # 10 USDC # Ticks (Approx from logs/logic, using TS=1) # Current Tick ~ -201984 (Price ~3050) # Just picking a valid range around current price CURRENT_TICK = -201984 TICK_LOWER = CURRENT_TICK - 200 TICK_UPPER = CURRENT_TICK + 200 def try_mint_simulation(fee_value): print(f"\n--- Testing Mint with fee={fee_value} ---") npm = w3.eth.contract(address=NPM_ADDRESS, abi=NONFUNGIBLE_POSITION_MANAGER_ABI) # FETCH REAL TICK pool_address = "0xb2cc224c1c9feE385f8ad6a55b4d94E92359DC59" # TS=100 Pool pool_abi = [{"inputs": [], "name": "slot0", "outputs": [{"internalType": "uint160", "name": "sqrtPriceX96", "type": "uint160"}, {"internalType": "int24", "name": "tick", "type": "int24"}, {"internalType": "uint16", "name": "observationIndex", "type": "uint16"}, {"internalType": "uint16", "name": "observationCardinality", "type": "uint16"}, {"internalType": "uint16", "name": "observationCardinalityNext", "type": "uint16"}, {"internalType": "bool", "name": "unlocked", "type": "bool"}], "stateMutability": "view", "type": "function"}] pool = w3.eth.contract(address=pool_address, abi=pool_abi) try: slot0 = pool.functions.slot0().call() current_tick = slot0[1] print(f"Current Tick: {current_tick}") except: current_tick = -200000 print("Failed to fetch tick, using default.") # Align to TS=100 TS = 100 tick_lower = (current_tick // TS) * TS - (TS * 2) # -200 ticks tick_upper = (current_tick // TS) * TS + (TS * 2) # +200 ticks print(f"Ticks: {tick_lower} <-> {tick_upper} (TS={TS})") # CHECK ALLOWANCES erc20_abi = [{"inputs": [{"internalType": "address", "name": "owner", "type": "address"}, {"internalType": "address", "name": "spender", "type": "address"}], "name": "allowance", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], "stateMutability": "view", "type": "function"}] weth_c = w3.eth.contract(address=WETH, abi=erc20_abi) usdc_c = w3.eth.contract(address=USDC, abi=erc20_abi) a0 = weth_c.functions.allowance(account.address, NPM_ADDRESS).call() a1 = usdc_c.functions.allowance(account.address, NPM_ADDRESS).call() print(f"Allowances: WETH={a0}, USDC={a1}") params = ( WETH, USDC, fee_value, # The value in question tick_lower, tick_upper, AMOUNT0, AMOUNT1, 0, 0, # Min amounts 0 account.address, int(time.time()) + 180 ) tx_params = { 'from': account.address, 'nonce': w3.eth.get_transaction_count(account.address), 'value': 0, 'gas': 500000, 'gasPrice': w3.eth.gas_price } try: # Simulate (call) npm.functions.mint(params).call(tx_params) print("✅ Simulation SUCCESS!") return True except Exception as e: print(f"❌ Simulation FAILED: {e}") return False if __name__ == "__main__": # Test candidates candidates = [1, 100, 200, 500, 3000, 10000] for fee in candidates: try_mint_simulation(fee)