def as_wei_value(expr, args, kwargs, context): # Denominations if args[1] == b"wei": denomination = 1 elif args[1] in (b"kwei", b"ada", b"lovelace"): denomination = 10**3 elif args[1] == b"babbage": denomination = 10**6 elif args[1] in (b"shannon", b"gwei"): denomination = 10**9 elif args[1] == b"szabo": denomination = 10**12 elif args[1] == b"finney": denomination = 10**15 elif args[1] == b"ether": denomination = 10**18 else: raise InvalidLiteralException("Invalid denomination: %s" % args[1], expr.args[1]) # Compute the amount of wei and return that value if isinstance(args[0], (int, float)): numstring, num, den = get_number_as_fraction(expr.args[0], context) if denomination % den: raise InvalidLiteralException( "Too many decimal places: %s" % numstring, expr.args[0]) sub = num * denomination // den elif args[0].typ.typ == 'num': sub = ['mul', args[0], denomination] else: sub = ['div', ['mul', args[0], denomination], DECIMAL_DIVISOR] return LLLnode.from_list(sub, typ=BaseType('num', {'wei': 1}), location=None, pos=getpos(expr))
def as_wei_value(expr, args, kwargs, context): # Denominations names_denom = { (b"wei", ): 1, (b"femtoether", b"kwei", b"babbage"): 10**3, (b"picoether", b"mwei", b"lovelace"): 10**6, (b"nanoether", b"gwei", b"shannon"): 10**9, (b"microether", b"szabo", ): 10**12, (b"milliether", b"finney", ): 10**15, (b"ether", ): 10**18, (b"kether", b"grand"): 10**21, } for names, denom in names_denom.items(): if args[1] in names: denomination = denom break else: raise InvalidLiteralException("Invalid denomination: %s" % args[1], expr.args[1]) # Compute the amount of wei and return that value if isinstance(args[0], (int, float)): numstring, num, den = get_number_as_fraction(expr.args[0], context) if denomination % den: raise InvalidLiteralException("Too many decimal places: %s" % numstring, expr.args[0]) sub = num * denomination // den elif args[0].typ.is_literal: if args[0].value <= 0: raise InvalidLiteralException("Negative wei value not allowed", expr) sub = ['mul', args[0].value, denomination] elif args[0].typ.typ == 'uint256': sub = ['mul', args[0], denomination] else: sub = ['div', ['mul', args[0], denomination], DECIMAL_DIVISOR] return LLLnode.from_list(sub, typ=BaseType('uint256', {'wei': 1}), location=None, pos=getpos(expr))
def as_wei_value(expr, args, kwargs, context): # Denominations wei_denominations = { ("wei", ): 1, ("femtoether", "kwei", "babbage"): 10**3, ("picoether", "mwei", "lovelace"): 10**6, ("nanoether", "gwei", "shannon"): 10**9, ( "microether", "szabo", ): 10**12, ( "milliether", "finney", ): 10**15, ("ether", ): 10**18, ("kether", "grand"): 10**21, } value, denom_name = args[0], args[1].decode() denom_divisor = next( (v for k, v in wei_denominations.items() if denom_name in k), False) if not denom_divisor: raise InvalidLiteralException( f"Invalid denomination: {denom_name}, valid denominations are: " f"{','.join(x[0] for x in wei_denominations)}", expr.args[1]) # Compute the amount of wei and return that value if isinstance(value, (int, float)): expr_args_0 = expr.args[0] # On constant reference fetch value node of constant assignment. if context.constants.ast_is_constant(expr.args[0]): expr_args_0 = context.constants._constants_ast[expr.args[0].id] numstring, num, den = get_number_as_fraction(expr_args_0, context) if denom_divisor % den: max_len = len(str(denom_divisor)) - 1 raise InvalidLiteralException( f"Wei value of denomination '{denom_name}' has maximum {max_len} decimal places", expr.args[0]) sub = num * denom_divisor // den elif value.typ.is_literal: if value.value <= 0: raise InvalidLiteralException("Negative wei value not allowed", expr) sub = ['mul', value.value, denom_divisor] elif value.typ.typ == 'uint256': sub = ['mul', value, denom_divisor] else: sub = ['div', ['mul', value, denom_divisor], DECIMAL_DIVISOR] return LLLnode.from_list( sub, typ=BaseType('uint256', {'wei': 1}), location=None, pos=getpos(expr), )
def parse_Decimal(self): numstring, num, den = get_number_as_fraction(self.expr, self.context) if not (SizeLimits.MINNUM * den <= num <= SizeLimits.MAXNUM * den): return if DECIMAL_DIVISOR % den: return return LLLnode.from_list( num * DECIMAL_DIVISOR // den, typ=BaseType("decimal", is_literal=True), pos=getpos(self.expr), )
def number(self): orignum = get_original_if_0_prefixed(self.expr, self.context) if orignum is None and isinstance(self.expr.n, int): # Literal (mostly likely) becomes int128 if SizeLimits.in_bounds('int128', self.expr.n) or self.expr.n < 0: return LLLnode.from_list(self.expr.n, typ=BaseType('int128', unit=None, is_literal=True), pos=getpos(self.expr)) # Literal is large enough (mostly likely) becomes uint256. else: return LLLnode.from_list(self.expr.n, typ=BaseType('uint256', unit=None, is_literal=True), pos=getpos(self.expr)) elif isinstance(self.expr.n, float): numstring, num, den = get_number_as_fraction(self.expr, self.context) # if not SizeLimits.in_bounds('decimal', num // den): # if not SizeLimits.MINDECIMAL * den <= num <= SizeLimits.MAXDECIMAL * den: 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', unit=None), pos=getpos(self.expr)) # Binary literal. elif orignum[:2] == '0b': str_val = orignum[2:] total_bits = len(orignum[2:]) total_bits = total_bits if total_bits % 8 == 0 else total_bits + 8 - (total_bits % 8) # ceil8 to get byte length. if len(orignum[2:]) != total_bits: # Support only full formed bit definitions. raise InvalidLiteralException("Bit notation requires a multiple of 8 bits / 1 byte. {} bit(s) are missing.".format(total_bits - len(orignum[2:])), self.expr) byte_len = int(total_bits / 8) placeholder = self.context.new_placeholder(ByteArrayType(byte_len)) seq = [] seq.append(['mstore', placeholder, byte_len]) for i in range(0, total_bits, 256): section = str_val[i:i + 256] int_val = int(section, 2) << (256 - len(section)) # bytes are right padded. seq.append( ['mstore', ['add', placeholder, i + 32], int_val]) return LLLnode.from_list(['seq'] + seq + [placeholder], typ=ByteArrayType(byte_len), location='memory', pos=getpos(self.expr), annotation='Create ByteArray (Binary literal): %s' % str_val) 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', is_literal=True), pos=getpos(self.expr)) elif len(orignum) == 66: return LLLnode.from_list(self.expr.n, typ=BaseType('bytes32', is_literal=True), 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 decimal(self): numstring, num, den = get_number_as_fraction(self.expr, self.context) # if not SizeLimits.in_bounds('decimal', num // den): # if not SizeLimits.MINDECIMAL * den <= num <= SizeLimits.MAXDECIMAL * den: if not (SizeLimits.MINNUM * den <= num <= SizeLimits.MAXNUM * den): raise InvalidLiteral("Number out of range: " + numstring, self.expr) if DECIMAL_DIVISOR % den: raise InvalidLiteral( "Type 'decimal' has maximum 10 decimal places", self.expr) return LLLnode.from_list( num * DECIMAL_DIVISOR // den, typ=BaseType('decimal', is_literal=True), pos=getpos(self.expr), )
def as_wei_value(expr, args, kwargs, context): # Denominations names_denom = { (b"wei", ): 1, (b"femtoether", b"kwei", b"babbage"): 10**3, (b"picoether", b"mwei", b"lovelace"): 10**6, (b"nanoether", b"gwei", b"shannon"): 10**9, (b"microether", b"szabo", ): 10**12, (b"milliether", b"finney", ): 10**15, (b"ether", ): 10**18, (b"kether", b"grand"): 10**21, } for names, denom in names_denom.items(): if args[1] in names: denomination = denom break else: raise InvalidLiteralException( f"Invalid denomination: {args[1]}, valid denominations are: " f"{','.join(x[0].decode() for x in names_denom)}", expr.args[1] ) # Compute the amount of wei and return that value if isinstance(args[0], (int, float)): expr_args_0 = expr.args[0] # On constant reference fetch value node of constant assignment. if context.constants.ast_is_constant(expr.args[0]): expr_args_0 = context.constants._constants_ast[expr.args[0].id] numstring, num, den = get_number_as_fraction(expr_args_0, context) if denomination % den: raise InvalidLiteralException(f"Too many decimal places: {numstring}", expr.args[0]) sub = num * denomination // den elif args[0].typ.is_literal: if args[0].value <= 0: raise InvalidLiteralException("Negative wei value not allowed", expr) sub = ['mul', args[0].value, denomination] elif args[0].typ.typ == 'uint256': sub = ['mul', args[0], denomination] else: sub = ['div', ['mul', args[0], denomination], DECIMAL_DIVISOR] return LLLnode.from_list( sub, typ=BaseType('uint256', {'wei': 1}), location=None, pos=getpos(expr), )
def build_LLL(self, expr, args, kwargs, context): value, denom_name = args[0], args[1].decode() denom_divisor = next( (v for k, v in self.wei_denoms.items() if denom_name in k), False) if not denom_divisor: raise InvalidLiteral( f"Invalid denomination: {denom_name}, valid denominations are: " f"{','.join(x[0] for x in self.wei_denoms)}", expr.args[1]) # Compute the amount of wei and return that value if isinstance(value, (int, Decimal)): expr_args_0 = expr.args[0] # On constant reference fetch value node of constant assignment. if context.constants.ast_is_constant(expr.args[0]): expr_args_0 = context.constants._constants_ast[expr.args[0].id] numstring, num, den = get_number_as_fraction(expr_args_0, context) if denom_divisor % den: max_len = len(str(denom_divisor)) - 1 raise InvalidLiteral( f"Wei value of denomination '{denom_name}' has max {max_len} decimal places", expr.args[0]) sub = num * denom_divisor // den elif value.typ.is_literal: if value.value <= 0: raise InvalidLiteral("Negative wei value not allowed", expr) sub = ['mul', value.value, denom_divisor] elif value.typ.typ == 'uint256': sub = ['mul', value, denom_divisor] else: sub = ['div', ['mul', value, denom_divisor], DECIMAL_DIVISOR] return LLLnode.from_list( sub, typ=BaseType('uint256'), location=None, pos=getpos(expr), )