-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdecoding.py
88 lines (69 loc) · 2.32 KB
/
decoding.py
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
88
"""
High level utilities for script decoding and printing.
"""
from typing import Union, List
from brownie.utils import color
from .ABI.storage import CachedStorage
from .decode import decode_function_call
from .decode.structure import Call, FuncInput
from .exceptions import (
ParseStructureError, ABIEtherscanStatusCode, ABIEtherscanNetworkError
)
from .parse import parse_script
def decode_evm_script(
script: str,
abi_storage: CachedStorage
) -> List[Union[Call, str]]:
"""
Parse and decode EVM script.
"""
try:
parsed = parse_script(script)
except ParseStructureError as err:
return [repr(err)]
calls = []
for call in parsed.calls:
try:
call = decode_function_call(
call.address, call.method_id,
call.encoded_call_data, abi_storage
)
calls.append(call)
for inp in call.inputs:
if inp.type == 'bytes' and inp.name == '_evmScript':
inp.value = decode_evm_script(inp.value, abi_storage)
break
except (ABIEtherscanNetworkError, ABIEtherscanStatusCode) as err:
calls.append(f'Network layer error: {repr(err)}')
return calls
def _input_pretty_print(inp: FuncInput, tabs: int) -> str:
offset: str = ' ' * tabs
if isinstance(inp.value, list) and isinstance(inp.value[0], Call):
calls = '\n'.join(
_calls_info_pretty_print(call, tabs + 3)
for call in inp.value
)
return f'{offset}{inp.name}: {inp.type} = [\n{calls}\n]'
return f'{offset}{inp.name}: {inp.type} = {inp.value}'
def _calls_info_pretty_print(
call: Union[str, Call], tabs: int = 0
) -> str:
if isinstance(call, str):
return f'Decoding failed: {call}'
else:
inputs = '\n'.join([
_input_pretty_print(inp, tabs)
for inp in call.inputs
])
offset: str = ' ' * tabs
return (
f'{offset}Contract: {call.contract_address}\n'
f'{offset}Function: {call.function_name}\n'
f'{offset}Inputs:\n'
f'{inputs}'
)
def calls_info_pretty_print(
call: Union[str, Call]
) -> str:
"""Format printing for Call instance."""
return color.highlight(_calls_info_pretty_print(call))