Exemplo n.º 1
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)
    # 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.º 2
0
def ecadd(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],
         avo(args[1], 0, pos)],
        ['mstore', ['add', placeholder_node, 96],
         avo(args[1], 1, pos)],
        [
            'assert',
            ['call', 500, 6, 0, placeholder_node, 128, placeholder_node, 64]
        ],
        placeholder_node,
    ],
                          typ=ListType(BaseType('uint256'), 2),
                          pos=getpos(expr),
                          location='memory')
    return o
Exemplo n.º 3
0
def raw_call(expr, args, kwargs, context):
    to, data = args
    gas, value, outsize = kwargs['gas'], kwargs['value'], kwargs['outsize']
    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('int128', {'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)
    output_placeholder = context.new_placeholder(ByteArrayType(outsize))
    output_node = LLLnode.from_list(output_placeholder,
                                    typ=ByteArrayType(outsize),
                                    location='memory')
    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.º 4
0
 def build_LLL(self, 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',
             [
                 'staticcall', ['gas'], 7, placeholder_node, 96,
                 placeholder_node, 64
             ]
         ],
         placeholder_node,
     ],
                           typ=ListType(BaseType('uint256'), 2),
                           pos=pos,
                           location='memory')
     return o
Exemplo n.º 5
0
 def binary(self):
     orignum = self.expr.node_source_code
     str_val = orignum[2:]
     total_bits = len(orignum[2:])
     total_bits = (
         total_bits
         if total_bits % 8 == 0
         else total_bits + 8 - (total_bits % 8)  # ceil8 to get byte length.
     )
     if len(orignum[2:]) != total_bits:  # Support only full formed bit definitions.
         raise InvalidLiteralException(
             f"Bit notation requires a multiple of 8 bits / 1 byte. "
             f"{total_bits - len(orignum[2:])} bit(s) are missing.",
             self.expr,
         )
     byte_len = int(total_bits / 8)
     placeholder = self.context.new_placeholder(ByteArrayType(byte_len))
     seq = []
     seq.append(['mstore', placeholder, byte_len])
     for i in range(0, total_bits, 256):
         section = str_val[i:i + 256]
         int_val = int(section, 2) << (256 - len(section))  # bytes are right padded.
         seq.append(
             ['mstore', ['add', placeholder, i + 32], int_val])
     return LLLnode.from_list(
         ['seq'] + seq + [placeholder],
         typ=ByteArrayType(byte_len),
         location='memory',
         pos=getpos(self.expr),
         annotation=f'Create ByteArray (Binary literal): {str_val}',
     )
Exemplo n.º 6
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))
Exemplo n.º 7
0
def raw_call(expr, args, kwargs, context):
    to, data = args
    gas, value, outsize, delegate_call = (
        kwargs['gas'],
        kwargs['value'],
        kwargs['outsize'],
        kwargs['is_delegate_call'],
    )
    if delegate_call.typ.is_literal is False:
        raise TypeMismatch(
            'The delegate_call parameter has to be a static/literal boolean value.'
        )
    if context.is_constant():
        raise ConstancyViolation(
            f"Cannot make calls from {context.pp_constancy()}",
            expr,
        )
    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',
    )

    # build LLL for call or delegatecall
    common_call_lll = [
        ['add', placeholder_node, 32],
        ['mload', placeholder_node],
        # if there is no return value, the return offset can be 0
        ['add', output_node, 32] if outsize else 0,
        outsize
    ]

    if delegate_call.value == 1:
        call_lll = ['delegatecall', gas, to] + common_call_lll
    else:
        call_lll = ['call', gas, to, value] + common_call_lll

    # build sequence LLL
    if outsize:
        # only copy the return value to memory if outsize > 0
        seq = [
            'seq', copier, ['assert', call_lll],
            ['mstore', output_node, outsize], output_node
        ]
        typ = ByteArrayType(outsize)
    else:
        seq = ['seq', copier, ['assert', call_lll]]
        typ = None

    return LLLnode.from_list(seq, typ=typ, location="memory", pos=getpos(expr))
Exemplo n.º 8
0
def concat(expr, context):
    args = [Expr(arg, context).lll_node for arg in expr.args]
    if len(args) < 2:
        raise StructureException("Concat expects at least two arguments", expr)
    for expr_arg, arg in zip(expr.args, args):
        if not isinstance(arg.typ, ByteArrayType) and not is_base_type(arg.typ, 'bytes32') and not is_base_type(arg.typ, 'method_id'):
            raise TypeMismatchException("Concat expects byte arrays or bytes32 objects", expr_arg)
    # Maximum length of the output
    total_maxlen = sum([arg.typ.maxlen if isinstance(arg.typ, ByteArrayType) else 32 for arg in args])
    # Node representing the position of the output in memory
    placeholder = context.new_placeholder(ByteArrayType(total_maxlen))
    # Object representing the output
    seq = []
    # For each argument we are concatenating...
    for arg in args:
        # Start pasting into a position the starts at zero, and keeps
        # incrementing as we concatenate arguments
        placeholder_node = LLLnode.from_list(['add', placeholder, '_poz'], typ=ByteArrayType(total_maxlen), location='memory')
        placeholder_node_plus_32 = LLLnode.from_list(['add', ['add', placeholder, '_poz'], 32], typ=ByteArrayType(total_maxlen), location='memory')
        if isinstance(arg.typ, ByteArrayType):
            # Ignore empty strings
            if arg.typ.maxlen == 0:
                continue
            # Get the length of the current argument
            if arg.location == "memory":
                length = LLLnode.from_list(['mload', '_arg'], typ=BaseType('int128'))
                argstart = LLLnode.from_list(['add', '_arg', 32], typ=arg.typ, location=arg.location)
            elif arg.location == "storage":
                length = LLLnode.from_list(['sload', ['sha3_32', '_arg']], typ=BaseType('int128'))
                argstart = LLLnode.from_list(['add', ['sha3_32', '_arg'], 1], typ=arg.typ, location=arg.location)
            # Make a copier to copy over data from that argyument
            seq.append(['with', '_arg', arg,
                            ['seq',
                                make_byte_slice_copier(placeholder_node_plus_32,
                                                       argstart,
                                                       length,
                                                       arg.typ.maxlen),
                                # Change the position to start at the correct
                                # place to paste the next value
                                ['set', '_poz', ['add', '_poz', length]]]])
        elif isinstance(arg.typ, BaseType) and arg.typ.typ == "method_id":
            seq.append(['seq',
                            ['mstore', ['add', placeholder_node, 32], arg.value * 2**224],
                            ['set', '_poz', ['add', '_poz', 4]]])
        else:
            seq.append(['seq',
                            ['mstore', ['add', placeholder_node, 32], unwrap_location(arg)],
                            ['set', '_poz', ['add', '_poz', 32]]])
    # The position, after all arguments are processing, equals the total
    # length. Paste this in to make the output a proper bytearray
    seq.append(['mstore', placeholder, '_poz'])
    # Memory location of the output
    seq.append(placeholder)
    return LLLnode.from_list(
        ['with', '_poz', 0, ['seq'] + seq], typ=ByteArrayType(total_maxlen), location='memory', pos=getpos(expr), annotation='concat'
    )
Exemplo n.º 9
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.º 10
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))
Exemplo n.º 11
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
Exemplo n.º 12
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 becomes int128
            if (SizeLimits.MINNUM <= self.expr.n <= SizeLimits.MAXNUM):
                return LLLnode.from_list(self.expr.n, typ=BaseType('int128', None, is_literal=True), pos=getpos(self.expr))
            # Literal is large enough, becomes uint256.
            elif 0 <= self.expr.n <= SizeLimits.MAX_UINT256:
                return LLLnode.from_list(self.expr.n, typ=BaseType('uint256', None, is_literal=True), pos=getpos(self.expr))
            else:
                raise InvalidLiteralException("Number out of range: " + str(self.expr.n), self.expr)

        elif isinstance(self.expr.n, float):
            numstring, num, den = get_number_as_fraction(self.expr, self.context)
            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', 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 total_bits != len(orignum[2:]):  # add necessary zero padding.
                pad_len = total_bits - len(orignum[2:])
                str_val = pad_len * '0' + str_val
            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)
Exemplo n.º 13
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.º 14
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={}, 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={}, 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: %s""" % 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)
Exemplo n.º 15
0
def pack_arguments(signature, args, context, pos):
    placeholder_typ = ByteArrayType(maxlen=sum([get_size_of_type(arg.typ) for arg in signature.args]) * 32 + 32)
    placeholder = context.new_placeholder(placeholder_typ)
    setters = [['mstore', placeholder, signature.method_id]]
    needpos = False
    staticarray_offset = 0
    expected_arg_count = len(signature.args)
    actual_arg_count = len(args)
    if actual_arg_count != expected_arg_count:
        raise StructureException("Wrong number of args for: %s (%s args, expected %s)" % (signature.name, actual_arg_count, expected_arg_count))

    for i, (arg, typ) in enumerate(zip(args, [arg.typ for arg in signature.args])):
        if isinstance(typ, BaseType):
            setters.append(make_setter(LLLnode.from_list(placeholder + staticarray_offset + 32 + i * 32, typ=typ), arg, 'memory', pos=pos))
        elif isinstance(typ, ByteArrayType):
            setters.append(['mstore', placeholder + staticarray_offset + 32 + i * 32, '_poz'])
            arg_copy = LLLnode.from_list('_s', typ=arg.typ, location=arg.location)
            target = LLLnode.from_list(['add', placeholder + 32, '_poz'], typ=typ, location='memory')
            setters.append(['with', '_s', arg, ['seq',
                                                    make_byte_array_copier(target, arg_copy),
                                                    ['set', '_poz', ['add', 32, ['add', '_poz', get_length(arg_copy)]]]]])
            needpos = True
        elif isinstance(typ, ListType):
            target = LLLnode.from_list([placeholder + 32 + staticarray_offset + i * 32], typ=typ, location='memory')
            setters.append(make_setter(target, arg, 'memory', pos=pos))
            staticarray_offset += 32 * (typ.count - 1)
        else:
            raise TypeMismatchException("Cannot pack argument of type %r" % typ)
    if needpos:
        return LLLnode.from_list(['with', '_poz', len(args) * 32 + staticarray_offset, ['seq'] + setters + [placeholder + 28]],
                                 typ=placeholder_typ, location='memory'), \
            placeholder_typ.maxlen - 28
    else:
        return LLLnode.from_list(['seq'] + setters + [placeholder + 28], typ=placeholder_typ, location='memory'), \
            placeholder_typ.maxlen - 28
Exemplo n.º 16
0
 def parse_assert(self):
     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', Expr.parse_value_expr(self.stmt.test, self.context), 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',
             Expr.parse_value_expr(self.stmt.test, self.context)
         ],
                                  typ=None,
                                  pos=getpos(self.stmt))
Exemplo n.º 17
0
    def build_LLL(self, expr, args, kwargs, context):
        value = kwargs['value']
        if context.is_constant():
            raise ConstancyViolation(
                f"Cannot make calls from {context.pp_constancy()}",
                expr,
            )
        placeholder = context.new_placeholder(ByteArrayType(96))

        kode = get_create_forwarder_to_bytecode()
        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, 96]],
            ],
            typ=BaseType('address'),
            pos=getpos(expr),
            add_gas_estimate=11000,
        )
Exemplo n.º 18
0
def create_forwarder_to(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 %s" % context.pp_constancy(),
            expr,
        )
    placeholder = context.new_placeholder(ByteArrayType(96))

    kode = get_create_forwarder_to_bytecode()
    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, 96]],
        ],
        typ=BaseType('address'),
        pos=getpos(expr),
        add_gas_estimate=11000,
    )
Exemplo n.º 19
0
    def _assert_reason(self, test_expr, msg):
        if isinstance(msg, vy_ast.Name) and msg.id == "UNREACHABLE":
            return LLLnode.from_list(["assert_unreachable", test_expr],
                                     typ=None,
                                     pos=getpos(msg))

        reason_str_type = ByteArrayType(len(msg.value.strip()))

        sig_placeholder = self.context.new_internal_variable(BaseType(32))
        arg_placeholder = self.context.new_internal_variable(BaseType(32))
        placeholder_bytes = Expr(msg, self.context).lll_node

        method_id = fourbytes_to_int(keccak256(b"Error(string)")[:4])

        revert_seq = [
            "seq",
            ["mstore", sig_placeholder, method_id],
            ["mstore", arg_placeholder, 32],
            placeholder_bytes,
            [
                "revert", sig_placeholder + 28,
                int(4 + get_size_of_type(reason_str_type) * 32)
            ],
        ]
        if test_expr:
            lll_node = ["if", ["iszero", test_expr], revert_seq]
        else:
            lll_node = revert_seq

        return LLLnode.from_list(lll_node, typ=None, pos=getpos(self.stmt))
Exemplo n.º 20
0
Arquivo: stmt.py Projeto: agroce/vyper
    def _assert_reason(self, test_expr, msg):
        if isinstance(msg, ast.Name) and msg.id == 'UNREACHABLE':
            return self._assert_unreachable(test_expr, msg)

        if not isinstance(msg, ast.Str):
            raise StructureException(
                'Reason parameter of assert needs to be a literal string '
                '(or UNREACHABLE constant).', msg)
        if len(msg.s.strip()) == 0:
            raise StructureException('Empty reason string not allowed.',
                                     self.stmt)
        reason_str = 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(msg, self.context).lll_node
        method_id = fourbytes_to_int(keccak256(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))
Exemplo n.º 21
0
    def parse_assert(self):

        with self.context.assertion_scope():
            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 not isinstance(self.stmt.msg, ast.Str):
                raise StructureException(
                    'Reason parameter of assert needs to be a literal string.',
                    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.º 22
0
    def _assert_reason(self, test_expr, msg):
        if isinstance(msg, vy_ast.Name) and msg.id == "UNREACHABLE":
            return LLLnode.from_list(["assert_unreachable", test_expr],
                                     typ=None,
                                     pos=getpos(msg))

        reason_str = 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(msg, self.context).lll_node
        method_id = fourbytes_to_int(keccak256(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 + get_size_of_type(reason_str_type) * 32),
            ],
        ]
        return LLLnode.from_list(assert_reason,
                                 typ=None,
                                 pos=getpos(self.stmt))
Exemplo n.º 23
0
def to_bytes(expr, args, kwargs, context):
    in_arg = args[0]
    if in_arg.typ.maxlen > args[1].slice.value.n:
        raise TypeMismatchException(
            'Cannot convert as input bytes are larger than max length', expr)
    return LLLnode(value=in_arg.value,
                   args=in_arg.args,
                   typ=ByteArrayType(in_arg.typ.maxlen),
                   pos=getpos(expr),
                   location=in_arg.location)
Exemplo n.º 24
0
def test_get_size_of_type():
    assert get_size_of_type(BaseType('int128')) == 1
    assert get_size_of_type(ByteArrayType(12)) == 3
    assert get_size_of_type(ByteArrayType(33)) == 4
    assert get_size_of_type(ListType(BaseType('int128'), 10)) == 10

    _tuple = TupleType([BaseType('int128'), BaseType('decimal')])
    assert get_size_of_type(_tuple) == 2

    _struct = StructType({'a': BaseType('int128'), 'b': BaseType('decimal')})
    assert get_size_of_type(_struct) == 2

    # Don't allow unknow types.
    with raises(Exception):
        get_size_of_type(int)

    # Maps are not supported for function arguments or outputs
    with raises(Exception):
        get_size_of_type(MappingType(BaseType('int128'), BaseType('int128')))
Exemplo n.º 25
0
def test_canonicalize_type():
    # Non-basetype not allowed
    with raises(Exception):
        canonicalize_type(int)
    # List of byte arrays not allowed
    a = ListType(ByteArrayType(12), 2)
    with raises(Exception):
        canonicalize_type(a)
    # Test ABI format of multiple args.
    c = TupleType([BaseType('int128'), BaseType('address')])
    assert canonicalize_type(c) == "(int128,address)"
Exemplo n.º 26
0
def ecmul(expr, args, kwargs, context):
    placeholder_node = LLLnode.from_list(context.new_placeholder(
        ByteArrayType(128)),
                                         typ=ByteArrayType(128),
                                         location='memory')

    o = LLLnode.from_list([
        'seq', ['mstore', placeholder_node,
                avo(args[0], 0)],
        ['mstore', ['add', placeholder_node, 32],
         avo(args[0], 1)], ['mstore', ['add', placeholder_node, 64], args[1]],
        [
            'assert',
            ['call', 40000, 7, 0, placeholder_node, 96, placeholder_node, 64]
        ], placeholder_node
    ],
                          typ=ListType(BaseType('num256'), 2),
                          pos=getpos(expr),
                          location='memory')
    return o
Exemplo n.º 27
0
def test_get_size_of_type():
    assert get_size_of_type(BaseType("int128")) == 1
    assert get_size_of_type(ByteArrayType(12)) == 3
    assert get_size_of_type(ByteArrayType(33)) == 4
    assert get_size_of_type(ListType(BaseType("int128"), 10)) == 10

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

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

    # Don't allow unknown types.
    with raises(Exception):
        get_size_of_type(int)

    # Maps are not supported for function arguments or outputs
    with raises(Exception):
        get_size_of_type(MappingType(BaseType("int128"), BaseType("int128")))
Exemplo n.º 28
0
def pack_arguments(signature, args, context, pos, return_placeholder=True):
    placeholder_typ = ByteArrayType(maxlen=sum([get_size_of_type(arg.typ) for arg in signature.args]) * 32 + 32)
    placeholder = context.new_placeholder(placeholder_typ)
    setters = [['mstore', placeholder, signature.method_id]]
    needpos = False
    staticarray_offset = 0
    expected_arg_count = len(signature.args)
    actual_arg_count = len(args)
    if actual_arg_count != expected_arg_count:
        raise StructureException("Wrong number of args for: %s (%s args, expected %s)" % (signature.name, actual_arg_count, expected_arg_count))

    for i, (arg, typ) in enumerate(zip(args, [arg.typ for arg in signature.args])):
        if isinstance(typ, BaseType):
            setters.append(make_setter(LLLnode.from_list(placeholder + staticarray_offset + 32 + i * 32, typ=typ), arg, 'memory', pos=pos, in_function_call=True))
        elif isinstance(typ, ByteArrayType):
            setters.append(['mstore', placeholder + staticarray_offset + 32 + i * 32, '_poz'])
            arg_copy = LLLnode.from_list('_s', typ=arg.typ, location=arg.location)
            target = LLLnode.from_list(['add', placeholder + 32, '_poz'], typ=typ, location='memory')
            setters.append(['with', '_s', arg, ['seq',
                                                    make_byte_array_copier(target, arg_copy, pos),
                                                    ['set', '_poz', ['add', 32, ['ceil32', ['add', '_poz', get_length(arg_copy)]]]]]])
            needpos = True
        elif isinstance(typ, (StructType, ListType)):
            if has_dynamic_data(typ):
                raise TypeMismatchException("Cannot pack bytearray in struct")
            target = LLLnode.from_list([placeholder + 32 + staticarray_offset + i * 32], typ=typ, location='memory')
            setters.append(make_setter(target, arg, 'memory', pos=pos))
            if (isinstance(typ, ListType)):
                count = typ.count
            else:
                count = len(typ.tuple_items())
            staticarray_offset += 32 * (count - 1)
        else:
            raise TypeMismatchException("Cannot pack argument of type %r" % typ)

    # For private call usage, doesn't use a returner.
    returner = [[placeholder + 28]] if return_placeholder else []
    if needpos:
        return (
            LLLnode.from_list(['with', '_poz', len(args) * 32 + staticarray_offset, ['seq'] + setters + returner],
                                 typ=placeholder_typ, location='memory'),
            placeholder_typ.maxlen - 28,
            placeholder + 32
        )
    else:
        return (
            LLLnode.from_list(['seq'] + setters + returner, typ=placeholder_typ, location='memory'),
            placeholder_typ.maxlen - 28,
            placeholder + 32
        )
Exemplo n.º 29
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('int128', {'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)
Exemplo n.º 30
0
def _RLPlist(expr, args, kwargs, context):
    # Second argument must be a list of types
    if not isinstance(args[1], ast.List):
        raise TypeMismatchException("Expecting list of types for second argument", args[1])
    if len(args[1].elts) == 0:
        raise TypeMismatchException("RLP list must have at least one item", expr)
    if len(args[1].elts) > 32:
        raise TypeMismatchException("RLP list must have at most 32 items", expr)
    # Get the output format
    _format = []
    for arg in args[1].elts:
        if isinstance(arg, ast.Name) and arg.id == "bytes":
            subtyp = ByteArrayType(args[0].typ.maxlen)
        else:
            subtyp = context.parse_type(arg, 'memory')
            if not isinstance(subtyp, BaseType):
                raise TypeMismatchException("RLP lists only accept BaseTypes and byte arrays", arg)
            if not is_base_type(subtyp, ('int128', 'uint256', 'bytes32', 'address', 'bool')):
                raise TypeMismatchException("Unsupported base type: %s" % subtyp.typ, arg)
        _format.append(subtyp)
    output_type = TupleType(_format)
    output_placeholder_type = ByteArrayType(
        (2 * len(_format) + 1 + get_size_of_type(output_type)) * 32,
    )
    output_placeholder = context.new_placeholder(output_placeholder_type)
    output_node = LLLnode.from_list(
        output_placeholder,
        typ=output_placeholder_type,
        location='memory',
    )
    # Create a decoder for each element in the tuple
    decoder = []
    for i, typ in enumerate(_format):
        # Decoder for bytes32
        if is_base_type(typ, 'bytes32'):
            decoder.append(LLLnode.from_list(
                [
                    'seq',
                    [
                        'assert',
                        [
                            'eq',
                            [
                                'mload',
                                [
                                    'add',
                                    output_node,
                                    ['mload', ['add', output_node, 32 * i]],
                                ],
                            ],
                            32,
                        ],
                    ],
                    [
                        'mload',
                        [
                            'add',
                            32,
                            [
                                'add',
                                output_node,
                                ['mload', ['add', output_node, 32 * i]],
                            ],
                        ],
                    ],
                ],
                typ,
                annotation='getting and checking bytes32 item',
            ))
        # Decoder for address
        elif is_base_type(typ, 'address'):
            decoder.append(LLLnode.from_list(
                [
                    'seq',
                    [
                        'assert',
                        [
                            'eq',
                            [
                                'mload',
                                [
                                    'add',
                                    output_node,
                                    ['mload', ['add', output_node, 32 * i]],
                                ],
                            ],
                            20,
                        ]
                    ],
                    [
                        'mod',
                        [
                            'mload',
                            [
                                'add',
                                20,
                                ['add', output_node, ['mload', ['add', output_node, 32 * i]]],
                            ],
                        ],
                        ['mload', MemoryPositions.ADDRSIZE],
                    ]
                ],
                typ,
                annotation='getting and checking address item',
            ))
        # Decoder for bytes
        elif isinstance(typ, ByteArrayType):
            decoder.append(LLLnode.from_list(
                [
                    'add',
                    output_node,
                    ['mload', ['add', output_node, 32 * i]],
                ],
                typ,
                location='memory',
                annotation='getting byte array',
            ))
        # Decoder for num and uint256
        elif is_base_type(typ, ('int128', 'uint256')):
            bytez = LLLnode.from_list(
                [
                    'add',
                    output_node,
                    ['mload', ['add', output_node, 32 * i]],
                ],
                typ,
                location='memory',
                annotation='getting and checking %s' % typ.typ,
            )
            decoder.append(byte_array_to_num(bytez, expr, typ.typ))
        # Decoder for bools
        elif is_base_type(typ, ('bool')):
            # This is basically a really clever way to test for a
            # length-prefixed one or zero. We take the 32 bytes starting one
            # byte *after* the start of the length declaration; this includes
            # the last 31 bytes of the length and the first byte of the value.
            # 0 corresponds to length 0, first byte 0, and 257 corresponds to
            # length 1, first byte \x01
            decoder.append(LLLnode.from_list(
                [
                    'with', '_ans', [
                        'mload',
                        [
                            'add',
                            1,
                            ['add', output_node, ['mload', ['add', output_node, 32 * i]]]
                        ],
                    ],
                    [
                        'seq',
                        ['assert', ['or', ['eq', '_ans', 0], ['eq', '_ans', 257]]],
                        ['div', '_ans', 257],
                    ],
                ],
                typ,
                annotation='getting and checking bool',
            ))
        else:
            # Should never reach because of top level base level check.
            raise Exception("Type not yet supported")  # pragma: no cover
    # Copy the input data to memory
    if args[0].location == "memory":
        variable_pointer = args[0]
    elif args[0].location == "storage":
        placeholder = context.new_placeholder(args[0].typ)
        placeholder_node = LLLnode.from_list(placeholder, typ=args[0].typ, location='memory')
        copier = make_byte_array_copier(
            placeholder_node,
            LLLnode.from_list('_ptr', typ=args[0].typ, location=args[0].location),
        )
        variable_pointer = ['with', '_ptr', args[0], ['seq', copier, placeholder_node]]
    else:
        # Should never reach because of top level base level check.
        raise Exception("Location not yet supported")  # pragma: no cover
    # Decode the input data
    initial_setter = LLLnode.from_list(
        ['seq',
            ['with', '_sub', variable_pointer,
                ['pop', ['call',
                         1500 + 400 * len(_format) + 10 * len(args),
                         LLLnode.from_list(RLP_DECODER_ADDRESS, annotation='RLP decoder'),
                         0,
                         ['add', '_sub', 32],
                         ['mload', '_sub'],
                         output_node,
                         64 * len(_format) + 32 + 32 * get_size_of_type(output_type)]]],
            ['assert', ['eq', ['mload', output_node], 32 * len(_format) + 32]]],
        typ=None)
    # Shove the input data decoder in front of the first variable decoder
    decoder[0] = LLLnode.from_list(
        ['seq', initial_setter, decoder[0]],
        typ=decoder[0].typ,
        location=decoder[0].location,
    )
    return LLLnode.from_list(
        ["multi"] + decoder,
        typ=output_type,
        location='memory',
        pos=getpos(expr),
    )