@prostiprof

Web3 python ошибка транзакции. Как исправить?

Не могу провести операцию в одну транзакцию, может не так ее собираю. Если скрипт делить на части, то транзакция проходит успешно. Если делать за одну, то ошибка выполнения

import json
import time
from web3 import Web3
from web3.exceptions import ContractLogicError

# Configuration
INFURA_URL = ''
PRIVATE_KEY = ''
POOL_ID = id # Указать
CHAIN_ID = 10  # Optimism

# Initialize Web3
web3 = Web3(Web3.HTTPProvider(INFURA_URL))
account = web3.eth.account.from_key(PRIVATE_KEY)

# Addresses
USDC_ADDRESS = Web3.to_checksum_address('0x0b2c639c533813f4aa9d7837caf62653d097ff85')
WETH_ADDRESS = Web3.to_checksum_address('0x4200000000000000000000000000000000000006')
POSITION_MANAGER_ADDRESS = Web3.to_checksum_address('0xC36442b4a4522E871399CD717aBDD847Ab11FE88')
ROUTER_ADDRESS = Web3.to_checksum_address('0xE592427A0AEce92De3Edee1F18E0157C05861564')

# Load ABIs
with open('/position_manager_abi.json', 'r') as file:
    position_manager_abi = json.load(file)
with open('/router_abi.json', 'r') as file:
    router_abi = json.load(file)

# Contracts
position_manager = web3.eth.contract(address=POSITION_MANAGER_ADDRESS, abi=position_manager_abi)
router = web3.eth.contract(address=ROUTER_ADDRESS, abi=router_abi)

def main():
    try:
        # Get pool information
        position_info = position_manager.functions.positions(POOL_ID).call()
        liquidity = position_info[7]
        print(f'Current position_info: {position_info}')
        print(f'Liquidity: {liquidity}')

        if liquidity == 0:
            raise ValueError("Liquidity is zero. Cannot decrease liquidity.")

        # Increase deadline
        deadline = int(time.time()) + 3600  # 1 hour from now

        # Encode decreaseLiquidity
        decrease_data = position_manager.encodeABI(fn_name='decreaseLiquidity', args=[(
            POOL_ID,
            liquidity,
            0,
            0,
            deadline
        )])

        # Encode collect
        collect_data = position_manager.encodeABI(fn_name='collect', args=[(
            POOL_ID,
            ROUTER_ADDRESS,
            2**128 - 1,
            2**128 - 1
        )])

        # Encode exactInputSingle for WETH to USDC swap
        swap_data = router.encodeABI(fn_name='exactInputSingle', args=[{
            'tokenIn': WETH_ADDRESS,
            'tokenOut': USDC_ADDRESS,
            'fee': 3000,
            'recipient': account.address,
            'deadline': deadline,
            'amountIn': 2**256 - 1,  # Max uint, will be limited by actual balance
            'amountOutMinimum': 0,
            'sqrtPriceLimitX96': 0
        }])

        # Encode sweepToken for any remaining WETH
        sweep_weth = router.encodeABI(fn_name='sweepToken', args=[
            WETH_ADDRESS,
            0,
            account.address
        ])

        # Encode sweepToken for USDC
        sweep_usdc = router.encodeABI(fn_name='sweepToken', args=[
            USDC_ADDRESS,
            0,
            account.address
        ])

        # Build multicall transaction for all operations
        multicall_data = [
            decrease_data,
            collect_data,
            swap_data,
            sweep_weth,
            sweep_usdc
        ]

        # Estimate gas for the multicall transaction
        estimated_gas = position_manager.functions.multicall(multicall_data).estimate_gas({
            'from': account.address,
            'nonce': web3.eth.get_transaction_count(account.address),
            'gasPrice': web3.eth.gas_price,
            'chainId': CHAIN_ID,
        })

        # Build the transaction
        transaction = position_manager.functions.multicall(multicall_data).build_transaction({
            'from': account.address,
            'nonce': web3.eth.get_transaction_count(account.address),
            'gas': int(estimated_gas * 1.2),  # Add 20% to the estimated gas
            'gasPrice': web3.eth.gas_price,
            'chainId': CHAIN_ID,
        })

        # Sign and send transaction
        signed_txn = web3.eth.account.sign_transaction(transaction, private_key=PRIVATE_KEY)
        tx_hash = web3.eth.send_raw_transaction(signed_txn.rawTransaction)
        print(f'Transaction hash: {tx_hash.hex()}')

        # Wait for transaction receipt
        txn_receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
        print(f'Transaction confirmed in block: {txn_receipt.blockNumber}')

        # Check transaction status
        if txn_receipt['status'] == 1:
            print('Transaction was successful')
        else:
            print('Transaction failed')
            raise Exception("Transaction failed")

    except ContractLogicError as e:
        print(f'Contract logic error: {str(e)}')
    except Exception as e:
        print(f'An error occurred: {str(e)}')

if __name__ == "__main__":
    main()
  • Вопрос задан
  • 157 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы