Skip to content

Commit 0f26553

Browse files
committed
Address PR feedback
1 parent 91de585 commit 0f26553

File tree

7 files changed

+62
-29
lines changed

7 files changed

+62
-29
lines changed

docs/contracts.rst

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -523,10 +523,11 @@ The following values will raise an error by default:
523523
524524
However, you may want to be stricter with acceptable values for bytes types.
525525
For this you can use the ``enable_strict_bytes_type_checking`` method,
526-
which is available on the w3 instance. When the method is called, a new codec is
527-
instatntiated and any string that is not prefixed with
528-
``0x`` will throw an error. Similarly, a bytestring that is less than the
529-
specified byte size will raise an error. Using the same ``bytes4`` example:
526+
which is available on the web3 instance. A web3 instance which has had this method
527+
invoked will enforce a stricter set of rules on which values are accepted.
528+
Any string that is not prefixed with ``0x`` will throw an error.
529+
Similarly, a bytestring that is less than the specified byte size
530+
will raise an error. Using the same ``bytes4`` example:
530531

531532
.. code-block:: python
532533

tests/core/contracts/test_contract_call_interface.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
import pytest
1010

1111
import eth_abi
12+
from eth_utils import (
13+
is_text,
14+
)
1215
from eth_utils.toolz import (
1316
identity,
1417
)
@@ -99,7 +102,13 @@ def address_contract(web3, WithConstructorAddressArgumentsContract, address_conv
99102

100103
@pytest.fixture(params=[b'\x04\x06', '0x0406', '0406'])
101104
def bytes_contract(web3, BytesContract, request, address_conversion_func):
102-
return deploy(web3, BytesContract, address_conversion_func, args=[request.param])
105+
if is_text(request.param) and request.param[:2] != '0x':
106+
with pytest.warns(
107+
DeprecationWarning,
108+
match='in v6 it will be invalid to pass a hexstring without the "0x" prefix'):
109+
return deploy(web3, BytesContract, address_conversion_func, args=[request.param])
110+
else:
111+
return deploy(web3, BytesContract, address_conversion_func, args=[request.param])
103112

104113

105114
@pytest.fixture()
@@ -126,8 +135,11 @@ def call_transaction():
126135
HexBytes('0406040604060406040604060406040604060406040604060406040604060406'),
127136
])
128137
def bytes32_contract(web3, Bytes32Contract, request, address_conversion_func):
129-
return deploy(web3, Bytes32Contract, address_conversion_func, args=[request.param])
130-
138+
if is_text(request.param) and request.param[:2] != '0x':
139+
with pytest.warns(DeprecationWarning):
140+
return deploy(web3, Bytes32Contract, address_conversion_func, args=[request.param])
141+
else:
142+
return deploy(web3, Bytes32Contract, address_conversion_func, args=[request.param])
131143

132144
@pytest.fixture()
133145
def undeployed_math_contract(web3, MathContract, address_conversion_func):

tests/core/contracts/test_extracting_event_data.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import pytest
22
import re
33

4-
from eth_abi.utils.padding import (
5-
zpad_right,
6-
)
74
from eth_utils import (
85
is_same_address,
96
)
@@ -407,7 +404,8 @@ def test_argument_extraction_strict_bytes_types(web3_strict_types,
407404
assert event_topic in log_entry['topics']
408405

409406
encoded_arg_0 = web3_strict_types.codec.encode_abi(['bytes2'], arg_0)
410-
arg_0_topic = web3_strict_types.keccak(zpad_right(encoded_arg_0, 32))
407+
padded_arg_0 = encoded_arg_0.ljust(32, b'\x00')
408+
arg_0_topic = web3_strict_types.keccak(padded_arg_0)
411409
assert arg_0_topic in log_entry['topics']
412410

413411
event_data = get_event_data(web3_strict_types.codec, event_abi, log_entry)

tests/core/utilities/test_abi_is_encodable.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,13 @@
4040
('rejects_invalid_names.eth', 'address', False), # no underscore in domain names
4141
4242
# Special bytes<M> behavior
43-
('12', 'bytes2', True), # undersize OK
4443
('0x12', 'bytes2', True), # with or without 0x OK
45-
('0123', 'bytes2', True), # exact size OK
4644
(b'\x12', 'bytes2', True), # as bytes value undersize OK
4745
('0123', 'bytes1', False), # no oversize hex strings
4846
('1', 'bytes2', False), # no odd length
4947
('0x1', 'bytes2', False), # no odd length
5048
5149
# Special bytes behavior
52-
('12', 'bytes', True),
5350
('0x12', 'bytes', True),
5451
('1', 'bytes', False),
5552
('0x1', 'bytes', False),
@@ -75,10 +72,29 @@
7572
)
7673
def test_is_encodable(value, _type, expected):
7774
w3 = Web3(EthereumTesterProvider())
78-
actual = w3.codec.is_encodable(_type, value)
75+
actual = w3.is_encodable(_type, value)
7976
assert actual is expected
8077

8178

79+
@pytest.mark.parametrize(
80+
'value,_type,expected',
81+
(
82+
('12', 'bytes2', True),
83+
('0123', 'bytes2', True),
84+
85+
('12', 'bytes', True),
86+
)
87+
)
88+
def test_is_encodable_warnings(value, _type, expected):
89+
w3 = Web3(EthereumTesterProvider())
90+
with pytest.warns(
91+
DeprecationWarning,
92+
match='in v6 it will be invalid to pass a hexstring without the "0x" prefix'
93+
):
94+
actual = w3.is_encodable(_type, value)
95+
assert actual is expected
96+
97+
8298
@pytest.mark.parametrize(
8399
'value,_type,expected',
84100
(
@@ -96,6 +112,7 @@ def test_is_encodable(value, _type, expected):
96112
('0x12', 'bytes', True),
97113
('1', 'bytes', False),
98114
('0x1', 'bytes', False),
115+
('0x0x0x0x', 'bytes', False),
99116
100117
# Special string behavior
101118
(b'', 'string', True),
@@ -107,5 +124,5 @@ def test_is_encodable_strict(value, _type, expected):
107124
w3 = Web3(EthereumTesterProvider())
108125
w3.enable_strict_bytes_type_checking()
109126

110-
actual = w3.codec.is_encodable(_type, value)
127+
actual = w3.is_encodable(_type, value)
111128
assert actual is expected

web3/_utils/abi.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,7 @@ def validate_value(cls, value):
151151

152152
class AcceptsHexStrMixin:
153153
def validate_value(self, value):
154-
if is_text(value) and value[:2] != '0x':
155-
warnings.warn(
156-
'in v6 it will be invalid to pass a hexstring without the "0x" prefix',
157-
category=DeprecationWarning
158-
)
154+
original_value = value
159155
if is_text(value):
160156
try:
161157
value = decode_hex(value)
@@ -164,6 +160,12 @@ def validate_value(self, value):
164160
value,
165161
msg=f'{value} is an invalid hex string',
166162
)
163+
else:
164+
if original_value[:2] != '0x':
165+
warnings.warn(
166+
'in v6 it will be invalid to pass a hexstring without the "0x" prefix',
167+
category=DeprecationWarning
168+
)
167169

168170
super().validate_value(value)
169171

@@ -184,8 +186,6 @@ def validate_value(self, value):
184186
msg=f'{value} is an invalid hex string',
185187
)
186188

187-
super().validate_value(value)
188-
189189

190190
class BytesEncoder(AcceptsHexStrMixin, encoding.BytesEncoder):
191191
pass
@@ -250,14 +250,10 @@ def encode(self, value):
250250
return self.encode_fn(value)
251251

252252
def validate_value(self, value):
253+
original_value = value
253254
if not is_bytes(value) and not is_text(value):
254255
self.invalidate_value(value)
255256

256-
if is_text(value) and value[:2] != '0x':
257-
self.invalidate_value(
258-
value,
259-
msg='hex string must be prefixed with 0x'
260-
)
261257
elif is_text(value):
262258
try:
263259
value = decode_hex(value)
@@ -266,6 +262,12 @@ def validate_value(self, value):
266262
value,
267263
msg='invalid hex string',
268264
)
265+
else:
266+
if original_value[:2] != '0x':
267+
self.invalidate_value(
268+
original_value,
269+
msg='hex string must be prefixed with 0x'
270+
)
269271

270272
byte_size = self.value_bit_size // 8
271273
if len(value) > byte_size:

web3/_utils/filters.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ def match_fn(w3, match_values_and_abi, data):
215215
continue
216216
normalized_data = normalize_data_values(abi_type, data_value)
217217
for value in match_values:
218-
if not w3.codec.is_encodable(abi_type, value):
218+
if not w3.is_encodable(abi_type, value):
219219
raise ValueError(
220220
f"Value {value} is of the wrong abi type. "
221221
f"Expected {abi_type} typed value."

web3/main.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,9 @@ def solidityKeccak(cls, abi_types, values):
226226
def isConnected(self):
227227
return self.provider.isConnected()
228228

229+
def is_encodable(self, _type, value):
230+
return self.codec.is_encodable(_type, value)
231+
229232
@property
230233
def ens(self):
231234
if self._ens is empty:

0 commit comments

Comments
 (0)