Exemple #1
0
def parse_other_functions(o,
                          otherfuncs,
                          _globals,
                          sigs,
                          external_contracts,
                          origcode,
                          runtime_only=False):
    sub = ['seq', initializer_lll]
    add_gas = initializer_lll.gas
    for _def in otherfuncs:
        sub.append(
            parse_func(_def, _globals, {
                **{
                    'self': sigs
                },
                **external_contracts
            }, origcode))
        sub[-1].total_gas += add_gas
        add_gas += 30
        sig = FunctionSignature.from_definition(_def, external_contracts)
        sig.gas = sub[-1].total_gas
        sigs[sig.name] = sig
    if runtime_only:
        return sub
    else:
        o.append(['return', 0, ['lll', sub, 0]])
        return o
Exemple #2
0
def mk_full_signature(code):
    o = []
    _contracts, _events, _defs, _globals = get_contracts_and_defs_and_globals(
        code)
    for code in _events:
        sig = EventSignature.from_declaration(code)
        o.append(sig.to_abi_dict())
    for code in _defs:
        sig = FunctionSignature.from_definition(code, _contracts)
        if not sig.private:
            o.append(sig.to_abi_dict())
    return o
Exemple #3
0
def parse_external_contracts(external_contracts, _contracts):
    for _contractname in _contracts:
        _contract_defs = _contracts[_contractname]
        _defnames = [_def.name for _def in _contract_defs]
        contract = {}
        if len(set(_defnames)) < len(_contract_defs):
            raise VariableDeclarationException(
                "Duplicate function name: %s" %
                [name for name in _defnames if _defnames.count(name) > 1][0])
        for _def in _contract_defs:
            sig = FunctionSignature.from_definition(_def)
            contract[sig.name] = sig
        external_contracts[_contractname] = contract
    return external_contracts
Exemple #4
0
def parse_func(code, _globals, sigs, origcode, _vars=None):
    if _vars is None:
        _vars = {}
    sig = FunctionSignature.from_definition(code, sigs)
    # Check for duplicate variables with globals
    for arg in sig.args:
        if arg.name in _globals:
            raise VariableDeclarationException(
                "Variable name duplicated between function arguments and globals: "
                + arg.name)
    # Create a context
    context = Context(vars=_vars,
                      globals=_globals,
                      sigs=sigs,
                      return_type=sig.output_type,
                      is_constant=sig.const,
                      is_payable=sig.payable,
                      origcode=origcode)
    # Copy calldata to memory for fixed-size arguments
    copy_size = sum([
        32 if isinstance(arg.typ, ByteArrayType) else
        get_size_of_type(arg.typ) * 32 for arg in sig.args
    ])
    context.next_mem += copy_size
    if not len(sig.args):
        copier = 'pass'
    elif sig.name == '__init__':
        copier = [
            'codecopy', MemoryPositions.RESERVED_MEMORY, '~codelen', copy_size
        ]
    else:
        copier = [
            'calldatacopy', MemoryPositions.RESERVED_MEMORY, 4, copy_size
        ]
    clampers = [copier]
    # Add asserts for payable and internal
    if not sig.payable:
        clampers.append(['assert', ['iszero', 'callvalue']])
    if sig.private:
        clampers.append(['assert', ['eq', 'caller', 'address']])
    # Fill in variable positions
    for arg in sig.args:
        clampers.append(
            make_clamper(arg.pos, context.next_mem, arg.typ,
                         sig.name == '__init__'))
        if isinstance(arg.typ, ByteArrayType):
            context.vars[arg.name] = VariableRecord(arg.name, context.next_mem,
                                                    arg.typ, False)
            context.next_mem += 32 * get_size_of_type(arg.typ)
        else:
            context.vars[arg.name] = VariableRecord(
                arg.name, MemoryPositions.RESERVED_MEMORY + arg.pos, arg.typ,
                False)
    # Create "clampers" (input well-formedness checkers)
    # Return function body
    if sig.name == '__init__':
        o = LLLnode.from_list(['seq'] + clampers +
                              [parse_body(code.body, context)],
                              pos=getpos(code))
    else:
        method_id_node = LLLnode.from_list(sig.method_id,
                                           pos=getpos(code),
                                           annotation='%s' % sig.name)
        o = LLLnode.from_list([
            'if', ['eq', ['mload', 0], method_id_node],
            ['seq'] + clampers + [parse_body(c, context)
                                  for c in code.body] + ['stop']
        ],
                              typ=None,
                              pos=getpos(code))

    # Check for at leasts one return statement if necessary.
    if context.return_type and context.function_return_count == 0:
        raise StructureException(
            "Missing return statement in function '%s' " % sig.name, code)

    o.context = context
    o.total_gas = o.gas + calc_mem_gas(o.context.next_mem)
    o.func_name = sig.name
    return o
Exemple #5
0
def parse_tree_to_lll(code, origcode):
    _contracts, _events, _defs, _globals = get_contracts_and_defs_and_globals(
        code)
    _names = [_def.name
              for _def in _defs] + [_event.target.id for _event in _events]
    # Checks for duplicate funciton / event names
    if len(set(_names)) < len(_names):
        raise VariableDeclarationException(
            "Duplicate function or event name: %s" %
            [name for name in _names if _names.count(name) > 1][0])
    contracts = {}
    # Create the main statement
    o = ['seq']
    # Initialization function
    initfunc = [_def for _def in _defs if is_initializer(_def)]
    # Regular functions
    otherfuncs = [_def for _def in _defs if not is_initializer(_def)]
    sigs = {}
    if _events:
        for event in _events:
            sigs[event.target.id] = EventSignature.from_declaration(event)
    for _contractname in _contracts:
        _c_defs = _contracts[_contractname]
        _defnames = [_def.name for _def in _c_defs]
        contract = {}
        if len(set(_defnames)) < len(_c_defs):
            raise VariableDeclarationException(
                "Duplicate function name: %s" %
                [name for name in _defnames if _defnames.count(name) > 1][0])
        c_otherfuncs = [_def for _def in _c_defs if not is_initializer(_def)]
        if c_otherfuncs:
            for _def in c_otherfuncs:
                sig = FunctionSignature.from_definition(_def)
                contract[sig.name] = sig
        contracts[_contractname] = contract
    _defnames = [_def.name for _def in _defs]
    if len(set(_defnames)) < len(_defs):
        raise VariableDeclarationException(
            "Duplicate function name: %s" %
            [name for name in _defnames if _defnames.count(name) > 1][0])
    # If there is an init func...
    if initfunc:
        o.append(['seq', initializer_lll])
        o.append(
            parse_func(initfunc[0], _globals, {
                **{
                    'self': sigs
                },
                **contracts
            }, origcode))
    # If there are regular functions...
    if otherfuncs:
        sub = ['seq', initializer_lll]
        add_gas = initializer_lll.gas
        for _def in otherfuncs:
            sub.append(
                parse_func(_def, _globals, {
                    **{
                        'self': sigs
                    },
                    **contracts
                }, origcode))
            sub[-1].total_gas += add_gas
            add_gas += 30
            sig = FunctionSignature.from_definition(_def)
            sig.gas = sub[-1].total_gas
            sigs[sig.name] = sig
        o.append(['return', 0, ['lll', sub, 0]])
    return LLLnode.from_list(o, typ=None)