have problem in swapping with web3.py in uniswap sepolia testnet by eth/usdc pool

2 weeks ago 14
ARTICLE AD BOX

i write a code with chatgpt help for swapping tokens in web3.py in eth/usdc pool sepolia testnet.

why?

I’m testing a Uniswap v3 swap on the Sepolia testnet using Python and web3.py.
Although the transaction succeeds on-chain, the USDC balance does not increase, even though Uniswap’s own UI (app.uniswap.org) swaps correctly on the exact same pool.

I have tested two transactions:

Swap via Uniswap UI → Works correctly

Swap via my Python script (exactInputSingle or Universal Router) → Transaction succeeds, but user
how to correct swap in code
how to fix this problem and what changed and what do i need to know router smart contract and other

code:

CHAIN_ID = 11155111 # Sepolia # Pool & token addresses USDC = w3.to_checksum_address("0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238") WETH = w3.to_checksum_address("0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14") # --- آدرس Pool جدید با Fee 100 (0.01%) --- POOL_ADDRESS = w3.to_checksum_address("0xFeEd501c2B21D315F04946F85fC6416B640240b5") # آدرس Universal Router (از دیتای UI شما) UNIVERSAL_ROUTER = w3.to_checksum_address(address) MAX_UINT256 = 2**256 - 1 # Uniswap Universal Commands V3_SWAP_EXACT_IN = 0x00 # WRAP_ETH = 0x01 # # ------------------------------------------------------------------ # ------------------------- ABIs (minimal) ------------------------- ERC20_ABI = [ {"constant":True,"inputs":[{"name":"account","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"type":"function"}, {"constant":True,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"type":"function"}, {"constant":False,"inputs":[{"name":"spender","type":"address"},{"name":"amount","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"type":"function"}, {"constant":True,"inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"type":"function"} ] WETH9_ABI = [ {"inputs":[],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"}, {"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}, ] + ERC20_ABI # ABI مخصوص Universal Router برای تابع Execute UNIVERSAL_ROUTER_ABI = json.loads(""" [ { "inputs": [ {"internalType": "bytes","name": "commands","type": "bytes"}, {"internalType": "bytes[]","name": "inputs","type": "bytes[]"}, {"internalType": "uint256","name": "deadline","type": "uint256"} ], "name": "execute", "outputs": [], "stateMutability": "payable", "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":"uint8","name":"feeProtocol","type":"uint8"}, {"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"} ] # ------------------------------------------------------------------ # ------------------------- CONTRACTS ------------------------- usdc = w3.eth.contract(address=USDC, abi=ERC20_ABI) weth = w3.eth.contract(address=WETH, abi=WETH9_ABI) universal_router = w3.eth.contract(address=UNIVERSAL_ROUTER, abi=UNIVERSAL_ROUTER_ABI) pool = w3.eth.contract(address=POOL_ADDRESS, abi=POOL_ABI) # ------------------------------------------------------------------ # ------------------------- HELPERS ------------------------- def human_balance(token_contract, addr): bal = token_contract.functions.balanceOf(addr).call() try: dec = token_contract.functions.decimals().call() except: dec = 18 human = decimal.Decimal(bal) / (decimal.Decimal(10) ** dec) return float(human), bal, dec def eth_balance(addr): b = w3.eth.get_balance(addr) return float(decimal.Decimal(b) / (decimal.Decimal(10) ** 18)), b def send_signed_tx(tx_dict): signed = w3.eth.account.sign_transaction(tx_dict, PRIVATE_KEY) txh = w3.eth.send_raw_transaction(signed.raw_transaction) receipt = w3.eth.wait_for_transaction_receipt(txh) return receipt def build_and_send(tx, value=0): nonce = w3.eth.get_transaction_count(WALLET) gas_price = int(w3.eth.gas_price * 1.0) tx_dict = tx.build_transaction({ "from": WALLET, "nonce": nonce, "gasPrice": gas_price, "value": value, "chainId": CHAIN_ID }) try: est = w3.eth.estimate_gas(tx_dict) tx_dict['gas'] = int(est * 1.2) except Exception as e: # افزایش گس به 1 میلیون برای Universal Router tx_dict.setdefault('gas', 1000000) return send_signed_tx(tx_dict) def encode_v3_swap_exact_in(recipient: str, amount_in: int, amount_out_min: int, path: bytes, payer_is_user: bool = True) -> bytes: # 0x00: V3_SWAP_EXACT_IN # recipient: address (20 bytes) # amount_in: uint256 (32 bytes) # amount_out_min: uint256 (32 bytes) # path: bytes variable length # payer_is_user: bool (1 byte, 0x01 for True) recipient_bytes = w3.to_bytes(hexstr=recipient) amount_in_bytes = w3.to_bytes(amount_in).rjust(32, b'\x00') amount_out_min_bytes = w3.to_bytes(amount_out_min).rjust(32, b'\x00') # Encode path (packed: Fee + TokenOut) # WETH -> USDC (Fee 100) # path_bytes = fee + tokenOut fee_bytes = w3.to_bytes(100).rjust(3, b'\x00') # 3 bytes for fee usdc_bytes = w3.to_bytes(hexstr=USDC) # 20 bytes for tokenOut encoded_path = fee_bytes + usdc_bytes # V3_SWAP_EXACT_IN Input structure: # recipient (20 bytes) + amountIn (32 bytes) + amountOutMin (32 bytes) + encoded_path_length (uint8: 1 byte) + encoded_path # Path encoding for single hop: fee(3) + tokenOut(20) = 23 bytes v3_swap_input = ( recipient_bytes + amount_in_bytes + amount_out_min_bytes + w3.to_bytes(len(encoded_path)).rjust(1, b'\x00') + # length of path (23 bytes) encoded_path ) return v3_swap_input # ------------------------------------------------------------------ # ------------------------- STEP 0: print pool on-chain info ------------------------- print("=== POOL ON-CHAIN INFO ===") slot0 = pool.functions.slot0().call() liquidity = pool.functions.liquidity().call() p_token0 = pool.functions.token0().call() p_token1 = pool.functions.token1().call() p_fee = pool.functions.fee().call() print("slot0 =", slot0) print("liquidity =", liquidity) print("token0 =", p_token0) print("token1 =", p_token1) print("fee =", p_fee) print() sqrtPriceX96 = int(slot0[0]) dec0 = usdc.functions.decimals().call() dec1 = weth.functions.decimals().call() price_token1_per_token0 = (decimal.Decimal(sqrtPriceX96) ** 2) / (decimal.Decimal(2) ** 192) * (decimal.Decimal(10) ** (dec0 - dec1)) print(f"approx price (token1 per token0) = {price_token1_per_token0} (note: token1 is WETH, token0 is USDC)") print() # ------------------------- STEP 1: balances BEFORE ------------------------- print("=== BALANCES BEFORE ===") eth_before_f, eth_before = eth_balance(WALLET) usdc_before_h, usdc_before_raw, usdc_dec = human_balance(usdc, WALLET) weth_before_h, weth_before_raw, weth_dec = human_balance(weth, WALLET) print(f"ETH before: {eth_before_f} (wei: {eth_before})") print(f"USDC before: {usdc_before_h} (raw: {usdc_before_raw}, dec: {usdc_dec})") print(f"WETH before: {weth_before_h} (raw: {weth_before_raw}, dec: {weth_dec})") print() # ------------------------- PARAMETERS FOR SWAP ------------------------- amount_in_eth = 0.002 amount_in_wei = w3.to_wei(amount_in_eth, 'ether') fee = int(p_fee) sqrtPriceLimitX96 = 0 # ------------------------- محاسبه دستی minOutAmount با 99% Slippage ------------------------- price_usdc_per_weth = 1 / price_token1_per_token0 amount_in_decimal = decimal.Decimal(str(amount_in_eth)) expected_usdc_raw = int(amount_in_decimal * price_usdc_per_weth * (10**usdc_dec)) SLIPPAGE_TOLERANCE_TEST = 99.0 min_out_amount = int(expected_usdc_raw * (1 - SLIPPAGE_TOLERANCE_TEST / 100)) print("=== CALCULATED MIN OUT AMOUNT (Manual @ 99% Slippage) ===") print(f"Expected USDC (raw): {expected_usdc_raw}") print(f"Min Out Amount (raw) @{SLIPPAGE_TOLERANCE_TEST}% Slippage: {min_out_amount}") print() # ------------------------------------------------------------------------- # ------------------------- STEP 2: BUILD COMMANDS AND INPUTS ------------------------- # 1. WRAP_ETH: ETH به WETH # 2. V3_SWAP_EXACT_IN: WETH به USDC commands = w3.to_bytes(WRAP_ETH) + w3.to_bytes(V3_SWAP_EXACT_IN) inputs = [] # Input for WRAP_ETH () inputs.append(b'') # Input for V3_SWAP_EXACT_IN # در Universal Router # recipient: WALLET # amountIn: مقدار WETH (amount_in_wei) # amountOutMin: min_out_amount # path: [Fee 100] + [USDC Address] swap_input_bytes = encode_v3_swap_exact_in( recipient=WALLET, amount_in=amount_in_wei, amount_out_min=min_out_amount, path=b'' # Path encode_v3_swap_exact_in ) inputs.append(swap_input_bytes) print("=== UNIVERSAL ROUTER COMMANDS ===") print("Commands (hex):", w3.to_hex(commands)) print(f"Input 1 (WRAP_ETH): {w3.to_hex(inputs[0])}") print(f"Input 2 (V3_SWAP_EXACT_IN): {w3.to_hex(inputs[1])}") print() # ------------------------- STEP 3: EXECUTE SWAP (Wrap + Swap) ------------------------- print("=== EXECUTE Universal Router Swap (ETH -> USDC) ===") deadline = int(time.time()) + 600 tx_swap = universal_router.functions.execute( commands, inputs, deadline ) rec_swap = build_and_send(tx_swap, value=amount_in_wei) print("Swap tx hash:", rec_swap.transactionHash.hex()) print() # ------------------------- STEP 4: balances AFTER ------------------------- print("=== BALANCES AFTER ===") eth_after_f2, eth_after2 = eth_balance(WALLET) usdc_after_h2, usdc_after_raw2, _ = human_balance(usdc, WALLET) weth_after_h2, weth_after_raw2, _ = human_balance(weth, WALLET) print(f"ETH after all: {eth_after_f2} (wei: {eth_after2})") print(f"USDC after: {usdc_after_h2} (raw: {usdc_after_raw2})") print(f"WETH after: {weth_after_h2} (raw: {weth_after_raw2})") print() print("diffs:") print("ETH diff (wei):", eth_after2 - eth_before) print("USDC diff (raw):", usdc_after_raw2 - usdc_before_raw) print("WETH diff (raw):", weth_after_raw2 - weth_before_raw)

out_put:

=== POOL ON-CHAIN INFO === slot0 = [794977517060454369285168142512446, 184283, 5, 6, 6, 0, True] liquidity = 4298703128131633 token0 = 0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238 token1 = 0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14 fee = 100 approx price (token1 per token0) = 0.0001006816966290053832334638390 (note: token1 is WETH, token0 is USDC) === BALANCES BEFORE === ETH before: 0.06559289167767096 (wei: 65592891677670960) USDC before: 40.056774 (raw: 40056774, dec: 6) WETH before: 0.016 (raw: 16000000000000000, dec: 18) === CALCULATED MIN OUT AMOUNT (Manual @ 99% Slippage) === Expected USDC (raw): 19864583 Min Out Amount (raw) @99.0% Slippage: 198645 === UNIVERSAL ROUTER COMMANDS === Commands (hex): 0x0100 Input 1 (WRAP_ETH): 0x Input 2 (V3_SWAP_EXACT_IN): 0x7868edefc36a74eba220c75acfb05c59a4e5582200000000000000000000000000000000000000000000000000071afd498d000000000000000000000000000000000000000000000000000000000000000307f5170000641c7d4b196cb0c7b01d743fbc6116a902379c7238 === EXECUTE Universal Router Swap (ETH -> USDC) === Swap tx hash: f47ef229e0823060907d199f468ba4e1d6977a9f8b55c221d0573cd0972f409f === BALANCES AFTER === ETH after all: 0.06559289167767096 (wei: 65592891677670960) USDC after: 40.056774 (raw: 40056774) WETH after: 0.016 (raw: 16000000000000000) diffs: ETH diff (wei): 0 USDC diff (raw): 0 WETH diff (raw): 0

why?

I’m testing a Uniswap v3 swap on the Sepolia testnet using Python and web3.py.
Although the transaction succeeds on-chain, the USDC balance does not increase, even though Uniswap’s own UI (app.uniswap.org) swaps correctly on the exact same pool.

I have tested two transactions:

Swap via Uniswap UI → Works correctly

Swap via my Python script (exactInputSingle or Universal Router) → Transaction succeeds, but user
how to correct swap in code
how to fix this problem and what changed and what do i need to know router smart contract and other

Read Entire Article