import os import sys import json from web3 import Web3 from dotenv import load_dotenv from decimal import Decimal # Add project root sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) # Load Env load_dotenv() RPC_URL = os.environ.get("MAINNET_RPC_URL") # Arbitrum RPC POOL_ADDRESS = "0xC6962004f452bE9203591991D15f6b388e09E8D0" # ARB/WETH 500 ERC20_ABI = [ {"constant": True, "inputs": [], "name": "symbol", "outputs": [{"name": "", "type": "string"}], "payable": False, "stateMutability": "view", "type": "function"}, {"constant": True, "inputs": [], "name": "decimals", "outputs": [{"name": "", "type": "uint8"}], "payable": False, "stateMutability": "view", "type": "function"}, {"constant": True, "inputs": [{"name": "_owner", "type": "address"}], "name": "balanceOf", "outputs": [{"name": "balance", "type": "uint256"}], "payable": False, "stateMutability": "view", "type": "function"} ] 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": "uint32", "name": "feeProtocol", "type": "uint32"}, {"internalType": "bool", "name": "unlocked", "type": "bool"}], "stateMutability": "view", "type": "function"}, {"inputs": [], "name": "liquidity", "outputs": [{"internalType": "uint128", "name": "", "type": "uint128"}], "stateMutability": "view", "type": "function"}, {"inputs": [], "name": "token0", "outputs": [{"internalType": "address", "name": "", "type": "address"}], "stateMutability": "view", "type": "function"}, {"inputs": [], "name": "token1", "outputs": [{"internalType": "address", "name": "", "type": "address"}], "stateMutability": "view", "type": "function"}, {"inputs": [], "name": "fee", "outputs": [{"internalType": "uint24", "name": "", "type": "uint24"}], "stateMutability": "view", "type": "function"} ] def main(): if not RPC_URL: print("Error: MAINNET_RPC_URL not found in .env") return w3 = Web3(Web3.HTTPProvider(RPC_URL)) if not w3.is_connected(): print("Error: Could not connect to RPC") return print(f"Connected to Arbitrum: {w3.eth.block_number}") pool_contract = w3.eth.contract(address=POOL_ADDRESS, abi=POOL_ABI) # 1. Metadata t0_addr = pool_contract.functions.token0().call() t1_addr = pool_contract.functions.token1().call() fee = pool_contract.functions.fee().call() t0_contract = w3.eth.contract(address=t0_addr, abi=ERC20_ABI) t1_contract = w3.eth.contract(address=t1_addr, abi=ERC20_ABI) t0_sym = t0_contract.functions.symbol().call() t1_sym = t1_contract.functions.symbol().call() t0_dec = t0_contract.functions.decimals().call() t1_dec = t1_contract.functions.decimals().call() print(f"\nPool: {t0_sym} / {t1_sym} ({fee/10000}%)") print(f"Token0: {t0_sym} ({t0_addr}) - {t0_dec} dec") print(f"Token1: {t1_sym} ({t1_addr}) - {t1_dec} dec") # 2. State slot0 = pool_contract.functions.slot0().call() sqrt_price = slot0[0] tick = slot0[1] liquidity = pool_contract.functions.liquidity().call() print(f"\nState:") print(f"Liquidity: {liquidity}") print(f"Tick: {tick}") print(f"SqrtPriceX96: {sqrt_price}") # 3. Price Calc # price = (sqrt / 2^96)^2 p = (Decimal(sqrt_price) / Decimal(2**96)) ** 2 # Adjust for decimals: Price = raw_price * 10^(d0 - d1) adj_price = p * (Decimal(10) ** (t0_dec - t1_dec)) inv_price = Decimal(1) / adj_price if adj_price > 0 else 0 print(f"\nPrices:") print(f"1 {t0_sym} = {adj_price:.6f} {t1_sym}") print(f"1 {t1_sym} = {inv_price:.6f} {t0_sym}") # 4. TVL Estimation (Balances) t0_bal = t0_contract.functions.balanceOf(POOL_ADDRESS).call() t1_bal = t1_contract.functions.balanceOf(POOL_ADDRESS).call() t0_human = Decimal(t0_bal) / Decimal(10**t0_dec) t1_human = Decimal(t1_bal) / Decimal(10**t1_dec) print(f"\nTVL (Locked in Contract):") print(f"{t0_human:,.2f} {t0_sym}") print(f"{t1_human:,.2f} {t1_sym}") # Assume WETH is approx 3350 (or whatever current market is, we can use slot0 price if one is stable) # If one is USD stable, we can calc total. # ARB / WETH. WETH is ~$3300. # Let's just output raw. if __name__ == "__main__": main()