diff --git a/docs/conventions.rst b/docs/conventions.rst index de9d68d13e..08c204ae66 100644 --- a/docs/conventions.rst +++ b/docs/conventions.rst @@ -18,8 +18,9 @@ Hexadecimal Representations Addresses --------- -All addresses must be supplied in one of two ways: +All addresses must be supplied in one of three ways: +* While connected to mainnet, an Ethereum Name Service name (often in the form ``myname.eth``) * A 20-byte hexadecimal that is checksummed using the `EIP-55 `_ spec. -* While connected to mainnet, an Ethereum Name Service name (often in the form ``myname.eth``) +* A 20-byte binary address. diff --git a/ens/main.py b/ens/main.py index 0c3cfc00b7..da2b742633 100644 --- a/ens/main.py +++ b/ens/main.py @@ -1,5 +1,6 @@ from eth_utils import ( + is_binary_address, is_checksum_address, to_checksum_address, ) @@ -122,6 +123,8 @@ def setup_address(self, name, address=default, transact={}): address = None elif address is default: address = owner + elif is_binary_address(address): + address = to_checksum_address(address) elif not is_checksum_address(address): raise ValueError("You must supply the address in checksum format") if self.address(name) == address: @@ -166,6 +169,8 @@ def setup_name(self, name, address=None, transact={}): address = self.owner(name) if not address: raise UnownedName("claim subdomain using setup_address() first") + if is_binary_address(address): + address = to_checksum_address(address) if not is_checksum_address(address): raise ValueError("You must supply the address in checksum format") self._assert_control(address, name) diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000000..7cf42a0d00 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,14 @@ +import pytest + +from eth_utils import ( + to_bytes, +) + +from web3.utils.toolz import ( + identity, +) + + +@pytest.fixture(scope="module", params=[lambda x: to_bytes(hexstr=x), identity]) +def address_conversion_func(request): + return request.param diff --git a/tests/core/contracts/conftest.py b/tests/core/contracts/conftest.py index 24b0c6b455..e407afd910 100644 --- a/tests/core/contracts/conftest.py +++ b/tests/core/contracts/conftest.py @@ -292,17 +292,19 @@ def Emitter(web3_empty, EMITTER): @pytest.fixture() -def emitter(web3_empty, Emitter, wait_for_transaction, wait_for_block): +def emitter(web3_empty, Emitter, wait_for_transaction, wait_for_block, address_conversion_func): web3 = web3_empty wait_for_block(web3) deploy_txn_hash = Emitter.constructor().transact({'from': web3.eth.coinbase, 'gas': 1000000}) deploy_receipt = wait_for_transaction(web3, deploy_txn_hash) - contract_address = deploy_receipt['contractAddress'] + contract_address = address_conversion_func(deploy_receipt['contractAddress']) bytecode = web3.eth.getCode(contract_address) assert bytecode == Emitter.bytecode_runtime - return Emitter(address=contract_address) + emitter_contract = Emitter(address=contract_address) + assert emitter_contract.address == contract_address + return emitter_contract CONTRACT_ARRAYS_SOURCE = """ @@ -527,8 +529,8 @@ def emitter_log_topics(): @pytest.fixture() -def some_address(): - return '0x5B2063246F2191f18F2675ceDB8b28102e957458' +def some_address(address_conversion_func): + return address_conversion_func('0x5B2063246F2191f18F2675ceDB8b28102e957458') def invoke_contract(api_style=None, diff --git a/tests/core/contracts/test_concise_contract.py b/tests/core/contracts/test_concise_contract.py index 7db0d5ca1b..982d36d731 100644 --- a/tests/core/contracts/test_concise_contract.py +++ b/tests/core/contracts/test_concise_contract.py @@ -25,8 +25,9 @@ def deploy(web3, Contract, args=None): @pytest.fixture() -def EMPTY_ADDR(): - return '0x' + '00' * 20 +def EMPTY_ADDR(address_conversion_func): + addr = '0x' + '00' * 20 + return address_conversion_func(addr) @pytest.fixture() diff --git a/tests/core/contracts/test_contract_ambiguous_functions.py b/tests/core/contracts/test_contract_ambiguous_functions.py index e97e3433aa..d7ab9c8d42 100644 --- a/tests/core/contracts/test_contract_ambiguous_functions.py +++ b/tests/core/contracts/test_contract_ambiguous_functions.py @@ -41,11 +41,13 @@ @pytest.fixture() -def string_contract(web3, StringContract): +def string_contract(web3, StringContract, address_conversion_func): deploy_txn = StringContract.constructor("Caqalai").transact() deploy_receipt = web3.eth.waitForTransactionReceipt(deploy_txn) assert deploy_receipt is not None - contract = StringContract(address=deploy_receipt['contractAddress']) + contract_address = address_conversion_func(deploy_receipt['contractAddress']) + contract = StringContract(address=contract_address) + assert contract.address == contract_address assert len(web3.eth.getCode(contract.address)) > 0 return contract diff --git a/tests/core/contracts/test_contract_buildTransaction.py b/tests/core/contracts/test_contract_buildTransaction.py index 640e72880c..6707399ff7 100644 --- a/tests/core/contracts/test_contract_buildTransaction.py +++ b/tests/core/contracts/test_contract_buildTransaction.py @@ -11,20 +11,24 @@ @pytest.fixture() -def math_contract(web3, MathContract): +def math_contract(web3, MathContract, address_conversion_func): deploy_txn = MathContract.constructor().transact() deploy_receipt = web3.eth.waitForTransactionReceipt(deploy_txn) assert deploy_receipt is not None - _math_contract = MathContract(address=deploy_receipt['contractAddress']) + math_contract_address = address_conversion_func(deploy_receipt['contractAddress']) + _math_contract = MathContract(address=math_contract_address) + assert _math_contract.address == math_contract_address return _math_contract @pytest.fixture() -def fallback_function_contract(web3, FallballFunctionContract): +def fallback_function_contract(web3, FallballFunctionContract, address_conversion_func): deploy_txn = FallballFunctionContract.constructor().transact() deploy_receipt = web3.eth.waitForTransactionReceipt(deploy_txn) assert deploy_receipt is not None - _fallback_contract = FallballFunctionContract(address=deploy_receipt['contractAddress']) + fallback_contract_address = address_conversion_func(deploy_receipt['contractAddress']) + _fallback_contract = FallballFunctionContract(address=fallback_contract_address) + assert _fallback_contract.address == fallback_contract_address return _fallback_contract diff --git a/tests/core/contracts/test_contract_call_interface.py b/tests/core/contracts/test_contract_call_interface.py index 295145c5e5..8a567f3253 100644 --- a/tests/core/contracts/test_contract_call_interface.py +++ b/tests/core/contracts/test_contract_call_interface.py @@ -20,62 +20,70 @@ from web3.utils.ens import ( contract_ens_addresses, ) +from web3.utils.toolz import ( + identity, +) # Ignore warning in pyethereum 1.6 - will go away with the upgrade pytestmark = pytest.mark.filterwarnings("ignore:implicit cast from 'char *'") -def deploy(web3, Contract, args=None): +def deploy(web3, Contract, apply_func=identity, args=None): args = args or [] deploy_txn = Contract.constructor(*args).transact() deploy_receipt = web3.eth.waitForTransactionReceipt(deploy_txn) assert deploy_receipt is not None - contract = Contract(address=deploy_receipt['contractAddress']) + address = apply_func(deploy_receipt['contractAddress']) + contract = Contract(address=address) + assert contract.address == address assert len(web3.eth.getCode(contract.address)) > 0 return contract @pytest.fixture() -def address_reflector_contract(web3, AddressReflectorContract): - return deploy(web3, AddressReflectorContract) +def address_reflector_contract(web3, AddressReflectorContract, address_conversion_func): + return deploy(web3, AddressReflectorContract, address_conversion_func) @pytest.fixture() -def math_contract(web3, MathContract): - return deploy(web3, MathContract) +def math_contract(web3, MathContract, address_conversion_func): + return deploy(web3, MathContract, address_conversion_func) @pytest.fixture() -def string_contract(web3, StringContract): - return deploy(web3, StringContract, args=["Caqalai"]) +def string_contract(web3, StringContract, address_conversion_func): + return deploy(web3, StringContract, address_conversion_func, args=["Caqalai"]) @pytest.fixture() -def arrays_contract(web3, ArraysContract): +def arrays_contract(web3, ArraysContract, address_conversion_func): # bytes_32 = [keccak('0'), keccak('1')] bytes32_array = [ b'\x04HR\xb2\xa6p\xad\xe5@~x\xfb(c\xc5\x1d\xe9\xfc\xb9eB\xa0q\x86\xfe:\xed\xa6\xbb\x8a\x11m', # noqa: E501 b'\xc8\x9e\xfd\xaaT\xc0\xf2\x0cz\xdfa(\x82\xdf\tP\xf5\xa9Qc~\x03\x07\xcd\xcbLg/)\x8b\x8b\xc6', # noqa: E501 ] byte_arr = [b'\xff', b'\xff', b'\xff', b'\xff'] - return deploy(web3, ArraysContract, args=[bytes32_array, byte_arr]) + return deploy(web3, ArraysContract, address_conversion_func, args=[bytes32_array, byte_arr]) @pytest.fixture() -def address_contract(web3, WithConstructorAddressArgumentsContract): - return deploy(web3, WithConstructorAddressArgumentsContract, args=[ - "0xd3CdA913deB6f67967B99D67aCDFa1712C293601", - ]) +def address_contract(web3, WithConstructorAddressArgumentsContract, address_conversion_func): + return deploy( + web3, + WithConstructorAddressArgumentsContract, + address_conversion_func, + args=["0xd3CdA913deB6f67967B99D67aCDFa1712C293601"] + ) @pytest.fixture(params=[b'\x04\x06', '0x0406', '0406']) -def bytes_contract(web3, BytesContract, request): - return deploy(web3, BytesContract, args=[request.param]) +def bytes_contract(web3, BytesContract, request, address_conversion_func): + return deploy(web3, BytesContract, address_conversion_func, args=[request.param]) @pytest.fixture() -def fixed_reflection_contract(web3, FixedReflectionContract): - return deploy(web3, FixedReflectionContract) +def fixed_reflection_contract(web3, FixedReflectionContract, address_conversion_func): + return deploy(web3, FixedReflectionContract, address_conversion_func) @pytest.fixture() @@ -91,30 +99,30 @@ def call_transaction(): '0406040604060406040604060406040604060406040604060406040604060406', HexBytes('0406040604060406040604060406040604060406040604060406040604060406'), ]) -def bytes32_contract(web3, Bytes32Contract, request): - return deploy(web3, Bytes32Contract, args=[request.param]) +def bytes32_contract(web3, Bytes32Contract, request, address_conversion_func): + return deploy(web3, Bytes32Contract, address_conversion_func, args=[request.param]) @pytest.fixture() -def undeployed_math_contract(web3, MathContract): - empty_address = "0x000000000000000000000000000000000000dEaD" +def undeployed_math_contract(web3, MathContract, address_conversion_func): + empty_address = address_conversion_func("0x000000000000000000000000000000000000dEaD") _undeployed_math_contract = MathContract(address=empty_address) return _undeployed_math_contract @pytest.fixture() -def mismatched_math_contract(web3, StringContract, MathContract): +def mismatched_math_contract(web3, StringContract, MathContract, address_conversion_func): deploy_txn = StringContract.constructor("Caqalai").transact() deploy_receipt = web3.eth.waitForTransactionReceipt(deploy_txn) assert deploy_receipt is not None - - _mismatched_math_contract = MathContract(address=deploy_receipt['contractAddress']) + address = address_conversion_func(deploy_receipt['contractAddress']) + _mismatched_math_contract = MathContract(address=address) return _mismatched_math_contract @pytest.fixture() -def fallback_function_contract(web3, FallballFunctionContract): - return deploy(web3, FallballFunctionContract) +def fallback_function_contract(web3, FallballFunctionContract, address_conversion_func): + return deploy(web3, FallballFunctionContract, address_conversion_func) def test_invalid_address_in_deploy_arg(web3, WithConstructorAddressArgumentsContract): diff --git a/tests/core/contracts/test_contract_constructor.py b/tests/core/contracts/test_contract_constructor.py index 1c3b11e76c..62995de406 100644 --- a/tests/core/contracts/test_contract_constructor.py +++ b/tests/core/contracts/test_contract_constructor.py @@ -64,40 +64,48 @@ def test_contract_constructor_gas_estimate_with_constructor_with_arguments( def test_contract_constructor_gas_estimate_with_constructor_with_address_argument( web3, - WithConstructorAddressArgumentsContract): + WithConstructorAddressArgumentsContract, + address_conversion_func): gas_estimate = WithConstructorAddressArgumentsContract.constructor( - "0x16D9983245De15E7A9A73bC586E01FF6E08dE737").estimateGas() + address_conversion_func("0x16D9983245De15E7A9A73bC586E01FF6E08dE737")).estimateGas() deploy_txn = WithConstructorAddressArgumentsContract.constructor( - "0x16D9983245De15E7A9A73bC586E01FF6E08dE737").transact() + address_conversion_func("0x16D9983245De15E7A9A73bC586E01FF6E08dE737")).transact() txn_receipt = web3.eth.waitForTransactionReceipt(deploy_txn) gas_used = txn_receipt.get('gasUsed') assert abs(gas_estimate - gas_used) < 21000 -def test_contract_constructor_transact_no_constructor(web3, MathContract, MATH_RUNTIME): +def test_contract_constructor_transact_no_constructor( + web3, + MathContract, + MATH_RUNTIME, + address_conversion_func): deploy_txn = MathContract.constructor().transact() txn_receipt = web3.eth.waitForTransactionReceipt(deploy_txn) assert txn_receipt is not None assert txn_receipt['contractAddress'] - contract_address = txn_receipt['contractAddress'] + contract_address = address_conversion_func(txn_receipt['contractAddress']) blockchain_code = web3.eth.getCode(contract_address) assert blockchain_code == decode_hex(MATH_RUNTIME) def test_contract_constructor_transact_with_constructor_without_arguments( - web3, SimpleConstructorContract, SIMPLE_CONSTRUCTOR_RUNTIME): + web3, + SimpleConstructorContract, + SIMPLE_CONSTRUCTOR_RUNTIME, + address_conversion_func): deploy_txn = SimpleConstructorContract.constructor().transact() txn_receipt = web3.eth.waitForTransactionReceipt(deploy_txn) assert txn_receipt is not None assert txn_receipt['contractAddress'] - contract_address = txn_receipt['contractAddress'] + contract_address = address_conversion_func(txn_receipt['contractAddress']) blockchain_code = web3.eth.getCode(contract_address) assert blockchain_code == decode_hex(SIMPLE_CONSTRUCTOR_RUNTIME) @@ -119,7 +127,8 @@ def test_contract_constructor_transact_with_constructor_with_arguments( constructor_args, constructor_kwargs, expected_a, - expected_b): + expected_b, + address_conversion_func): deploy_txn = WithConstructorArgumentsContract.constructor( *constructor_args, **constructor_kwargs).transact() @@ -127,7 +136,7 @@ def test_contract_constructor_transact_with_constructor_with_arguments( assert txn_receipt is not None assert txn_receipt['contractAddress'] - contract_address = txn_receipt['contractAddress'] + contract_address = address_conversion_func(txn_receipt['contractAddress']) blockchain_code = web3.eth.getCode(contract_address) assert blockchain_code == decode_hex(WITH_CONSTRUCTOR_ARGUMENTS_RUNTIME) @@ -138,12 +147,15 @@ def test_contract_constructor_transact_with_constructor_with_arguments( def test_contract_constructor_transact_with_constructor_with_address_arguments( - web3, WithConstructorAddressArgumentsContract, WITH_CONSTRUCTOR_ADDRESS_RUNTIME): + web3, + WithConstructorAddressArgumentsContract, + WITH_CONSTRUCTOR_ADDRESS_RUNTIME, + address_conversion_func): deploy_txn = WithConstructorAddressArgumentsContract.constructor(TEST_ADDRESS).transact() txn_receipt = web3.eth.waitForTransactionReceipt(deploy_txn) assert txn_receipt is not None assert txn_receipt['contractAddress'] - contract_address = txn_receipt['contractAddress'] + contract_address = address_conversion_func(txn_receipt['contractAddress']) blockchain_code = web3.eth.getCode(contract_address) assert blockchain_code == decode_hex(WITH_CONSTRUCTOR_ADDRESS_RUNTIME) assert TEST_ADDRESS == WithConstructorAddressArgumentsContract( @@ -155,8 +167,13 @@ def test_contract_constructor_build_transaction_to_field_error(MathContract): MathContract.constructor().buildTransaction({'to': '123'}) -def test_contract_constructor_build_transaction_no_constructor(web3, MathContract): - txn_hash = MathContract.constructor().transact({'from': web3.eth.accounts[0]}) +def test_contract_constructor_build_transaction_no_constructor( + web3, + MathContract, + address_conversion_func): + txn_hash = MathContract.constructor().transact( + {'from': address_conversion_func(web3.eth.accounts[0])} + ) txn = web3.eth.getTransaction(txn_hash) nonce = web3.eth.getTransactionCount(web3.eth.coinbase) unsent_txn = MathContract.constructor().buildTransaction({'nonce': nonce}) @@ -168,9 +185,13 @@ def test_contract_constructor_build_transaction_no_constructor(web3, MathContrac assert new_txn['nonce'] == nonce -def test_contract_constructor_build_transaction_with_constructor_without_argument(web3, - MathContract): - txn_hash = MathContract.constructor().transact({'from': web3.eth.accounts[0]}) +def test_contract_constructor_build_transaction_with_constructor_without_argument( + web3, + MathContract, + address_conversion_func): + txn_hash = MathContract.constructor().transact( + {'from': address_conversion_func(web3.eth.accounts[0])} + ) txn = web3.eth.getTransaction(txn_hash) nonce = web3.eth.getTransactionCount(web3.eth.coinbase) unsent_txn = MathContract.constructor().buildTransaction({'nonce': nonce}) @@ -195,9 +216,12 @@ def test_contract_constructor_build_transaction_with_constructor_with_argument( web3, WithConstructorArgumentsContract, constructor_args, - constructor_kwargs): + constructor_kwargs, + address_conversion_func): txn_hash = WithConstructorArgumentsContract.constructor( - *constructor_args, **constructor_kwargs).transact({'from': web3.eth.accounts[0]}) + *constructor_args, **constructor_kwargs).transact( + {'from': address_conversion_func(web3.eth.accounts[0])} + ) txn = web3.eth.getTransaction(txn_hash) nonce = web3.eth.getTransactionCount(web3.eth.coinbase) unsent_txn = WithConstructorArgumentsContract.constructor( diff --git a/tests/core/contracts/test_contract_estimateGas.py b/tests/core/contracts/test_contract_estimateGas.py index 139120b994..841619a0a1 100644 --- a/tests/core/contracts/test_contract_estimateGas.py +++ b/tests/core/contracts/test_contract_estimateGas.py @@ -11,7 +11,8 @@ def math_contract(web3, MATH_ABI, MATH_CODE, MATH_RUNTIME, - wait_for_transaction): + wait_for_transaction, + address_conversion_func): MathContract = web3.eth.contract( abi=MATH_ABI, bytecode=MATH_CODE, @@ -21,10 +22,11 @@ def math_contract(web3, deploy_receipt = web3.eth.waitForTransactionReceipt(deploy_txn) assert deploy_receipt is not None - contract_address = deploy_receipt['contractAddress'] + contract_address = address_conversion_func(deploy_receipt['contractAddress']) web3.isAddress(contract_address) _math_contract = MathContract(address=contract_address) + assert _math_contract.address == contract_address return _math_contract @@ -33,7 +35,8 @@ def fallback_function_contract(web3, FALLBACK_FUNCTION_ABI, FALLBACK_FUNCTION_CODE, FALLBACK_FUNCTION_RUNTIME, - wait_for_transaction): + wait_for_transaction, + address_conversion_func): fallback_contract = web3.eth.contract( abi=FALLBACK_FUNCTION_ABI, bytecode=FALLBACK_FUNCTION_CODE, @@ -43,10 +46,11 @@ def fallback_function_contract(web3, deploy_receipt = web3.eth.waitForTransactionReceipt(deploy_txn) assert deploy_receipt is not None - contract_address = deploy_receipt['contractAddress'] + contract_address = address_conversion_func(deploy_receipt['contractAddress']) web3.isAddress(contract_address) _fallback_function_contract = fallback_contract(address=contract_address) + assert _fallback_function_contract.address == contract_address return _fallback_function_contract diff --git a/tests/core/contracts/test_contract_init.py b/tests/core/contracts/test_contract_init.py index d50e07f03e..c70b80ceab 100644 --- a/tests/core/contracts/test_contract_init.py +++ b/tests/core/contracts/test_contract_init.py @@ -10,13 +10,13 @@ ) -@pytest.fixture -def math_addr(MathContract): +@pytest.fixture() +def math_addr(MathContract, address_conversion_func): web3 = MathContract.web3 deploy_txn = MathContract.constructor().transact({'from': web3.eth.coinbase}) deploy_receipt = web3.eth.waitForTransactionReceipt(deploy_txn) assert deploy_receipt is not None - return deploy_receipt['contractAddress'] + return address_conversion_func(deploy_receipt['contractAddress']) def test_contract_with_unset_address(MathContract): diff --git a/tests/core/contracts/test_contract_transact_interface.py b/tests/core/contracts/test_contract_transact_interface.py index e734bea18f..106221250d 100644 --- a/tests/core/contracts/test_contract_transact_interface.py +++ b/tests/core/contracts/test_contract_transact_interface.py @@ -15,34 +15,40 @@ @pytest.fixture() -def math_contract(web3, MathContract): +def math_contract(web3, MathContract, address_conversion_func): deploy_txn = MathContract.constructor().transact() deploy_receipt = web3.eth.waitForTransactionReceipt(deploy_txn) assert deploy_receipt is not None - _math_contract = MathContract(address=deploy_receipt['contractAddress']) + address = address_conversion_func(deploy_receipt['contractAddress']) + _math_contract = MathContract(address=address) + assert _math_contract.address == address return _math_contract @pytest.fixture() -def string_contract(web3, StringContract): +def string_contract(web3, StringContract, address_conversion_func): deploy_txn = StringContract.constructor("Caqalai").transact() deploy_receipt = web3.eth.waitForTransactionReceipt(deploy_txn) assert deploy_receipt is not None - _math_contract = StringContract(address=deploy_receipt['contractAddress']) - return _math_contract + address = address_conversion_func(deploy_receipt['contractAddress']) + _string_contract = StringContract(address=address) + assert _string_contract.address == address + return _string_contract @pytest.fixture() -def fallback_function_contract(web3, FallballFunctionContract): +def fallback_function_contract(web3, FallballFunctionContract, address_conversion_func): deploy_txn = FallballFunctionContract.constructor().transact() deploy_receipt = web3.eth.waitForTransactionReceipt(deploy_txn) assert deploy_receipt is not None - _fallback_contract = FallballFunctionContract(address=deploy_receipt['contractAddress']) + address = address_conversion_func(deploy_receipt['contractAddress']) + _fallback_contract = FallballFunctionContract(address=address) + assert _fallback_contract.address == address return _fallback_contract @pytest.fixture() -def arrays_contract(web3, ArraysContract): +def arrays_contract(web3, ArraysContract, address_conversion_func): # bytes_32 = [keccak('0'), keccak('1')] bytes32_array = [ b'\x04HR\xb2\xa6p\xad\xe5@~x\xfb(c\xc5\x1d\xe9\xfc\xb9eB\xa0q\x86\xfe:\xed\xa6\xbb\x8a\x11m', # noqa: E501 @@ -52,7 +58,8 @@ def arrays_contract(web3, ArraysContract): deploy_txn = ArraysContract.constructor(bytes32_array, byte_arr).transact() deploy_receipt = web3.eth.waitForTransactionReceipt(deploy_txn) assert deploy_receipt is not None - _arrays_contract = ArraysContract(address=deploy_receipt['contractAddress']) + address = address_conversion_func(deploy_receipt['contractAddress']) + _arrays_contract = ArraysContract(address=address) return _arrays_contract diff --git a/tests/core/contracts/test_extracting_event_data.py b/tests/core/contracts/test_extracting_event_data.py index ecb991b4c8..6d93535a6f 100644 --- a/tests/core/contracts/test_extracting_event_data.py +++ b/tests/core/contracts/test_extracting_event_data.py @@ -18,15 +18,17 @@ def Emitter(web3, EMITTER): @pytest.fixture() -def emitter(web3, Emitter, wait_for_transaction, wait_for_block): +def emitter(web3, Emitter, wait_for_transaction, wait_for_block, address_conversion_func): wait_for_block(web3) deploy_txn_hash = Emitter.constructor().transact({'from': web3.eth.coinbase, 'gas': 1000000}) deploy_receipt = web3.eth.waitForTransactionReceipt(deploy_txn_hash) - contract_address = deploy_receipt['contractAddress'] + contract_address = address_conversion_func(deploy_receipt['contractAddress']) bytecode = web3.eth.getCode(contract_address) assert bytecode == Emitter.bytecode_runtime - return Emitter(address=contract_address) + _emitter = Emitter(address=contract_address) + assert _emitter.address == contract_address + return _emitter @pytest.mark.parametrize( diff --git a/tests/core/contracts/test_extracting_event_data_old.py b/tests/core/contracts/test_extracting_event_data_old.py index 38412a5724..791c181da2 100644 --- a/tests/core/contracts/test_extracting_event_data_old.py +++ b/tests/core/contracts/test_extracting_event_data_old.py @@ -18,15 +18,17 @@ def Emitter(web3, EMITTER): @pytest.fixture() -def emitter(web3, Emitter, wait_for_transaction, wait_for_block): +def emitter(web3, Emitter, wait_for_transaction, wait_for_block, address_conversion_func): wait_for_block(web3) deploy_txn_hash = Emitter.constructor().transact({'from': web3.eth.coinbase, 'gas': 1000000}) deploy_receipt = web3.eth.waitForTransactionReceipt(deploy_txn_hash) - contract_address = deploy_receipt['contractAddress'] + contract_address = address_conversion_func(deploy_receipt['contractAddress']) bytecode = web3.eth.getCode(contract_address) assert bytecode == Emitter.bytecode_runtime - return Emitter(address=contract_address) + _emitter = Emitter(address=contract_address) + assert _emitter.address == contract_address + return _emitter @pytest.mark.parametrize( diff --git a/tests/core/contracts/test_implicit_contract.py b/tests/core/contracts/test_implicit_contract.py index 5b5011348b..5defe47617 100644 --- a/tests/core/contracts/test_implicit_contract.py +++ b/tests/core/contracts/test_implicit_contract.py @@ -10,7 +10,7 @@ @pytest.fixture() -def math_contract(web3, MATH_ABI, MATH_CODE, MATH_RUNTIME): +def math_contract(web3, MATH_ABI, MATH_CODE, MATH_RUNTIME, address_conversion_func): # Deploy math contract # NOTE Must use non-specialized contract factory or else deploy() doesn't work MathContract = web3.eth.contract( @@ -20,7 +20,7 @@ def math_contract(web3, MATH_ABI, MATH_CODE, MATH_RUNTIME): ) tx_hash = MathContract.constructor().transact() tx_receipt = web3.eth.waitForTransactionReceipt(tx_hash) - math_address = tx_receipt['contractAddress'] + math_address = address_conversion_func(tx_receipt['contractAddress']) # Return interactive contract instance at deployed address # TODO Does parent class not implement 'deploy()' for a reason? MathContract = web3.eth.contract( @@ -29,7 +29,9 @@ def math_contract(web3, MATH_ABI, MATH_CODE, MATH_RUNTIME): bytecode_runtime=MATH_RUNTIME, ContractFactoryClass=ImplicitContract, ) - return MathContract(math_address) + contract = MathContract(math_address) + assert contract.address == math_address + return contract @pytest.fixture() diff --git a/tests/core/eth-module/test_eth_contract.py b/tests/core/eth-module/test_eth_contract.py index da23730f88..3cfc9f2d68 100644 --- a/tests/core/eth-module/test_eth_contract.py +++ b/tests/core/eth-module/test_eth_contract.py @@ -3,8 +3,13 @@ Mock, ) +from eth_utils import ( + to_bytes, +) + ABI = [{}] ADDRESS = '0xd3CdA913deB6f67967B99D67aCDFa1712C293601' +BYTES_ADDRESS = to_bytes(hexstr=ADDRESS) NON_CHECKSUM_ADDRESS = '0xd3cda913deb6f67967b99d67acdfa1712c293601' INVALID_CHECKSUM_ADDRESS = '0xd3CDA913deB6f67967B99D67aCDFa1712C293601' @@ -13,6 +18,7 @@ 'args,kwargs,expected', ( ((ADDRESS,), {}, None), + ((BYTES_ADDRESS,), {}, None), ((INVALID_CHECKSUM_ADDRESS,), {}, ValueError), ((NON_CHECKSUM_ADDRESS,), {}, ValueError), ((), {'address': ADDRESS}, None), diff --git a/tests/core/filtering/conftest.py b/tests/core/filtering/conftest.py index 84472fd8ff..690018f2df 100644 --- a/tests/core/filtering/conftest.py +++ b/tests/core/filtering/conftest.py @@ -53,15 +53,17 @@ def Emitter(web3, EMITTER): @pytest.fixture() -def emitter(web3, Emitter, wait_for_transaction, wait_for_block): +def emitter(web3, Emitter, wait_for_transaction, wait_for_block, address_conversion_func): wait_for_block(web3) deploy_txn_hash = Emitter.constructor().transact({'from': web3.eth.coinbase, 'gas': 1000000}) deploy_receipt = wait_for_transaction(web3, deploy_txn_hash) - contract_address = deploy_receipt['contractAddress'] + contract_address = address_conversion_func(deploy_receipt['contractAddress']) bytecode = web3.eth.getCode(contract_address) assert bytecode == Emitter.bytecode_runtime - return Emitter(address=contract_address) + _emitter = Emitter(address=contract_address) + assert _emitter.address == contract_address + return _emitter class LogFunctions: diff --git a/tests/core/filtering/test_contract_on_event_filtering.py b/tests/core/filtering/test_contract_on_event_filtering.py index eab60573ec..15892b34ea 100644 --- a/tests/core/filtering/test_contract_on_event_filtering.py +++ b/tests/core/filtering/test_contract_on_event_filtering.py @@ -17,7 +17,6 @@ def test_create_filter_address_parameter(web3, emitter, Emitter, call_as_instanc if call_as_instance: # Assert this is a single string value, and not a list of addresses - assert isinstance(event_filter.filter_params['address'], str) assert is_address(event_filter.filter_params['address']) else: # Undeployed contract shouldnt have address... @@ -135,3 +134,12 @@ def test_on_sync_filter_with_event_name_and_non_indexed_argument( old_logs = post_event_filter.get_all_entries() assert len(old_logs) == 1 assert old_logs[0]['transactionHash'] == txn_hashes[1] + + +def test_filter_with_contract_address(web3, emitter, emitter_event_ids, wait_for_transaction): + event_filter = web3.eth.filter(filter_params={'address': emitter.address}) + txn_hash = emitter.functions.logNoArgs(emitter_event_ids.LogNoArguments).transact() + wait_for_transaction(web3, txn_hash) + seen_logs = event_filter.get_new_entries() + assert len(seen_logs) == 1 + assert seen_logs[0]['transactionHash'] == txn_hash diff --git a/tests/core/filtering/test_contract_past_event_filtering.py b/tests/core/filtering/test_contract_past_event_filtering.py index 6f87022f50..c9521d2afa 100644 --- a/tests/core/filtering/test_contract_past_event_filtering.py +++ b/tests/core/filtering/test_contract_past_event_filtering.py @@ -1,5 +1,9 @@ import pytest +from eth_utils import ( + is_same_address, +) + # Ignore warning in pyethereum 1.6 - will go away with the upgrade pytestmark = pytest.mark.filterwarnings("ignore:implicit cast from 'char *'") @@ -60,5 +64,5 @@ def test_get_all_entries_returned_block_data( assert event_data['blockHash'] == txn_receipt['blockHash'] assert event_data['blockNumber'] == txn_receipt['blockNumber'] assert event_data['transactionIndex'] == txn_receipt['transactionIndex'] - assert event_data['address'] == emitter.address + assert is_same_address(event_data['address'], emitter.address) assert event_data['event'] == 'LogNoArguments' diff --git a/tests/core/pm-module/test_pm_init.py b/tests/core/pm-module/test_pm_init.py index 61b6700374..7e1222955c 100644 --- a/tests/core/pm-module/test_pm_init.py +++ b/tests/core/pm-module/test_pm_init.py @@ -1,9 +1,5 @@ import pytest -from web3.pm import ( - PM, -) - VALID_MANIFEST = { 'package_name': 'foo', 'manifest_version': '2', @@ -14,10 +10,15 @@ # Returns web3 instance with `pm` module attached @pytest.fixture def web3(): + try: + from web3.pm import PM + except ModuleNotFoundError as exc: + assert False, "eth-pm import failed because: %s" % exc PM.attach(web3, 'pm') return web3 +@pytest.mark.xfail(reason="eth-pm will not installed by default until it is stable") def test_pm_init_with_minimal_manifest(web3): pm = web3.pm.get_package_from_manifest(VALID_MANIFEST) assert pm.name == 'foo' diff --git a/tests/core/utilities/test_validation.py b/tests/core/utilities/test_validation.py index b44a73a262..618bcb5267 100644 --- a/tests/core/utilities/test_validation.py +++ b/tests/core/utilities/test_validation.py @@ -1,5 +1,9 @@ import pytest +from eth_utils import ( + to_bytes, +) + from web3.exceptions import ( InvalidAddress, ) @@ -64,9 +68,12 @@ ] ADDRESS = '0xd3CdA913deB6f67967B99D67aCDFa1712C293601' +BYTES_ADDRESS = to_bytes(hexstr=ADDRESS) PADDED_ADDRESS = '0x000000000000000000000000d3cda913deb6f67967b99d67acdfa1712c293601' INVALID_CHECKSUM_ADDRESS = '0xd3CDA913deB6f67967B99D67aCDFa1712C293601' NON_CHECKSUM_ADDRESS = '0xd3cda913deb6f67967b99d67acdfa1712c293601' +BYTES_ADDRESS_LEN_LT_20 = bytes(1) * 19 +BYTES_ADDRESS_LEN_GT_20 = bytes(1) * 21 @pytest.mark.parametrize( @@ -78,11 +85,14 @@ (MALFORMED_SELECTOR_COLLISION_ABI, validate_abi, ValueError), (MALFORMED_SIGNATURE_COLLISION_ABI, validate_abi, ValueError), (ADDRESS, validate_address, None), + (BYTES_ADDRESS, validate_address, None), (PADDED_ADDRESS, validate_address, InvalidAddress), (INVALID_CHECKSUM_ADDRESS, validate_address, InvalidAddress), (NON_CHECKSUM_ADDRESS, validate_address, InvalidAddress), + (BYTES_ADDRESS_LEN_LT_20, validate_address, InvalidAddress), + (BYTES_ADDRESS_LEN_GT_20, validate_address, InvalidAddress), ("NotAddress", validate_address, InvalidAddress), - (b'not string', validate_address, TypeError), + (b'not string', validate_address, InvalidAddress), ('bool', validate_abi_type, None), ('bool[', validate_abi_type, ValueError), ('sbool', validate_abi_type, ValueError), @@ -115,7 +125,7 @@ def test_validation(param, validation, expected): ('uint8', -5, TypeError), ('int8', -5, None), ('address', "just a string", InvalidAddress), - ('address', b'not even a string', TypeError), + ('address', b'not even a string', InvalidAddress), ('address[][]', [[4, 5], [True]], TypeError), ('address[][]', [[ADDRESS]], None), ('address[2][]', [[ADDRESS], [ADDRESS, ADDRESS]], TypeError), diff --git a/tests/ens/conftest.py b/tests/ens/conftest.py index c16be6ffe5..b0f7805181 100644 --- a/tests/ens/conftest.py +++ b/tests/ens/conftest.py @@ -222,3 +222,8 @@ def ens(ens_setup, mocker): mocker.patch('web3.middleware.stalecheck._isfresh', return_value=True) ens_setup.web3.eth.defaultAccount = ens_setup.web3.eth.coinbase return ens_setup + + +@pytest.fixture() +def TEST_ADDRESS(address_conversion_func): + return address_conversion_func("0x000000000000000000000000000000000000dEaD") diff --git a/tests/ens/test_get_registry.py b/tests/ens/test_get_registry.py index 319c2468cc..6bc85c2329 100644 --- a/tests/ens/test_get_registry.py +++ b/tests/ens/test_get_registry.py @@ -26,7 +26,8 @@ def test_resolver_empty(ens): ), ], ) -def test_reverse_domain(address, expected_reverse): +def test_reverse_domain(address, expected_reverse, address_conversion_func): + address = address_conversion_func(address) assert ENS.reverse_domain(address) == expected_reverse diff --git a/tests/ens/test_setup_address.py b/tests/ens/test_setup_address.py index a21dd830ca..022c9337aa 100644 --- a/tests/ens/test_setup_address.py +++ b/tests/ens/test_setup_address.py @@ -4,6 +4,11 @@ patch, ) +from eth_utils import ( + is_same_address, + to_bytes, +) + from ens.constants import ( EMPTY_ADDR_HEX, ) @@ -12,12 +17,11 @@ ) from web3 import Web3 + ''' API at: https://github.com/carver/ens.py/issues/2 ''' -TEST_ADDRESS = "0x000000000000000000000000000000000000dEaD" - @pytest.mark.parametrize( 'name, full_name, namehash_hex', @@ -66,23 +70,23 @@ ), ], ) -def test_set_address(ens, name, full_name, namehash_hex): +def test_set_address(ens, name, full_name, namehash_hex, TEST_ADDRESS): assert ens.address(name) is None owner = ens.owner('tester') ens.setup_address(name, TEST_ADDRESS) - assert ens.address(name) == TEST_ADDRESS + assert is_same_address(ens.address(name), TEST_ADDRESS) # check that .eth is only appended if guess_tld is True namehash = Web3.toBytes(hexstr=namehash_hex) normal_name = ens.nameprep(full_name) if ens.nameprep(name) == normal_name: - assert ens.address(name, guess_tld=False) == TEST_ADDRESS + assert is_same_address(ens.address(name, guess_tld=False), TEST_ADDRESS) else: assert ens.address(name, guess_tld=False) is None # check that the correct namehash is set: - assert ens.resolver(normal_name).addr(namehash) == TEST_ADDRESS + assert is_same_address(ens.resolver(normal_name).addr(namehash), TEST_ADDRESS) # check that the correct owner is set: assert ens.owner(name) == owner @@ -98,12 +102,12 @@ def test_set_address(ens, name, full_name, namehash_hex): ('unicÖde.tester.eth', 'unicöde.tester.eth'), ], ) -def test_set_address_equivalence(ens, name, equivalent): +def test_set_address_equivalence(ens, name, equivalent, TEST_ADDRESS): assert ens.address(name) is None ens.setup_address(name, TEST_ADDRESS) - assert ens.address(name) == TEST_ADDRESS - assert ens.address(equivalent) == TEST_ADDRESS + assert is_same_address(ens.address(name), TEST_ADDRESS) + assert is_same_address(ens.address(equivalent), TEST_ADDRESS) ens.setup_address(name, None) assert ens.address(name) is None @@ -112,7 +116,11 @@ def test_set_address_equivalence(ens, name, equivalent): @pytest.mark.parametrize( 'set_address', [ - TEST_ADDRESS, + # since the test uses getTransactionCount, + # using a same address converted to bytes and hex will error with same count, + # use two different addresses of each type (hex, bytes) + "0x000000000000000000000000000000000000dEaD", + to_bytes(hexstr="0x5B2063246F2191f18F2675ceDB8b28102e957458"), EMPTY_ADDR_HEX, None, '', @@ -129,7 +137,7 @@ def test_set_address_noop(ens, set_address): assert eth.getTransactionCount(owner) == starting_transactions -def test_set_address_unauthorized(ens): +def test_set_address_unauthorized(ens, TEST_ADDRESS): with pytest.raises(UnauthorizedError): ens.setup_address('eth', TEST_ADDRESS) @@ -156,7 +164,7 @@ def getowner(name): (addr, ['abcdefg', 'bcdefgh'], 'cdefghi.eth') -def test_set_resolver_leave_default(ens): +def test_set_resolver_leave_default(ens, TEST_ADDRESS): owner = ens.owner('tester') ens.setup_address('leave-default-resolver.tester.eth', TEST_ADDRESS) eth = ens.web3.eth diff --git a/tests/ens/test_setup_name.py b/tests/ens/test_setup_name.py index 311ff12566..a907289b07 100644 --- a/tests/ens/test_setup_name.py +++ b/tests/ens/test_setup_name.py @@ -8,11 +8,15 @@ ) from web3 import Web3 + ''' API at: https://github.com/carver/ens.py/issues/2 ''' -TEST_ADDRESS = "0x000000000000000000000000000000000000dEaD" + +@pytest.fixture() +def TEST_ADDRESS(address_conversion_func): + return address_conversion_func("0x000000000000000000000000000000000000dEaD") @pytest.mark.parametrize( @@ -86,7 +90,7 @@ def test_setup_name(ens, name, normalized_name, namehash_hex): assert not ens.address(name) -def test_cannot_set_name_on_mismatch_address(ens): +def test_cannot_set_name_on_mismatch_address(ens, TEST_ADDRESS): ens.setup_address('mismatch-reverse.tester.eth', TEST_ADDRESS) with pytest.raises(AddressMismatch): ens.setup_name('mismatch-reverse.tester.eth', '0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413') @@ -121,7 +125,7 @@ def test_setup_name_unowned_exception(ens): ens.setup_name('unowned-name.tester.eth') -def test_setup_name_unauthorized(ens): +def test_setup_name_unauthorized(ens, TEST_ADDRESS): with pytest.raises(UnauthorizedError): ens.setup_name('root-owned-tld', TEST_ADDRESS) diff --git a/tests/integration/go_ethereum/conftest.py b/tests/integration/go_ethereum/conftest.py index 242c995c2e..bd5173841f 100644 --- a/tests/integration/go_ethereum/conftest.py +++ b/tests/integration/go_ethereum/conftest.py @@ -167,11 +167,21 @@ def math_contract(web3, math_contract_factory, geth_fixture_data): return math_contract_factory(address=geth_fixture_data['math_address']) +@pytest.fixture(scope="module") +def math_contract_address(math_contract, address_conversion_func): + return address_conversion_func(math_contract.address) + + @pytest.fixture(scope="module") def emitter_contract(web3, emitter_contract_factory, geth_fixture_data): return emitter_contract_factory(address=geth_fixture_data['emitter_address']) +@pytest.fixture(scope="module") +def emitter_contract_address(emitter_contract, address_conversion_func): + return address_conversion_func(emitter_contract.address) + + @pytest.fixture def unlocked_account(web3, unlockable_account, unlockable_account_pw): web3.personal.unlockAccount(unlockable_account, unlockable_account_pw) @@ -189,6 +199,18 @@ def unlockable_account(web3, coinbase): yield coinbase +@pytest.fixture() +def unlockable_account_dual_type(unlockable_account, address_conversion_func): + return address_conversion_func(unlockable_account) + + +@pytest.yield_fixture +def unlocked_account_dual_type(web3, unlockable_account_dual_type, unlockable_account_pw): + web3.personal.unlockAccount(unlockable_account_dual_type, unlockable_account_pw) + yield unlockable_account_dual_type + web3.personal.lockAccount(unlockable_account_dual_type) + + @pytest.fixture(scope="module") def funded_account_for_raw_txn(geth_fixture_data): account = geth_fixture_data['raw_txn_account'] diff --git a/tests/integration/go_ethereum/test_goethereum_ws.py b/tests/integration/go_ethereum/test_goethereum_ws.py index 8203133ea5..4499dcaf64 100644 --- a/tests/integration/go_ethereum/test_goethereum_ws.py +++ b/tests/integration/go_ethereum/test_goethereum_ws.py @@ -6,7 +6,6 @@ from tests.integration.utils import ( wait_for_ws, ) - from web3 import Web3 from .common import ( diff --git a/tests/integration/parity/common.py b/tests/integration/parity/common.py index d5113a9822..3e05c180a3 100644 --- a/tests/integration/parity/common.py +++ b/tests/integration/parity/common.py @@ -196,8 +196,8 @@ def test_trace_block(self, web3, block_with_txn): def test_trace_transaction(self, web3, parity_fixture_data): super().test_trace_transaction(web3, parity_fixture_data) - def test_trace_call(self, web3, math_contract): - super().test_trace_call(web3, math_contract) + def test_trace_call(self, web3, math_contract, math_contract_address): + super().test_trace_call(web3, math_contract, math_contract_address) - def test_eth_call_with_0_result(self, web3, math_contract): - super().test_eth_call_with_0_result(web3, math_contract) + def test_eth_call_with_0_result(self, web3, math_contract, math_contract_address): + super().test_eth_call_with_0_result(web3, math_contract, math_contract_address) diff --git a/tests/integration/parity/conftest.py b/tests/integration/parity/conftest.py index 2d825f0d37..94081567af 100644 --- a/tests/integration/parity/conftest.py +++ b/tests/integration/parity/conftest.py @@ -138,11 +138,21 @@ def math_contract(web3, math_contract_factory, parity_fixture_data): return math_contract_factory(address=parity_fixture_data['math_address']) +@pytest.fixture() +def math_contract_address(math_contract, address_conversion_func): + return address_conversion_func(math_contract.address) + + @pytest.fixture(scope="module") def emitter_contract(web3, emitter_contract_factory, parity_fixture_data): return emitter_contract_factory(address=parity_fixture_data['emitter_address']) +@pytest.fixture() +def emitter_contract_address(emitter_contract, address_conversion_func): + return address_conversion_func(emitter_contract.address) + + @pytest.fixture(scope="module") def unlocked_account(web3, unlockable_account, unlockable_account_pw): yield unlockable_account @@ -158,6 +168,16 @@ def unlockable_account(web3, coinbase): yield coinbase +@pytest.fixture() +def unlockable_account_dual_type(unlockable_account, address_conversion_func): + return address_conversion_func(unlockable_account) + + +@pytest.fixture +def unlocked_account_dual_type(unlockable_account_dual_type): + return unlockable_account_dual_type + + @pytest.fixture(scope="module") def funded_account_for_raw_txn(parity_fixture_data): account = parity_fixture_data['raw_txn_account'] diff --git a/tests/integration/parity/install_parity.py b/tests/integration/parity/install_parity.py index d14ab861ed..020652e926 100644 --- a/tests/integration/parity/install_parity.py +++ b/tests/integration/parity/install_parity.py @@ -73,7 +73,13 @@ def install_parity(version_string): uri, checksum = get_uri(**params)[0] if not os.path.exists(path): - download_binary(path, uri, checksum) + try: + download_binary(path, uri, checksum) + except AssertionError as exc: + raise Exception("failed to download binary at uri %r with params %r" % ( + uri, + params, + )) from exc return path @@ -82,7 +88,7 @@ def download_binary(path, uri, checksum): r = get_binary_stream(uri) total_size = int(r.headers.get('content-length', 0)) os.makedirs(os.path.dirname(path), exist_ok=True) - digest = hashlib.md5() + digest = hashlib.sha256() with open(path, 'wb') as f: with tqdm(total=total_size, unit='B', @@ -92,7 +98,8 @@ def download_binary(path, uri, checksum): f.write(data) pbar.update(len(data)) digest.update(data) - assert digest.hexdigest() == checksum + hex_digest = digest.hexdigest() + assert hex_digest == checksum, "digest vs checksum: %r vs %r" % (hex_digest, checksum) chmod_plus_x(path) diff --git a/tests/integration/parity/test_parity_http.py b/tests/integration/parity/test_parity_http.py index 6923a26972..ceb5e1c5b4 100644 --- a/tests/integration/parity/test_parity_http.py +++ b/tests/integration/parity/test_parity_http.py @@ -4,7 +4,6 @@ from tests.integration.parity.utils import ( wait_for_http, ) - from web3 import Web3 from web3.utils.module_testing import ( NetModuleTest, diff --git a/tests/integration/parity/test_parity_ipc.py b/tests/integration/parity/test_parity_ipc.py index 29a1276329..a9d821348a 100644 --- a/tests/integration/parity/test_parity_ipc.py +++ b/tests/integration/parity/test_parity_ipc.py @@ -5,7 +5,6 @@ from tests.integration.parity.utils import ( wait_for_socket, ) - from web3 import Web3 from web3.utils.module_testing import ( NetModuleTest, diff --git a/tests/integration/parity/test_parity_ws.py b/tests/integration/parity/test_parity_ws.py index e5a5bd7238..3e8bafa7c5 100644 --- a/tests/integration/parity/test_parity_ws.py +++ b/tests/integration/parity/test_parity_ws.py @@ -7,7 +7,6 @@ from tests.integration.utils import ( wait_for_ws, ) - from web3 import Web3 from web3.utils.module_testing import ( NetModuleTest, diff --git a/tests/integration/test_ethereum_tester.py b/tests/integration/test_ethereum_tester.py index ef495de409..0fd81ff6de 100644 --- a/tests/integration/test_ethereum_tester.py +++ b/tests/integration/test_ethereum_tester.py @@ -63,9 +63,15 @@ def math_contract(web3, math_contract_factory, math_contract_deploy_txn_hash): return math_contract_factory(contract_address) +@pytest.fixture(scope="module") +def math_contract_address(math_contract, address_conversion_func): + return address_conversion_func(math_contract.address) + # # Emitter Contract Setup # + + @pytest.fixture(scope="module") def emitter_contract_deploy_txn_hash(web3, emitter_contract_factory): deploy_txn_hash = emitter_contract_factory.constructor().transact({'from': web3.eth.coinbase}) @@ -81,6 +87,11 @@ def emitter_contract(web3, emitter_contract_factory, emitter_contract_deploy_txn return emitter_contract_factory(contract_address) +@pytest.fixture(scope="module") +def emitter_contract_address(emitter_contract, address_conversion_func): + return address_conversion_func(emitter_contract.address) + + @pytest.fixture(scope="module") def empty_block(web3): web3.testing.mine() @@ -151,6 +162,18 @@ def unlocked_account(web3, unlockable_account, unlockable_account_pw): web3.personal.lockAccount(unlockable_account) +@pytest.fixture() +def unlockable_account_dual_type(unlockable_account, address_conversion_func): + return address_conversion_func(unlockable_account) + + +@pytest.fixture +def unlocked_account_dual_type(web3, unlockable_account_dual_type, unlockable_account_pw): + web3.personal.unlockAccount(unlockable_account_dual_type, unlockable_account_pw) + yield unlockable_account_dual_type + web3.personal.lockAccount(unlockable_account_dual_type) + + @pytest.fixture(scope="module") def funded_account_for_raw_txn(web3): account = '0x39EEed73fb1D3855E90Cbd42f348b3D7b340aAA6' @@ -253,6 +276,10 @@ def test_eth_call_old_contract_state(self, eth_tester, web3, math_contract, unlo else: raise AssertionError("eth-tester was unexpectedly able to give the pending call result") + def test_eth_getStorageAt(self, web3, emitter_contract_address): + pytest.xfail('json-rpc method is not implemented on eth-tester') + super().test_eth_getStorageAt(web3, emitter_contract_address) + class TestEthereumTesterVersionModule(VersionModuleTest): pass diff --git a/web3/pm.py b/web3/pm.py index f14328ba32..6a277d0482 100644 --- a/web3/pm.py +++ b/web3/pm.py @@ -1,11 +1,17 @@ -from ethpm import ( - Package, -) - from web3.module import ( Module, ) +try: + from ethpm import ( + Package, + ) +except ImportError as exc: + raise Exception( + "To use the (alpha) ethpm package, you must install it explicitly. " + "Install with `pip install --upgrade ethpm`." + ) from exc + # Package Management is currently still in alpha # It is not automatically available on a web3 object. diff --git a/web3/utils/module_testing/eth_module.py b/web3/utils/module_testing/eth_module.py index 4ae3baaa6f..abb4560d7e 100644 --- a/web3/utils/module_testing/eth_module.py +++ b/web3/utils/module_testing/eth_module.py @@ -23,7 +23,7 @@ InvalidAddress, ) -UNKNOWN_ADDRESS = '0xdeadbeef00000000000000000000000000000000' +UNKNOWN_ADDRESS = '0xdEADBEeF00000000000000000000000000000000' UNKNOWN_HASH = '0xdeadbeef00000000000000000000000000000000000000000000000000000000' @@ -95,21 +95,25 @@ def test_eth_getBalance(self, web3): assert is_integer(balance) assert balance >= 0 - def test_eth_getStorageAt(self, web3): - coinbase = web3.eth.coinbase + def test_eth_getStorageAt(self, web3, emitter_contract_address): + storage = web3.eth.getStorageAt(emitter_contract_address, 0) + assert isinstance(storage, HexBytes) + def test_eth_getStorageAt_invalid_address(self, web3): + coinbase = web3.eth.coinbase with pytest.raises(InvalidAddress): web3.eth.getStorageAt(coinbase.lower(), 0) - def test_eth_getTransactionCount(self, web3): + def test_eth_getTransactionCount(self, web3, unlocked_account_dual_type): + transaction_count = web3.eth.getTransactionCount(unlocked_account_dual_type) + assert is_integer(transaction_count) + assert transaction_count >= 0 + + def test_eth_getTransactionCount_invalid_address(self, web3): coinbase = web3.eth.coinbase - transaction_count = web3.eth.getTransactionCount(coinbase) with pytest.raises(InvalidAddress): web3.eth.getTransactionCount(coinbase.lower()) - assert is_integer(transaction_count) - assert transaction_count >= 0 - def test_eth_getBlockTransactionCountByHash_empty_block(self, web3, empty_block): transaction_count = web3.eth.getBlockTransactionCount(empty_block['hash']) @@ -146,35 +150,43 @@ def test_eth_getUncleCountByBlockNumber(self, web3, empty_block): assert is_integer(uncle_count) assert uncle_count == 0 - def test_eth_getCode(self, web3, math_contract): - code = web3.eth.getCode(math_contract.address) - with pytest.raises(InvalidAddress): - code = web3.eth.getCode(math_contract.address.lower()) + def test_eth_getCode(self, web3, math_contract_address): + code = web3.eth.getCode(math_contract_address) assert is_string(code) assert len(code) > 2 - def test_eth_sign(self, web3, unlocked_account): - signature = web3.eth.sign(unlocked_account, text='Message tö sign. Longer than hash!') + def test_eth_getCode_invalid_address(self, web3, math_contract): + with pytest.raises(InvalidAddress): + web3.eth.getCode(math_contract.address.lower()) + + def test_eth_sign(self, web3, unlocked_account_dual_type): + signature = web3.eth.sign( + unlocked_account_dual_type, text='Message tö sign. Longer than hash!' + ) assert is_bytes(signature) assert len(signature) == 32 + 32 + 1 # test other formats hexsign = web3.eth.sign( - unlocked_account, + unlocked_account_dual_type, hexstr='0x4d6573736167652074c3b6207369676e2e204c6f6e676572207468616e206861736821' ) assert hexsign == signature intsign = web3.eth.sign( - unlocked_account, + unlocked_account_dual_type, 0x4d6573736167652074c3b6207369676e2e204c6f6e676572207468616e206861736821 ) assert intsign == signature - bytessign = web3.eth.sign(unlocked_account, b'Message t\xc3\xb6 sign. Longer than hash!') + bytessign = web3.eth.sign( + unlocked_account_dual_type, b'Message t\xc3\xb6 sign. Longer than hash!' + ) assert bytessign == signature - new_signature = web3.eth.sign(unlocked_account, text='different message is different') + new_signature = web3.eth.sign( + unlocked_account_dual_type, text='different message is different' + ) assert new_signature != signature def test_eth_sendTransaction_addr_checksum_required(self, web3, unlocked_account): @@ -195,10 +207,10 @@ def test_eth_sendTransaction_addr_checksum_required(self, web3, unlocked_account invalid_params = dict(txn_params, **{'to': non_checksum_addr}) web3.eth.sendTransaction(invalid_params) - def test_eth_sendTransaction(self, web3, unlocked_account): + def test_eth_sendTransaction(self, web3, unlocked_account_dual_type): txn_params = { - 'from': unlocked_account, - 'to': unlocked_account, + 'from': unlocked_account_dual_type, + 'to': unlocked_account_dual_type, 'value': 1, 'gas': 21000, 'gasPrice': web3.eth.gasPrice, @@ -232,10 +244,10 @@ def test_eth_sendTransaction_with_nonce(self, web3, unlocked_account): assert txn['gasPrice'] == txn_params['gasPrice'] assert txn['nonce'] == txn_params['nonce'] - def test_eth_replaceTransaction(self, web3, unlocked_account): + def test_eth_replaceTransaction(self, web3, unlocked_account_dual_type): txn_params = { - 'from': unlocked_account, - 'to': unlocked_account, + 'from': unlocked_account_dual_type, + 'to': unlocked_account_dual_type, 'value': 1, 'gas': 21000, 'gasPrice': web3.eth.gasPrice, @@ -252,10 +264,11 @@ def test_eth_replaceTransaction(self, web3, unlocked_account): assert replace_txn['gas'] == 21000 assert replace_txn['gasPrice'] == txn_params['gasPrice'] - def test_eth_replaceTransaction_non_existing_transaction(self, web3, unlocked_account): + def test_eth_replaceTransaction_non_existing_transaction( + self, web3, unlocked_account_dual_type): txn_params = { - 'from': unlocked_account, - 'to': unlocked_account, + 'from': unlocked_account_dual_type, + 'to': unlocked_account_dual_type, 'value': 1, 'gas': 21000, 'gasPrice': web3.eth.gasPrice, @@ -267,10 +280,10 @@ def test_eth_replaceTransaction_non_existing_transaction(self, web3, unlocked_ac ) # auto mine is enabled for this test - def test_eth_replaceTransaction_already_mined(self, web3, unlocked_account): + def test_eth_replaceTransaction_already_mined(self, web3, unlocked_account_dual_type): txn_params = { - 'from': unlocked_account, - 'to': unlocked_account, + 'from': unlocked_account_dual_type, + 'to': unlocked_account_dual_type, 'value': 1, 'gas': 21000, 'gasPrice': web3.eth.gasPrice, @@ -297,10 +310,10 @@ def test_eth_replaceTransaction_incorrect_nonce(self, web3, unlocked_account): with pytest.raises(ValueError): web3.eth.replaceTransaction(txn_hash, txn_params) - def test_eth_replaceTransaction_gas_price_too_low(self, web3, unlocked_account): + def test_eth_replaceTransaction_gas_price_too_low(self, web3, unlocked_account_dual_type): txn_params = { - 'from': unlocked_account, - 'to': unlocked_account, + 'from': unlocked_account_dual_type, + 'to': unlocked_account_dual_type, 'value': 1, 'gas': 21000, 'gasPrice': 10, @@ -442,11 +455,10 @@ def test_eth_call_with_0_result(self, web3, math_contract): result = decode_single('uint256', call_result) assert result == 0 - def test_eth_estimateGas(self, web3): - coinbase = web3.eth.coinbase + def test_eth_estimateGas(self, web3, unlocked_account_dual_type): gas_estimate = web3.eth.estimateGas({ - 'from': coinbase, - 'to': coinbase, + 'from': unlocked_account_dual_type, + 'to': unlocked_account_dual_type, 'value': 1, }) assert is_integer(gas_estimate) @@ -529,10 +541,10 @@ def test_eth_getTransactionReceipt_mined(self, web3, block_with_txn, mined_txn_h assert receipt['transactionIndex'] == 0 assert receipt['transactionHash'] == HexBytes(mined_txn_hash) - def test_eth_getTransactionReceipt_unmined(self, web3, unlocked_account): + def test_eth_getTransactionReceipt_unmined(self, web3, unlocked_account_dual_type): txn_hash = web3.eth.sendTransaction({ - 'from': unlocked_account, - 'to': unlocked_account, + 'from': unlocked_account_dual_type, + 'to': unlocked_account_dual_type, 'value': 1, 'gas': 21000, 'gasPrice': web3.eth.gasPrice, @@ -664,7 +676,7 @@ def test_eth_getLogs_with_logs( self, web3, block_with_txn_with_log, - emitter_contract, + emitter_contract_address, txn_hash_with_log): def assert_contains_log(result): @@ -673,7 +685,7 @@ def assert_contains_log(result): assert log_entry['blockNumber'] == block_with_txn_with_log['number'] assert log_entry['blockHash'] == block_with_txn_with_log['hash'] assert log_entry['logIndex'] == 0 - assert is_same_address(log_entry['address'], emitter_contract.address) + assert is_same_address(log_entry['address'], emitter_contract_address) assert log_entry['transactionIndex'] == 0 assert log_entry['transactionHash'] == HexBytes(txn_hash_with_log) @@ -699,7 +711,7 @@ def assert_contains_log(result): # filter with emitter_contract.address filter_params = { "fromBlock": 0, - "address": emitter_contract.address, + "address": emitter_contract_address, } result = web3.eth.getLogs(filter_params) assert_contains_log(result) diff --git a/web3/utils/module_testing/parity_module.py b/web3/utils/module_testing/parity_module.py index 1dda766f4f..c3a6ac39f2 100644 --- a/web3/utils/module_testing/parity_module.py +++ b/web3/utils/module_testing/parity_module.py @@ -39,12 +39,12 @@ def test_trace_transaction(self, web3, parity_fixture_data): trace = web3.parity.traceTransaction(parity_fixture_data['mined_txn_hash']) assert trace[0]['action']['from'] == add_0x_prefix(parity_fixture_data['coinbase']) - def test_trace_call(self, web3, math_contract): + def test_trace_call(self, web3, math_contract, math_contract_address): coinbase = web3.eth.coinbase txn_params = math_contract._prepare_transaction( fn_name='add', fn_args=(7, 11), - transaction={'from': coinbase, 'to': math_contract.address}, + transaction={'from': coinbase, 'to': math_contract_address}, ) trace = web3.parity.traceCall(txn_params) assert trace['stateDiff'] is None @@ -52,12 +52,12 @@ def test_trace_call(self, web3, math_contract): result = hex_to_integer(trace['output']) assert result == 18 - def test_eth_call_with_0_result(self, web3, math_contract): + def test_eth_call_with_0_result(self, web3, math_contract, math_contract_address): coinbase = web3.eth.coinbase txn_params = math_contract._prepare_transaction( fn_name='add', fn_args=(0, 0), - transaction={'from': coinbase, 'to': math_contract.address}, + transaction={'from': coinbase, 'to': math_contract_address}, ) trace = web3.parity.traceCall(txn_params) assert trace['stateDiff'] is None diff --git a/web3/utils/module_testing/personal_module.py b/web3/utils/module_testing/personal_module.py index 7f2768c960..9853399fb6 100644 --- a/web3/utils/module_testing/personal_module.py +++ b/web3/utils/module_testing/personal_module.py @@ -28,21 +28,21 @@ def test_personal_listAccounts(self, web3): in accounts )) - def test_personal_lockAccount(self, web3, unlocked_account): + def test_personal_lockAccount(self, web3, unlockable_account_dual_type): # TODO: how do we test this better? - web3.personal.lockAccount(unlocked_account) + web3.personal.lockAccount(unlockable_account_dual_type) def test_personal_unlockAccount_success(self, web3, - unlockable_account, + unlockable_account_dual_type, unlockable_account_pw): - result = web3.personal.unlockAccount(unlockable_account, unlockable_account_pw) + result = web3.personal.unlockAccount(unlockable_account_dual_type, unlockable_account_pw) assert result is True def test_personal_unlockAccount_failure(self, web3, - unlockable_account): - result = web3.personal.unlockAccount(unlockable_account, 'bad-password') + unlockable_account_dual_type): + result = web3.personal.unlockAccount(unlockable_account_dual_type, 'bad-password') assert result is False def test_personal_newAccount(self, web3): @@ -51,12 +51,12 @@ def test_personal_newAccount(self, web3): def test_personal_sendTransaction(self, web3, - unlockable_account, + unlockable_account_dual_type, unlockable_account_pw): - assert web3.eth.getBalance(unlockable_account) > web3.toWei(1, 'ether') + assert web3.eth.getBalance(unlockable_account_dual_type) > web3.toWei(1, 'ether') txn_params = { - 'from': unlockable_account, - 'to': unlockable_account, + 'from': unlockable_account_dual_type, + 'to': unlockable_account_dual_type, 'gas': 21000, 'value': 1, 'gasPrice': web3.toWei(1, 'gwei'), @@ -64,17 +64,18 @@ def test_personal_sendTransaction(self, txn_hash = web3.personal.sendTransaction(txn_params, unlockable_account_pw) assert txn_hash transaction = web3.eth.getTransaction(txn_hash) - assert transaction['from'] == txn_params['from'] - assert transaction['to'] == txn_params['to'] + + assert is_same_address(transaction['from'], txn_params['from']) + assert is_same_address(transaction['to'], txn_params['to']) assert transaction['gas'] == txn_params['gas'] assert transaction['value'] == txn_params['value'] assert transaction['gasPrice'] == txn_params['gasPrice'] def test_personal_sign_and_ecrecover(self, web3, - unlockable_account, + unlockable_account_dual_type, unlockable_account_pw): message = 'test-web3-personal-sign' - signature = web3.personal.sign(message, unlockable_account, unlockable_account_pw) + signature = web3.personal.sign(message, unlockable_account_dual_type, unlockable_account_pw) signer = web3.personal.ecRecover(message, signature) - assert is_same_address(signer, unlockable_account) + assert is_same_address(signer, unlockable_account_dual_type) diff --git a/web3/utils/normalizers.py b/web3/utils/normalizers.py index 0d50d2c0fd..7e7d266076 100644 --- a/web3/utils/normalizers.py +++ b/web3/utils/normalizers.py @@ -9,6 +9,9 @@ from eth_utils import ( to_checksum_address, ) +from eth_utils.address import ( + is_binary_address, +) from hexbytes import ( HexBytes, ) @@ -119,6 +122,8 @@ def abi_bytes_to_bytes(abi_type, data): def abi_address_to_hex(abi_type, data): if abi_type == 'address': validate_address(data) + if is_binary_address(data): + return abi_type, to_checksum_address(data) @curry diff --git a/web3/utils/rpc_abi.py b/web3/utils/rpc_abi.py index 0881b47185..9adfa89bde 100644 --- a/web3/utils/rpc_abi.py +++ b/web3/utils/rpc_abi.py @@ -24,6 +24,12 @@ FILTER_PARAMS_ABIS = { 'to': 'address', + 'address': 'address', +} + +TRACE_PARAMS_ABIS = { + 'to': 'address', + 'from': 'address', } RPC_ABIS = { @@ -47,6 +53,10 @@ 'eth_sign': ['address', 'bytes'], # personal 'personal_sendTransaction': TRANSACTION_PARAMS_ABIS, + 'personal_lockAccount': ['address'], + 'personal_unlockAccount': ['address', None, None], + 'personal_sign': [None, 'address', None], + 'trace_call': TRACE_PARAMS_ABIS, } diff --git a/web3/utils/validation.py b/web3/utils/validation.py index bcf09f18d0..b9a2fda5ef 100644 --- a/web3/utils/validation.py +++ b/web3/utils/validation.py @@ -3,6 +3,7 @@ from eth_utils import ( function_abi_to_4byte_selector, is_0x_prefixed, + is_binary_address, is_boolean, is_bytes, is_checksum_address, @@ -142,6 +143,11 @@ def validate_address(value): """ Helper function for validating an address """ + if is_bytes(value): + if not is_binary_address(value): + raise InvalidAddress("Address must be 20 bytes when input type is bytes", value) + return + if not isinstance(value, str): raise TypeError('Address {} must be provided as a string'.format(value)) if not is_hex_address(value):