def tuple_literals(self): if not len(self.expr.elts): raise StructureException("Tuple must have elements", self.expr) o = [] for elt in self.expr.elts: o.append(Expr(elt, self.context).lll_node) return LLLnode.from_list(["multi"] + o, typ=TupleType(o), pos=getpos(self.expr))
def parse_Tuple(self): if not len(self.expr.elements): return call_lll = [] multi_lll = [] for node in self.expr.elements: if isinstance(node, vy_ast.Call): # for calls inside the tuple, we perform the call prior to building the tuple and # assign it's result to memory - otherwise there is potential for memory corruption lll_node = Expr(node, self.context).lll_node target = LLLnode.from_list( self.context.new_internal_variable(lll_node.typ), typ=lll_node.typ, location="memory", pos=getpos(self.expr), ) call_lll.append(make_setter(target, lll_node, "memory", pos=getpos(self.expr))) multi_lll.append( LLLnode.from_list( target, typ=lll_node.typ, pos=getpos(self.expr), location="memory" ), ) else: multi_lll.append(Expr(node, self.context).lll_node) typ = TupleType([x.typ for x in multi_lll], is_literal=True) multi_lll = LLLnode.from_list(["multi"] + multi_lll, typ=typ, pos=getpos(self.expr)) if not call_lll: return multi_lll lll_node = ["seq_unchecked"] + call_lll + [multi_lll] return LLLnode.from_list(lll_node, typ=typ, pos=getpos(self.expr))
def parse_Tuple(self): if not len(self.expr.elements): return lll_node = [] for node in self.expr.elements: lll_node.append(Expr(node, self.context).lll_node) typ = TupleType([x.typ for x in lll_node], is_literal=True) return LLLnode.from_list(["multi"] + lll_node, typ=typ, pos=getpos(self.expr))
def test_canonicalize_type(): # Non-basetype not allowed with raises(Exception): canonicalize_type(int) # List of byte arrays not allowed a = ListType(ByteArrayType(12), 2) with raises(Exception): canonicalize_type(a) # Test ABI format of multiple args. c = TupleType([BaseType('int128'), BaseType('address')]) assert canonicalize_type(c) == "(int128,address)"
def parse_Tuple(self): call_lll, multi_lll = parse_sequence(self.expr, self.expr.elements, self.context) typ = TupleType([x.typ for x in multi_lll], is_literal=True) multi_lll = LLLnode.from_list(["multi"] + multi_lll, typ=typ, pos=getpos(self.expr)) if not call_lll: return multi_lll lll_node = ["seq_unchecked"] + call_lll + [multi_lll] return LLLnode.from_list(lll_node, typ=typ, pos=getpos(self.expr))
def test_get_size_of_type(): assert get_size_of_type(BaseType('int128')) == 1 assert get_size_of_type(ByteArrayType(12)) == 3 assert get_size_of_type(ByteArrayType(33)) == 4 assert get_size_of_type(ListType(BaseType('int128'), 10)) == 10 _tuple = TupleType([BaseType('int128'), BaseType('decimal')]) assert get_size_of_type(_tuple) == 2 _struct = StructType({'a': BaseType('int128'), 'b': BaseType('decimal')}) assert get_size_of_type(_struct) == 2 # Don't allow unknow types. with raises(Exception): get_size_of_type(int) # Maps are not supported for function arguments or outputs with raises(Exception): get_size_of_type(MappingType(BaseType('int128'), BaseType('int128')))
def test_get_size_of_type(): assert get_size_of_type(BaseType("int128")) == 1 assert get_size_of_type(ByteArrayType(12)) == 3 assert get_size_of_type(ByteArrayType(33)) == 4 assert get_size_of_type(ListType(BaseType("int128"), 10)) == 10 _tuple = TupleType([BaseType("int128"), BaseType("decimal")]) assert get_size_of_type(_tuple) == 2 _struct = StructType({ "a": BaseType("int128"), "b": BaseType("decimal") }, "Foo") assert get_size_of_type(_struct) == 2 # Don't allow unknown types. with raises(Exception): get_size_of_type(int) # Maps are not supported for function arguments or outputs with raises(Exception): get_size_of_type(MappingType(BaseType("int128"), BaseType("int128")))
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 test_tuple_node_types(): node1 = TupleType([BaseType('int128'), BaseType('decimal')]) node2 = TupleType([BaseType('int128'), BaseType('decimal')]) assert node1 == node2 assert str(node1) == "(int128, decimal)"