Возникла проблема с заменой на web3.py в тестовой сети uniswap sepolia с помощью пула eth/usdcPython

Программы на Python
Ответить
Anonymous
 Возникла проблема с заменой на web3.py в тестовой сети uniswap sepolia с помощью пула eth/usdc

Сообщение Anonymous »

Я пишу код с помощью chatgpt для обмена токенов в web3.py в тестовой сети sepolia пула eth/usdc.
почему?
Я тестирую обмен Uniswap v3 в тестовой сети Sepolia с использованием Python и web3.py.

Хотя транзакция успешна в сети баланс USDC не увеличивается, даже несмотря на то, что собственный пользовательский интерфейс Uniswap (app.uniswap.org) правильно обменивается в одном и том же пуле.
Я протестировал две транзакции:
  • Обмен через Uniswap UI → Работает правильно
  • Обмен через мой скрипт Python (exactInputSingle или Universal Router) → Транзакция прошла успешно, но пользователь

    как исправить обмен в коде

    как исправить эту проблему и что изменилось и что мне нужно знать смарт-контракт маршрутизатора и другое
код:

Код: Выделить всё

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
почему?
Я тестирую своп Uniswap v3 в тестовой сети Sepolia с использованием Python и web3.py.

Хотя транзакция успешно проходит в цепочке, баланс USDC не увеличивается, даже несмотря на собственный пользовательский интерфейс Uniswap (app.uniswap.org) правильно обменивается в одном и том же пуле.
Я протестировал две транзакции:
  • Обмен через пользовательский интерфейс Uniswap → Работает правильно
  • Обмен через мой скрипт Python (exactInputSingle или Universal Router) → Транзакция прошла успешно, но пользователь

    как исправить обмен код

    как решить эту проблему и что изменилось и что мне нужно знать смарт-контракт маршрутизатора и другое


Подробнее здесь: https://stackoverflow.com/questions/798 ... h-usdc-poo
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»