You need to decode input params.
You can do this if you know ABI of the smart-contract address.
In your case it is not hard.
- Smart contract address:
0xEf1c6E67703c7BD7107eed8303Fbe6EC2554BF6B
- ABI (go to etherscan) to https://etherscan.io/address/0xEf1c6E67703c7BD7107eed8303Fbe6EC2554BF6B#code. Scroll down to 'Contract ABI' and copy it
- a little portion of code
In [1]: from web3 import Web3
In [2]: w3 = Web3(Web3.HTTPProvider('https://mainnet.infura.io/v3/<i use infura token>'))
In [3]: router_contract = w3.eth.contract(address='0xEf1c6E67703c7BD7107eed8303Fbe6EC2554BF6B', abi='<paste here abi>')
In [4]: input_params = '0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000
...: 0000000000000000000000000000006457ef7700000000000000000000000000000000000000000000000000000000000000020b0800000000000000000000000000000000000000000000000000000000000000000000000000
...: 00000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000
...: 0000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000de0b6
...: b3a764000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000
...: 0000000de0b6b3a7640000000000000000000000000000000000000000000066fe4797754b1ebfb5b5f3c600000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000
...: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000
...: 000000471a202f69d6e975da55e363dab1bdb2e86e0c0f'
In [5]: router_contract.decode_function_input(input_params)
Out[5]:
(<Function execute(bytes,bytes[],uint256)>,
{'commands': b'\x0b\x08',
'inputs': [b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r\xe0\xb6\xb3\xa7d\x00\x00',
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r\xe0\xb6\xb3\xa7d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xfeG\x97uK\x1e\xbf\xb5\xb5\xf3\xc6\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0*\xaa9\xb2#\xfe\x8d\n\x0e\\O'\xea\xd9\x08<ul\xc2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00G\x1a /i\xd6\xe9u\xdaU\xe3c\xda\xb1\xbd\xb2\xe8n\x0c\x0f"],
'deadline': 1683484535})
In [6]: next_params = router_contract.decode_function_input(input_params)[1]['inputs']
We are now understand that it is params to call an execute
method from universal router (https://blog.uniswap.org/permit2-and-universal-router).
Let's read more docs from github repo to understand what is command https://github.com/Uniswap/universal-router#how-the-command-byte-is-structured.
'commands': b'\x0b\x08'
means V2_SWAP_EXACT_IN. Input params for each command covered in docs https://docs.uniswap.org/contracts/universal-router/technical-reference#command. V2_SWAP_EXACT_IN accepts address
, uint256
, uint256
, address[]
, bool
as input parameters.
Let's take a look on next_params
content in hex.
In [7]: Web3.to_hex(next_params[0])
Out[7]: '0x00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000de0b6b3a7640000'
In [8]: Web3.to_hex(next_params[1])
Out[8]: '0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000066fe4797754b1ebfb5b5f3c600000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000471a202f69d6e975da55e363dab1bdb2e86e0c0f'
The second one looks prominent. Let's use eth_abi
to decode.
In [9]: from eth_abi import decode
In [10]: decode(['address', 'uint256', 'uint256', 'address[]', 'bool'], next_params[1])
Out[10]:
('0x0000000000000000000000000000000000000001',
1000000000000000000,
31874876241889834629682557894,
('0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
'0x471a202f69d6e975da55e363dab1bdb2e86e0c0f'),
False)
Voilà!
This transaction is an swap ecxact input value of Uniswap V2 liq pool.
Tokens:
Amounts:
About second input. Honestly, I don't find docs but running this gives at least understanding about input params structure.
In [48]: decode(['address', 'uint256'], next_params[0])
Out[48]: ('0x0000000000000000000000000000000000000002', 1000000000000000000)
Based on all list of commands from a full list: https://docs.uniswap.org/contracts/universal-router/technical-reference#wrap_eth
I bet that first command is the WRAP_ETH
.
Using WRAP_ETH
+ V2_SWAP_EXACT_IN
looks very logically when you sell ETH to Geke.