Exemplo n.º 1
0
def to_uint256(expr, args, kwargs, context):
    in_node = args[0]
    input_type, len = get_type(in_node)

    if isinstance(in_node, int):
        if not SizeLimits.in_bounds('uint256', in_node):
            raise InvalidLiteralException(
                "Number out of range: {}".format(in_node))
        _unit = in_node.typ.unit if input_type == 'int128' else None
        return LLLnode.from_list(in_node,
                                 typ=BaseType('uint256', _unit),
                                 pos=getpos(expr))

    elif isinstance(in_node,
                    LLLnode) and input_type in ('int128', 'num_literal'):
        _unit = in_node.typ.unit if input_type == 'int128' else None
        return LLLnode.from_list(['clampge', in_node, 0],
                                 typ=BaseType('uint256', _unit),
                                 pos=getpos(expr))

    elif isinstance(in_node, LLLnode) and input_type in ('bytes32', 'address'):
        return LLLnode(value=in_node.value,
                       args=in_node.args,
                       typ=BaseType('uint256'),
                       pos=getpos(expr))

    else:
        raise InvalidLiteralException(
            "Invalid input for uint256: %r" % in_node, expr)
Exemplo n.º 2
0
 def parse_name(self):
     if self.stmt.id == "vdb":
         return LLLnode('debugger', typ=None, pos=getpos(self.stmt))
     elif self.stmt.id == "throw":
         return LLLnode.from_list(['assert', 0], typ=None, pos=getpos(self.stmt))
     else:
         raise StructureException("Unsupported statement type: %s" % type(self.stmt), self.stmt)
Exemplo n.º 3
0
    def variables(self):
        builtin_constants = {
            'ZERO_ADDRESS': LLLnode.from_list([0], typ=BaseType('address', None, is_literal=True), pos=getpos(self.expr)),
            'MAX_INT128': LLLnode.from_list(['mload', MemoryPositions.MAXNUM], typ=BaseType('int128', None, is_literal=True), pos=getpos(self.expr)),
            'MIN_INT128': LLLnode.from_list(['mload', MemoryPositions.MINNUM], typ=BaseType('int128', None, is_literal=True), pos=getpos(self.expr)),
            'MAX_DECIMAL': LLLnode.from_list(['mload', MemoryPositions.MAXDECIMAL], typ=BaseType('decimal', None, is_literal=True), pos=getpos(self.expr)),
            'MIN_DECIMAL': LLLnode.from_list(['mload', MemoryPositions.MINDECIMAL], typ=BaseType('decimal', None, is_literal=True), pos=getpos(self.expr)),
            'MAX_UINT256': LLLnode.from_list([2**256 - 1], typ=BaseType('uint256', None, is_literal=True), pos=getpos(self.expr)),
        }

        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='memory', pos=getpos(self.expr), annotation=self.expr.id, mutable=var.mutable)
        elif self.expr.id in builtin_constants:
            return builtin_constants[self.expr.id]
        elif self.expr.id in self.context.constants:
            # check if value is compatible with
            const = self.context.constants[self.expr.id]
            if isinstance(const, ast.AnnAssign):  # Handle ByteArrays.
                expr = Expr(const.value, self.context).lll_node
                return expr
            # Other types are already unwrapped, no need
            return self.context.constants[self.expr.id]
        else:
            raise VariableDeclarationException("Undeclared variable: " + self.expr.id, self.expr)
Exemplo n.º 4
0
def call_self_public(stmt_expr, context, sig):
    # self.* style call to a public function.
    method_name, expr_args, sig = call_lookup_specs(stmt_expr, context)
    add_gas = sig.gas  # gas of call
    inargs, inargsize, _ = pack_arguments(sig,
                                          expr_args,
                                          context,
                                          pos=getpos(stmt_expr))
    output_placeholder, returner, output_size = call_make_placeholder(
        stmt_expr, context, sig)
    assert_call = [
        'assert',
        [
            'call', ['gas'], ['address'], 0, inargs, inargsize,
            output_placeholder, output_size
        ]
    ]
    if output_size > 0:
        assert_call = ['seq', assert_call, returner]
    o = LLLnode.from_list(assert_call,
                          typ=sig.output_type,
                          location='memory',
                          pos=getpos(stmt_expr),
                          add_gas_estimate=add_gas,
                          annotation='Internal Call: %s' % method_name)
    o.gas += sig.gas
    return o
Exemplo n.º 5
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:
         return LLLnode.from_list(None, typ=NullType(), pos=getpos(self.expr))
     else:
         raise Exception("Unknown name constant: %r" % self.expr.value.value)
Exemplo n.º 6
0
def raw_call(expr, args, kwargs, context):
    to, data = args
    gas, value, outsize, delegate_call = kwargs['gas'], kwargs[
        'value'], kwargs['outsize'], kwargs['delegate_call']
    if delegate_call.typ.is_literal is False:
        raise TypeMismatchException(
            'The delegate_call parameter has to be a static/literal boolean value.'
        )
    if context.is_constant:
        raise ConstancyViolationException(
            "Cannot make calls from a constant function", expr)
    if value != zero_value:
        enforce_units(value.typ, get_keyword(expr, 'value'),
                      BaseType('uint256', {'wei': 1}))
    placeholder = context.new_placeholder(data.typ)
    placeholder_node = LLLnode.from_list(placeholder,
                                         typ=data.typ,
                                         location='memory')
    copier = make_byte_array_copier(placeholder_node, data, pos=getpos(expr))
    output_placeholder = context.new_placeholder(ByteArrayType(outsize))
    output_node = LLLnode.from_list(output_placeholder,
                                    typ=ByteArrayType(outsize),
                                    location='memory')

    if delegate_call.value == 1:
        z = LLLnode.from_list([
            'seq', copier,
            [
                'assert',
                [
                    'delegatecall', gas, to, ['add', placeholder_node, 32],
                    ['mload', placeholder_node], ['add', output_node, 32],
                    outsize
                ]
            ], ['mstore', output_node, outsize], output_node
        ],
                              typ=ByteArrayType(outsize),
                              location='memory',
                              pos=getpos(expr))
    else:
        z = LLLnode.from_list([
            'seq', copier,
            [
                'assert',
                [
                    'call', gas, to, value, ['add', placeholder_node, 32],
                    ['mload', placeholder_node], ['add', output_node, 32],
                    outsize
                ]
            ], ['mstore', output_node, outsize], output_node
        ],
                              typ=ByteArrayType(outsize),
                              location='memory',
                              pos=getpos(expr))
    return z
Exemplo n.º 7
0
def _slice(expr, args, kwargs, context):
    sub, start, length = args[0], kwargs['start'], kwargs['len']
    if not are_units_compatible(start.typ, BaseType('int128')):
        raise TypeMismatchException(
            "Type for slice start index must be a unitless number")
    # Expression representing the length of the slice
    if not are_units_compatible(length.typ, BaseType('int128')):
        raise TypeMismatchException(
            "Type for slice length must be a unitless number")
    # Node representing the position of the output in memory
    np = context.new_placeholder(ByteArrayType(maxlen=sub.typ.maxlen + 32))
    placeholder_node = LLLnode.from_list(np, typ=sub.typ, location='memory')
    placeholder_plus_32_node = LLLnode.from_list(np + 32,
                                                 typ=sub.typ,
                                                 location='memory')
    # Copies over bytearray data
    if sub.location == 'storage':
        adj_sub = LLLnode.from_list(
            ['add', ['sha3_32', sub], ['add', ['div', '_start', 32], 1]],
            typ=sub.typ,
            location=sub.location)
    else:
        adj_sub = LLLnode.from_list([
            'add', sub, ['add', ['sub', '_start', ['mod', '_start', 32]], 32]
        ],
                                    typ=sub.typ,
                                    location=sub.location)
    copier = make_byte_slice_copier(placeholder_plus_32_node,
                                    adj_sub, ['add', '_length', 32],
                                    sub.typ.maxlen,
                                    pos=getpos(expr))
    # New maximum length in the type of the result
    newmaxlen = length.value if not len(length.args) else sub.typ.maxlen
    maxlen = ['mload',
              Expr(sub,
                   context=context).lll_node]  # Retrieve length of the bytes.
    out = [
        'with', '_start', start,
        [
            'with', '_length', length,
            [
                'with', '_opos',
                ['add', placeholder_node, ['mod', '_start', 32]],
                [
                    'seq',
                    ['assert', ['le', ['add', '_start', '_length'], maxlen]],
                    copier, ['mstore', '_opos', '_length'], '_opos'
                ]
            ]
        ]
    ]
    return LLLnode.from_list(out,
                             typ=ByteArrayType(newmaxlen),
                             location='memory',
                             pos=getpos(expr))
Exemplo n.º 8
0
 def ann_assign(self):
     self.context.set_in_assignment(True)
     typ = parse_type(self.stmt.annotation, location='memory', custom_units=self.context.custom_units)
     if isinstance(self.stmt.target, ast.Attribute) and self.stmt.target.value.id == 'self':
         raise TypeMismatchException('May not redefine storage variables.', self.stmt)
     varname = self.stmt.target.id
     pos = self.context.new_variable(varname, typ)
     o = LLLnode.from_list('pass', typ=None, pos=pos)
     if self.stmt.value is not None:
         sub = Expr(self.stmt.value, self.context).lll_node
         self._check_valid_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))
     self.context.set_in_assignment(False)
     return o
Exemplo n.º 9
0
def to_decimal(expr, args, kwargs, context):
    input = args[0]
    if input.typ.typ == 'uint256':
        return LLLnode.from_list([
            'uclample', ['mul', input, DECIMAL_DIVISOR],
            ['mload', MemoryPositions.MAXDECIMAL]
        ],
                                 typ=BaseType('decimal', input.typ.unit,
                                              input.typ.positional),
                                 pos=getpos(expr))
    else:
        return LLLnode.from_list(['mul', input, DECIMAL_DIVISOR],
                                 typ=BaseType('decimal', input.typ.unit,
                                              input.typ.positional),
                                 pos=getpos(expr))
Exemplo n.º 10
0
def selfdestruct(expr, args, kwargs, context):
    if context.is_constant:
        raise ConstancyViolationException(
            "Cannot %s inside a constant function!" % expr.func.id, expr.func)
    return LLLnode.from_list(['selfdestruct', args[0]],
                             typ=None,
                             pos=getpos(expr))
Exemplo n.º 11
0
def blockhash(expr, args, kwargs, contact):
    return LLLnode.from_list([
        'blockhash',
        ['uclamplt', ['clampge', args[0], ['sub', ['number'], 256]], 'number']
    ],
                             typ=BaseType('bytes32'),
                             pos=getpos(expr))
Exemplo n.º 12
0
 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))
Exemplo n.º 13
0
def minmax(expr, args, kwargs, context, is_min):
    def _can_compare_with_uint256(operand):
        if operand.typ.typ == 'uint256':
            return True
        elif operand.typ.typ == 'int128' and operand.typ.is_literal and SizeLimits.in_bounds(
                'uint256', operand.value):
            return True
        return False

    left, right = args[0], args[1]
    if not are_units_compatible(left.typ,
                                right.typ) and not are_units_compatible(
                                    right.typ, left.typ):
        raise TypeMismatchException("Units must be compatible", expr)
    if left.typ.typ == 'uint256':
        comparator = 'gt' if is_min else 'lt'
    else:
        comparator = 'sgt' if is_min else 'slt'
    if left.typ.typ == right.typ.typ:
        o = ['if', [comparator, '_l', '_r'], '_r', '_l']
        otyp = left.typ
        otyp.is_literal = False
    elif _can_compare_with_uint256(left) and _can_compare_with_uint256(right):
        o = ['if', [comparator, '_l', '_r'], '_r', '_l']
        if right.typ.typ == 'uint256':
            otyp = right.typ
        else:
            otyp = left.typ
        otyp.is_literal = False
    else:
        raise TypeMismatchException("Minmax types incompatible: %s %s" %
                                    (left.typ.typ, right.typ.typ))
    return LLLnode.from_list(['with', '_l', left, ['with', '_r', right, o]],
                             typ=otyp,
                             pos=getpos(expr))
Exemplo n.º 14
0
def ceil(expr, args, kwards, context):
    return LLLnode.from_list([
        'if', ['slt', args[0], 0], ['sdiv', args[0], DECIMAL_DIVISOR],
        ['sdiv', ['add', args[0], DECIMAL_DIVISOR - 1], DECIMAL_DIVISOR]
    ],
                             typ=BaseType('int128', args[0].typ.unit,
                                          args[0].typ.positional),
                             pos=getpos(expr))
Exemplo n.º 15
0
    def parse_for(self):
        from .parser import (
            parse_body,
        )
        # Type 0 for, e.g. for i in list(): ...
        if self._is_list_iter():
            return self.parse_for_list()

        if not isinstance(self.stmt.iter, ast.Call) or \
            not isinstance(self.stmt.iter.func, ast.Name) or \
                not isinstance(self.stmt.target, ast.Name) or \
                    self.stmt.iter.func.id != "range" or \
                        len(self.stmt.iter.args) not in (1, 2):
            raise StructureException("For statements must be of the form `for i in range(rounds): ..` or `for i in range(start, start + rounds): ..`", self.stmt.iter)  # noqa

        block_scope_id = id(self.stmt.orelse)
        self.context.start_blockscope(block_scope_id)
        # Type 1 for, e.g. for i in range(10): ...
        if len(self.stmt.iter.args) == 1:
            if not isinstance(self.stmt.iter.args[0], ast.Num):
                raise StructureException("Range only accepts literal values", self.stmt.iter)
            start = LLLnode.from_list(0, typ='int128', pos=getpos(self.stmt))
            rounds = self.stmt.iter.args[0].n
        elif isinstance(self.stmt.iter.args[0], ast.Num) and isinstance(self.stmt.iter.args[1], ast.Num):
            # Type 2 for, e.g. for i in range(100, 110): ...
            start = LLLnode.from_list(self.stmt.iter.args[0].n, typ='int128', pos=getpos(self.stmt))
            rounds = LLLnode.from_list(self.stmt.iter.args[1].n - self.stmt.iter.args[0].n, typ='int128', pos=getpos(self.stmt))
        else:
            # Type 3 for, e.g. for i in range(x, x + 10): ...
            if not isinstance(self.stmt.iter.args[1], ast.BinOp) or not isinstance(self.stmt.iter.args[1].op, ast.Add):
                raise StructureException("Two-arg for statements must be of the form `for i in range(start, start + rounds): ...`",
                                            self.stmt.iter.args[1])
            if ast.dump(self.stmt.iter.args[0]) != ast.dump(self.stmt.iter.args[1].left):
                raise StructureException("Two-arg for statements of the form `for i in range(x, x + y): ...` must have x identical in both places: %r %r" % (ast.dump(self.stmt.iter.args[0]), ast.dump(self.stmt.iter.args[1].left)), self.stmt.iter)
            if not isinstance(self.stmt.iter.args[1].right, ast.Num):
                raise StructureException("Range only accepts literal values", self.stmt.iter.args[1])
            start = Expr.parse_value_expr(self.stmt.iter.args[0], self.context)
            rounds = self.stmt.iter.args[1].right.n
        varname = self.stmt.target.id
        pos = self.context.new_variable(varname, BaseType('int128'))
        self.context.forvars[varname] = True
        o = LLLnode.from_list(['repeat', pos, start, rounds, parse_body(self.stmt.body, self.context)], typ=None, pos=getpos(self.stmt))
        del self.context.vars[varname]
        del self.context.forvars[varname]
        self.context.end_blockscope(block_scope_id)
        return o
Exemplo n.º 16
0
    def build_in_comparator(self):
        from ophydia.parser.parser import make_setter
        left = Expr(self.expr.left, self.context).lll_node
        right = Expr(self.expr.comparators[0], self.context).lll_node

        if left.typ.typ != right.typ.subtype.typ:
            raise TypeMismatchException("%s cannot be in a list of %s" % (left.typ.typ, right.typ.subtype.typ))
        result_placeholder = self.context.new_placeholder(BaseType('bool'))
        setter = []

        # Load nth item from list in memory.
        if right.value == 'multi':
            # Copy literal to memory to be compared.
            tmp_list = LLLnode.from_list(
                obj=self.context.new_placeholder(ListType(right.typ.subtype, right.typ.count)),
                typ=ListType(right.typ.subtype, right.typ.count),
                location='memory'
            )
            setter = make_setter(tmp_list, right, 'memory', pos=getpos(self.expr))
            load_i_from_list = ['mload', ['add', tmp_list, ['mul', 32, ['mload', MemoryPositions.FREE_LOOP_INDEX]]]]
        elif right.location == "storage":
            load_i_from_list = ['sload', ['add', ['sha3_32', right], ['mload', MemoryPositions.FREE_LOOP_INDEX]]]
        else:
            load_i_from_list = ['mload', ['add', right, ['mul', 32, ['mload', MemoryPositions.FREE_LOOP_INDEX]]]]

        # Condition repeat loop has to break on.
        break_loop_condition = [
            'if',
            ['eq', unwrap_location(left), load_i_from_list],
            ['seq',
                ['mstore', '_result', 1],  # store true.
                'break']
        ]

        # Repeat loop to loop-compare each item in the list.
        for_loop_sequence = [
            ['mstore', result_placeholder, 0],
            ['with', '_result', result_placeholder,
                ['repeat', MemoryPositions.FREE_LOOP_INDEX, 0, right.typ.count, break_loop_condition]],
            ['mload', result_placeholder]
        ]

        # Save list to memory, so one can iterate over it,
        # used when literal was created with tmp_list.
        if setter:
            compare_sequence = ['seq', setter] + for_loop_sequence
        else:
            compare_sequence = ['seq'] + for_loop_sequence

        # Compare the result of the repeat loop to 1, to know if a match was found.
        o = LLLnode.from_list([
            'eq', 1,
            compare_sequence],
            typ='bool',
            annotation="in comporator"
        )

        return o
Exemplo n.º 17
0
 def string(self):
     bytez, bytez_length = string_to_bytes(self.expr.s)
     placeholder = self.context.new_placeholder(ByteArrayType(bytez_length))
     seq = []
     seq.append(['mstore', placeholder, bytez_length])
     for i in range(0, len(bytez), 32):
         seq.append(['mstore', ['add', placeholder, i + 32], bytes_to_int((bytez + b'\x00' * 31)[i: i + 32])])
     return LLLnode.from_list(['seq'] + seq + [placeholder],
         typ=ByteArrayType(bytez_length), location='memory', pos=getpos(self.expr), annotation='Create ByteArray: %s' % bytez)
Exemplo n.º 18
0
def parse_body(code, context):
    if not isinstance(code, list):
        return parse_stmt(code, context)
    o = []
    for stmt in code:
        lll = parse_stmt(stmt, context)
        o.append(lll)
    return LLLnode.from_list(['seq'] + o,
                             pos=getpos(code[0]) if code else None)
Exemplo n.º 19
0
def send(expr, args, kwargs, context):
    to, value = args
    if context.is_constant:
        raise ConstancyViolationException(
            "Cannot send ether inside a constant function!", expr)
    enforce_units(value.typ, expr.args[1], BaseType('uint256', {'wei': 1}))
    return LLLnode.from_list(['assert', ['call', 0, to, value, 0, 0, 0, 0]],
                             typ=None,
                             pos=getpos(expr))
Exemplo n.º 20
0
def _sha3(expr, args, kwargs, context):
    sub = args[0]
    # Can hash literals
    if isinstance(sub, bytes):
        return LLLnode.from_list(bytes_to_int(sha3(sub)),
                                 typ=BaseType('bytes32'),
                                 pos=getpos(expr))
    # Can hash bytes32 objects
    if is_base_type(sub.typ, 'bytes32'):
        return LLLnode.from_list([
            'seq', ['mstore', MemoryPositions.FREE_VAR_SPACE, sub],
            ['sha3', MemoryPositions.FREE_VAR_SPACE, 32]
        ],
                                 typ=BaseType('bytes32'),
                                 pos=getpos(expr))
    # Copy the data to an in-memory array
    if sub.location == "memory":
        # If we are hashing a value in memory, no need to copy it, just hash in-place
        return LLLnode.from_list([
            'with', '_sub', sub,
            ['sha3', ['add', '_sub', 32], ['mload', '_sub']]
        ],
                                 typ=BaseType('bytes32'),
                                 pos=getpos(expr))
    elif sub.location == "storage":
        lengetter = LLLnode.from_list(['sload', ['sha3_32', '_sub']],
                                      typ=BaseType('int128'))
    else:
        # This should never happen, but just left here for future compiler-writers.
        raise Exception("Unsupported location: %s" %
                        sub.location)  # pragma: no test
    placeholder = context.new_placeholder(sub.typ)
    placeholder_node = LLLnode.from_list(placeholder,
                                         typ=sub.typ,
                                         location='memory')
    copier = make_byte_array_copier(
        placeholder_node,
        LLLnode.from_list('_sub', typ=sub.typ, location=sub.location))
    return LLLnode.from_list([
        'with', '_sub', sub,
        ['seq', copier, ['sha3', ['add', placeholder, 32], lengetter]]
    ],
                             typ=BaseType('bytes32'),
                             pos=getpos(expr))
Exemplo n.º 21
0
def method_id(expr, args, kwargs, context):
    if b' ' in args[0]:
        raise TypeMismatchException(
            'Invalid function signature no spaces allowed.')
    method_id = fourbytes_to_int(sha3(args[0])[:4])
    if args[1] == 'bytes32':
        return LLLnode(method_id, typ=BaseType('bytes32'), pos=getpos(expr))
    elif args[1] == 'bytes[4]':
        placeholder = LLLnode.from_list(
            context.new_placeholder(ByteArrayType(4)))
        return LLLnode.from_list([
            'seq', ['mstore', ['add', placeholder, 4], method_id],
            ['mstore', placeholder, 4], placeholder
        ],
                                 typ=ByteArrayType(4),
                                 location='memory',
                                 pos=getpos(expr))
    else:
        raise StructureException(
            'Can only produce bytes32 or bytes[4] as outputs')
Exemplo n.º 22
0
def raw_log(expr, args, kwargs, context):
    if not isinstance(args[0], ast.List) or len(args[0].elts) > 4:
        raise StructureException(
            "Expecting a list of 0-4 topics as first argument", args[0])
    topics = []
    for elt in args[0].elts:
        arg = Expr.parse_value_expr(elt, context)
        if not is_base_type(arg.typ, 'bytes32'):
            raise TypeMismatchException(
                "Expecting a bytes32 argument as topic", elt)
        topics.append(arg)
    if args[1].location == "memory":
        return LLLnode.from_list([
            "with", "_arr", args[1],
            ["log" + str(len(topics)), ["add", "_arr", 32], ["mload", "_arr"]]
            + topics
        ],
                                 typ=None,
                                 pos=getpos(expr))
    placeholder = context.new_placeholder(args[1].typ)
    placeholder_node = LLLnode.from_list(placeholder,
                                         typ=args[1].typ,
                                         location='memory')
    copier = make_byte_array_copier(placeholder_node,
                                    LLLnode.from_list(
                                        '_sub',
                                        typ=args[1].typ,
                                        location=args[1].location),
                                    pos=getpos(expr))
    return LLLnode.from_list([
        "with", "_sub", args[1],
        [
            "seq", copier,
            [
                "log" + str(len(topics)), ["add", placeholder_node, 32],
                ["mload", placeholder_node]
            ] + topics
        ]
    ],
                             typ=None,
                             pos=getpos(expr))
Exemplo n.º 23
0
    def unary_operations(self):
        operand = Expr.parse_value_expr(self.expr.operand, self.context)
        if isinstance(self.expr.op, ast.Not):
            if isinstance(operand.typ, BaseType) and operand.typ.typ == 'bool':
                return LLLnode.from_list(["iszero", operand], typ='bool', pos=getpos(self.expr))
            else:
                raise TypeMismatchException("Only bool is supported for not operation, %r supplied." % operand.typ, self.expr)
        elif isinstance(self.expr.op, ast.USub):
            if not is_numeric_type(operand.typ):
                raise TypeMismatchException("Unsupported type for negation: %r" % operand.typ, operand)

            if operand.typ.is_literal and 'int' in operand.typ.typ:
                num = ast.Num(0 - operand.value)
                num.source_code = self.expr.source_code
                num.lineno = self.expr.lineno
                num.col_offset = self.expr.col_offset
                return Expr.parse_value_expr(num, self.context)

            return LLLnode.from_list(["sub", 0, operand], typ=operand.typ, pos=getpos(self.expr))
        else:
            raise StructureException("Only the 'not' unary operator is supported")
Exemplo n.º 24
0
def make_call(stmt_expr, context):
    method_name, _, sig = call_lookup_specs(stmt_expr, context)

    if context.is_constant and not sig.const:
        raise ConstancyViolationException(
            "May not call non-constant function '%s' within a constant function."
            % (method_name), getpos(stmt_expr))

    if sig.private:
        return call_self_private(stmt_expr, context, sig)
    else:
        return call_self_public(stmt_expr, context, sig)
Exemplo n.º 25
0
def uint256_mulmod(expr, args, kwargs, context):
    return LLLnode.from_list([
        'seq', ['assert', args[2]],
        [
            'assert',
            [
                'or', ['iszero', args[0]],
                ['eq', ['div', ['mul', args[0], args[1]], args[0]], args[1]]
            ]
        ], ['mulmod', args[0], args[1], args[2]]
    ],
                             typ=BaseType('uint256'),
                             pos=getpos(expr))
Exemplo n.º 26
0
 def parse_assert(self):
     test_expr = Expr.parse_value_expr(self.stmt.test, self.context)
     if not self.is_bool_expr(test_expr):
         raise TypeMismatchException('Only boolean expressions allowed', self.stmt.test)
     if self.stmt.msg:
         if len(self.stmt.msg.s.strip()) == 0:
             raise StructureException('Empty reason string not allowed.', self.stmt)
         reason_str = self.stmt.msg.s.strip()
         sig_placeholder = self.context.new_placeholder(BaseType(32))
         arg_placeholder = self.context.new_placeholder(BaseType(32))
         reason_str_type = ByteArrayType(len(reason_str))
         placeholder_bytes = Expr(self.stmt.msg, self.context).lll_node
         method_id = fourbytes_to_int(sha3(b"Error(string)")[:4])
         assert_reason = \
             ['seq',
                 ['mstore', sig_placeholder, method_id],
                 ['mstore', arg_placeholder, 32],
                 placeholder_bytes,
                 ['assert_reason', test_expr, int(sig_placeholder + 28), int(4 + 32 + get_size_of_type(reason_str_type) * 32)]]
         return LLLnode.from_list(assert_reason, typ=None, pos=getpos(self.stmt))
     else:
         return LLLnode.from_list(['assert', test_expr], typ=None, pos=getpos(self.stmt))
Exemplo n.º 27
0
def external_contract_call(node,
                           context,
                           contract_name,
                           contract_address,
                           pos,
                           value=None,
                           gas=None):
    if value is None:
        value = 0
    if gas is None:
        gas = 'gas'
    if contract_name not in context.sigs:
        raise VariableDeclarationException("Contract not declared yet: %s" %
                                           contract_name)
    method_name = node.func.attr
    if method_name not in context.sigs[contract_name]:
        raise FunctionDeclarationException(
            "Function not declared yet: %s (reminder: "
            "function must be declared in the correct contract)" % method_name,
            pos)
    sig = context.sigs[contract_name][method_name]
    inargs, inargsize, _ = pack_arguments(
        sig, [parse_expr(arg, context) for arg in node.args], context, pos=pos)
    output_placeholder, output_size, returner = get_external_contract_call_output(
        sig, context)
    sub = [
        'seq', ['assert', ['extcodesize', contract_address]],
        ['assert', ['ne', 'address', contract_address]]
    ]
    if context.is_constant or sig.const:
        sub.append([
            'assert',
            [
                'staticcall', gas, contract_address, inargs, inargsize,
                output_placeholder, output_size
            ]
        ])
    else:
        sub.append([
            'assert',
            [
                'call', gas, contract_address, value, inargs, inargsize,
                output_placeholder, output_size
            ]
        ])
    sub.extend(returner)
    o = LLLnode.from_list(sub,
                          typ=sig.output_type,
                          location='memory',
                          pos=getpos(node))
    return o
Exemplo n.º 28
0
 def list_literals(self):
     if not len(self.expr.elts):
         raise StructureException("List must have elements", self.expr)
     o = []
     out_type = None
     for elt in self.expr.elts:
         o.append(Expr(elt, self.context).lll_node)
         if not out_type:
             out_type = o[-1].typ
         previous_type = o[-1].typ.subtype.typ if hasattr(o[-1].typ, 'subtype') else o[-1].typ
         current_type = out_type.subtype.typ if hasattr(out_type, 'subtype') else out_type
         if len(o) > 1 and previous_type != current_type:
             raise TypeMismatchException("Lists may only contain one type", self.expr)
     return LLLnode.from_list(["multi"] + o, typ=ListType(out_type, len(o)), pos=getpos(self.expr))
Exemplo n.º 29
0
 def assign(self):
     # Assignment (e.g. x[4] = y)
     if len(self.stmt.targets) != 1:
         raise StructureException("Assignment statement must have one target", self.stmt)
     self.context.set_in_assignment(True)
     sub = Expr(self.stmt.value, self.context).lll_node
     # Determine if it's an RLPList assignment.
     if isinstance(self.stmt.value, ast.Call) and getattr(self.stmt.value.func, 'id', '') is 'RLPList':
         pos = self.context.new_variable(self.stmt.targets[0].id, sub.typ)
         variable_loc = LLLnode.from_list(pos, typ=sub.typ, location='memory', pos=getpos(self.stmt), annotation=self.stmt.targets[0].id)
         o = make_setter(variable_loc, sub, 'memory', pos=getpos(self.stmt))
     # All other assignments are forbidden.
     elif isinstance(self.stmt.targets[0], ast.Name) and self.stmt.targets[0].id not in self.context.vars:
         raise VariableDeclarationException("Variable type not defined", self.stmt)
     elif isinstance(self.stmt.targets[0], ast.Tuple) and isinstance(self.stmt.value, ast.Tuple):
         raise VariableDeclarationException("Tuple to tuple assignment not supported", self.stmt)
     else:
         # Checks to see if assignment is valid
         target = self.get_target(self.stmt.targets[0])
         o = make_setter(target, sub, target.location, pos=getpos(self.stmt))
     o.pos = getpos(self.stmt)
     self.context.set_in_assignment(False)
     return o
Exemplo n.º 30
0
    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)