Example #1
0
    def parse_Hex(self):
        hexstr = self.expr.value

        t = self.expr._metadata.get("type")

        n_bytes = (len(hexstr) - 2) // 2  # e.g. "0x1234" is 2 bytes

        if t is not None:
            inferred_type = new_type_to_old_type(self.expr._metadata["type"])
        # This branch is a band-aid to deal with bytes20 vs address literals
        # TODO handle this properly in the type checker
        elif len(hexstr) == 42:
            inferred_type = BaseType("address", is_literal=True)
        else:
            inferred_type = BaseType(f"bytes{n_bytes}", is_literal=True)

        if is_base_type(inferred_type, "address"):
            # sanity check typechecker did its job
            assert len(hexstr) == 42 and is_checksum_encoded(hexstr)
            typ = BaseType("address")
            return IRnode.from_list(int(self.expr.value, 16), typ=typ)

        elif is_bytes_m_type(inferred_type):
            assert n_bytes == inferred_type._bytes_info.m

            # bytes_m types are left padded with zeros
            val = int(hexstr, 16) << 8 * (32 - n_bytes)

            typ = BaseType(f"bytes{n_bytes}", is_literal=True)
            return IRnode.from_list(val, typ=typ)
Example #2
0
def keccak256_helper(expr, ir_arg, context):
    sub = ir_arg  # TODO get rid of useless variable
    _check_byteslike(sub.typ, expr)

    # Can hash literals
    # TODO this is dead code.
    if isinstance(sub, bytes):
        return IRnode.from_list(bytes_to_int(keccak256(sub)),
                                typ=BaseType("bytes32"))

    # Can hash bytes32 objects
    if is_base_type(sub.typ, "bytes32"):
        return IRnode.from_list(
            [
                "seq",
                ["mstore", MemoryPositions.FREE_VAR_SPACE, sub],
                ["sha3", MemoryPositions.FREE_VAR_SPACE, 32],
            ],
            typ=BaseType("bytes32"),
            add_gas_estimate=_gas_bound(1),
        )

    sub = ensure_in_memory(sub, context)

    return IRnode.from_list(
        [
            "with",
            "_buf",
            sub,
            ["sha3", ["add", "_buf", 32], ["mload", "_buf"]],
        ],
        typ=BaseType("bytes32"),
        annotation="keccak256",
        add_gas_estimate=_gas_bound(ceil(sub.typ.maxlen / 32)),
    )
Example #3
0
def keccak256_helper(expr, to_hash, context):
    _check_byteslike(to_hash.typ, expr)

    # Can hash literals
    # TODO this is dead code.
    if isinstance(to_hash, bytes):
        return IRnode.from_list(bytes_to_int(keccak256(to_hash)),
                                typ=BaseType("bytes32"))

    # Can hash bytes32 objects
    if is_base_type(to_hash.typ, "bytes32"):
        return IRnode.from_list(
            [
                "seq",
                ["mstore", MemoryPositions.FREE_VAR_SPACE, to_hash],
                ["sha3", MemoryPositions.FREE_VAR_SPACE, 32],
            ],
            typ=BaseType("bytes32"),
            add_gas_estimate=_gas_bound(1),
        )

    to_hash = ensure_in_memory(to_hash, context)

    with to_hash.cache_when_complex("buf") as (b1, to_hash):
        data = bytes_data_ptr(to_hash)
        len_ = get_bytearray_length(to_hash)
        return b1.resolve(
            IRnode.from_list(
                ["sha3", data, len_],
                typ="bytes32",
                annotation="keccak256",
                add_gas_estimate=_gas_bound(ceil(to_hash.typ.maxlen / 32)),
            ))
Example #4
0
def test_mapping_node_types():

    with raises(Exception):
        MappingType(int, int)

    node1 = MappingType(BaseType("int128"), BaseType("int128"))
    node2 = MappingType(BaseType("int128"), BaseType("int128"))
    assert node1 == node2
    assert str(node1) == "HashMap[int128, int128]"
Example #5
0
 def parse_Int(self):
     # Literal (mostly likely) becomes int256
     if self.expr.n < 0:
         return IRnode.from_list(self.expr.n,
                                 typ=BaseType("int256", is_literal=True))
     # Literal is large enough (mostly likely) becomes uint256.
     else:
         return IRnode.from_list(self.expr.n,
                                 typ=BaseType("uint256", is_literal=True))
Example #6
0
 def parse_NameConstant(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),
         )
Example #7
0
 def parse_Hex(self):
     orignum = self.expr.value
     if len(orignum) == 42 and checksum_encode(orignum) == orignum:
         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),
         )
Example #8
0
 def internal_memory_scope(self):
     if not self._mock_vars:
         for i in range(20):
             self._new_variable(f"#mock{i}", BaseType(self._size),
                                self._size, bool(i % 2))
         self._mock_vars = True
     return super().internal_memory_scope()
Example #9
0
    def parse_AnnAssign(self):
        typ = parse_type(
            self.stmt.annotation,
            sigs=self.context.sigs,
            custom_structs=self.context.structs,
        )
        varname = self.stmt.target.id
        pos = self.context.new_variable(varname, typ)
        if self.stmt.value is None:
            return

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

        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 = IRnode(
                util.bytes_to_int(self.stmt.value.s),
                typ=BaseType("bytes32"),
            )

        variable_loc = IRnode.from_list(pos, typ=typ, location=MEMORY)

        ir_node = make_setter(variable_loc, sub)

        return ir_node
Example #10
0
    def parse_Name(self):

        if self.expr.id == "self":
            return LLLnode.from_list(["address"],
                                     typ="address",
                                     pos=getpos(self.expr))
        elif self.expr.id in self.context.vars:
            var = self.context.vars[self.expr.id]
            return LLLnode.from_list(
                var.pos,
                typ=var.typ,
                location=var.
                location,  # either 'memory' or 'calldata' storage is handled above.
                encoding=var.encoding,
                pos=getpos(self.expr),
                annotation=self.expr.id,
                mutable=var.mutable,
            )

        elif self.expr.id in BUILTIN_CONSTANTS:
            obj, typ = BUILTIN_CONSTANTS[self.expr.id]
            return LLLnode.from_list([obj],
                                     typ=BaseType(typ, is_literal=True),
                                     pos=getpos(self.expr))
        elif self.expr._metadata["type"].is_immutable:
            # immutable variable
            # need to handle constructor and outside constructor
            var = self.context.globals[self.expr.id]
            is_constructor = self.expr.get_ancestor(
                vy_ast.FunctionDef).get("name") == "__init__"
            if is_constructor:
                # store memory position for later access in module.py in the variable record
                memory_loc = self.context.new_variable(self.expr.id, var.typ)
                self.context.global_ctx._globals[self.expr.id].pos = memory_loc
                # store the data offset in the variable record as well for accessing
                data_offset = self.expr._metadata["type"].position.offset
                self.context.global_ctx._globals[
                    self.expr.id].data_offset = data_offset

                return LLLnode.from_list(
                    memory_loc,
                    typ=var.typ,
                    location="memory",
                    pos=getpos(self.expr),
                    annotation=self.expr.id,
                    mutable=True,
                )
            else:
                immutable_section_size = self.context.global_ctx.immutable_section_size
                offset = self.expr._metadata["type"].position.offset
                # TODO: resolve code offsets for immutables at compile time
                return LLLnode.from_list(
                    ["sub", "codesize", immutable_section_size - offset],
                    typ=var.typ,
                    location="code",
                    pos=getpos(self.expr),
                    annotation=self.expr.id,
                    mutable=False,
                )
Example #11
0
    def from_list(
        cls,
        obj: Any,
        typ: NodeType = None,
        location: Optional[AddrSpace] = None,
        source_pos: Optional[Tuple[int, int]] = None,
        annotation: Optional[str] = None,
        error_msg: Optional[str] = None,
        mutable: bool = True,
        add_gas_estimate: int = 0,
        encoding: Encoding = Encoding.VYPER,
    ) -> "IRnode":
        if isinstance(typ, str):
            typ = BaseType(typ)

        if isinstance(obj, IRnode):
            # note: this modify-and-returnclause is a little weird since
            # the input gets modified. CC 20191121.
            if typ is not None:
                obj.typ = typ
            if obj.source_pos is None:
                obj.source_pos = source_pos
            if obj.location is None:
                obj.location = location
            if obj.encoding is None:
                obj.encoding = encoding
            if obj.error_msg is None:
                obj.error_msg = error_msg

            return obj
        elif not isinstance(obj, list):
            return cls(
                obj,
                [],
                typ,
                location=location,
                annotation=annotation,
                mutable=mutable,
                add_gas_estimate=add_gas_estimate,
                source_pos=source_pos,
                encoding=encoding,
                error_msg=error_msg,
            )
        else:
            return cls(
                obj[0],
                [cls.from_list(o, source_pos=source_pos) for o in obj[1:]],
                typ,
                location=location,
                annotation=annotation,
                mutable=mutable,
                source_pos=source_pos,
                add_gas_estimate=add_gas_estimate,
                encoding=encoding,
                error_msg=error_msg,
            )
Example #12
0
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, "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))
Example #13
0
    def parse_Decimal(self):
        val = self.expr.value * DECIMAL_DIVISOR

        # sanity check that type checker did its job
        assert isinstance(val, decimal.Decimal)
        assert SizeLimits.in_bounds("decimal", val)
        assert math.ceil(val) == math.floor(val)

        val = int(val)

        return IRnode.from_list(val, typ=BaseType("decimal", is_literal=True))
Example #14
0
    def from_list(
        cls,
        obj: Any,
        typ: NodeType = None,
        location: str = None,
        pos: Tuple[int, int] = None,
        annotation: Optional[str] = None,
        mutable: bool = True,
        add_gas_estimate: int = 0,
        valency: Optional[int] = None,
        encoding: Encoding = Encoding.VYPER,
    ) -> "LLLnode":
        if isinstance(typ, str):
            typ = BaseType(typ)

        if isinstance(obj, LLLnode):
            # note: this modify-and-returnclause is a little weird since
            # the input gets modified. CC 20191121.
            if typ is not None:
                obj.typ = typ
            if obj.pos is None:
                obj.pos = pos
            if obj.location is None:
                obj.location = location
            if obj.encoding is None:
                obj.encoding = encoding

            return obj
        elif not isinstance(obj, list):
            return cls(
                obj,
                [],
                typ,
                location=location,
                pos=pos,
                annotation=annotation,
                mutable=mutable,
                add_gas_estimate=add_gas_estimate,
                valency=valency,
                encoding=encoding,
            )
        else:
            return cls(
                obj[0],
                [cls.from_list(o, pos=pos) for o in obj[1:]],
                typ,
                location=location,
                pos=pos,
                annotation=annotation,
                mutable=mutable,
                add_gas_estimate=add_gas_estimate,
                valency=valency,
                encoding=encoding,
            )
Example #15
0
 def parse_Decimal(self):
     numstring, num, den = get_number_as_fraction(self.expr, self.context)
     if not (SizeLimits.MIN_INT128 * den <= num <=
             SizeLimits.MAX_INT128 * 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),
     )
Example #16
0
def test_bytearray_node_type():

    node1 = ByteArrayType(12)
    node2 = ByteArrayType(12)

    assert node1 == node2

    node3 = ByteArrayType(13)
    node4 = BaseType("int128")

    assert node1 != node3
    assert node1 != node4
Example #17
0
    def parse_Hex(self):
        hexstr = self.expr.value

        if len(hexstr) == 42:
            # sanity check typechecker did its job
            assert checksum_encode(hexstr) == hexstr
            typ = BaseType("address")
            # TODO allow non-checksum encoded bytes20
            return IRnode.from_list(int(self.expr.value, 16), typ=typ)

        else:
            n_bytes = (len(hexstr) - 2) // 2  # e.g. "0x1234" is 2 bytes
            # TODO: typ = new_type_to_old_type(self.expr._metadata["type"])
            #       assert n_bytes == typ._bytes_info.m

            # bytes_m types are left padded with zeros
            val = int(hexstr, 16) << 8 * (32 - n_bytes)

            typ = BaseType(f"bytes{n_bytes}", is_literal=True)
            typ.is_literal = True
            return IRnode.from_list(val, typ=typ)
Example #18
0
    def _parse_For_range(self):
        # attempt to use the type specified by type checking, fall back to `int256`
        # this is a stopgap solution to allow uint256 - it will be properly solved
        # once we refactor type system
        iter_typ = "int256"
        if "type" in self.stmt.target._metadata:
            iter_typ = self.stmt.target._metadata["type"]._id

        # Get arg0
        arg0 = self.stmt.iter.args[0]
        num_of_args = len(self.stmt.iter.args)

        # Type 1 for, e.g. for i in range(10): ...
        if num_of_args == 1:
            arg0_val = self._get_range_const_value(arg0)
            start = IRnode.from_list(0, typ=iter_typ)
            rounds = arg0_val

        # Type 2 for, e.g. for i in range(100, 110): ...
        elif self._check_valid_range_constant(self.stmt.iter.args[1],
                                              raise_exception=False)[0]:
            arg0_val = self._get_range_const_value(arg0)
            arg1_val = self._get_range_const_value(self.stmt.iter.args[1])
            start = IRnode.from_list(arg0_val, typ=iter_typ)
            rounds = IRnode.from_list(arg1_val - arg0_val, typ=iter_typ)

        # Type 3 for, e.g. for i in range(x, x + 10): ...
        else:
            arg1 = self.stmt.iter.args[1]
            rounds = self._get_range_const_value(arg1.right)
            start = Expr.parse_value_expr(arg0, self.context)

        r = rounds if isinstance(rounds, int) else rounds.value
        if r < 1:
            return

        varname = self.stmt.target.id
        i = IRnode.from_list(self.context.fresh_varname("range_ix"),
                             typ="uint256")
        iptr = self.context.new_variable(varname, BaseType(iter_typ))

        self.context.forvars[varname] = True

        loop_body = ["seq"]
        # store the current value of i so it is accessible to userland
        loop_body.append(["mstore", iptr, i])
        loop_body.append(parse_body(self.stmt.body, self.context))

        ir_node = IRnode.from_list(
            ["repeat", i, start, rounds, rounds, loop_body])
        del self.context.forvars[varname]

        return ir_node
Example #19
0
def _encode_dyn_array_helper(dst, ir_node, context):
    # if it's a literal, first serialize to memory as we
    # don't have a compile-time abi encoder
    # TODO handle this upstream somewhere
    if ir_node.value == "multi":
        buf = context.new_internal_variable(dst.typ)
        buf = IRnode.from_list(buf, typ=dst.typ, location=MEMORY)
        _bufsz = dst.typ.abi_type.size_bound()
        return [
            "seq",
            make_setter(buf, ir_node),
            [
                "set", "dyn_ofst",
                abi_encode(dst, buf, context, _bufsz, returns_len=True)
            ],
        ]

    subtyp = ir_node.typ.subtype
    child_abi_t = subtyp.abi_type

    ret = ["seq"]

    len_ = get_dyn_array_count(ir_node)
    with len_.cache_when_complex("len") as (b, len_):
        # set the length word
        ret.append(STORE(dst, len_))

        # prepare the loop
        t = BaseType("uint256")
        i = IRnode.from_list(context.fresh_varname("ix"), typ=t)

        # offset of the i'th element in ir_node
        child_location = get_element_ptr(ir_node, i, array_bounds_check=False)

        # offset of the i'th element in dst
        dst = add_ofst(dst, 32)  # jump past length word
        static_elem_size = child_abi_t.embedded_static_size()
        static_ofst = ["mul", i, static_elem_size]
        loop_body = _encode_child_helper(dst, child_location, static_ofst,
                                         "dyn_child_ofst", context)
        loop = ["repeat", i, 0, len_, ir_node.typ.count, loop_body]

        x = ["seq", loop, "dyn_child_ofst"]
        start_dyn_ofst = ["mul", len_, static_elem_size]
        run_children = ["with", "dyn_child_ofst", start_dyn_ofst, x]
        new_dyn_ofst = ["add", "dyn_ofst", run_children]
        # size of dynarray is size of encoded children + size of the length word
        # TODO optimize by adding 32 to the initial value of dyn_ofst
        new_dyn_ofst = ["add", 32, new_dyn_ofst]
        ret.append(["set", "dyn_ofst", new_dyn_ofst])

        return b.resolve(ret)
Example #20
0
def get_dyn_array_count(arg):
    assert isinstance(arg.typ, DArrayType)

    typ = BaseType("uint256")

    if arg.value == "multi":
        return IRnode.from_list(len(arg.args), typ=typ)

    if arg.value == "~empty":
        # empty(DynArray[...])
        return IRnode.from_list(0, typ=typ)

    return IRnode.from_list(LOAD(arg), typ=typ)
Example #21
0
def get_dyn_array_count(arg):
    assert isinstance(arg.typ, DArrayType)

    typ = BaseType("uint256")

    if arg.value == "multi":
        return LLLnode.from_list(len(arg.args), typ=typ)

    if arg.value == "~empty":
        # empty(DynArray[])
        return LLLnode.from_list(0, typ=typ)

    return LLLnode.from_list([load_op(arg.location), arg], typ=typ)
Example #22
0
def byte_array_to_num(arg, out_type):
    """
    Takes a <32 byte array as input, and outputs a number.
    """
    # the location of the bytestring
    bs_start = (LLLnode.from_list(
        "bs_start", typ=arg.typ, location=arg.location, encoding=arg.encoding)
                if arg.is_complex_lll else arg)

    if arg.location == "storage":
        len_ = get_bytearray_length(bs_start)
        data = LLLnode.from_list(["sload", add_ofst(bs_start, 1)],
                                 typ=BaseType("int256"))
    else:
        op = load_op(arg.location)
        len_ = LLLnode.from_list([op, bs_start], typ=BaseType("int256"))
        data = LLLnode.from_list([op, add_ofst(bs_start, 32)],
                                 typ=BaseType("int256"))

    # converting a bytestring to a number:
    # bytestring is right-padded with zeroes, int is left-padded.
    # convert by shr the number of zero bytes (converted to bits)
    # e.g. "abcd000000000000" -> bitcast(000000000000abcd, output_type)
    num_zero_bits = ["mul", 8, ["sub", 32, "len_"]]
    bitcasted = LLLnode.from_list(shr(num_zero_bits, "val"), typ=out_type)

    result = clamp_basetype(bitcasted)

    # TODO use cache_when_complex for these `with` values
    ret = ["with", "val", data, ["with", "len_", len_, result]]
    if arg.is_complex_lll:
        ret = ["with", "bs_start", arg, ret]
    return LLLnode.from_list(
        ret,
        typ=BaseType(out_type),
        annotation=f"__intrinsic__byte_array_to_num({out_type})",
    )
Example #23
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)
Example #24
0
    def parse_Name(self):

        if self.expr.id == "self":
            return LLLnode.from_list(["address"],
                                     typ="address",
                                     pos=getpos(self.expr))
        elif self.expr.id in self.context.vars:
            var = self.context.vars[self.expr.id]
            return LLLnode.from_list(
                var.pos,
                typ=var.typ,
                location=var.
                location,  # either 'memory' or 'calldata' storage is handled above.
                encoding=var.encoding,
                pos=getpos(self.expr),
                annotation=self.expr.id,
                mutable=var.mutable,
            )

        elif self.expr.id in BUILTIN_CONSTANTS:
            obj, typ = BUILTIN_CONSTANTS[self.expr.id]
            return LLLnode.from_list([obj],
                                     typ=BaseType(typ, is_literal=True),
                                     pos=getpos(self.expr))

        elif self.expr._metadata["type"].is_immutable:
            var = self.context.globals[self.expr.id]
            ofst = self.expr._metadata["type"].position.offset

            if self.context.sig.is_init_func:
                mutable = True
                location = "immutables"
            else:
                mutable = False
                location = "data"

            return LLLnode.from_list(
                ofst,
                typ=var.typ,
                location=location,
                pos=getpos(self.expr),
                annotation=self.expr.id,
                mutable=mutable,
            )
Example #25
0
    def parse_BinOp(self):
        left = Expr.parse_value_expr(self.expr.left, self.context)
        right = Expr.parse_value_expr(self.expr.right, self.context)

        if not is_numeric_type(left.typ) or not is_numeric_type(right.typ):
            return

        ltyp, rtyp = left.typ.typ, right.typ.typ

        # Sanity check - ensure that we aren't dealing with different types
        # This should be unreachable due to the type check pass
        assert ltyp == rtyp, f"unreachable, {ltyp}!={rtyp}, {self.expr}"

        if isinstance(self.expr.op, vy_ast.BitAnd):
            new_typ = left.typ
            return IRnode.from_list(["and", left, right], typ=new_typ)
        if isinstance(self.expr.op, vy_ast.BitOr):
            new_typ = left.typ
            return IRnode.from_list(["or", left, right], typ=new_typ)
        if isinstance(self.expr.op, vy_ast.BitXor):
            new_typ = left.typ
            return IRnode.from_list(["xor", left, right], typ=new_typ)

        out_typ = BaseType(ltyp)

        with left.cache_when_complex("x") as (
                b1, x), right.cache_when_complex("y") as (b2, y):
            if isinstance(self.expr.op, vy_ast.Add):
                ret = arithmetic.safe_add(x, y)
            elif isinstance(self.expr.op, vy_ast.Sub):
                ret = arithmetic.safe_sub(x, y)
            elif isinstance(self.expr.op, vy_ast.Mult):
                ret = arithmetic.safe_mul(x, y)
            elif isinstance(self.expr.op, vy_ast.Div):
                ret = arithmetic.safe_div(x, y)
            elif isinstance(self.expr.op, vy_ast.Mod):
                ret = arithmetic.safe_mod(x, y)
            elif isinstance(self.expr.op, vy_ast.Pow):
                ret = arithmetic.safe_pow(x, y)
            else:
                return  # raises

            return IRnode.from_list(b1.resolve(b2.resolve(ret)), typ=out_typ)
Example #26
0
def to_uint8(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 uint8",
                expr,
            )
        else:
            # uint8 clamp is already applied in byte_array_to_num
            in_arg = byte_array_to_num(in_arg, "uint8")

    else:
        # cast to output type so clamp_basetype works
        in_arg = LLLnode.from_list(in_arg, typ="uint8")

    return LLLnode.from_list(clamp_basetype(in_arg),
                             typ=BaseType("uint8"),
                             pos=getpos(expr))
Example #27
0
def test_type_storage_sizes():
    assert BaseType("int128").storage_size_in_words == 1
    assert ByteArrayType(12).storage_size_in_words == 2
    assert ByteArrayType(33).storage_size_in_words == 3
    assert SArrayType(BaseType("int128"), 10).storage_size_in_words == 10

    _tuple = TupleType([BaseType("int128"), BaseType("decimal")])
    assert _tuple.storage_size_in_words == 2

    _struct = StructType({
        "a": BaseType("int128"),
        "b": BaseType("decimal")
    }, "Foo")
    assert _struct.storage_size_in_words == 2

    # Don't allow unknown types.
    with raises(Exception):
        _ = int.storage_size_in_words

    # Maps are not supported for function arguments or outputs
    with raises(Exception):
        _ = MappingType(BaseType("int128"),
                        BaseType("int128")).storage_size_in_words
Example #28
0
def test_canonicalize_type():
    # TODO add more types

    # Test ABI format of multiple args.
    c = TupleType([BaseType("int128"), BaseType("address")])
    assert c.abi_type.selector_name() == "(int128,address)"
Example #29
0
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)"
Example #30
0
def get_bytearray_length(arg):
    typ = BaseType("uint256")

    # TODO add "~empty" case to mirror get_dyn_array_count

    return IRnode.from_list(LOAD(arg), typ=typ)