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}%")