mirror of
https://github.com/FlipsideCrypto/web3.py.git
synced 2026-02-06 10:56:47 +00:00
Fix address[] return types
This commit is contained in:
parent
8d8b9dcd4a
commit
e11c87cd13
35
tests/contracts/test_normalization_of_return_types.py
Normal file
35
tests/contracts/test_normalization_of_return_types.py
Normal file
@ -0,0 +1,35 @@
|
||||
import pytest
|
||||
|
||||
from eth_abi import encode_single
|
||||
from web3.utils.abi import normalize_return_type
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'data_type,data_value,expected_value',
|
||||
(
|
||||
(
|
||||
'bytes32',
|
||||
'arst\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',
|
||||
'arst\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',
|
||||
),
|
||||
(
|
||||
'address',
|
||||
'd3cda913deb6f67967b99d67acdfa1712c293601',
|
||||
'0xd3cda913deb6f67967b99d67acdfa1712c293601',
|
||||
),
|
||||
(
|
||||
'address[]',
|
||||
[
|
||||
'd3cda913deb6f67967b99d67acdfa1712c293601',
|
||||
'bb9bc244d798123fde783fcc1c72d3bb8c189413',
|
||||
],
|
||||
[
|
||||
'0xd3cda913deb6f67967b99d67acdfa1712c293601',
|
||||
'0xbb9bc244d798123fde783fcc1c72d3bb8c189413',
|
||||
],
|
||||
),
|
||||
)
|
||||
)
|
||||
def test_normalizing_return_values(data_type, data_value, expected_value):
|
||||
actual_value = normalize_return_type(data_type, data_value)
|
||||
assert actual_value == expected_value
|
||||
@ -1,7 +1,7 @@
|
||||
import pytest
|
||||
|
||||
|
||||
from web3.utils.abi import (
|
||||
from web3.utils.events import (
|
||||
construct_event_data_set,
|
||||
)
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import pytest
|
||||
|
||||
|
||||
from web3.utils.abi import (
|
||||
from web3.utils.events import (
|
||||
construct_event_topic_set,
|
||||
)
|
||||
|
||||
|
||||
@ -35,6 +35,7 @@ from web3.utils.abi import (
|
||||
check_if_arguments_can_be_encoded,
|
||||
function_abi_to_4byte_selector,
|
||||
merge_args_and_kwargs,
|
||||
normalize_return_type,
|
||||
)
|
||||
from web3.utils.decorators import (
|
||||
combomethod,
|
||||
@ -642,10 +643,11 @@ def call_contract_function(contract,
|
||||
output_data = decode_abi(output_types, return_data)
|
||||
|
||||
normalized_data = [
|
||||
add_0x_prefix(data_value) if data_type == 'address' else data_value
|
||||
normalize_return_type(data_type, data_value)
|
||||
for data_type, data_value
|
||||
in zip(output_types, output_data)
|
||||
]
|
||||
|
||||
if len(normalized_data) == 1:
|
||||
return normalized_data[0]
|
||||
else:
|
||||
|
||||
@ -2,10 +2,8 @@ import itertools
|
||||
|
||||
from eth_abi.abi import (
|
||||
process_type,
|
||||
encode_single,
|
||||
)
|
||||
|
||||
from .encoding import encode_hex
|
||||
from .crypto import sha3
|
||||
from .string import (
|
||||
coerce_args_to_bytes,
|
||||
@ -226,85 +224,16 @@ def event_abi_to_log_topic(event_abi):
|
||||
|
||||
|
||||
@coerce_return_to_text
|
||||
def construct_event_topic_set(event_abi, arguments=None):
|
||||
if arguments is None:
|
||||
arguments = {}
|
||||
if isinstance(arguments, (list, tuple)):
|
||||
if len(arguments) != len(event_abi['inputs']):
|
||||
raise ValueError(
|
||||
"When passing an argument list, the number of arguments must "
|
||||
"match the event constructor."
|
||||
)
|
||||
arguments = {
|
||||
arg['name']: [arg_value]
|
||||
for arg, arg_value
|
||||
in zip(event_abi['inputs'], arguments)
|
||||
}
|
||||
def normalize_return_type(data_type, data_value):
|
||||
try:
|
||||
base, sub, arrlist = data_type
|
||||
except ValueError:
|
||||
base, sub, arrlist = process_type(data_type)
|
||||
|
||||
normalized_args = {
|
||||
key: value if is_array(value) else [value]
|
||||
for key, value in arguments.items()
|
||||
}
|
||||
|
||||
event_topic = event_abi_to_log_topic(event_abi)
|
||||
indexed_args = get_indexed_event_inputs(event_abi)
|
||||
zipped_abi_and_args = [
|
||||
(arg, normalized_args.get(arg['name'], [None]))
|
||||
for arg in indexed_args
|
||||
]
|
||||
encoded_args = [
|
||||
[
|
||||
None if option is None else encode_hex(encode_single(arg['type'], option))
|
||||
for option in arg_options]
|
||||
for arg, arg_options in zipped_abi_and_args
|
||||
]
|
||||
|
||||
topics = [
|
||||
[event_topic] + list(permutation)
|
||||
if any(value is not None for value in permutation)
|
||||
else [event_topic]
|
||||
for permutation in itertools.product(*encoded_args)
|
||||
]
|
||||
return topics
|
||||
|
||||
|
||||
@coerce_return_to_text
|
||||
def construct_event_data_set(event_abi, arguments=None):
|
||||
if arguments is None:
|
||||
arguments = {}
|
||||
if isinstance(arguments, (list, tuple)):
|
||||
if len(arguments) != len(event_abi['inputs']):
|
||||
raise ValueError(
|
||||
"When passing an argument list, the number of arguments must "
|
||||
"match the event constructor."
|
||||
)
|
||||
arguments = {
|
||||
arg['name']: [arg_value]
|
||||
for arg, arg_value
|
||||
in zip(event_abi['inputs'], arguments)
|
||||
}
|
||||
|
||||
normalized_args = {
|
||||
key: value if is_array(value) else [value]
|
||||
for key, value in arguments.items()
|
||||
}
|
||||
|
||||
indexed_args = exclude_indexed_event_inputs(event_abi)
|
||||
zipped_abi_and_args = [
|
||||
(arg, normalized_args.get(arg['name'], [None]))
|
||||
for arg in indexed_args
|
||||
]
|
||||
encoded_args = [
|
||||
[
|
||||
None if option is None else encode_hex(encode_single(arg['type'], option))
|
||||
for option in arg_options]
|
||||
for arg, arg_options in zipped_abi_and_args
|
||||
]
|
||||
|
||||
topics = [
|
||||
list(permutation)
|
||||
if any(value is not None for value in permutation)
|
||||
else []
|
||||
for permutation in itertools.product(*encoded_args)
|
||||
]
|
||||
return topics
|
||||
if arrlist:
|
||||
sub_type = (base, sub, arrlist[:-1])
|
||||
return [normalize_return_type(sub_type, sub_value) for sub_value in data_value]
|
||||
elif base == 'address':
|
||||
return add_0x_prefix(data_value)
|
||||
else:
|
||||
return data_value
|
||||
|
||||
@ -3,17 +3,108 @@ import itertools
|
||||
from eth_abi import (
|
||||
decode_abi,
|
||||
decode_single,
|
||||
encode_single,
|
||||
)
|
||||
|
||||
from .encoding import encode_hex
|
||||
from .types import (
|
||||
is_array,
|
||||
)
|
||||
from .string import (
|
||||
coerce_return_to_text,
|
||||
)
|
||||
from .abi import (
|
||||
get_abi_input_types,
|
||||
get_abi_input_names,
|
||||
get_indexed_event_inputs,
|
||||
exclude_indexed_event_inputs,
|
||||
event_abi_to_log_topic,
|
||||
)
|
||||
|
||||
|
||||
ABI_EVENT_TYPE_MAP = {
|
||||
}
|
||||
@coerce_return_to_text
|
||||
def construct_event_topic_set(event_abi, arguments=None):
|
||||
if arguments is None:
|
||||
arguments = {}
|
||||
if isinstance(arguments, (list, tuple)):
|
||||
if len(arguments) != len(event_abi['inputs']):
|
||||
raise ValueError(
|
||||
"When passing an argument list, the number of arguments must "
|
||||
"match the event constructor."
|
||||
)
|
||||
arguments = {
|
||||
arg['name']: [arg_value]
|
||||
for arg, arg_value
|
||||
in zip(event_abi['inputs'], arguments)
|
||||
}
|
||||
|
||||
normalized_args = {
|
||||
key: value if is_array(value) else [value]
|
||||
for key, value in arguments.items()
|
||||
}
|
||||
|
||||
event_topic = event_abi_to_log_topic(event_abi)
|
||||
indexed_args = get_indexed_event_inputs(event_abi)
|
||||
zipped_abi_and_args = [
|
||||
(arg, normalized_args.get(arg['name'], [None]))
|
||||
for arg in indexed_args
|
||||
]
|
||||
encoded_args = [
|
||||
[
|
||||
None if option is None else encode_hex(encode_single(arg['type'], option))
|
||||
for option in arg_options]
|
||||
for arg, arg_options in zipped_abi_and_args
|
||||
]
|
||||
|
||||
topics = [
|
||||
[event_topic] + list(permutation)
|
||||
if any(value is not None for value in permutation)
|
||||
else [event_topic]
|
||||
for permutation in itertools.product(*encoded_args)
|
||||
]
|
||||
return topics
|
||||
|
||||
|
||||
@coerce_return_to_text
|
||||
def construct_event_data_set(event_abi, arguments=None):
|
||||
if arguments is None:
|
||||
arguments = {}
|
||||
if isinstance(arguments, (list, tuple)):
|
||||
if len(arguments) != len(event_abi['inputs']):
|
||||
raise ValueError(
|
||||
"When passing an argument list, the number of arguments must "
|
||||
"match the event constructor."
|
||||
)
|
||||
arguments = {
|
||||
arg['name']: [arg_value]
|
||||
for arg, arg_value
|
||||
in zip(event_abi['inputs'], arguments)
|
||||
}
|
||||
|
||||
normalized_args = {
|
||||
key: value if is_array(value) else [value]
|
||||
for key, value in arguments.items()
|
||||
}
|
||||
|
||||
indexed_args = exclude_indexed_event_inputs(event_abi)
|
||||
zipped_abi_and_args = [
|
||||
(arg, normalized_args.get(arg['name'], [None]))
|
||||
for arg in indexed_args
|
||||
]
|
||||
encoded_args = [
|
||||
[
|
||||
None if option is None else encode_hex(encode_single(arg['type'], option))
|
||||
for option in arg_options]
|
||||
for arg, arg_options in zipped_abi_and_args
|
||||
]
|
||||
|
||||
topics = [
|
||||
list(permutation)
|
||||
if any(value is not None for value in permutation)
|
||||
else []
|
||||
for permutation in itertools.product(*encoded_args)
|
||||
]
|
||||
return topics
|
||||
|
||||
|
||||
def coerce_event_abi_types_for_decoding(input_types):
|
||||
|
||||
@ -6,7 +6,7 @@ from .types import (
|
||||
is_string,
|
||||
is_array,
|
||||
)
|
||||
from .abi import (
|
||||
from .events import (
|
||||
construct_event_topic_set,
|
||||
construct_event_data_set,
|
||||
)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user