def test_contract_estimateGas(web3, math_contract): increment_abi = math_contract._find_matching_fn_abi('increment', []) call_data = function_abi_to_4byte_selector(increment_abi) gas_estimate = math_contract.estimateGas().increment() try: assert abs(gas_estimate - 21472) < 200 # Geth except AssertionError: assert abs(gas_estimate - 43020) < 200 # TestRPC pass
def _get_function_info(cls, fn_name, args=None, kwargs=None): if args is None: args = tuple() if kwargs is None: kwargs = {} fn_abi = cls._find_matching_fn_abi(fn_name, args, kwargs) fn_selector = encode_hex(function_abi_to_4byte_selector(fn_abi)) fn_arguments = merge_args_and_kwargs(fn_abi, args, kwargs) return fn_abi, fn_selector, fn_arguments
def _get_function_info(cls, fn_name, args=None, kwargs=None): if args is None: args = tuple() if kwargs is None: kwargs = {} fn_abi = cls._find_matching_fn_abi(fn_name, args, kwargs) fn_selector = encode_hex(function_abi_to_4byte_selector(fn_abi)) fn_arguments = merge_args_and_kwargs(fn_abi, args, kwargs) return fn_abi, fn_selector, fn_arguments
def _set_function_info(self): self.abi = find_matching_fn_abi(self.contract_abi, self.function_identifier, self.args, self.kwargs) if self.function_identifier is FallbackFn: self.selector = encode_hex(b'') elif is_text(self.function_identifier): self.selector = encode_hex(function_abi_to_4byte_selector(self.abi)) else: raise TypeError("Unsupported function identifier") self.arguments = merge_args_and_kwargs(self.abi, self.args, self.kwargs)
def _set_function_info(self): self.abi = find_matching_fn_abi(self.contract_abi, self.function_identifier, self.args, self.kwargs) if self.function_identifier is FallbackFn: self.selector = encode_hex(b'') elif is_text(self.function_identifier): self.selector = encode_hex(function_abi_to_4byte_selector(self.abi)) else: raise TypeError("Unsupported function identifier") self.arguments = merge_args_and_kwargs(self.abi, self.args, self.kwargs)
def get_function_info(fn_name, contract_abi=None, fn_abi=None, args=None, kwargs=None): if args is None: args = tuple() if kwargs is None: kwargs = {} if fn_abi is None: fn_abi = find_matching_fn_abi(contract_abi, fn_name, args, kwargs) fn_selector = encode_hex(function_abi_to_4byte_selector(fn_abi)) fn_arguments = merge_args_and_kwargs(fn_abi, args, kwargs) return fn_abi, fn_selector, fn_arguments
def get_function_info(fn_name, contract_abi=None, fn_abi=None, args=None, kwargs=None): if args is None: args = tuple() if kwargs is None: kwargs = {} if fn_abi is None: fn_abi = find_matching_fn_abi(contract_abi, fn_name, args, kwargs) fn_selector = encode_hex(function_abi_to_4byte_selector(fn_abi)) fn_arguments = merge_args_and_kwargs(fn_abi, args, kwargs) return fn_abi, fn_selector, fn_arguments
def _make_call_gas_burner_transaction(eth_tester, contract_address, fn_name, fn_args=tuple()): fn_abi = GAS_BURNER_ABI[fn_name] arg_types = [arg_abi['type'] for arg_abi in fn_abi['inputs']] fn_selector = function_abi_to_4byte_selector(fn_abi) transaction = { "from": eth_tester.get_accounts()[0], "to": contract_address, "gas": 500000, "data": encode_hex(fn_selector + encode_abi(arg_types, fn_args)), } return transaction
def test_eth_estimateGas(web3, math_contract): increment_abi = math_contract._find_matching_fn_abi('increment', []) call_data = encode_hex(function_abi_to_4byte_selector(increment_abi)) gas_estimate = web3.eth.estimateGas({ 'to': math_contract.address, 'from': web3.eth.coinbase, 'data': call_data, }) try: assert abs(gas_estimate - 21472) < 200 # Geth except AssertionError: assert abs(gas_estimate - 43020) < 200 # TestRPC pass
def compile_method_definition(contract_name, method_name, method): selector = encode_hex(function_abi_to_4byte_selector(method)) signature = abi_to_signature(method) data_asserts = generate_data_asserts(method).replace('\n', '\n' + 4 * ' ') assign_block = generate_assign_block(method).replace('\n', '\n' + 4 * ' ') try: data_len = compute_data_len(method) except UnsupportedDataType: data_len = None ret = compile_method_declaration(contract_name, method_name, method) if data_len is None: return ret + generate_unsupported_method() return ret + f'''
def __call__(self, instance, *args, **kwargs): for attr, value in instance.__dict__.items(): setattr(self, attr, value) data = encode_hex(function_abi_to_4byte_selector(self.abi)) self.abi['outputs'] = [{'name': '', 'type': self.function(instance, args)}] self.encoded = Contract._encode_abi(self.abi, args, data).decode() self.arguments = dict(zip([arg['name'] for arg in self.abi['inputs']], args)) self.value = 0 return self
def decode_contract_call(contract_abi: list, call_data: str): """ https://ethereum.stackexchange.com/a/33887/34898 """ call_data = call_data.lower().replace("0x", "") call_data_bin = decode_hex(call_data) method_signature = call_data_bin[:4] for description in contract_abi: if description.get('type') != 'function': continue if function_abi_to_4byte_selector(description) == method_signature: method_name = description['name'] arg_types = [item['type'] for item in description['inputs']] args = decode_abi(arg_types, call_data_bin[4:]) return method_name, args
def abi_to_sql(abi, template, contract_address): if abi["type"] == "event": selector = "0x" + event_abi_to_log_topic(abi).hex() else: selector = "0x" + function_abi_to_4byte_selector(abi).hex() struct_fields = create_struct_fields_from_event_abi(abi) columns = get_columns_from_event_abi(abi) return template.render( abi=dumps(abi), contract_address=contract_address.lower(), selector=selector, struct_fields=struct_fields, columns=columns, )
def eth_abi_encode(func: dict, args: list) -> str: """ >> func = {"constant":True,"inputs":[{"name":"","type":"address"}], "name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":False,"stateMutability":"view","type":"function"} >> eth_abi_encode(abi, ['9d3d4cc1986d81f9109f2b091b7732e7d9bcf63b']) >> '70a082310000000000000000000000009d3d4cc1986d81f9109f2b091b7732e7d9bcf63b' ## address must be lower case """ if not func: return "00" types = list([inp['type'] for inp in func.get('inputs', [])]) if func.get('name'): result = function_abi_to_4byte_selector(func) + encode_abi(types, args) else: result = encode_abi(types, args) return result.hex()
def __call__(self, instance, *args, **kwargs): selector = encode_hex(function_abi_to_4byte_selector(self.abi)) if len(args) != 0 and isinstance(args[0], dict): params = self.__order_dict_args(args[0]) else: params = args return { "to": instance.address, "value": 0, "data": Contract._encode_abi(self.abi, params, selector).decode(), "parent": { "inputs": self.abi["inputs"], "outputs": self.abi["outputs"] } }
def _make_call_math_transaction(eth_tester, contract_address, fn_name, fn_args=None): from eth_abi import encode_abi if fn_args is None: fn_args = tuple() fn_abi = MATH_ABI[fn_name] arg_types = [arg_abi['type'] for arg_abi in fn_abi['inputs']] fn_selector = function_abi_to_4byte_selector(fn_abi) transaction = { "from": eth_tester.get_accounts()[0], "to": contract_address, "gas": 500000, "data": encode_hex(fn_selector + encode_abi(arg_types, fn_args)), } return transaction
def func(*args, **kwargs): if attr not in self.abi: raise ValueError("Function name not match this contract") fn = self.abi[attr] if len(fn["inputs"]) != len(args): raise ValueError("Input not match") sig = to_hex(function_abi_to_4byte_selector(fn)) input_type = [p["type"] for p in fn["inputs"]] output_type = [p["type"] for p in fn["outputs"]] data = to_hex(encode_abi(input_type, args)) if "value" in kwargs: value = to_hex(kwargs["value"]) else: value = to_hex(0) raw_output = requests.post( BASE_URL, json={ "jsonrpc": "2.0", "method": "eth_call", "params": [ { "to": self.address, "data": sig + data[2:], "value": value, }, self.block_height, ], "id": 12, }, ).json()["result"] raw_value = decode_abi(output_type, to_bytes(hexstr=raw_output)) if len(raw_value) == 1: return raw_value[0] Custom = namedtuple( "Custom", [decamelize.convert(p["name"]) for p in fn["outputs"]]) return Custom._make(raw_value)
def __init__(self, contractInfo): self.w3 = web3.Web3() self.interface = self.w3.eth.contract(address=contractInfo["address"], abi=contractInfo["abi"]) self.address_string = contractInfo["address"] self.address = eth_utils.to_int(hexstr=self.address_string) self.abi = contractInfo["abi"] self.name = contractInfo["name"] self.funcs = {} self.functions = [] self.code = bytes.fromhex(contractInfo["code"][2:]) self.storage = {} if "storage" in contractInfo: raw_storage = contractInfo["storage"] for item in raw_storage: key = eth_utils.to_int(hexstr=item) self.storage[key] = eth_utils.to_int(hexstr=raw_storage[item]) self.address = eth_utils.to_int(hexstr=contractInfo["address"]) for func_interface in self.interface.abi: if func_interface["type"] == "function": id_bytes = eth_utils.function_abi_to_4byte_selector( func_interface) func_id = eth_utils.big_endian_to_int(id_bytes) self.funcs[func_id] = func_interface elif func_interface["type"] == "event": id_bytes = eth_utils.event_abi_to_log_topic(func_interface) func_id = eth_utils.big_endian_to_int(id_bytes) self.funcs[func_id] = func_interface funcs = [ x for x in dir(self.interface.functions) if x[0] != '_' and x != "abi" ] for func in funcs: setattr( ArbContract, func, generate_func(func, self.interface, contractInfo["address"])) setattr(ArbContract, "_" + func, generate_func2(func, self.interface)) self.functions.append(func)
def get_function_info( fn_name: str, abi_codec: ABICodec, contract_abi: ABI = None, fn_abi: ABIFunction = None, args: Sequence[Any] = None, kwargs: Any = None, ) -> Tuple[ABIFunction, HexStr, Sequence[Any]]: if args is None: args = tuple() if kwargs is None: kwargs = {} if fn_abi is None: fn_abi = find_matching_fn_abi(contract_abi, abi_codec, fn_name, args, kwargs) fn_selector = encode_hex(function_abi_to_4byte_selector(fn_abi)) fn_arguments = merge_args_and_kwargs(fn_abi, args, kwargs) _, aligned_fn_arguments = get_aligned_abi_inputs(fn_abi, fn_arguments) return fn_abi, fn_selector, aligned_fn_arguments
def get_selector(deployments, contract, fn): function_abi = [ x for x in deployments.get_instance(contract).abi if x["name"] == fn ][0] return function_abi_to_4byte_selector(function_abi)
def callable_check(fn_abi): return encode_hex(function_abi_to_4byte_selector( fn_abi)) == to_4byte_hex(selector)
def _generate_selectors_with_abis_from_contract(self, contract: Contract) -> Dict[bytes, ContractFunction]: return {function_abi_to_4byte_selector(contract_fn.abi): contract_fn for contract_fn in contract.all_functions()}
def _set_function_info(self): self.abi = find_matching_fn_abi(self.contract_abi, self.fn_name, self.args, self.kwargs) self.selector = encode_hex(function_abi_to_4byte_selector(self.abi)) self.arguments = merge_args_and_kwargs(self.abi, self.args, self.kwargs)
def _set_function_info(self): self.abi = find_matching_fn_abi(self.contract_abi, self.fn_name, self.args, self.kwargs) self.selector = encode_hex(function_abi_to_4byte_selector(self.abi)) self.arguments = merge_args_and_kwargs(self.abi, self.args, self.kwargs)
def calc_function_selector(abi_json: dict) -> bytes: ''' Calculate the function selector (4 bytes) from the abi json ''' f = FUNCTION(abi_json) return eth_utils.function_abi_to_4byte_selector(f)
print batchtimes[-50:] while True: batch_start_nonce = w3.eth.getTransactionCount(pool_addr) curr_nonce = batch_start_nonce while True: try: w3.personal.unlockAccount(pool_addr, '') break except: pass t0 = time.time() # do tx fn_abi = abi[4] assert fn_abi['name'] == 'mint' fn_selector = function_abi_to_4byte_selector(fn_abi) if gas_price > max_buy: gas_price = max_buy assert (gas_price <= max_buy) # sanity check circuit breaker for i in range(0, batch_size): transaction = { "from": pool_addr, "to": contract_address, "gas": 999999, # 982615, 0x1a | 216k 5 "gasPrice": (gas_price), "data": encode_hex(fn_selector + encode_abi(["uint256"], [0x1a])), "nonce": curr_nonce } txn_hash = None while True: try:
def abi_to_selector(parser_type, abi): if parser_type == 'log': return '0x' + event_abi_to_log_topic(abi).hex() else: return '0x' + function_abi_to_4byte_selector(abi).hex()
def abi_to_method_selector(abi): return '0x' + function_abi_to_4byte_selector(abi).hex()
from vyper import compiler from eth_utils import function_abi_to_4byte_selector import binascii casper_abi = compiler.mk_full_signature( open("../casper/casper/contracts/simple_casper.v.py").read()) for item in casper_abi: b = ''.join( [f'\\x{l:02x}' for l in list(function_abi_to_4byte_selector(item))]) print(item["name"], '\t', b)
def callable_check(fn_abi): return encode_hex(function_abi_to_4byte_selector(fn_abi)) == to_4byte_hex(selector)