Example #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("num")):
        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("num")):
        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
    out = ['with', '_start', start,
              ['with', '_length', length,
                  ['with', '_opos', ['add', placeholder_node, ['mod', '_start', 32]],
                       ['seq',
                           ['assert', ['lt', ['add', '_start', '_length'], sub.typ.maxlen]],
                           copier,
                           ['mstore', '_opos', '_length'],
                           '_opos']]]]
    return LLLnode.from_list(out, typ=ByteArrayType(newmaxlen), location='memory', pos=getpos(expr))
Example #2
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('num', {'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
Example #3
0
def test_sha3_32():
    lll = ['sha3_32', 0]
    evm = [
        'PUSH1', 0, 'PUSH1', 192, 'MSTORE', 'PUSH1', 32, 'PUSH1', 192, 'SHA3'
    ]
    assert compile_lll.compile_to_assembly(LLLnode.from_list(lll)) == evm
    assert compile_lll.compile_to_assembly(
        optimizer.optimize(LLLnode.from_list(lll))) == evm
Example #4
0
def as_num256(expr, args, kwargs, context):
    if isinstance(args[0], int):
        if not(0 <= args[0] <= 2**256 - 1):
            raise InvalidLiteralException("Number out of range: " + str(expr.args[0].n), expr.args[0])
        return LLLnode.from_list(args[0], typ=BaseType('num256'), pos=getpos(expr))
    elif isinstance(args[0], LLLnode):
        return LLLnode.from_list(['clampge', args[0], 0], typ=BaseType('num256'), pos=getpos(expr))
    else:
        raise InvalidLiteralException("Invalid input for num256: %r" % args[0], expr)
Example #5
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))
Example #6
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
Example #7
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))
Example #8
0
def as_num128(expr, args, kwargs, context):
    return LLLnode.from_list([
        'clamp', ['mload', MemoryPositions.MINNUM], args[0],
        ['mload', MemoryPositions.MAXNUM]
    ],
                             typ=BaseType("num"),
                             pos=getpos(expr))
Example #9
0
def minmax(expr, args, kwargs, context, is_min):
    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 == 'num256':
        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
    elif left.typ.typ == 'num' and right.typ.typ == 'decimal':
        o = [
            'if', [comparator, ['mul', '_l', DECIMAL_DIVISOR], '_r'], '_r',
            ['mul', '_l', DECIMAL_DIVISOR]
        ]
        otyp = 'decimal'
    elif left.typ.typ == 'decimal' and right.typ.typ == 'num':
        o = [
            'if', [comparator, '_l', ['mul', '_r', DECIMAL_DIVISOR]],
            ['mul', '_r', DECIMAL_DIVISOR], '_l'
        ]
        otyp = 'decimal'
    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))
Example #10
0
def as_wei_value(expr, args, kwargs, context):
    # Denominations
    if args[1] == "wei":
        denomination = 1
    elif args[1] in ("kwei", "ada", "lovelace"):
        denomination = 10**3
    elif args[1] == "babbage":
        denomination = 10**6
    elif args[1] in ("shannon", "gwei"):
        denomination = 10**9
    elif args[1] == "szabo":
        denomination = 10**12
    elif args[1] == "finney":
        denomination = 10**15
    elif args[1] == "ether":
        denomination = 10**18
    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.typ == 'num':
        sub = ['mul', args[0], denomination]
    else:
        sub = ['div', ['mul', args[0], denomination], DECIMAL_DIVISOR]
    return LLLnode.from_list(sub, typ=BaseType('num', {'wei': 1}), location=None, pos=getpos(expr))
Example #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))
Example #12
0
def decimal(expr, args, kwargs, context):
    if args[0].typ.typ == 'decimal':
        return args[0]
    else:
        return LLLnode.from_list(
            ['mul', args[0], DECIMAL_DIVISOR], typ=BaseType('decimal', args[0].typ.unit, args[0].typ.positional),
            pos=getpos(expr)
        )
Example #13
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('num'))
    else:
        raise Exception("Unsupported location: %s" % sub.location)
    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)
    )
Example #14
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('num', {'wei': 1}))
    return LLLnode.from_list(['assert', ['call', 0, to, value, 0, 0, 0, 0]],
                             typ=None,
                             pos=getpos(expr))
Example #15
0
def num256_sub(expr, args, kwargs, context):
    return LLLnode.from_list(
        [
            'seq',
            # Checks that: a >= b
            ['assert', ['ge', args[0], args[1]]],
            ['sub', args[0], args[1]]
        ],
        typ=BaseType('num256'),
        pos=getpos(expr))
Example #16
0
def num256_div(expr, args, kwargs, context):
    return LLLnode.from_list(
        [
            'seq',
            # Checks that:  b != 0
            ['assert', args[1]],
            ['div', args[0], args[1]]
        ],
        typ=BaseType('num256'),
        pos=getpos(expr))
Example #17
0
def concat(expr, context):
    from viper.parser.parser import parse_expr, unwrap_location
    args = [parse_expr(arg, context) 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('num'))
                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('num'))
                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)
    )
Example #18
0
def as_num256(expr, args, kwargs, context):
    if isinstance(args[0], int):
        if not(0 <= args[0] <= 2**256 - 1):
            raise InvalidLiteralException("Number out of range: " + str(expr.args[0].n), expr.args[0])
        return LLLnode.from_list(args[0], typ=BaseType('num256', None), pos=getpos(expr))
    elif isinstance(args[0], LLLnode):
        if args[0].value == "sub" and args[0].args[0].value == 0 and args[0].args[1].value > 0:
            raise InvalidLiteralException("Negative numbers cannot be num256 literals")
        return LLLnode(value=args[0].value, args=args[0].args, typ=BaseType('num256'), pos=getpos(expr))
    else:
        raise InvalidLiteralException("Invalid input for num256: %r" % args[0], expr)
Example #19
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', ['sle', '_s', 0],
                                           ['div', '_v', ['exp', 2, ['sub', 0, '_s']]],
                                           ['mul', '_v', ['exp', 2, '_s']]]]],
    typ=BaseType('num256'), pos=getpos(expr))
Example #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))
    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))
Example #21
0
def num256_exp(expr, args, kwargs, context):
    return LLLnode.from_list([
        'seq',
        [
            'assert',
            [
                'or', ['or', ['eq', args[1], 1], ['iszero', args[1]]],
                ['lt', args[0], ['exp', args[0], args[1]]]
            ]
        ], ['exp', args[0], args[1]]
    ],
                             typ=BaseType('num256'),
                             pos=getpos(expr))
Example #22
0
def num256_mulmod(expr, args, kwargs, context):
    return LLLnode.from_list([
        'seq',
        [
            '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('num256'),
                             pos=getpos(expr))
Example #23
0
def extract32(expr, args, kwargs, context):
    sub, index = args
    ret_type = kwargs['type']
    # Get length and specific element
    if sub.location == "memory":
        lengetter = LLLnode.from_list(['mload', '_sub'], typ=BaseType('num'))
        elementgetter = lambda index: LLLnode.from_list(
            ['mload', ['add', '_sub', ['add', 32, ['mul', 32, index]]]], typ=BaseType('num')
        )
    elif sub.location == "storage":
        lengetter = LLLnode.from_list(['sload', ['sha3_32', '_sub']], typ=BaseType('num'))
        elementgetter = lambda index: LLLnode.from_list(
            ['sload', ['add', ['sha3_32', '_sub'], ['add', 1, index]]], typ=BaseType('num')
        )
    # Special case: index known to be a multiple of 32
    if isinstance(index.value, int) and not index.value % 32:
        o = LLLnode.from_list(
            ['with', '_sub', sub, elementgetter(['div', ['clamp', 0, index, ['sub', lengetter, 32]], 32])],
            typ=BaseType(ret_type), annotation='extracting 32 bytes'
        )
    # General case
    else:
        o = LLLnode.from_list(
            ['with', '_sub', sub,
             ['with', '_len', lengetter,
              ['with', '_index', ['clamp', 0, index, ['sub', '_len', 32]],
               ['with', '_mi32', ['mod', '_index', 32],
                ['with', '_di32', ['div', '_index', 32],
                 ['if',
                  '_mi32',
                  ['add',
                   ['mul',
                    elementgetter('_di32'),
                    ['exp', 256, '_mi32']],
                   ['div',
                    elementgetter(['add', '_di32', 1]),
                    ['exp', 256, ['sub', 32, '_mi32']]]],
                  elementgetter('_di32')]]]]]],
        typ=BaseType(ret_type), pos=getpos(expr), annotation='extracting 32 bytes')
    if ret_type == 'num128':
        return LLLnode.from_list(['clamp', ['mload', MemoryPositions.MINNUM], o, ['mload', MemoryPositions.MAXNUM]], typ=BaseType("num"), pos=getpos(expr))
    elif ret_type == 'address':
        return LLLnode.from_list(['uclamplt', o, ['mload', MemoryPositions.ADDRSIZE]], typ=BaseType(ret_type), pos=getpos(expr))
    else:
        return o
Example #24
0
def num256_add(expr, args, kwargs, context):
    return LLLnode.from_list(
        [
            'seq',
            # Checks that: a + b > a
            [
                'assert',
                [
                    'or', ['iszero', args[1]],
                    ['gt', ['add', args[0], args[1]], args[0]]
                ]
            ],
            ['add', args[0], args[1]]
        ],
        typ=BaseType('num256'),
        pos=getpos(expr))
Example #25
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('num', {'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)
Example #26
0
def num256_mul(expr, args, kwargs, context):
    return LLLnode.from_list(
        [
            'seq',
            # Checks that: a == 0 || a / b == b
            [
                'assert',
                [
                    'or', ['iszero', args[0]],
                    [
                        'eq', ['div', ['mul', args[0], args[1]], args[0]],
                        args[1]
                    ]
                ]
            ],
            ['mul', args[0], args[1]]
        ],
        typ=BaseType('num256'),
        pos=getpos(expr))
Example #27
0
 def lll_compiler(lll):
     lll = optimizer.optimize(LLLnode.from_list(lll))
     byte_code = compile_lll.assembly_to_evm(compile_lll.compile_to_assembly(lll))
     t.s.tx(to=b'', data=byte_code)
Example #28
0
rlp_decoder_lll = LLLnode.from_list([
    'seq',
    [
        'return',
        [0],
        [
            'lll',
            [
                'seq',
                ['mstore', position_index, 0],
                ['mstore', data_pos, 0],
                ['mstore', c, call_data_char(0)],
                ['mstore', i, 0],
                ['mstore', position_offset, 0],
                ['assert', ['ge', ['mload', c], 192]],  # Must be a list
                [
                    'if',
                    ['lt', ['mload', c], 248],  # if c < 248:
                    [
                        'seq',
                        [
                            'assert',
                            ['eq', ['calldatasize'],
                             sub(['mload', c], 191)]
                        ],  # assert ~calldatasize() == (c - 191)
                        ['mstore', i, 1]  # i = 1
                    ],
                    [
                        'seq',
                        [
                            'assert',
                            [
                                'eq', ['calldatasize'],
                                add(
                                    sub(['mload', c], 246),
                                    call_data_bytes_as_int(
                                        1, sub(['mload', c], 247)))
                            ]
                        ],  # assert ~calldatasize() == (c - 246) + calldatabytes_as_int(1, c - 247)
                        ['mstore', i, sub(['mload', c], 246)]  # i = c - 246
                    ],
                ],
                # Main loop
                # Here, we simultaneously build up data in two places:
                # (i) starting from memory index 64, a list of 32-byte numbers
                #     representing the start positions of each value
                # (ii) starting from memory index 1088, the values, in format
                #     <length as 32 byte int> <value>, packed one after the other
                [
                    'repeat', loop_memory_position, 1, 100,
                    [
                        'seq',
                        ['if', ['ge', ['mload', i], 'calldatasize'], 'break'],
                        ['mstore', c,
                         call_data_char(['mload', i])],
                        [
                            'mstore',
                            add(positions,
                                ['mul', ['mload', position_index], 32]),
                            ['mload', data_pos]
                        ],
                        [
                            'mstore', position_index,
                            add(['mload', position_index], 1)
                        ],
                        [
                            'if', ['lt', ['mload', c], 128],
                            [
                                'seq',
                                ['mstore',
                                 add(data, ['mload', data_pos]), 1],
                                [
                                    'calldatacopy',
                                    add(data + 32, ['mload', data_pos]),
                                    ['mload', i], 1
                                ], ['mstore', i,
                                    add(['mload', i], 1)],
                                [
                                    'mstore', data_pos,
                                    add(['mload', data_pos], 33)
                                ]
                            ],
                            [
                                'if', ['lt', ['mload', c], 184],
                                [
                                    'seq',
                                    [
                                        'mstore',
                                        add(data, ['mload', data_pos]),
                                        sub(['mload', c], 128)
                                    ],
                                    [
                                        'calldatacopy',
                                        add(data + 32, ['mload', data_pos]),
                                        add(['mload', i], 1),
                                        sub(['mload', c], 128)
                                    ],
                                    [
                                        'if', ['eq', ['mload', c], 129],
                                        [
                                            'assert',
                                            [
                                                'ge',
                                                call_data_char(
                                                    add(['mload', i], 1)), 128
                                            ]
                                        ]
                                    ],
                                    [
                                        'mstore', i,
                                        add(['mload', i], sub(['mload', c],
                                                              127))
                                    ],
                                    [
                                        'mstore', data_pos,
                                        add(['mload', data_pos],
                                            sub(['mload', c], 96))
                                    ]
                                ],
                                [
                                    'if', ['lt', ['mload', c], 192],
                                    [
                                        'seq',
                                        [
                                            'mstore', L,
                                            call_data_bytes_as_int(
                                                add(['mload', i], 1),
                                                sub(['mload', c], 183))
                                        ],
                                        [
                                            'assert',
                                            [
                                                'mul',
                                                call_data_char(
                                                    add(['mload', i], 1)),
                                                ['ge', ['mload', L], 56]
                                            ]
                                        ],
                                        [
                                            'mstore',
                                            add(data, ['mload', data_pos]),
                                            ['mload', L]
                                        ],
                                        [
                                            'calldatacopy',
                                            add(data + 32,
                                                ['mload', data_pos]),
                                            add(['mload', i],
                                                sub(['mload', c], 182)),
                                            ['mload', L]
                                        ],
                                        [
                                            'mstore', i,
                                            add(
                                                add(['mload', i],
                                                    sub(['mload', c], 182)),
                                                ['mload', L])
                                        ],
                                        [
                                            'mstore', data_pos,
                                            add(['mload', data_pos],
                                                add(['mload', L], 32))
                                        ]
                                    ], ['invalid']
                                ]
                            ]
                        ],
                    ]
                ],
                ['assert', ['le', ['mload', position_index], 31]],
                [
                    'mstore', position_offset,
                    add(['mul', ['mload', position_index], 32], 32)
                ],
                ['mstore', i, sub(['mload', position_offset], 32)],
                [
                    'repeat',
                    loop_memory_position,
                    1,
                    100,
                    [
                        'seq',
                        ['if', ['slt', ['mload', i], 0], 'break'],
                        [
                            'mstore',
                            add(sub(data, ['mload', position_offset]),
                                ['mload', i]),
                            add(['mload',
                                 add(positions, ['mload', i])],
                                ['mload', position_offset])
                        ],
                        # ~mstore(data - positionOffset + i, ~mload(positions + i) + positionOffset)
                        ['mstore', i, sub(['mload', i], 32)],
                    ]
                ],
                [
                    'mstore',
                    sub(data, 32),
                    add(['mload', position_offset], ['mload', data_pos])
                ],
                [
                    'return',
                    sub(data, ['mload', position_offset]),
                    add(['mload', position_offset], ['mload', data_pos])
                ]
            ],
            [0]
        ]
    ]
])
Example #29
0
def num256_le(expr, args, kwargs, context):
    return LLLnode.from_list(['le', args[0], args[1]], typ=BaseType('bool'), pos=getpos(expr))
Example #30
0
def bitwise_not(expr, args, kwargs, context):
    return LLLnode.from_list(['not', args[0]], typ=BaseType('num256'), pos=getpos(expr))