Ejemplo n.º 1
0
 def validate(self):
     if "_" in self.value:
         raise InvalidLiteral("Underscores not allowed in hex literals",
                              self)
     if len(self.value) % 2:
         raise InvalidLiteral(
             "Hex notation requires an even number of digits", self)
Ejemplo n.º 2
0
 def from_literal(cls, node: vy_ast.Constant) -> BaseTypeDefinition:
     obj = super().from_literal(node)
     if isinstance(node, vy_ast.Bytes) and len(node.value.hex()) != 64:
         raise InvalidLiteral("Invalid literal for type bytes32", node)
     if isinstance(node, vy_ast.Hex) and len(node.value) != 66:
         raise InvalidLiteral("Invalid literal for type bytes32", node)
     return obj
Ejemplo n.º 3
0
Archivo: expr.py Proyecto: 6pakla/vyper
 def hexstring(self):
     orignum = self.expr.node_source_code
     if len(orignum) == 42:
         if checksum_encode(orignum) != orignum:
             raise InvalidLiteral(
                 "Address checksum mismatch. If you are sure this is the "
                 f"right address, the correct checksummed form is: {checksum_encode(orignum)}",
                 self.expr
             )
         return LLLnode.from_list(
             int(self.expr.value, 16),
             typ=BaseType('address', is_literal=True),
             pos=getpos(self.expr),
         )
     elif len(orignum) == 66:
         return LLLnode.from_list(
             int(self.expr.value, 16),
             typ=BaseType('bytes32', is_literal=True),
             pos=getpos(self.expr),
         )
     else:
         raise InvalidLiteral(
             f"Cannot read 0x value with length {len(orignum)}. Expecting 42 (address "
             "incl 0x) or 66 (bytes32 incl 0x)",
             self.expr
         )
Ejemplo n.º 4
0
 def validate(self):
     if len(self.value) % 2:
         raise InvalidLiteral("Hex notation requires an even number of digits", self)
     if len(self.value) == 42 and checksum_encode(self.value) != self.value:
         raise InvalidLiteral(
             "Address checksum mismatch. If you are sure this is the right "
             f"address, the correct checksummed form is: {checksum_encode(self.value)}",
             self,
         )
Ejemplo n.º 5
0
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 InvalidLiteral(
            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 InvalidLiteral(
                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 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', {'wei': 1}),
        location=None,
        pos=getpos(expr),
    )
Ejemplo n.º 6
0
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 in ("int128", "int256"):
        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 in ("bool", "uint8"):
        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, "uint256")

    else:
        raise InvalidLiteral(f"Invalid input for uint256: {in_arg}", expr)
Ejemplo n.º 7
0
    def types_from_List(self, node):
        # literal array
        if not node.elements:
            raise InvalidLiteral("Cannot have an empty array", node)

        types_list = get_common_types(*node.elements)
        if types_list:
            return [ArrayDefinition(i, len(node.elements)) for i in types_list]

        raise InvalidLiteral("Array contains multiple, incompatible types", node)
Ejemplo n.º 8
0
def base_type_conversion(orig, frm, to, pos, in_function_call=False):
    orig = unwrap_location(orig)
    is_valid_int128_to_decimal = (is_base_type(frm, 'int128') and is_base_type(
        to, 'decimal')) and are_units_compatible(frm, to)

    if getattr(frm, 'is_literal', False):
        if frm.typ in ('int128', 'uint256'):
            if not SizeLimits.in_bounds(frm.typ, orig.value):
                raise InvalidLiteral(f"Number out of range: {orig.value}", pos)
            # Special Case: Literals in function calls should always convey unit type as well.
            if in_function_call and not (frm.unit == to.unit
                                         and frm.positional == to.positional):
                raise InvalidLiteral(
                    f"Function calls require explicit unit definitions on calls, expected {to}",
                    pos)
        if to.typ in ('int128', 'uint256'):
            if not SizeLimits.in_bounds(to.typ, orig.value):
                raise InvalidLiteral(f"Number out of range: {orig.value}", pos)

    if not isinstance(frm,
                      (BaseType, NullType)) or not isinstance(to, BaseType):
        raise TypeMismatch(
            f"Base type conversion from or to non-base type: {frm} {to}", pos)
    elif is_base_type(frm, to.typ) and are_units_compatible(frm, to):
        return LLLnode(orig.value,
                       orig.args,
                       typ=to,
                       add_gas_estimate=orig.add_gas_estimate)
    elif isinstance(frm, ContractType) and to == BaseType('address'):
        return LLLnode(orig.value,
                       orig.args,
                       typ=to,
                       add_gas_estimate=orig.add_gas_estimate)
    elif is_valid_int128_to_decimal:
        return LLLnode.from_list(
            ['mul', orig, DECIMAL_DIVISOR],
            typ=BaseType('decimal', to.unit, to.positional),
        )
    elif isinstance(frm, NullType):
        if to.typ not in ('int128', 'bool', 'uint256', 'address', 'bytes32',
                          'decimal'):
            # This is only to future proof the use of  base_type_conversion.
            raise TypeMismatch(  # pragma: no cover
                f"Cannot convert null-type object to type {to}", pos)
        return LLLnode.from_list(0, typ=to)
    # Integer literal conversion.
    elif (frm.typ, to.typ, frm.is_literal) == ('int128', 'uint256', True):
        return LLLnode(orig.value,
                       orig.args,
                       typ=to,
                       add_gas_estimate=orig.add_gas_estimate)
    else:
        raise TypeMismatch(
            f"Typecasting from base type {frm} to {to} unavailable", pos)
Ejemplo n.º 9
0
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 InvalidLiteral(f"Number out of range: {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 InvalidLiteral(
                    f"Number out of range: {math.trunc(in_arg)}")
            return LLLnode.from_list(math.trunc(in_arg),
                                     typ=BaseType('uint256', _unit),
                                     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', _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 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)
Ejemplo n.º 10
0
 def from_literal(cls, node: vy_ast.Constant) -> AddressDefinition:
     super().from_literal(node)
     addr = node.value
     if len(addr) != 42:
         raise InvalidLiteral("Invalid literal for type 'address'", node)
     if checksum_encode(addr) != addr:
         raise InvalidLiteral(
             "Address checksum mismatch. If you are sure this is the right "
             f"address, the correct checksummed form is: {checksum_encode(addr)}",
             node,
         )
     return AddressDefinition()
Ejemplo n.º 11
0
    def from_literal(cls, node: vy_ast.Constant) -> BaseTypeDefinition:
        obj = super().from_literal(node)
        val = node.value
        m = cls._length

        if len(val) != 2 + 2 * m:
            raise InvalidLiteral("Invalid literal for type bytes32", node)

        nibbles = val[2:]  # strip leading 0x
        if nibbles not in (nibbles.lower(), nibbles.upper()):
            raise InvalidLiteral(
                f"Cannot mix uppercase and lowercase for bytes{m} literal",
                node)

        return obj
Ejemplo n.º 12
0
 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),
     )
Ejemplo n.º 13
0
Archivo: expr.py Proyecto: 6pakla/vyper
 def dict_fail(self):
     warnings.warn(
         "Anonymous structs have been removed in"
         " favor of named structs, see VIP300",
         DeprecationWarning
     )
     raise InvalidLiteral("Invalid literal.", self.expr)
Ejemplo n.º 14
0
    def from_literal(cls, node: vy_ast.Constant) -> "BaseTypeDefinition":
        """
        Generate a `BaseTypeDefinition` instance of this type from a literal constant.

        This method is called on every primitive class in order to determine
        potential types for a `Constant` AST node.

        Types that may be assigned from literals should include a `_valid_literal`
        attribute, containing a list of AST node classes that may be valid for
        this type. If the `_valid_literal` attribute is not included, the type
        cannot be assigned to a literal.

        Arguments
        ---------
        node : VyperNode
            `Constant` Vyper ast node, or a list or tuple of constants.

        Returns
        -------
        BaseTypeDefinition
            BaseTypeDefinition related to the primitive that the method was called on.
        """
        if not isinstance(node, vy_ast.Constant):
            raise UnexpectedNodeType(
                f"Attempted to validate a '{node.ast_type}' node.")
        if not isinstance(node, cls._valid_literal):
            raise InvalidLiteral(f"Invalid literal type for {cls.__name__}",
                                 node)
        return cls._type()
Ejemplo n.º 15
0
 def validate(self):
     if self.value.as_tuple().exponent < -MAX_DECIMAL_PLACES:
         raise InvalidLiteral("Vyper supports a maximum of ten decimal points", self)
     if self.value < SizeLimits.MIN_INT128:
         raise OverflowException("Value is below lower bound for decimal types", self)
     if self.value > SizeLimits.MAX_INT128:
         raise OverflowException("Value exceeds upper bound for decimal types", self)
Ejemplo n.º 16
0
    def from_literal(cls, node: vy_ast.Constant) -> AddressDefinition:
        super().from_literal(node)
        addr = node.value
        if len(addr) != 42:
            n_bytes = (len(addr) - 2) // 2
            raise InvalidLiteral(
                f"Invalid address. Expected 20 bytes, got {n_bytes}.", node)

        if not is_checksum_encoded(addr):
            raise InvalidLiteral(
                "Address checksum mismatch. If you are sure this is the right "
                f"address, the correct checksummed form is: {checksum_encode(addr)}",
                node,
            )

        return AddressDefinition()
Ejemplo n.º 17
0
def get_number_as_fraction(expr, context):
    context_line = context.origcode.splitlines()[expr.lineno - 1]
    context_slice = context_line[expr.col_offset:expr.end_col_offset]
    literal = Decimal(context_slice)
    sign, digits, exponent = literal.as_tuple()

    if exponent < -10:
        raise InvalidLiteral(
            f"`decimal` literal cannot have more than 10 decimal places: {literal}",
            expr)

    sign = (-1 if sign == 1 else 1
            )  # Positive Decimal has `sign` of 0, negative `sign` of 1
    # Decimal `digits` is a tuple of each digit, so convert to a regular integer
    top = int(Decimal((0, digits, 0)))
    top = sign * top * 10**(exponent if exponent > 0 else 0
                            )  # Convert to a fixed point integer
    bottom = (1 if exponent > 0 else 10**abs(exponent)
              )  # Make denominator a power of 10
    assert Decimal(top) / Decimal(bottom) == literal  # Sanity check

    # TODO: Would be best to raise >10 decimal place exception here
    #       (unless Decimal is used more widely)

    return context_slice, top, bottom
Ejemplo n.º 18
0
 def binary(self):
     orignum = self.expr.node_source_code
     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 InvalidLiteral(
             f"Bit notation requires a multiple of 8 bits / 1 byte. "
             f"{total_bits - len(orignum[2:])} bit(s) are missing.",
             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=f'Create ByteArray (Binary literal): {str_val}',
     )
Ejemplo n.º 19
0
def string_to_bytes(str):
    bytez = b""
    for c in str:
        if ord(c) >= 256:
            raise InvalidLiteral(f"Cannot insert special character {c} into byte array")
        bytez += bytes([ord(c)])
    bytez_length = len(bytez)
    return bytez, bytez_length
Ejemplo n.º 20
0
 def from_literal(cls, node: vy_ast.Constant) -> AddressDefinition:
     super().from_literal(node)
     addr = node.value
     if len(addr) != 42:
         raise InvalidLiteral("Invalid literal for type 'address'", node)
     if checksum_encode(addr) != addr:
         # this should have been caught in `vyper.ast.nodes.Hex.validate`
         raise CompilerPanic("Address checksum mismatch")
     return AddressDefinition()
Ejemplo n.º 21
0
def base_type_conversion(orig, frm, to, pos, in_function_call=False):
    orig = unwrap_location(orig)

    # do the base type check so we can use BaseType attributes
    if not isinstance(frm, BaseType) or not isinstance(to, BaseType):
        raise TypeMismatch(
            f"Base type conversion from or to non-base type: {frm} {to}", pos)

    if getattr(frm, 'is_literal', False):
        if frm.typ in ('int128', 'uint256'):
            if not SizeLimits.in_bounds(frm.typ, orig.value):
                raise InvalidLiteral(f"Number out of range: {orig.value}", pos)

        if to.typ in ('int128', 'uint256'):
            if not SizeLimits.in_bounds(to.typ, orig.value):
                raise InvalidLiteral(f"Number out of range: {orig.value}", pos)

    is_decimal_int128_conversion = frm.typ == 'int128' and to.typ == 'decimal'
    is_same_type = frm.typ == to.typ
    is_literal_conversion = frm.is_literal and (frm.typ, to.typ) == ('int128',
                                                                     'uint256')
    is_address_conversion = isinstance(frm,
                                       ContractType) and to.typ == 'address'
    if not (is_same_type or is_literal_conversion or is_address_conversion
            or is_decimal_int128_conversion):
        raise TypeMismatch(
            f"Typecasting from base type {frm} to {to} unavailable", pos)

    # handle None value inserted by `empty()`
    if orig.value is None:
        return LLLnode.from_list(0, typ=to)

    if is_decimal_int128_conversion:
        return LLLnode.from_list(
            ['mul', orig, DECIMAL_DIVISOR],
            typ=BaseType('decimal'),
        )

    return LLLnode(orig.value,
                   orig.args,
                   typ=to,
                   add_gas_estimate=orig.add_gas_estimate)
Ejemplo n.º 22
0
    def ann_assign(self):
        with self.context.assignment_scope():
            typ = parse_type(
                self.stmt.annotation,
                location='memory',
                custom_units=self.context.custom_units,
                custom_structs=self.context.structs,
                constants=self.context.constants,
            )
            if isinstance(self.stmt.target, vy_ast.Attribute):
                raise TypeMismatch(
                    f'May not set type for field {self.stmt.target.attr}',
                    self.stmt,
                )
            varname = self.stmt.target.id
            pos = self.context.new_variable(varname, typ)
            if self.stmt.value is None:
                raise StructureException(
                    'New variables must be initialized explicitly', self.stmt)

            sub = Expr(self.stmt.value, self.context).lll_node

            # Disallow assignment to None
            if isinstance(sub.typ, NullType):
                raise InvalidLiteral(
                    ('Assignment to None is not allowed, use a default '
                     'value or built-in `clear()`.'), self.stmt)

            is_literal_bytes32_assign = (isinstance(sub.typ, ByteArrayType)
                                         and sub.typ.maxlen == 32
                                         and isinstance(typ, BaseType)
                                         and typ.typ == 'bytes32'
                                         and sub.typ.is_literal)

            # If bytes[32] to bytes32 assignment rewrite sub as bytes32.
            if is_literal_bytes32_assign:
                sub = LLLnode(
                    bytes_to_int(self.stmt.value.s),
                    typ=BaseType('bytes32'),
                    pos=getpos(self.stmt),
                )

            self._check_valid_assign(sub)
            self._check_same_variable_assign(sub)
            variable_loc = LLLnode.from_list(
                pos,
                typ=typ,
                location='memory',
                pos=getpos(self.stmt),
            )
            o = make_setter(variable_loc, sub, 'memory', pos=getpos(self.stmt))
            # o.pos = getpos(self.stmt) # TODO: Should this be here like in assign()?

            return o
Ejemplo n.º 23
0
 def _check_valid_assign(self, sub):
     if (isinstance(self.stmt.annotation, vy_ast.Name)
             and self.stmt.annotation.id == 'bytes32'):
         # CMC 04/07/2020 this check could be much clearer, more like:
         # if isinstance(ByteArrayLike) and maxlen == 32
         #   or isinstance(BaseType) and typ.typ == 'bytes32'
         #   then GOOD
         #   else RAISE
         if isinstance(sub.typ, ByteArrayLike):
             if sub.typ.maxlen != 32:
                 raise TypeMismatch(
                     'Invalid type, expected: bytes32. String is incorrect length.',
                     self.stmt)
             return
         elif isinstance(sub.typ, BaseType):
             if sub.typ.typ != 'bytes32':
                 raise TypeMismatch('Invalid type, expected: bytes32',
                                    self.stmt)
             return
         else:
             raise TypeMismatch("Invalid type, expected: bytes32",
                                self.stmt)
     elif isinstance(self.stmt.annotation, vy_ast.Subscript):
         # check list assign:
         if not isinstance(sub.typ, (ListType, ByteArrayLike)):
             raise TypeMismatch(
                 f'Invalid type, expected: {self.stmt.annotation.value.id},'
                 f' got: {sub.typ}', self.stmt)
     elif sub.typ is None:
         # Check that the object to be assigned is not of NoneType
         raise TypeMismatch(
             f"Invalid type, expected {self.stmt.annotation.id}", self.stmt)
     elif isinstance(sub.typ, StructType):
         # This needs to get more sophisticated in the presence of
         # foreign structs.
         if not sub.typ.name == self.stmt.annotation.id:
             raise TypeMismatch(
                 f"Invalid type, expected {self.stmt.annotation.id}",
                 self.stmt)
     # Check that the integer literal, can be assigned to uint256 if necessary.
     elif (self.stmt.annotation.id,
           sub.typ.typ) == ('uint256', 'int128') and sub.typ.is_literal:
         if not SizeLimits.in_bounds('uint256', sub.value):
             raise InvalidLiteral(
                 'Invalid uint256 assignment, value not in uint256 range.',
                 self.stmt)
     elif self.stmt.annotation.id != sub.typ.typ:
         raise TypeMismatch(
             f'Invalid type {sub.typ.typ}, expected: {self.stmt.annotation.id}',
             self.stmt,
         )
     else:
         return True
Ejemplo n.º 24
0
    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),
        )
Ejemplo n.º 25
0
 def _check_valid_assign(self, sub):
     if isinstance(self.stmt.annotation,
                   vy_ast.Call):  # unit style: num(wei)
         if self.stmt.annotation.func.id != sub.typ.typ and not sub.typ.is_literal:
             raise TypeMismatch(
                 f'Invalid type, expected: {self.stmt.annotation.func.id}',
                 self.stmt)
     elif (isinstance(self.stmt.annotation, vy_ast.Name)
           and self.stmt.annotation.id == 'bytes32'):
         if isinstance(sub.typ, ByteArrayLike):
             if sub.typ.maxlen != 32:
                 raise TypeMismatch(
                     'Invalid type, expected: bytes32. String is incorrect length.',
                     self.stmt)
             return
         elif isinstance(sub.typ, BaseType):
             if sub.typ.typ != 'bytes32':
                 raise TypeMismatch('Invalid type, expected: bytes32',
                                    self.stmt)
             return
         else:
             raise TypeMismatch('Invalid type, expected: bytes32',
                                self.stmt)
     elif isinstance(self.stmt.annotation, vy_ast.Subscript):
         if not isinstance(sub.typ,
                           (ListType, ByteArrayLike)):  # check list assign.
             raise TypeMismatch(
                 f'Invalid type, expected: {self.stmt.annotation.value.id}',
                 self.stmt)
     elif isinstance(sub.typ, StructType):
         # This needs to get more sophisticated in the presence of
         # foreign structs.
         if not sub.typ.name == self.stmt.annotation.id:
             raise TypeMismatch(
                 f"Invalid type, expected {self.stmt.annotation.id}",
                 self.stmt)
     # Check that the integer literal, can be assigned to uint256 if necessary.
     elif (self.stmt.annotation.id,
           sub.typ.typ) == ('uint256', 'int128') and sub.typ.is_literal:
         if not SizeLimits.in_bounds('uint256', sub.value):
             raise InvalidLiteral(
                 'Invalid uint256 assignment, value not in uint256 range.',
                 self.stmt)
     elif self.stmt.annotation.id != sub.typ.typ and not sub.typ.unit:
         raise TypeMismatch(
             f'Invalid type {sub.typ.typ}, expected: {self.stmt.annotation.id}',
             self.stmt,
         )
     else:
         return True
Ejemplo n.º 26
0
def _literal_int(expr, out_typ):
    # TODO: possible to reuse machinery from expr.py?
    int_info = out_typ._int_info
    if isinstance(expr, vy_ast.Hex):
        val = int(expr.value, 16)
    elif isinstance(expr, vy_ast.Bytes):
        val = int.from_bytes(expr.value, "big")
    else:
        # Int, Decimal
        val = int(expr.value)
    (lo, hi) = int_info.bounds
    if not (lo <= val <= hi):
        raise InvalidLiteral("Number out of range", expr)
    return IRnode.from_list(val, typ=out_typ)
Ejemplo n.º 27
0
def _literal_decimal(expr, out_typ):
    # TODO: possible to reuse machinery from expr.py?
    if isinstance(expr, vy_ast.Hex):
        val = decimal.Decimal(int(expr.value, 16))
    else:
        val = decimal.Decimal(expr.value)  # should work for Int, Decimal

    val = val * DECIMAL_DIVISOR

    if not SizeLimits.in_bounds("decimal", val):
        raise InvalidLiteral("Number out of range", expr)

    # sanity check type checker did its job
    assert math.ceil(val) == math.floor(val)

    return IRnode.from_list(int(val), typ=out_typ)
Ejemplo n.º 28
0
    def types_from_Constant(self, node):
        # literal value (integer, string, etc)
        types_list = []
        for primitive in types.get_primitive_types().values():
            try:
                obj = primitive.from_literal(node)
                types_list.append(obj)
            except VyperException:
                continue
        if types_list:
            return types_list

        if isinstance(node, vy_ast.Num):
            raise OverflowException(
                "Numeric literal is outside of allowable range for number types", node,
            )
        raise InvalidLiteral(f"Could not determine type for literal value '{node.value}'", node)
Ejemplo n.º 29
0
 def constants(self):
     if self.expr.value is True:
         return LLLnode.from_list(
             1,
             typ=BaseType('bool', is_literal=True),
             pos=getpos(self.expr),
         )
     elif self.expr.value is False:
         return LLLnode.from_list(
             0,
             typ=BaseType('bool', is_literal=True),
             pos=getpos(self.expr),
         )
     elif self.expr.value is None:
         # block None
         raise InvalidLiteral('None is not allowed in vyper'
                              '(use a default value or built-in `empty()`')
     else:
         raise Exception(f"Unknown name constant: {self.expr.value.value}")
Ejemplo n.º 30
0
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