def pack_args_by_32(holder, maxlen, arg, typ, context, placeholder): if isinstance(typ, BaseType): input = parse_expr(arg, context) input = base_type_conversion(input, input.typ, typ) holder.append( LLLnode.from_list(['mstore', placeholder, input], typ=typ, location='memory')) elif isinstance(typ, ByteArrayType): bytez = b'' # String literals if isinstance(arg, ast.Str): if len(arg.s) > typ.maxlen: raise TypeMismatchException( "Data input bytes are to big: %r %r" % (len(arg.s), typ)) for c in arg.s: if ord(c) >= 256: raise InvalidLiteralException( "Cannot insert special character %r into byte array" % c) bytez += bytes([ord(c)]) bytez_length = len(bytez) if len(bytez) > 32: raise InvalidLiteralException( "Can only log a maximum of 32 bytes at a time.") holder.append( LLLnode.from_list([ 'mstore', placeholder, bytes_to_int(bytez + b'\x00' * (32 - bytez_length)) ], typ=typ, location='memory')) # Variables else: input = parse_expr(arg, context) if input.typ.maxlen > typ.maxlen: raise TypeMismatchException( "Data input bytes are to big: %r %r" % (input.typ, typ)) if arg.id in context.vars: size = context.vars[arg.id].size holder.append( LLLnode.from_list([ 'mstore', placeholder, byte_array_to_num(parse_expr(arg, context), arg, 'num256', size) ], typ=typ, location='memory')) elif isinstance(typ, ListType): maxlen += (typ.count - 1) * 32 typ = typ.subtype holder, maxlen = pack_args_by_32(holder, maxlen, arg.elts[0], typ, context, placeholder) for j, arg2 in enumerate(arg.elts[1:]): holder, maxlen = pack_args_by_32( holder, maxlen, arg2, typ, context, context.new_placeholder(BaseType(32))) return holder, maxlen
def pack_logging_topics(event_id, args, expected_topics, context): topics = [event_id] for pos, expected_topic in enumerate(expected_topics): typ = expected_topic.typ arg = args[pos] value = parse_expr(arg, context) if isinstance(typ, ByteArrayType) and ( isinstance(arg, ast.Str) or (isinstance(arg, ast.Name) and arg.id not in reserved_words)): if value.typ.maxlen > typ.maxlen: raise TypeMismatchException( "Topic input bytes are to big: %r %r" % (value.typ, typ)) 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.") topics.append( bytes_to_int(bytez + b'\x00' * (32 - bytez_length))) else: size = context.vars[arg.id].size topics.append(byte_array_to_num(value, arg, 'num256', size)) else: value = unwrap_location(value) value = base_type_conversion(value, value.typ, typ) topics.append(value) return topics
def number(self): orignum = get_original_if_0x_prefixed(self.expr, self.context) if orignum is None and isinstance(self.expr.n, int): if not (SizeLimits.MINNUM <= self.expr.n <= SizeLimits.MAXNUM): raise InvalidLiteralException( "Number out of range: " + str(self.expr.n), self.expr) return LLLnode.from_list(self.expr.n, typ=BaseType('num', None), pos=getpos(self.expr)) elif isinstance(self.expr.n, float): numstring, num, den = get_number_as_fraction( self.expr, self.context) if not (SizeLimits.MINNUM * den < num < SizeLimits.MAXNUM * den): raise InvalidLiteralException( "Number out of range: " + numstring, self.expr) if DECIMAL_DIVISOR % den: raise InvalidLiteralException( "Too many decimal places: " + numstring, self.expr) return LLLnode.from_list(num * DECIMAL_DIVISOR // den, typ=BaseType('decimal', None), pos=getpos(self.expr)) elif len(orignum) == 42: if checksum_encode(orignum) != orignum: raise InvalidLiteralException( "Address checksum mismatch. If you are sure this is the " "right address, the correct checksummed form is: " + checksum_encode(orignum), self.expr) return LLLnode.from_list(self.expr.n, typ=BaseType('address'), pos=getpos(self.expr)) elif len(orignum) == 66: return LLLnode.from_list(self.expr.n, typ=BaseType('bytes32'), pos=getpos(self.expr)) else: raise InvalidLiteralException( "Cannot read 0x value with length %d. Expecting 42 (address incl 0x) or 66 (bytes32 incl 0x)" % len(orignum), self.expr)
def pack_args_by_32(holder, maxlen, arg, typ, context, placeholder): if isinstance(typ, BaseType): value = parse_expr(arg, context) value = base_type_conversion(value, value.typ, typ) holder.append( LLLnode.from_list(['mstore', placeholder, value], typ=typ, location='memory')) elif isinstance(typ, ByteArrayType): bytez = b'' # Bytes from Storage if isinstance(arg, ast.Attribute) and arg.value.id == 'self': stor_bytes = context.globals[arg.attr] if stor_bytes.typ.maxlen > 32: raise TypeMismatchException( "Can only log a maximum of 32 bytes at a time.") arg2 = LLLnode.from_list([ 'sload', ['add', ['sha3_32', Expr(arg, context).lll_node], 1] ], typ=BaseType(32)) holder, maxlen = pack_args_by_32( holder, maxlen, arg2, BaseType(32), context, context.new_placeholder(BaseType(32))) # String literals elif isinstance(arg, ast.Str): if len(arg.s) > typ.maxlen: raise TypeMismatchException( "Data input bytes are to big: %r %r" % (len(arg.s), typ)) for c in arg.s: if ord(c) >= 256: raise InvalidLiteralException( "Cannot insert special character %r into byte array" % c) bytez += bytes([ord(c)]) bytez_length = len(bytez) if len(bytez) > 32: raise InvalidLiteralException( "Can only log a maximum of 32 bytes at a time.") holder.append( LLLnode.from_list([ 'mstore', placeholder, bytes_to_int(bytez + b'\x00' * (32 - bytez_length)) ], typ=typ, location='memory')) # Variables else: value = parse_expr(arg, context) if value.typ.maxlen > typ.maxlen: raise TypeMismatchException( "Data input bytes are to big: %r %r" % (value.typ, typ)) holder.append( LLLnode.from_list( ['mstore', placeholder, ['mload', ['add', value, 32]]], typ=typ, location='memory')) elif isinstance(typ, ListType): maxlen += (typ.count - 1) * 32 typ = typ.subtype def check_list_type_match(provided): # Check list types match. if provided != typ: raise TypeMismatchException( "Log list type '%s' does not match provided, expected '%s'" % (provided, typ)) # List from storage if isinstance(arg, ast.Attribute) and arg.value.id == 'self': stor_list = context.globals[arg.attr] check_list_type_match(stor_list.typ.subtype) size = stor_list.typ.count for offset in range(0, size): arg2 = LLLnode.from_list([ 'sload', ['add', ['sha3_32', Expr(arg, context).lll_node], offset] ], typ=typ) holder, maxlen = pack_args_by_32( holder, maxlen, arg2, typ, context, context.new_placeholder(BaseType(32))) # List from variable. elif isinstance(arg, ast.Name): size = context.vars[arg.id].size pos = context.vars[arg.id].pos check_list_type_match(context.vars[arg.id].typ.subtype) for i in range(0, size): offset = 32 * i arg2 = LLLnode.from_list(pos + offset, typ=typ, location='memory') holder, maxlen = pack_args_by_32( holder, maxlen, arg2, typ, context, context.new_placeholder(BaseType(32))) # is list literal. else: holder, maxlen = pack_args_by_32(holder, maxlen, arg.elts[0], typ, context, placeholder) for j, arg2 in enumerate(arg.elts[1:]): holder, maxlen = pack_args_by_32( holder, maxlen, arg2, typ, context, context.new_placeholder(BaseType(32))) return holder, maxlen
def pack_args_by_32(holder, maxlen, arg, typ, context, placeholder, dynamic_offset_counter=None, datamem_start=None): """ Copy necessary variables to pre-allocated memory section. :param holder: Complete holder for all args :param maxlen: Total length in bytes of the full arg section (static + dynamic). :param arg: Current arg to pack :param context: Context of arg :param placeholder: Static placeholder for static argument part. :param dynamic_offset_counter: position counter stored in static args. :param dynamic_placeholder: pointer to current position in memory to write dynamic values to. :param datamem_start: position where the whole datemem section starts. """ if isinstance(typ, BaseType): value = parse_expr(arg, context) value = base_type_conversion(value, value.typ, typ) holder.append( LLLnode.from_list(['mstore', placeholder, value], typ=typ, location='memory')) elif isinstance(typ, ByteArrayType): bytez = b'' source_expr = Expr(arg, context) if isinstance(arg, ast.Str): if len(arg.s) > typ.maxlen: raise TypeMismatchException( "Data input bytes are to big: %r %r" % (len(arg.s), typ)) for c in arg.s: if ord(c) >= 256: raise InvalidLiteralException( "Cannot insert special character %r into byte array" % c) bytez += bytes([ord(c)]) holder.append(source_expr.lll_node) # Set static offset, in arg slot. holder.append( LLLnode.from_list( ['mstore', placeholder, ['mload', dynamic_offset_counter]])) # Get the biginning to write the ByteArray to. dest_placeholder = LLLnode.from_list( ['add', datamem_start, ['mload', dynamic_offset_counter]], typ=typ, location='memory', annotation="pack_args_by_32:dest_placeholder") copier = make_byte_array_copier(dest_placeholder, source_expr.lll_node) holder.append(copier) # Increment offset counter. increment_counter = LLLnode.from_list([ 'mstore', dynamic_offset_counter, [ 'add', [ 'add', ['mload', dynamic_offset_counter], ['ceil32', ['mload', dest_placeholder]] ], 32 ] ]) holder.append(increment_counter) elif isinstance(typ, ListType): maxlen += (typ.count - 1) * 32 typ = typ.subtype def check_list_type_match(provided): # Check list types match. if provided != typ: raise TypeMismatchException( "Log list type '%s' does not match provided, expected '%s'" % (provided, typ)) # List from storage if isinstance(arg, ast.Attribute) and arg.value.id == 'self': stor_list = context.globals[arg.attr] check_list_type_match(stor_list.typ.subtype) size = stor_list.typ.count for offset in range(0, size): arg2 = LLLnode.from_list([ 'sload', ['add', ['sha3_32', Expr(arg, context).lll_node], offset] ], typ=typ) holder, maxlen = pack_args_by_32( holder, maxlen, arg2, typ, context, context.new_placeholder(BaseType(32))) # List from variable. elif isinstance(arg, ast.Name): size = context.vars[arg.id].size pos = context.vars[arg.id].pos check_list_type_match(context.vars[arg.id].typ.subtype) for i in range(0, size): offset = 32 * i arg2 = LLLnode.from_list(pos + offset, typ=typ, location='memory') holder, maxlen = pack_args_by_32( holder, maxlen, arg2, typ, context, context.new_placeholder(BaseType(32))) # is list literal. else: holder, maxlen = pack_args_by_32(holder, maxlen, arg.elts[0], typ, context, placeholder) for j, arg2 in enumerate(arg.elts[1:]): holder, maxlen = pack_args_by_32( holder, maxlen, arg2, typ, context, context.new_placeholder(BaseType(32))) return holder, maxlen
def pack_args_by_32(holder, maxlen, arg, typ, context, placeholder): if isinstance(typ, BaseType): value = parse_expr(arg, context) value = base_type_conversion(value, value.typ, typ) holder.append( LLLnode.from_list(['mstore', placeholder, value], typ=typ, location='memory')) elif isinstance(typ, ByteArrayType): bytez = b'' # String literals if isinstance(arg, ast.Str): if len(arg.s) > typ.maxlen: raise TypeMismatchException( "Data input bytes are to big: %r %r" % (len(arg.s), typ)) for c in arg.s: if ord(c) >= 256: raise InvalidLiteralException( "Cannot insert special character %r into byte array" % c) bytez += bytes([ord(c)]) bytez_length = len(bytez) if len(bytez) > 32: raise InvalidLiteralException( "Can only log a maximum of 32 bytes at a time.") holder.append( LLLnode.from_list([ 'mstore', placeholder, bytes_to_int(bytez + b'\x00' * (32 - bytez_length)) ], typ=typ, location='memory')) # Variables else: value = parse_expr(arg, context) if value.typ.maxlen > typ.maxlen: raise TypeMismatchException( "Data input bytes are to big: %r %r" % (value.typ, typ)) holder.append( LLLnode.from_list( ['mstore', placeholder, ['mload', ['add', value, 32]]], typ=typ, location='memory')) elif isinstance(typ, ListType): maxlen += (typ.count - 1) * 32 typ = typ.subtype if isinstance(arg, ast.Name): size = context.vars[arg.id].size pos = context.vars[arg.id].pos for i in range(0, size): offset = 32 * i arg2 = LLLnode.from_list(pos + offset, typ=typ, location='memory') holder, maxlen = pack_args_by_32( holder, maxlen, arg2, typ, context, context.new_placeholder(BaseType(32))) else: # is list literal. holder, maxlen = pack_args_by_32(holder, maxlen, arg.elts[0], typ, context, placeholder) for j, arg2 in enumerate(arg.elts[1:]): holder, maxlen = pack_args_by_32( holder, maxlen, arg2, typ, context, context.new_placeholder(BaseType(32))) return holder, maxlen