Skip to content

Commit

Permalink
Look up ENS names in soliditySha3 'address' values
Browse files Browse the repository at this point in the history
  • Loading branch information
carver committed Nov 17, 2017
1 parent eaad747 commit 0066634
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 5 deletions.
19 changes: 17 additions & 2 deletions web3/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,25 @@
RequestManager,
)

from web3.utils.abi import (
map_abi_data,
)
from web3.utils.datastructures import (
HexBytes,
)
from web3.utils.decorators import (
combomethod,
)
from web3.utils.encoding import (
hex_encode_abi_type,
to_bytes,
to_int,
to_hex,
to_text,
)
from web3.utils.normalizers import (
abi_ens_resolver,
)

default = object()

Expand Down Expand Up @@ -132,7 +141,7 @@ def sha3(primitive=None, text=None, hexstr=None):
)
)

@classmethod
@combomethod
def soliditySha3(cls, abi_types, values):
"""
Executes sha3 (keccak256) exactly as Solidity does.
Expand All @@ -145,10 +154,16 @@ def soliditySha3(cls, abi_types, values):
"{0} types and {1} values.".format(len(abi_types), len(values))
)

if isinstance(cls, type):
w3 = None
else:
w3 = cls
normalized_values = map_abi_data([abi_ens_resolver(w3)], abi_types, values)

hex_string = add_0x_prefix(''.join(
remove_0x_prefix(hex_encode_abi_type(abi_type, value))
for abi_type, value
in zip(abi_types, values)
in zip(abi_types, normalized_values)
))
return cls.sha3(hexstr=hex_string)

Expand Down
32 changes: 31 additions & 1 deletion web3/utils/module_testing/web3_module.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import pytest

from web3 import Web3

from web3.exceptions import (
InvalidAddress,
)

from web3.utils.datastructures import HexBytes
from web3.utils.ens import ens_addresses


class Web3ModuleTest(object):
Expand Down Expand Up @@ -83,7 +86,6 @@ def _check_web3_clientVersion(self, client_version):
],
HexBytes("0xd78a84d65721b67e4011b10c99dafdedcdcd7cb30153064f773e210b4762e22f"),
),
(
['string'],
['testing a string!'],
Expand Down Expand Up @@ -168,6 +170,34 @@ def test_soliditySha3(self, web3, types, values, expected):
actual = web3.soliditySha3(types, values)
assert actual == expected

@pytest.mark.parametrize(
'types, values, expected',
(
(
['address'],
['one.eth'],
HexBytes("0x2ff37b5607484cd4eecf6d13292e22bd6e5401eaffcc07e279583bc742c68882"),
),
(
['address[]'],
[['one.eth', 'two.eth']],
HexBytes("0xb98565c0c26a962fd54d93b0ed6fb9296e03e9da29d2281ed3e3473109ef7dde"),
),
),
)
def test_soliditySha3_ens(self, web3, types, values, expected):
with ens_addresses(web3, {
'one.eth': "0x49EdDD3769c0712032808D86597B84ac5c2F5614",
'two.eth': "0xA6b759bBbf4B59D24acf7E06e79f3a5D104fdCE5",
}):
# when called as class method, any name lookup attempt will fail
with pytest.raises(InvalidAddress):
Web3.soliditySha3(types, values)

# when called as instance method method, ens lookups can succeed
actual = web3.soliditySha3(types, values)
assert actual == expected

@pytest.mark.parametrize(
'types,values',
(
Expand Down
7 changes: 5 additions & 2 deletions web3/utils/normalizers.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
to_checksum_address,
)

from web3.exceptions import (
InvalidAddress,
)
from web3.utils.encoding import (
hexstr_if_str,
text_if_str,
Expand Down Expand Up @@ -108,9 +111,9 @@ def abi_address_to_hex(abi_type, data):
def abi_ens_resolver(w3, abi_type, val):
if abi_type == 'address' and is_ens_name(val):
if w3 is None:
raise ValueError("Could not look up name, because no web3 connection available")
raise InvalidAddress("Could not look up name, because no web3 connection available")
elif w3.ens is None:
raise ValueError("Could not look up name, because ENS is set to None")
raise InvalidAddress("Could not look up name, because ENS is set to None")
else:
return (abi_type, validate_name_has_address(w3.ens, val))
else:
Expand Down

0 comments on commit 0066634

Please sign in to comment.