def to_bool(expr, args, kwargs, context): in_arg = args[0] input_type, _ = get_type(in_arg) if input_type == 'bytes': if in_arg.typ.maxlen > 32: raise TypeMismatchException( "Cannot convert bytes array of max length {} to bool".format( in_arg.value, ), expr, ) else: num = byte_array_to_num(in_arg, expr, 'uint256') return LLLnode.from_list( ['iszero', ['iszero', num]], typ=BaseType('bool'), pos=getpos(expr) ) else: return LLLnode.from_list( ['iszero', ['iszero', in_arg]], typ=BaseType('bool', in_arg.typ.unit), pos=getpos(expr) )
def to_int128(expr, args, kwargs, context): in_node = args[0] input_type, _ = get_type(in_node) if input_type in ('uint256', 'bytes32'): if in_node.typ.is_literal and not SizeLimits.in_bounds( 'int128', in_node.value): raise InvalidLiteralException( "Number out of range: {}".format(in_node.value), expr) return LLLnode.from_list([ 'clamp', ['mload', MemoryPositions.MINNUM], in_node, ['mload', MemoryPositions.MAXNUM] ], typ=BaseType('int128', in_node.typ.unit), pos=getpos(expr)) elif input_type is 'bytes': if in_node.typ.maxlen > 32: raise InvalidLiteralException( "Cannot convert bytes array of max length {} to int128".format( in_node.value), expr) return byte_array_to_num(in_node, expr, 'int128') elif input_type is 'bool': return LLLnode.from_list([ 'clamp', ['mload', MemoryPositions.MINNUM], in_node, ['mload', MemoryPositions.MAXNUM] ], typ=BaseType('int128', in_node.typ.unit), pos=getpos(expr)) else: raise InvalidLiteralException("Invalid input for int128: %r" % in_node, expr)
def pack_logging_topics(event_id, args, expected_topics, context, pos): topics = [event_id] for pos, expected_topic in enumerate(expected_topics): expected_type = expected_topic.typ arg = args[pos] value = parse_expr(arg, context) arg_type = value.typ if isinstance(arg_type, ByteArrayType) and isinstance(expected_type, ByteArrayType): if arg_type.maxlen > expected_type.maxlen: raise TypeMismatchException("Topic input bytes are too big: %r %r" % (arg_type, expected_type), pos) if isinstance(arg, ast.Str): bytez, bytez_length = string_to_bytes(arg.s) if len(bytez) > 32: raise InvalidLiteralException("Can only log a maximum of 32 bytes at a time.", pos) topics.append(bytes_to_int(bytez + b'\x00' * (32 - bytez_length))) else: if value.location == "memory": size = ['mload', value] elif value.location == "storage": size = ['sload', ['sha3_32', value]] topics.append(byte_array_to_num(value, arg, 'uint256', size)) else: value = unwrap_location(value) value = base_type_conversion(value, arg_type, expected_type, pos=pos) topics.append(value) return topics
def to_uint256(expr, args, kwargs, context): in_arg = args[0] input_type, _ = get_type(in_arg) _unit = in_arg.typ.unit if input_type in ('int128', 'decimal') else None if input_type == 'num_literal': if isinstance(in_arg, int): if not SizeLimits.in_bounds('uint256', in_arg): raise InvalidLiteralException( "Number out of range: {}".format(in_arg)) return LLLnode.from_list(in_arg, typ=BaseType('uint256', _unit), pos=getpos(expr)) elif isinstance(in_arg, float): if not SizeLimits.in_bounds('uint256', math.trunc(in_arg)): raise InvalidLiteralException("Number out of range: {}".format( math.trunc(in_arg))) return LLLnode.from_list(math.trunc(in_arg), typ=BaseType('uint256', _unit), pos=getpos(expr)) else: raise InvalidLiteralException( "Unknown numeric literal type: {}".fornat(in_arg)) elif isinstance(in_arg, LLLnode) and input_type == 'int128': return LLLnode.from_list(['clampge', in_arg, 0], typ=BaseType('uint256', _unit), pos=getpos(expr)) elif isinstance(in_arg, LLLnode) and input_type == 'decimal': return LLLnode.from_list( ['div', ['clampge', in_arg, 0], DECIMAL_DIVISOR], typ=BaseType('uint256', _unit), pos=getpos(expr)) elif isinstance(in_arg, LLLnode) and input_type == 'bool': return LLLnode.from_list(in_arg, typ=BaseType('uint256'), pos=getpos(expr)) elif isinstance(in_arg, LLLnode) and input_type in ('bytes32', 'address'): return LLLnode(value=in_arg.value, args=in_arg.args, typ=BaseType('uint256'), pos=getpos(expr)) elif isinstance(in_arg, LLLnode) and input_type == 'bytes': if in_arg.typ.maxlen > 32: raise InvalidLiteralException( "Cannot convert bytes array of max length {} to uint256". format(in_arg.value), expr, ) return byte_array_to_num(in_arg, expr, 'uint256') else: raise InvalidLiteralException("Invalid input for uint256: %r" % in_arg, expr)
def to_int128(expr, args, kwargs, context): input = args[0] typ, len = get_type(input) if typ in ('int128', 'uint256', 'bytes32'): return LLLnode.from_list( ['clamp', ['mload', MemoryPositions.MINNUM], input, ['mload', MemoryPositions.MAXNUM]], typ=BaseType('int128'), pos=getpos(expr) ) else: return byte_array_to_num(input, expr, 'int128')
def to_int128(expr, args, kwargs, context): in_node = args[0] typ, len = get_type(in_node) if typ in ('int128', 'uint256', 'bytes32'): if in_node.typ.is_literal and not SizeLimits.in_bounds( 'int128', in_node.value): raise InvalidLiteralException( "Number out of range: {}".format(in_node.value), expr) return LLLnode.from_list([ 'clamp', ['mload', MemoryPositions.MINNUM], in_node, ['mload', MemoryPositions.MAXNUM] ], typ=BaseType('int128', in_node.typ.unit), pos=getpos(expr)) if in_node.typ.is_literal and in_node[:2] == '0x': return byte_array_to_num(binascii.unhexlify(in_node[2:]), expr, 'int128') else: return byte_array_to_num(in_node, expr, 'int128')
def to_uint256(expr, args, kwargs, context): in_arg = args[0] input_type, _ = get_type(in_arg) if input_type == "num_literal": if isinstance(in_arg, int): if not SizeLimits.in_bounds("uint256", in_arg): raise InvalidLiteral(f"Number out of range: {in_arg}") return LLLnode.from_list(in_arg, typ=BaseType("uint256", ), pos=getpos(expr)) elif isinstance(in_arg, Decimal): if not SizeLimits.in_bounds("uint256", math.trunc(in_arg)): raise InvalidLiteral( f"Number out of range: {math.trunc(in_arg)}") return LLLnode.from_list(math.trunc(in_arg), typ=BaseType("uint256"), pos=getpos(expr)) else: raise InvalidLiteral(f"Unknown numeric literal type: {in_arg}") elif isinstance(in_arg, LLLnode) and input_type == "int128": return LLLnode.from_list(["clampge", in_arg, 0], typ=BaseType("uint256"), pos=getpos(expr)) elif isinstance(in_arg, LLLnode) and input_type == "decimal": return LLLnode.from_list( ["div", ["clampge", in_arg, 0], DECIMAL_DIVISOR], typ=BaseType("uint256"), pos=getpos(expr), ) elif isinstance(in_arg, LLLnode) and input_type == "bool": return LLLnode.from_list(in_arg, typ=BaseType("uint256"), pos=getpos(expr)) elif isinstance(in_arg, LLLnode) and input_type in ("bytes32", "address"): return LLLnode(value=in_arg.value, args=in_arg.args, typ=BaseType("uint256"), pos=getpos(expr)) elif isinstance(in_arg, LLLnode) and input_type == "Bytes": if in_arg.typ.maxlen > 32: raise InvalidLiteral( f"Cannot convert bytes array of max length {in_arg.typ.maxlen} to uint256", expr, ) return byte_array_to_num(in_arg, expr, "uint256") else: raise InvalidLiteral(f"Invalid input for uint256: {in_arg}", expr)
def to_decimal(expr, args, kwargs, context): in_arg = args[0] input_type, _ = get_type(in_arg) if input_type == 'bytes': if in_arg.typ.maxlen > 32: raise TypeMismatchException( "Cannot convert bytes array of max length {} to decimal". format(in_arg.value), expr) num = byte_array_to_num(in_arg, expr, 'int128') return LLLnode.from_list(['mul', num, DECIMAL_DIVISOR], typ=BaseType('decimal'), pos=getpos(expr)) else: _unit = in_arg.typ.unit _positional = in_arg.typ.positional if input_type == 'uint256': if in_arg.typ.is_literal and not SizeLimits.in_bounds( 'int128', (in_arg.value * DECIMAL_DIVISOR)): raise InvalidLiteralException( "Number out of range: {}".format(in_arg.value), expr) return LLLnode.from_list([ 'uclample', ['mul', in_arg, DECIMAL_DIVISOR], ['mload', MemoryPositions.MAXDECIMAL] ], typ=BaseType('decimal', _unit, _positional), pos=getpos(expr)) elif input_type == 'bytes32': if in_arg.typ.is_literal and not SizeLimits.in_bounds( 'int128', (in_arg.value * DECIMAL_DIVISOR)): raise InvalidLiteralException( "Number out of range: {}".format(in_arg.value), expr) return LLLnode.from_list([ 'clamp', ['mload', MemoryPositions.MINDECIMAL], ['mul', in_arg, DECIMAL_DIVISOR], ['mload', MemoryPositions.MAXDECIMAL] ], typ=BaseType('decimal', _unit, _positional), pos=getpos(expr)) elif input_type in ('int128', 'bool'): return LLLnode.from_list(['mul', in_arg, DECIMAL_DIVISOR], typ=BaseType('decimal', _unit, _positional), pos=getpos(expr)) else: raise InvalidLiteralException( "Invalid input for decimal: %r" % in_arg, expr)
def to_bool(expr, args, kwargs, context): in_arg = args[0] input_type, _ = get_type(in_arg) if input_type == "Bytes": if in_arg.typ.maxlen > 32: raise TypeMismatch( f"Cannot convert bytes array of max length {in_arg.typ.maxlen} to bool", expr, ) else: num = byte_array_to_num(in_arg, expr, "uint256") return LLLnode.from_list( ["iszero", ["iszero", num]], typ=BaseType("bool"), pos=getpos(expr) ) else: return LLLnode.from_list( ["iszero", ["iszero", in_arg]], typ=BaseType("bool"), pos=getpos(expr) )
def pack_logging_topics(event_id, args, expected_topics, context, pos): topics = [event_id] code_pos = pos for pos, expected_topic in enumerate(expected_topics): expected_type = expected_topic.typ arg = args[pos] value = Expr(arg, context).lll_node arg_type = value.typ if isinstance(arg_type, ByteArrayLike) and isinstance( expected_type, ByteArrayLike): if arg_type.maxlen > expected_type.maxlen: raise TypeMismatch( f"Topic input bytes are too big: {arg_type} {expected_type}", code_pos) if isinstance(arg, vy_ast.Str): bytez, bytez_length = string_to_bytes(arg.s) if len(bytez) > 32: raise InvalidLiteral( "Can only log a maximum of 32 bytes at a time.", code_pos) topics.append( bytes_to_int(bytez + b'\x00' * (32 - bytez_length))) else: if value.location == "memory": size = ['mload', value] elif value.location == "storage": size = ['sload', ['sha3_32', value]] topics.append(byte_array_to_num(value, arg, 'uint256', size)) else: if arg_type != expected_type: raise TypeMismatch( f"Invalid type for logging topic, got {arg_type} expected {expected_type}", value.pos) value = unwrap_location(value) value = base_type_conversion(value, arg_type, expected_type, pos=code_pos) topics.append(value) return topics
def to_bool(expr, args, kwargs, context): in_arg = args[0] input_type, _ = get_type(in_arg) if input_type == 'bytes': if in_arg.typ.maxlen > 32: raise TypeMismatchException( "Cannot convert bytes array of max length {} to int128".format( in_arg.value), expr) else: num = byte_array_to_num(in_arg, expr, 'uint256') return LLLnode.from_list(['iszero', ['iszero', num]], typ=BaseType('bool'), pos=getpos(expr)) elif in_arg.typ.is_literal and in_arg.typ.typ == 'bool': raise InvalidLiteralException( "Cannot convert to `bool` with boolean input literal.", expr) else: return LLLnode.from_list(['iszero', ['iszero', in_arg]], typ=BaseType('bool', in_arg.typ.unit), pos=getpos(expr))
def to_uint256(expr, args, kwargs, context): in_node = args[0] input_type, _ = get_type(in_node) if isinstance(in_node, int): if not SizeLimits.in_bounds('uint256', in_node): raise InvalidLiteralException( "Number out of range: {}".format(in_node)) _unit = in_node.typ.unit if input_type == 'int128' else None return LLLnode.from_list(in_node, typ=BaseType('uint256', _unit), pos=getpos(expr)) elif isinstance( in_node, LLLnode) and input_type in ('int128', 'num_literal', 'bool'): _unit = in_node.typ.unit if input_type == 'int128' else None return LLLnode.from_list(['clampge', in_node, 0], typ=BaseType('uint256', _unit), pos=getpos(expr)) elif isinstance(in_node, LLLnode) and input_type in ('bytes32', 'address'): return LLLnode(value=in_node.value, args=in_node.args, typ=BaseType('uint256'), pos=getpos(expr)) elif isinstance(in_node, LLLnode) and input_type is 'bytes': if in_node.typ.maxlen > 32: raise InvalidLiteralException( "Cannot convert bytes array of max length {} to uint256". format(in_node.value), expr) return byte_array_to_num(in_node, expr, 'uint256') else: raise InvalidLiteralException( "Invalid input for uint256: %r" % in_node, expr)
def _RLPlist(expr, args, kwargs, context): # Second argument must be a list of types if not isinstance(args[1], ast.List): raise TypeMismatchException("Expecting list of types for second argument", args[1]) if len(args[1].elts) == 0: raise TypeMismatchException("RLP list must have at least one item", expr) if len(args[1].elts) > 32: raise TypeMismatchException("RLP list must have at most 32 items", expr) # Get the output format _format = [] for arg in args[1].elts: if isinstance(arg, ast.Name) and arg.id == "bytes": subtyp = ByteArrayType(args[0].typ.maxlen) else: subtyp = context.parse_type(arg, 'memory') if not isinstance(subtyp, BaseType): raise TypeMismatchException("RLP lists only accept BaseTypes and byte arrays", arg) if not is_base_type(subtyp, ('int128', 'uint256', 'bytes32', 'address', 'bool')): raise TypeMismatchException("Unsupported base type: %s" % subtyp.typ, arg) _format.append(subtyp) output_type = TupleType(_format) output_placeholder_type = ByteArrayType( (2 * len(_format) + 1 + get_size_of_type(output_type)) * 32, ) output_placeholder = context.new_placeholder(output_placeholder_type) output_node = LLLnode.from_list( output_placeholder, typ=output_placeholder_type, location='memory', ) # Create a decoder for each element in the tuple decoder = [] for i, typ in enumerate(_format): # Decoder for bytes32 if is_base_type(typ, 'bytes32'): decoder.append(LLLnode.from_list( [ 'seq', [ 'assert', [ 'eq', [ 'mload', [ 'add', output_node, ['mload', ['add', output_node, 32 * i]], ], ], 32, ], ], [ 'mload', [ 'add', 32, [ 'add', output_node, ['mload', ['add', output_node, 32 * i]], ], ], ], ], typ, annotation='getting and checking bytes32 item', )) # Decoder for address elif is_base_type(typ, 'address'): decoder.append(LLLnode.from_list( [ 'seq', [ 'assert', [ 'eq', [ 'mload', [ 'add', output_node, ['mload', ['add', output_node, 32 * i]], ], ], 20, ] ], [ 'mod', [ 'mload', [ 'add', 20, ['add', output_node, ['mload', ['add', output_node, 32 * i]]], ], ], ['mload', MemoryPositions.ADDRSIZE], ] ], typ, annotation='getting and checking address item', )) # Decoder for bytes elif isinstance(typ, ByteArrayType): decoder.append(LLLnode.from_list( [ 'add', output_node, ['mload', ['add', output_node, 32 * i]], ], typ, location='memory', annotation='getting byte array', )) # Decoder for num and uint256 elif is_base_type(typ, ('int128', 'uint256')): bytez = LLLnode.from_list( [ 'add', output_node, ['mload', ['add', output_node, 32 * i]], ], typ, location='memory', annotation='getting and checking %s' % typ.typ, ) decoder.append(byte_array_to_num(bytez, expr, typ.typ)) # Decoder for bools elif is_base_type(typ, ('bool')): # This is basically a really clever way to test for a # length-prefixed one or zero. We take the 32 bytes starting one # byte *after* the start of the length declaration; this includes # the last 31 bytes of the length and the first byte of the value. # 0 corresponds to length 0, first byte 0, and 257 corresponds to # length 1, first byte \x01 decoder.append(LLLnode.from_list( [ 'with', '_ans', [ 'mload', [ 'add', 1, ['add', output_node, ['mload', ['add', output_node, 32 * i]]] ], ], [ 'seq', ['assert', ['or', ['eq', '_ans', 0], ['eq', '_ans', 257]]], ['div', '_ans', 257], ], ], typ, annotation='getting and checking bool', )) else: # Should never reach because of top level base level check. raise Exception("Type not yet supported") # pragma: no cover # Copy the input data to memory if args[0].location == "memory": variable_pointer = args[0] elif args[0].location == "storage": placeholder = context.new_placeholder(args[0].typ) placeholder_node = LLLnode.from_list(placeholder, typ=args[0].typ, location='memory') copier = make_byte_array_copier( placeholder_node, LLLnode.from_list('_ptr', typ=args[0].typ, location=args[0].location), ) variable_pointer = ['with', '_ptr', args[0], ['seq', copier, placeholder_node]] else: # Should never reach because of top level base level check. raise Exception("Location not yet supported") # pragma: no cover # Decode the input data initial_setter = LLLnode.from_list( ['seq', ['with', '_sub', variable_pointer, ['pop', ['call', 1500 + 400 * len(_format) + 10 * len(args), LLLnode.from_list(RLP_DECODER_ADDRESS, annotation='RLP decoder'), 0, ['add', '_sub', 32], ['mload', '_sub'], output_node, 64 * len(_format) + 32 + 32 * get_size_of_type(output_type)]]], ['assert', ['eq', ['mload', output_node], 32 * len(_format) + 32]]], typ=None) # Shove the input data decoder in front of the first variable decoder decoder[0] = LLLnode.from_list( ['seq', initial_setter, decoder[0]], typ=decoder[0].typ, location=decoder[0].location, ) return LLLnode.from_list( ["multi"] + decoder, typ=output_type, location='memory', pos=getpos(expr), )
def bytes_to_num(expr, args, kwargs, context): return byte_array_to_num(args[0], expr, 'num')
def to_int128(expr, args, kwargs, context): in_arg = args[0] input_type, _ = get_type(in_arg) _unit = in_arg.typ.unit if input_type in ('uint256', 'decimal') else None if input_type == 'num_literal': if isinstance(in_arg, int): if not SizeLimits.in_bounds('int128', in_arg): raise InvalidLiteralException( "Number out of range: {}".format(in_arg)) return LLLnode.from_list(in_arg, typ=BaseType('int128', _unit), pos=getpos(expr)) elif isinstance(in_arg, float): if not SizeLimits.in_bounds('int128', math.trunc(in_arg)): raise InvalidLiteralException("Number out of range: {}".format( math.trunc(in_arg))) return LLLnode.from_list(math.trunc(in_arg), typ=BaseType('int128', _unit), pos=getpos(expr)) else: raise InvalidLiteralException( "Unknown numeric literal type: {}".fornat(in_arg)) elif input_type == 'bytes32': if in_arg.typ.is_literal: if not SizeLimits.in_bounds('int128', in_arg.value): raise InvalidLiteralException( "Number out of range: {}".format(in_arg.value), expr) else: return LLLnode.from_list(in_arg, typ=BaseType('int128', _unit), pos=getpos(expr)) else: return LLLnode.from_list([ 'clamp', ['mload', MemoryPositions.MINNUM], in_arg, ['mload', MemoryPositions.MAXNUM], ], typ=BaseType('int128', _unit), pos=getpos(expr)) elif input_type in ('string', 'bytes'): if in_arg.typ.maxlen > 32: raise TypeMismatchException( "Cannot convert bytes array of max length {} to int128".format( in_arg.value), expr, ) return byte_array_to_num(in_arg, expr, 'int128') elif input_type == 'uint256': if in_arg.typ.is_literal: if not SizeLimits.in_bounds('int128', in_arg.value): raise InvalidLiteralException( "Number out of range: {}".format(in_arg.value), expr) else: return LLLnode.from_list(in_arg, typ=BaseType('int128', _unit), pos=getpos(expr)) else: return LLLnode.from_list( ['uclample', in_arg, ['mload', MemoryPositions.MAXNUM]], typ=BaseType('int128', _unit), pos=getpos(expr)) elif input_type == 'decimal': return LLLnode.from_list([ 'clamp', ['mload', MemoryPositions.MINNUM], ['sdiv', in_arg, DECIMAL_DIVISOR], ['mload', MemoryPositions.MAXNUM], ], typ=BaseType('int128', _unit), pos=getpos(expr)) elif input_type == 'bool': return LLLnode.from_list(in_arg, typ=BaseType('int128', _unit), pos=getpos(expr)) else: raise InvalidLiteralException("Invalid input for int128: %r" % in_arg, expr)
def to_decimal(expr, args, kwargs, context): in_arg = args[0] input_type, _ = get_type(in_arg) if input_type == 'bytes': if in_arg.typ.maxlen > 32: raise TypeMismatch( f"Cannot convert bytes array of max length {in_arg.typ.maxlen} to decimal", expr, ) num = byte_array_to_num(in_arg, expr, 'int128') return LLLnode.from_list(['mul', num, DECIMAL_DIVISOR], typ=BaseType('decimal'), pos=getpos(expr)) else: _unit = in_arg.typ.unit _positional = in_arg.typ.positional if input_type == 'uint256': if in_arg.typ.is_literal: if not SizeLimits.in_bounds('int128', (in_arg.value * DECIMAL_DIVISOR)): raise InvalidLiteral( f"Number out of range: {in_arg.value}", expr, ) else: return LLLnode.from_list(['mul', in_arg, DECIMAL_DIVISOR], typ=BaseType( 'decimal', _unit, _positional), pos=getpos(expr)) else: return LLLnode.from_list([ 'uclample', ['mul', in_arg, DECIMAL_DIVISOR], ['mload', MemoryPositions.MAXDECIMAL] ], typ=BaseType('decimal', _unit, _positional), pos=getpos(expr)) elif input_type == 'address': return LLLnode.from_list([ 'mul', [ 'signextend', 15, ['and', in_arg, (SizeLimits.ADDRSIZE - 1)], ], DECIMAL_DIVISOR ], typ=BaseType('decimal', _unit, _positional), pos=getpos(expr)) elif input_type == 'bytes32': if in_arg.typ.is_literal: if not SizeLimits.in_bounds('int128', (in_arg.value * DECIMAL_DIVISOR)): raise InvalidLiteral( f"Number out of range: {in_arg.value}", expr, ) else: return LLLnode.from_list(['mul', in_arg, DECIMAL_DIVISOR], typ=BaseType( 'decimal', _unit, _positional), pos=getpos(expr)) else: return LLLnode.from_list([ 'clamp', ['mload', MemoryPositions.MINDECIMAL], ['mul', in_arg, DECIMAL_DIVISOR], ['mload', MemoryPositions.MAXDECIMAL], ], typ=BaseType('decimal', _unit, _positional), pos=getpos(expr)) elif input_type in ('int128', 'bool'): return LLLnode.from_list(['mul', in_arg, DECIMAL_DIVISOR], typ=BaseType('decimal', _unit, _positional), pos=getpos(expr)) else: raise InvalidLiteral(f"Invalid input for decimal: {in_arg}", expr)
def to_int256(expr, args, kwargs, context): in_arg = args[0] input_type, _ = get_type(in_arg) if input_type == "num_literal": if isinstance(in_arg, int): if not SizeLimits.in_bounds("int256", in_arg): raise InvalidLiteral(f"Number out of range: {in_arg}") return LLLnode.from_list(in_arg, typ=BaseType("int256", ), pos=getpos(expr)) elif isinstance(in_arg, Decimal): if not SizeLimits.in_bounds("int256", math.trunc(in_arg)): raise InvalidLiteral( f"Number out of range: {math.trunc(in_arg)}") return LLLnode.from_list(math.trunc(in_arg), typ=BaseType("int256"), pos=getpos(expr)) else: raise InvalidLiteral(f"Unknown numeric literal type: {in_arg}") elif isinstance(in_arg, LLLnode) and input_type == "int128": return LLLnode.from_list(in_arg, typ=BaseType("int256"), pos=getpos(expr)) elif isinstance(in_arg, LLLnode) and input_type == "uint256": if version_check(begin="constantinople"): upper_bound = ["shl", 255, 1] else: upper_bound = -(2**255) return LLLnode.from_list(["uclamplt", in_arg, upper_bound], typ=BaseType("int256"), pos=getpos(expr)) elif isinstance(in_arg, LLLnode) and input_type == "decimal": return LLLnode.from_list( ["sdiv", in_arg, DECIMAL_DIVISOR], typ=BaseType("int256"), pos=getpos(expr), ) elif isinstance(in_arg, LLLnode) and input_type == "bool": return LLLnode.from_list(in_arg, typ=BaseType("int256"), pos=getpos(expr)) elif isinstance(in_arg, LLLnode) and input_type in ("bytes32", "address"): return LLLnode(value=in_arg.value, args=in_arg.args, typ=BaseType("int256"), pos=getpos(expr)) elif isinstance(in_arg, LLLnode) and input_type in ("Bytes", "String"): if in_arg.typ.maxlen > 32: raise TypeMismatch( f"Cannot convert bytes array of max length {in_arg.typ.maxlen} to int256", expr, ) return byte_array_to_num(in_arg, expr, "int256") else: raise InvalidLiteral(f"Invalid input for int256: {in_arg}", expr)
def to_int128(expr, args, kwargs, context): in_arg = args[0] input_type, _ = get_type(in_arg) if input_type == "num_literal": if isinstance(in_arg, int): if not SizeLimits.in_bounds("int128", in_arg): raise InvalidLiteral(f"Number out of range: {in_arg}") return LLLnode.from_list(in_arg, typ=BaseType("int128"), pos=getpos(expr)) elif isinstance(in_arg, Decimal): if not SizeLimits.in_bounds("int128", math.trunc(in_arg)): raise InvalidLiteral(f"Number out of range: {math.trunc(in_arg)}") return LLLnode.from_list(math.trunc(in_arg), typ=BaseType("int128"), pos=getpos(expr)) else: raise InvalidLiteral(f"Unknown numeric literal type: {in_arg}") elif input_type == "bytes32": if in_arg.typ.is_literal: if not SizeLimits.in_bounds("int128", in_arg.value): raise InvalidLiteral(f"Number out of range: {in_arg.value}", expr) else: return LLLnode.from_list(in_arg, typ=BaseType("int128"), pos=getpos(expr)) else: return LLLnode.from_list( [ "clamp", ["mload", MemoryPositions.MINNUM], in_arg, ["mload", MemoryPositions.MAXNUM], ], typ=BaseType("int128"), pos=getpos(expr), ) elif input_type == "address": return LLLnode.from_list( ["signextend", 15, ["and", in_arg, (SizeLimits.ADDRSIZE - 1)]], typ=BaseType("int128"), pos=getpos(expr), ) elif input_type in ("String", "Bytes"): if in_arg.typ.maxlen > 32: raise TypeMismatch( f"Cannot convert bytes array of max length {in_arg.typ.maxlen} to int128", expr, ) return byte_array_to_num(in_arg, expr, "int128") elif input_type == "uint256": if in_arg.typ.is_literal: if not SizeLimits.in_bounds("int128", in_arg.value): raise InvalidLiteral(f"Number out of range: {in_arg.value}", expr) else: return LLLnode.from_list(in_arg, typ=BaseType("int128"), pos=getpos(expr)) else: return LLLnode.from_list( ["uclample", in_arg, ["mload", MemoryPositions.MAXNUM]], typ=BaseType("int128"), pos=getpos(expr), ) elif input_type == "decimal": return LLLnode.from_list( [ "clamp", ["mload", MemoryPositions.MINNUM], ["sdiv", in_arg, DECIMAL_DIVISOR], ["mload", MemoryPositions.MAXNUM], ], typ=BaseType("int128"), pos=getpos(expr), ) elif input_type == "bool": return LLLnode.from_list(in_arg, typ=BaseType("int128"), pos=getpos(expr)) else: raise InvalidLiteral(f"Invalid input for int128: {in_arg}", expr)
def to_decimal(expr, args, kwargs, context): in_arg = args[0] input_type, _ = get_type(in_arg) if input_type == "Bytes": if in_arg.typ.maxlen > 32: raise TypeMismatch( f"Cannot convert bytes array of max length {in_arg.typ.maxlen} to decimal", expr, ) num = byte_array_to_num(in_arg, expr, "int128") return LLLnode.from_list( ["mul", num, DECIMAL_DIVISOR], typ=BaseType("decimal"), pos=getpos(expr) ) else: if input_type == "uint256": if in_arg.typ.is_literal: if not SizeLimits.in_bounds("int128", (in_arg.value * DECIMAL_DIVISOR)): raise InvalidLiteral( f"Number out of range: {in_arg.value}", expr, ) else: return LLLnode.from_list( ["mul", in_arg, DECIMAL_DIVISOR], typ=BaseType("decimal"), pos=getpos(expr) ) else: return LLLnode.from_list( [ "uclample", ["mul", in_arg, DECIMAL_DIVISOR], ["mload", MemoryPositions.MAXDECIMAL], ], typ=BaseType("decimal"), pos=getpos(expr), ) elif input_type == "address": return LLLnode.from_list( [ "mul", ["signextend", 15, ["and", in_arg, (SizeLimits.ADDRSIZE - 1)]], DECIMAL_DIVISOR, ], typ=BaseType("decimal"), pos=getpos(expr), ) elif input_type == "bytes32": if in_arg.typ.is_literal: if not SizeLimits.in_bounds("int128", (in_arg.value * DECIMAL_DIVISOR)): raise InvalidLiteral( f"Number out of range: {in_arg.value}", expr, ) else: return LLLnode.from_list( ["mul", in_arg, DECIMAL_DIVISOR], typ=BaseType("decimal"), pos=getpos(expr) ) else: return LLLnode.from_list( [ "clamp", ["mload", MemoryPositions.MINDECIMAL], ["mul", in_arg, DECIMAL_DIVISOR], ["mload", MemoryPositions.MAXDECIMAL], ], typ=BaseType("decimal"), pos=getpos(expr), ) elif input_type in ("int128", "bool"): return LLLnode.from_list( ["mul", in_arg, DECIMAL_DIVISOR], typ=BaseType("decimal"), pos=getpos(expr) ) else: raise InvalidLiteral(f"Invalid input for decimal: {in_arg}", expr)
def to_int128(expr, args, kwargs, context): in_arg = args[0] input_type, _ = get_type(in_arg) if input_type == 'num_literal': if isinstance(in_arg, int): if not SizeLimits.in_bounds('int128', in_arg): raise InvalidLiteral(f"Number out of range: {in_arg}") return LLLnode.from_list(in_arg, typ=BaseType('int128'), pos=getpos(expr)) elif isinstance(in_arg, Decimal): if not SizeLimits.in_bounds('int128', math.trunc(in_arg)): raise InvalidLiteral( f"Number out of range: {math.trunc(in_arg)}") return LLLnode.from_list(math.trunc(in_arg), typ=BaseType('int128'), pos=getpos(expr)) else: raise InvalidLiteral(f"Unknown numeric literal type: {in_arg}") elif input_type == 'bytes32': if in_arg.typ.is_literal: if not SizeLimits.in_bounds('int128', in_arg.value): raise InvalidLiteral(f"Number out of range: {in_arg.value}", expr) else: return LLLnode.from_list(in_arg, typ=BaseType('int128'), pos=getpos(expr)) else: return LLLnode.from_list([ 'clamp', ['mload', MemoryPositions.MINNUM], in_arg, ['mload', MemoryPositions.MAXNUM], ], typ=BaseType('int128'), pos=getpos(expr)) elif input_type == 'address': return LLLnode.from_list([ 'signextend', 15, ['and', in_arg, (SizeLimits.ADDRSIZE - 1)], ], typ=BaseType('int128'), pos=getpos(expr)) elif input_type in ('string', 'bytes'): if in_arg.typ.maxlen > 32: raise TypeMismatch( f"Cannot convert bytes array of max length {in_arg.typ.maxlen} to int128", expr, ) return byte_array_to_num(in_arg, expr, 'int128') elif input_type == 'uint256': if in_arg.typ.is_literal: if not SizeLimits.in_bounds('int128', in_arg.value): raise InvalidLiteral(f"Number out of range: {in_arg.value}", expr) else: return LLLnode.from_list(in_arg, typ=BaseType('int128'), pos=getpos(expr)) else: return LLLnode.from_list( ['uclample', in_arg, ['mload', MemoryPositions.MAXNUM]], typ=BaseType('int128'), pos=getpos(expr)) elif input_type == 'decimal': return LLLnode.from_list([ 'clamp', ['mload', MemoryPositions.MINNUM], ['sdiv', in_arg, DECIMAL_DIVISOR], ['mload', MemoryPositions.MAXNUM], ], typ=BaseType('int128'), pos=getpos(expr)) elif input_type == 'bool': return LLLnode.from_list(in_arg, typ=BaseType('int128'), pos=getpos(expr)) else: raise InvalidLiteral(f"Invalid input for int128: {in_arg}", expr)