0

I am writing some code on Python utilising the Web3 library. I am accessing the mempool and I am trying to access the slippage on pending transactions on swaps made on the Binance Smart Chain with PancakeSwap.

Lets use this transaction as an example. https://bscscan.com/tx/0x99ebc809a63897925fa421a58d2e978b6c3e12cd9edf952993f9c7b3e32325fe

Below is the transaction input.

0x472b43f300000000000000000000000000000000000000000000a7e9b0f7650000450520000000000000000000000000000000000000000000000000026233275e989c16000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c841780c34c17190bceeefb6d986aaca4fb95e31000000000000000000000000bb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c0x49404b7c000000000000000000000000000000000000000000000000026233275e989c16000000000000000000000000d407934d50b917bb8eabe9c651d547b8a1de7def

How would I achieve this?

Below is a sample of code I attempted to use.

contract = web3.eth.contract(address=Web3.to_checksum_address('0x10ED43C718714eb63d5aA57B78B54704E256024E'), abi=pancakeABI)

contract.decode_function_input(transaction_input)

Error

https://lab.miguelmota.com/ethereum-input-data-decoder/example/ I used this website as well with the PancakeSwap ABI and the same transaction input and I got null. So what is the issue?

2

2 Answers 2

1

You are almost there! The main issue is that you are using the wrong contract and tx data in this example.

The transaction you are trying to decode is to PancakeSwap V3, but you are using the V2 router address (and ABI probably); also, the tx data looks different than the data in BSCscan.

Here is the code with the correct parameters:

Make sure to add the Router V3 ABI; I didn't put it here as it is very long.

Note that this code uses web3.py V6.

from web3 import Web3

# Initialize the Web3 instance
w3 = Web3(Web3.HTTPProvider('NODE_URL'))

# Define PancakeSwap Router contract address and ABI
pancake_router_address = '0x13f4EA83D0bd40E75C8222255bc855a974568Dd4'
pancake_abi = [ABI_V3_HERE]

# Set up the PancakeSwap Router contract
contract = w3.eth.contract(address=Web3.to_checksum_address(pancake_router_address), abi=pancake_abi)

# Transaction input (replace this with the actual input you want to decode)
transaction_input = "0x5ae401dc00000000000000000000000000000000000000000000000000000000644d9b0d000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000e4472b43f300000000000000000000000000000000000000000000a7e9b0f7650000450520000000000000000000000000000000000000000000000000026233275e989c16000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c841780c34c17190bceeefb6d986aaca4fb95e31000000000000000000000000bb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004449404b7c000000000000000000000000000000000000000000000000026233275e989c16000000000000000000000000d407934d50b917bb8eabe9c651d547b8a1de7def00000000000000000000000000000000000000000000000000000000"


# Decode the transaction input
function_signature, arguments = contract.decode_function_input(transaction_input)

# Print the decoded input
print("Arguments:")
for arg_name, arg_value in arguments.items():
    if isinstance(arg_value, list):
        hex_args = [arg.hex() for arg in arg_value]
        print(f"  {arg_name}: {hex_args}")
    else:
        print(f"  {arg_name}: {arg_value}")

# Iterate through the data elements
for i, data_element in enumerate(arguments["data"]):
    # Extract the function selector and arguments
    selector = data_element[:4]
    args_data = data_element[4:]
    
    # Decode the function input for this data element
    function_signature, args = contract.decode_function_input(selector + args_data)

    # Print the decoded input for this data element
    print(f"Data element {i + 1}:")
    print(f"  Function signature: {function_signature}")
    print("  Arguments:")
    for arg_name, arg_value in args.items():
        print(f"    {arg_name}: {arg_value}")
    print()

When you place the correct ABI, it will give you something like this as the output:

Arguments:
  deadline: 1682807565
  data: ['472b43f300000000000000000000000000000000000000000000a7e9b0f7650000450520000000000000000000000000000000000000000000000000026233275e989c16000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c841780c34c17190bceeefb6d986aaca4fb95e31000000000000000000000000bb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c', '49404b7c000000000000000000000000000000000000000000000000026233275e989c16000000000000000000000000d407934d50b917bb8eabe9c651d547b8a1de7def']
Data element 1:
  Function signature: <Function swapExactTokensForTokens(uint256,uint256,address[],address)>
  Arguments:
    amountIn: 792946045780325677991200
    amountOutMin: 171755979977301014
    path: ['0xc841780C34c17190bCEeeFb6d986aaCA4fb95e31', '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c']

Data element 2:
  Function signature: <Function unwrapWETH9(uint256,address)>
  Arguments:
    amountMinimum: 171755979977301014
    recipient: 0xD407934d50b917bB8EAbe9C651D547B8a1dE7DEf

You can see the amounts in and out used as parameters for the transaction.

To calculate the slippage, you need to get the actual amount out that the address received. In this example, it will look like this. Just note that the amount is hardcoded.

# Slippage
expected_amount_out = 171755979977301014
actual_amount_out = 172365853540100574

slippage_percentage = ((expected_amount_out - actual_amount_out) / expected_amount_out) * 100

print(f"Slippage percentage: {slippage_percentage:.2f}%")
2
  • Question: I did that, got the function exactInput, and with it a path like b"\xbbL\xdb\x9c\xbd6\xb0\x1b\xd1\xcb\xae\xbf-\xe0\x8d\x91s\xbc\t\\\x00\x01\xf4U\xd3\x982o\x99\x05\x9f\xf7uHRF\x99\x90'\xb3\x19yU". Any idea how to decode that please? Commented Dec 13, 2023 at 13:22
  • Hi, for some reason, it returned the response in bytes and not hex. What transaction_input did you use so I can try to reproduce it? You can decode it into hex using this in web3.py ``` # Decode the data decoded_data = Web3.to_hex(byte_data) print(decoded_data) ``` But you'll need some more processing to extract the addresses. Commented Dec 13, 2023 at 15:21
0

You should use contract.decode_function_input(transaction.input)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.