def is_encodable(_type, value): if not isinstance(_type, str): raise ValueError("is_encodable only accepts type strings") base, sub, arrlist = process_type(_type) if arrlist: if not is_list_like(value): return False if arrlist[-1] and len(value) != arrlist[-1][0]: return False sub_type = (base, sub, arrlist[:-1]) return all(is_encodable(collapse_type(*sub_type), sub_value) for sub_value in value) elif base == 'address' and is_ens_name(value): # ENS names can be used anywhere an address is needed # Web3.py will resolve the name to an address before encoding it return True elif base == 'bytes' and isinstance(value, str): # Hex-encoded bytes values can be used anywhere a bytes value is needed if is_hex(value) and len(value) % 2 == 0: # Require hex-encoding of full bytes (even length) bytes_val = to_bytes(hexstr=value) return eth_abi_is_encodable(_type, bytes_val) else: return False elif base == 'string' and isinstance(value, bytes): # bytes that were encoded with utf-8 can be used anywhere a string is needed try: string_val = to_text(value) except UnicodeDecodeError: return False else: return eth_abi_is_encodable(_type, string_val) else: return eth_abi_is_encodable(_type, value)
def is_encodable(_type, value): try: base, sub, arrlist = _type except ValueError: base, sub, arrlist = process_type(_type) if arrlist: if not is_list_like(value): return False if arrlist[-1] and len(value) != arrlist[-1][0]: return False sub_type = (base, sub, arrlist[:-1]) return all(is_encodable(sub_type, sub_value) for sub_value in value) elif base == 'address' and is_ens_name(value): # ENS names can be used anywhere an address is needed # Web3.py will resolve the name to an address before encoding it return True elif base == 'bytes' and isinstance(value, str): # Hex-encoded bytes values can be used anywhere a bytes value is needed if is_hex(value) and len(value) % 2 == 0: # Require hex-encoding of full bytes (even length) bytes_val = to_bytes(hexstr=value) return eth_abi_is_encodable(_type, bytes_val) else: return False elif base == 'string' and isinstance(value, bytes): # bytes that were encoded with utf-8 can be used anywhere a string is needed try: string_val = to_text(value) except UnicodeDecodeError: return False else: return eth_abi_is_encodable(_type, string_val) else: return eth_abi_is_encodable(_type, value)
def function_definition_to_kwargs(function_abi): """ Construct kwargs suitable for submitting a function signature to the signature DB """ kwargs = { '_name': function_abi['name'], 'dataTypes': [], 'subs': [], 'arrListLengths': [], 'arrListsDynamic': [], 'arrListsSize': [], } for argument_abi in function_abi['inputs']: kwargs['dataTypes'].append(DataTypes.from_string(argument_abi['type'])) base, sub, arrlist = process_type(argument_abi['type']) if sub: kwargs['subs'].append(int(sub)) else: kwargs['subs'].append(0) kwargs['arrListLengths'].append(len(arrlist)) for arr_value in arrlist: kwargs['arrListsDynamic'].append(not bool(arr_value)) if arr_value: kwargs['arrListsSize'].append(arr_value[0]) else: kwargs['arrListsSize'].append(0) return kwargs
def is_encodable(_type, value): try: base, sub, arrlist = _type except ValueError: base, sub, arrlist = process_type(_type) if arrlist: if not is_list_like(value): return False if arrlist[-1] and len(value) != arrlist[-1][0]: return False sub_type = (base, sub, arrlist[:-1]) return all(is_encodable(sub_type, sub_value) for sub_value in value) elif base == 'bool': return is_boolean(value) elif base == 'uint': if not is_integer(value): return False exp = int(sub) if value < 0 or value >= 2**exp: return False return True elif base == 'int': if not is_integer(value): return False exp = int(sub) if value <= -1 * 2**(exp - 1) or value >= 2**(exp - 1): return False return True elif base == 'string': if not is_string(value): return False return True elif base == 'bytes': if not is_string(value): return False if not sub: return True max_length = int(sub) if isinstance(value, str): decodable = is_hex(value) and len(value) % 2 == 0 return decodable and len(decode_hex(value)) <= max_length elif isinstance(value, bytes): return len(value) <= max_length else: return False elif base == 'address': if is_ens_name(value): return True elif is_address(value): return True else: return False else: raise ValueError("Unsupported type")
def is_dynamic_sized_type(_type): base_type, type_size, arrlist = process_type(_type) if arrlist: return True elif base_type == 'string': return True elif base_type == 'bytes' and type_size == '': return True return False
def is_dynamic_sized_type(_type): base_type, type_size, arrlist = process_type(_type) if arrlist: return True elif base_type == 'string': return True elif base_type == 'bytes' and type_size == '': return True return False
def abi_bytes_to_hex(abi_type, data): base, sub, arrlist = process_type(abi_type) if base == 'bytes' and not arrlist: bytes_data = hexstr_if_str(to_bytes, data) if len(bytes_data) != int(sub): raise ValueError( "This value was expected to be %d bytes, but instead was %d: %r" % ((sub, len(bytes_data), data))) return abi_type, to_hex(bytes_data)
def is_encodable(_type, value): try: base, sub, arrlist = _type except ValueError: base, sub, arrlist = process_type(_type) if arrlist: if not is_list_like(value): return False if arrlist[-1] and len(value) != arrlist[-1][0]: return False sub_type = (base, sub, arrlist[:-1]) return all(is_encodable(sub_type, sub_value) for sub_value in value) elif base == 'bool': return is_boolean(value) elif base == 'uint': if not is_integer(value): return False exp = int(sub) if value < 0 or value >= 2**exp: return False return True elif base == 'int': if not is_integer(value): return False exp = int(sub) if value <= -1 * 2**(exp - 1) or value >= 2**(exp - 1): return False return True elif base == 'string': if not is_string(value): return False return True elif base == 'bytes': if not is_string(value): return False if not sub: return True max_length = int(sub) if isinstance(value, str): decodable = is_hex(value) and len(value) % 2 == 0 return decodable and len(decode_hex(value)) <= max_length elif isinstance(value, bytes): return len(value) <= max_length else: False elif base == 'address': if is_ens_name(value): return True elif is_address(value): return True else: return False else: raise ValueError("Unsupported type")
def normalize_return_type(data_type, data_value): try: base, sub, arrlist = data_type except ValueError: base, sub, arrlist = process_type(data_type) if arrlist: sub_type = (base, sub, arrlist[:-1]) return [normalize_return_type(sub_type, sub_value) for sub_value in data_value] elif base == 'address': return add_0x_prefix(data_value) else: return data_value
def normalize_return_type(data_type, data_value): try: base, sub, arrlist = data_type except ValueError: base, sub, arrlist = process_type(data_type) if arrlist: sub_type = (base, sub, arrlist[:-1]) return [normalize_return_type(sub_type, sub_value) for sub_value in data_value] elif base == 'address': return add_0x_prefix(data_value) else: return data_value
def abi_bytes_to_hex(abi_type, data): base, sub, arrlist = process_type(abi_type) if base == 'bytes' and not arrlist: bytes_data = hexstr_if_str(to_bytes, data) if not sub: return abi_type, to_hex(bytes_data) else: num_bytes = int(sub) if len(bytes_data) <= num_bytes: padded = bytes_data.ljust(num_bytes, b'\0') return abi_type, to_hex(padded) else: raise ValueError( "This value was expected to be at most %d bytes, but instead was %d: %r" % ((num_bytes, len(bytes_data), data)))
def abi_sub_tree(data_type, data_value): try: base, sub, arrlist = data_type except ValueError: base, sub, arrlist = process_type(data_type) collapsed = collapse_type(base, sub, arrlist) if arrlist: sub_type = (base, sub, arrlist[:-1]) return ABITypedData([ collapsed, [abi_sub_tree(sub_type, sub_value) for sub_value in data_value], ]) else: return ABITypedData([collapsed, data_value])
def abi_bytes_to_hex(abi_type, data): base, sub, arrlist = process_type(abi_type) if base == 'bytes' and not arrlist: bytes_data = hexstr_if_str(to_bytes, data) if not sub: return abi_type, to_hex(bytes_data) else: num_bytes = int(sub) if len(bytes_data) <= num_bytes: padded = bytes_data.ljust(num_bytes, b'\0') return abi_type, to_hex(padded) else: raise ValueError( "This value was expected to be at most %d bytes, but instead was %d: %r" % ( (num_bytes, len(bytes_data), data) ) )
def validate_argument(_type, value): base, sub, arr_list = abi.process_type(_type) if arr_list: arr_value, remainder = arr_list[-1], arr_list[:-1] if arr_value and len(value) != arr_value[0]: return False subtype = ''.join((base, sub, ''.join((str(v) for v in remainder)))) return all(validate_argument(subtype, v) for v in value) elif base == 'int': if not isinstance(value, utils.int_types): return False exp = int(sub) lower_bound = -1 * 2**exp // 2 upper_bound = (2**exp) // 2 - 1 return lower_bound <= value <= upper_bound elif base == 'uint': if not isinstance(value, utils.int_types): return False exp = int(sub) lower_bound = 0 upper_bound = (2**exp) - 1 return lower_bound <= value <= upper_bound elif base == 'address': if not isinstance(value, utils.text_types): return False _value = value[2:] if value.startswith('0x') else value if set(_value).difference('1234567890abcdef'): return False return len(_value) == 40 elif base == 'bytes': if not isinstance(value, utils.text_types): return False try: max_length = int(sub) except ValueError: if sub == '': return True raise return len(value) <= max_length elif base == 'string': return isinstance(value, utils.text_types) else: raise ValueError("Unsupported base: '{0}'".format(base))
def validate_argument(_type, value): base, sub, arr_list = abi.process_type(_type) if arr_list: arr_value, remainder = arr_list[-1], arr_list[:-1] if arr_value and len(value) != arr_value[0]: return False subtype = ''.join((base, sub, ''.join((str(v) for v in remainder)))) return all(validate_argument(subtype, v) for v in value) elif base == 'int': if not isinstance(value, (int, long)): return False exp = int(sub) lower_bound = -1 * 2 ** exp / 2 upper_bound = (2 ** exp) / 2 - 1 return lower_bound <= value <= upper_bound elif base == 'uint': if not isinstance(value, (int, long)): return False exp = int(sub) lower_bound = 0 upper_bound = (2 ** exp) - 1 return lower_bound <= value <= upper_bound elif base == 'address': if not isinstance(value, basestring): return False _value = value[2:] if value.startswith('0x') else value if set(_value).difference('1234567890abcdef'): return False return len(_value) == 40 elif base == 'bytes': if not isinstance(value, basestring): return False try: max_length = int(sub) except ValueError: if sub == '': return True raise return len(value) <= max_length elif base == 'string': return isinstance(value, basestring) else: raise ValueError("Unsupported base: '{0}'".format(base))
def from_string(cls, type_string): base, sub, _ = process_type(type_string) if base == 'bytes': if sub: return cls.BytesFixed else: return cls.BytesDynamic elif base == 'string': return cls.String elif base == 'int': return cls.Int elif base == 'uint': return cls.UInt elif base == 'bool': return cls.Bool elif base == 'address': return cls.Address else: raise ValueError("Unknown type: {0}".format(type_string))
def utils_abi_is_encodable(_type, value): from eth_utils import is_integer from eth_abi.abi import process_type try: base, sub, arrlist = _type except ValueError: base, sub, arrlist = process_type(_type) if not arrlist: if base == 'fixed' and not arrlist: return True elif base == 'int': if not is_integer(value): return False exp = int(sub) if value < -1 * 2**(exp - 1) or value > 2**(exp - 1) + 1: return False return True # default behaviour return original_is_encodable(_type, value)
def is_encodable(_type, value): try: base, sub, arrlist = _type except ValueError: base, sub, arrlist = process_type(_type) if arrlist: if not is_array(value): return False if arrlist[-1] and len(value) != arrlist[-1][0]: return False sub_type = (base, sub, arrlist[:-1]) return all(is_encodable(sub_type, sub_value) for sub_value in value) elif base == 'bool': return is_boolean(value) elif base == 'uint': if not is_integer(value): return False exp = int(sub) if value < 0 or value >= 2**exp: return False return True elif base == 'int': if not is_integer(value): return False exp = int(sub) if value <= -1 * 2**(exp - 1) or value >= 2**(exp - 1): return False return True elif base == 'bytes': if not is_string(value): return False if not sub: return True max_length = int(sub) return len(value) <= max_length else: raise ValueError("Unsupported type")
def abi_sub_tree(data_type, data_value): if data_type is None: return ABITypedData([None, data_value]) try: base, sub, arrlist = data_type except ValueError: base, sub, arrlist = process_type(data_type) collapsed = collapse_type(base, sub, arrlist) if arrlist: sub_type = (base, sub, arrlist[:-1]) return ABITypedData([ collapsed, [ abi_sub_tree(sub_type, sub_value) for sub_value in data_value ], ]) else: return ABITypedData([collapsed, data_value])
def hexstrs_to_bytes(abi_type, data): base, sub, arrlist = process_type(abi_type) if base in {'string', 'bytes'}: return abi_type, hexstr_if_str(to_bytes, data)
def abi_int_to_hex(abi_type, data): base, _sub, arrlist = process_type(abi_type) if base == 'uint' and not arrlist: return abi_type, hexstr_if_str(to_hex, data)
def abi_bytes_to_bytes(abi_type, data): base, sub, arrlist = process_type(abi_type) if base == 'bytes' and not arrlist: return abi_type, hexstr_if_str(to_bytes, data)
def abi_bytes_to_bytes(abi_type, data): base, sub, arrlist = process_type(abi_type) if base == 'bytes' and not arrlist: return abi_type, hexstr_if_str(to_bytes, data)