-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathaction.py
More file actions
87 lines (69 loc) · 2.44 KB
/
action.py
File metadata and controls
87 lines (69 loc) · 2.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
"""
Decoding functions callings to human-readable format.
"""
import web3
from typing import Union, Tuple, Optional
from ..script_specification import HEX_PREFIX
from .structure import Call, FuncInput
from evmscript_parser.core.ABI.storage import (
CachedStorage, ABI, ABIKey
)
# ============================================================================
# ================================= Decoding =================================
# ============================================================================
_CacheT = CachedStorage[Union[ABIKey, Tuple[ABIKey, ABIKey]], ABI]
def decode_function_call(
contract_address: str, function_signature: str,
call_data: str, abi_storage: _CacheT
) -> Optional[Call]:
"""
Decode function call.
:param contract_address: str, contract address.
:param function_signature: str, the first fourth bytes
of function signature
:param call_data: str, encoded call data.
:param abi_storage: CachedStorage, storage of contracts ABI.
:return: Call, decoded description of function calling.
"""
key = ABIKey(contract_address, function_signature)
abi = abi_storage[key]
function_description = abi.func_storage.get(function_signature, None)
if function_description is None:
return function_description
address = web3.Web3.toChecksumAddress(contract_address)
contract = web3.Web3().eth.contract(
address=address, abi=abi.raw
)
inputs_spec = function_description['inputs']
if call_data.startswith(HEX_PREFIX):
call_data = call_data[len(HEX_PREFIX):]
_, decoded_inputs = contract.decode_function_input(
f'{function_signature}{call_data}'
)
inputs = [
FuncInput(
inp['name'],
inp['type'],
decoded_inputs[inp['name']]
)
for inp in inputs_spec
]
properties = {
'constant': function_description.get(
'constant', 'unknown'
),
'payable': function_description.get(
'payable', 'unknown'
),
'stateMutability': function_description.get(
'stateMutability', 'unknown'
),
'type': function_description.get(
'type', 'unknown'
)
}
return Call(
contract_address, function_signature,
function_description.get('name', 'unknown'), inputs,
properties, function_description['outputs']
)