diff --git a/web3/contract.py b/web3/contract.py index 9a28ed9f92..493aa5d92b 100644 --- a/web3/contract.py +++ b/web3/contract.py @@ -29,7 +29,6 @@ MismatchedABI, NoABIEventsFound, NoABIFunctionsFound, - ValidationError, ) from web3.utils.abi import ( abi_to_signature, @@ -1354,11 +1353,6 @@ def call_contract_function( Helper function for interacting with a contract function using the `eth_call` API. """ - if fn_abi is None: - fn_abi = find_matching_fn_abi(contract_abi, function_identifier, args, kwargs) - - validate_payable(transaction, fn_abi) - call_transaction = prepare_transaction( address, web3, @@ -1375,6 +1369,9 @@ def call_contract_function( else: return_data = web3.eth.call(call_transaction, block_identifier=block_id) + if fn_abi is None: + fn_abi = find_matching_fn_abi(contract_abi, function_identifier, args, kwargs) + output_types = get_abi_output_types(fn_abi) try: @@ -1449,12 +1446,6 @@ def transact_with_contract_function( Helper function for interacting with a contract function by sending a transaction. """ - - if fn_abi is None: - fn_abi = find_matching_fn_abi(contract_abi, function_name, args, kwargs) - - validate_payable(transaction, fn_abi) - transact_transaction = prepare_transaction( address, web3, @@ -1484,12 +1475,6 @@ def estimate_gas_for_function( Don't call this directly, instead use :meth:`Contract.estimateGas` on your contract instance. """ - - if fn_abi is None: - fn_abi = find_matching_fn_abi(contract_abi, fn_identifier, args, kwargs) - - validate_payable(transaction, fn_abi) - estimate_transaction = prepare_transaction( address, web3, @@ -1519,12 +1504,6 @@ def build_transaction_for_function( Don't call this directly, instead use :meth:`Contract.buildTransaction` on your contract instance. """ - - if fn_abi is None: - fn_abi = find_matching_fn_abi(contract_abi, function_name, args, kwargs) - - validate_payable(transaction, fn_abi) - prepared_transaction = prepare_transaction( address, web3, @@ -1568,17 +1547,3 @@ def get_function_by_identifier(fns, identifier): 'Could not find any function with matching {0}'.format(identifier) ) return fns[0] - - -def validate_payable(transaction, abi): - """Raise ValidationError if non-zero ether - is sent to a non payable function. - """ - if 'value' in transaction: - if transaction['value'] != 0: - if "payable" in abi and not abi["payable"]: - raise ValidationError( - "Sending non-zero ether to a contract function " - "with payable=False. Please ensure that " - "transaction's value is 0." - ) diff --git a/web3/utils/contracts.py b/web3/utils/contracts.py index 3de3693a13..254c47f8e2 100644 --- a/web3/utils/contracts.py +++ b/web3/utils/contracts.py @@ -182,6 +182,11 @@ def prepare_transaction( TODO: make this a public API TODO: add new prepare_deploy_transaction API """ + if fn_abi is None: + fn_abi = find_matching_fn_abi(contract_abi, fn_identifier, fn_args, fn_kwargs) + + validate_payable(transaction, fn_abi) + if transaction is None: prepared_transaction = {} else: @@ -245,3 +250,17 @@ def get_function_info(fn_name, contract_abi=None, fn_abi=None, args=None, kwargs fn_arguments = merge_args_and_kwargs(fn_abi, args, kwargs) return fn_abi, fn_selector, fn_arguments + + +def validate_payable(transaction, abi): + """Raise ValidationError if non-zero ether + is sent to a non payable function. + """ + if 'value' in transaction: + if transaction['value'] != 0: + if "payable" in abi and not abi["payable"]: + raise ValidationError( + "Sending non-zero ether to a contract function " + "with payable=False. Please ensure that " + "transaction's value is 0." + )