Beispiel #1
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)
Beispiel #2
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)
Beispiel #3
0
    def call(self):
        from .parser import (
            pack_logging_data,
            pack_logging_topics,
            external_contract_call,
        )
        if isinstance(self.stmt.func, ast.Name):
            if self.stmt.func.id in stmt_dispatch_table:
                return stmt_dispatch_table[self.stmt.func.id](self.stmt, self.context)
            elif self.stmt.func.id in dispatch_table:
                raise StructureException("Function {} can not be called without being used.".format(self.stmt.func.id), self.stmt)
            else:
                raise StructureException("Unknown function: '{}'.".format(self.stmt.func.id), self.stmt)
        elif isinstance(self.stmt.func, ast.Attribute) and isinstance(self.stmt.func.value, ast.Name) and self.stmt.func.value.id == "self":
            return self_call.make_call(self.stmt, self.context)
        elif isinstance(self.stmt.func, ast.Attribute) and isinstance(self.stmt.func.value, ast.Call):
            contract_name = self.stmt.func.value.func.id
            contract_address = Expr.parse_value_expr(self.stmt.func.value.args[0], self.context)
            return external_contract_call(self.stmt, self.context, contract_name, contract_address, pos=getpos(self.stmt))
        elif isinstance(self.stmt.func.value, ast.Attribute) and self.stmt.func.value.attr in self.context.sigs:
            contract_name = self.stmt.func.value.attr
            var = self.context.globals[self.stmt.func.value.attr]
            contract_address = unwrap_location(LLLnode.from_list(var.pos, typ=var.typ, location='storage', pos=getpos(self.stmt), annotation='self.' + self.stmt.func.value.attr))
            return external_contract_call(self.stmt, self.context, contract_name, contract_address, pos=getpos(self.stmt))
        elif isinstance(self.stmt.func.value, ast.Attribute) and self.stmt.func.value.attr in self.context.globals:
            contract_name = self.context.globals[self.stmt.func.value.attr].typ.unit
            var = self.context.globals[self.stmt.func.value.attr]
            contract_address = unwrap_location(LLLnode.from_list(var.pos, typ=var.typ, location='storage', pos=getpos(self.stmt), annotation='self.' + self.stmt.func.value.attr))
            return external_contract_call(self.stmt, self.context, contract_name, contract_address, pos=getpos(self.stmt))
        elif isinstance(self.stmt.func, ast.Attribute) and self.stmt.func.value.id == 'log':
            if self.stmt.func.attr not in self.context.sigs['self']:
                raise EventDeclarationException("Event not declared yet: %s" % self.stmt.func.attr)
            event = self.context.sigs['self'][self.stmt.func.attr]
            if len(event.indexed_list) != len(self.stmt.args):
                raise EventDeclarationException("%s received %s arguments but expected %s" % (event.name, len(self.stmt.args), len(event.indexed_list)))
            expected_topics, topics = [], []
            expected_data, data = [], []
            for pos, is_indexed in enumerate(event.indexed_list):
                if is_indexed:
                    expected_topics.append(event.args[pos])
                    topics.append(self.stmt.args[pos])
                else:
                    expected_data.append(event.args[pos])
                    data.append(self.stmt.args[pos])
            topics = pack_logging_topics(event.event_id, topics, expected_topics, self.context, pos=getpos(self.stmt))
            inargs, inargsize, inargsize_node, inarg_start = pack_logging_data(expected_data, data, self.context, pos=getpos(self.stmt))

            if inargsize_node is None:
                sz = inargsize
            else:
                sz = ['mload', inargsize_node]

            return LLLnode.from_list(['seq', inargs,
                LLLnode.from_list(["log" + str(len(topics)), inarg_start, sz] + topics, add_gas_estimate=inargsize * 10)], typ=None, pos=getpos(self.stmt))
        else:
            raise StructureException("Unsupported operator: %r" % ast.dump(self.stmt), self.stmt)
Beispiel #4
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
Beispiel #5
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))
Beispiel #6
0
 def zero_pad(bytez_placeholder, maxlen):
     zero_padder = LLLnode.from_list(['pass'])
     if maxlen > 0:
         zero_pad_i = self.context.new_placeholder(BaseType('uint256'))  # Iterator used to zero pad memory.
         zero_padder = LLLnode.from_list(
             ['repeat', zero_pad_i, ['mload', bytez_placeholder], maxlen,
                 ['seq',
                     ['if', ['gt', ['mload', zero_pad_i], maxlen], 'break'],  # stay within allocated bounds
                     ['mstore8', ['add', ['add', 32, bytez_placeholder], ['mload', zero_pad_i]], 0]]],
             annotation="Zero pad"
         )
     return zero_padder
Beispiel #7
0
def replace_with_value(node, var, value):
    if node.value == "with" and node.args[0].value == var:
        return LLLnode(node.value, [
            node.args[0],
            replace_with_value(node.args[1], var, value), node.args[2]
        ], node.typ, node.location, node.annotation)
    elif node.value == var:
        return LLLnode(value, [], node.typ, node.location, node.annotation)
    else:
        return LLLnode(
            node.value,
            [replace_with_value(arg, var, value)
             for arg in node.args], node.typ, node.location, node.annotation)
Beispiel #8
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))
Beispiel #9
0
 def aug_assign(self):
     target = self.get_target(self.stmt.target)
     sub = Expr.parse_value_expr(self.stmt.value, self.context)
     if not isinstance(self.stmt.op, (ast.Add, ast.Sub, ast.Mult, ast.Div, ast.Mod)):
         raise Exception("Unsupported operator for augassign")
     if not isinstance(target.typ, BaseType):
         raise TypeMismatchException("Can only use aug-assign operators with simple types!", self.stmt.target)
     if target.location == 'storage':
         o = Expr.parse_value_expr(ast.BinOp(left=LLLnode.from_list(['sload', '_stloc'], typ=target.typ, pos=target.pos),
                                 right=sub, op=self.stmt.op, lineno=self.stmt.lineno, col_offset=self.stmt.col_offset), self.context)
         return LLLnode.from_list(['with', '_stloc', target, ['sstore', '_stloc', base_type_conversion(o, o.typ, target.typ, pos=getpos(self.stmt))]], typ=None, pos=getpos(self.stmt))
     elif target.location == 'memory':
         o = Expr.parse_value_expr(ast.BinOp(left=LLLnode.from_list(['mload', '_mloc'], typ=target.typ, pos=target.pos),
                                 right=sub, op=self.stmt.op, lineno=self.stmt.lineno, col_offset=self.stmt.col_offset), self.context)
         return LLLnode.from_list(['with', '_mloc', target, ['mstore', '_mloc', base_type_conversion(o, o.typ, target.typ, pos=getpos(self.stmt))]], typ=None, pos=getpos(self.stmt))
Beispiel #10
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
Beispiel #11
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))
Beispiel #12
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))
Beispiel #13
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))
Beispiel #14
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
Beispiel #15
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))
Beispiel #16
0
def to_bytes32(expr, args, kwargs, context):
    input = args[0]
    typ, len = get_type(input)
    if typ == 'bytes':
        if len != 32:
            raise TypeMismatchException(
                "Unable to convert bytes[{}] to bytes32".format(len))
        if input.location == "memory":
            return LLLnode.from_list(['mload', ['add', input, 32]],
                                     typ=BaseType('bytes32'))
        elif input.location == "storage":
            return LLLnode.from_list(['sload', ['add', ['sha3_32', input], 1]],
                                     typ=BaseType('bytes32'))
    else:
        return LLLnode(value=input.value,
                       args=input.args,
                       typ=BaseType('bytes32'),
                       pos=getpos(expr))
Beispiel #17
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))
Beispiel #18
0
def ecrecover(expr, args, kwargs, context):
    placeholder_node = LLLnode.from_list(context.new_placeholder(
        ByteArrayType(128)),
                                         typ=ByteArrayType(128),
                                         location='memory')
    return LLLnode.from_list([
        'seq', ['mstore', placeholder_node, args[0]],
        ['mstore', ['add', placeholder_node, 32], args[1]],
        ['mstore', ['add', placeholder_node, 64], args[2]],
        ['mstore', ['add', placeholder_node, 96], args[3]],
        [
            'pop',
            [
                'call', 3000, 1, 0, placeholder_node, 128,
                MemoryPositions.FREE_VAR_SPACE, 32
            ]
        ], ['mload', MemoryPositions.FREE_VAR_SPACE]
    ],
                             typ=BaseType('address'),
                             pos=getpos(expr))
Beispiel #19
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')
Beispiel #20
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))
Beispiel #21
0
def ecmul(expr, args, kwargs, context):
    placeholder_node = LLLnode.from_list(context.new_placeholder(
        ByteArrayType(128)),
                                         typ=ByteArrayType(128),
                                         location='memory')
    pos = getpos(expr)
    o = LLLnode.from_list([
        'seq', ['mstore', placeholder_node,
                avo(args[0], 0, pos)],
        ['mstore', ['add', placeholder_node, 32],
         avo(args[0], 1, pos)],
        ['mstore', ['add', placeholder_node, 64], args[1]],
        [
            'assert',
            ['call', 40000, 7, 0, placeholder_node, 96, placeholder_node, 64]
        ], placeholder_node
    ],
                          typ=ListType(BaseType('uint256'), 2),
                          pos=pos,
                          location='memory')
    return o
Beispiel #22
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))
Beispiel #23
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))
Beispiel #24
0
    def parse_delete(self):
        from .parser import (
            make_setter,
        )
        if len(self.stmt.targets) != 1:
            raise StructureException("Can delete one variable at a time", self.stmt)
        target = self.stmt.targets[0]
        target_lll = Expr(self.stmt.targets[0], self.context).lll_node

        if isinstance(target, ast.Subscript):
            if target_lll.location == "storage":
                return make_setter(target_lll, LLLnode.from_list(None, typ=NullType()), "storage", pos=getpos(self.stmt))

        raise StructureException("Deleting type not supported.", self.stmt)
Beispiel #25
0
def to_int128(expr, args, kwargs, context):
    in_node = args[0]
    typ, len = get_type(in_node)
    if typ in ('uint256', 'bytes32'):
        if in_node.typ.is_literal and not SizeLimits.in_bounds(
                'int128', in_node.value):
            raise InvalidLiteralException(
                "Number out of range: {}".format(in_node.value), expr)
        return LLLnode.from_list([
            'clamp', ['mload', MemoryPositions.MINNUM], in_node,
            ['mload', MemoryPositions.MAXNUM]
        ],
                                 typ=BaseType('int128', in_node.typ.unit),
                                 pos=getpos(expr))
    else:
        return byte_array_to_num(in_node, expr, 'int128')
Beispiel #26
0
def as_wei_value(expr, args, kwargs, context):
    # Denominations
    names_denom = {
        (b"wei", ): 1,
        (b"femtoether", b"kwei", b"babbage"): 10**3,
        (b"picoether", b"mwei", b"lovelace"): 10**6,
        (b"nanoether", b"gwei", b"shannon"): 10**9,
        (
            b"microether",
            b"szabo",
        ): 10**12,
        (
            b"milliether",
            b"finney",
        ): 10**15,
        (b"ether", ): 10**18,
        (b"kether", b"grand"): 10**21,
    }

    for names, denom in names_denom.items():
        if args[1] in names:
            denomination = denom
            break
    else:
        raise InvalidLiteralException("Invalid denomination: %s" % args[1],
                                      expr.args[1])
    # Compute the amount of wei and return that value
    if isinstance(args[0], (int, float)):
        numstring, num, den = get_number_as_fraction(expr.args[0], context)
        if denomination % den:
            raise InvalidLiteralException(
                "Too many decimal places: %s" % numstring, expr.args[0])
        sub = num * denomination // den
    elif args[0].typ.is_literal:
        if args[0].value <= 0:
            raise InvalidLiteralException("Negative wei value not allowed",
                                          expr)
        sub = ['mul', args[0].value, denomination]
    elif args[0].typ.typ == 'uint256':
        sub = ['mul', args[0], denomination]
    else:
        sub = ['div', ['mul', args[0], denomination], DECIMAL_DIVISOR]

    return LLLnode.from_list(sub,
                             typ=BaseType('uint256', {'wei': 1}),
                             location=None,
                             pos=getpos(expr))
Beispiel #27
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))
Beispiel #28
0
def create_with_code_of(expr, args, kwargs, context):
    value = kwargs['value']
    if value != zero_value:
        enforce_units(value.typ, get_keyword(expr, 'value'),
                      BaseType('uint256', {'wei': 1}))
    if context.is_constant:
        raise ConstancyViolationException(
            "Cannot make calls from a constant function", expr)
    placeholder = context.new_placeholder(ByteArrayType(96))
    kode = b'`.`\x0c`\x009`.`\x00\xf36`\x00`\x007a\x10\x00`\x006`\x00s\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Z\xf4\x15XWa\x10\x00`\x00\xf3'
    assert len(kode) <= 64
    high = bytes_to_int(kode[:32])
    low = bytes_to_int((kode + b'\x00' * 32)[47:79])
    return LLLnode.from_list([
        'seq', ['mstore', placeholder, high],
        ['mstore', ['add', placeholder, 27], ['mul', args[0], 2**96]],
        ['mstore', ['add', placeholder, 47], low],
        ['clamp_nonzero', ['create', value, placeholder, 64]]
    ],
                             typ=BaseType('address'),
                             pos=getpos(expr),
                             add_gas_estimate=10000)
Beispiel #29
0
def shift(expr, args, kwargs, context):
    return LLLnode.from_list(
        [
            'with',
            '_v',
            args[0],
            [
                'with',
                '_s',
                args[1],
                # If second argument is positive, left-shift so multiply by a power of two
                # If it is negative, divide by a power of two
                # node that if the abs of the second argument >= 256, then in the EVM
                # 2**(second arg) = 0, and multiplying OR dividing by 0 gives 0
                [
                    'if', ['slt', '_s', 0],
                    ['div', '_v', ['exp', 2, ['sub', 0, '_s']]],
                    ['mul', '_v', ['exp', 2, '_s']]
                ]
            ]
        ],
        typ=BaseType('uint256'),
        pos=getpos(expr))
Beispiel #30
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