Exemple #1
0
    def _getRootNode(self, contractAddr: str,
                     versionString: str) -> solcast.nodes.NodeBase:

        solc_input_json_str = self.solc_input_json_str_skeleton % (
            contractAddr, self.contract_src_path_skeleton % (contractAddr))
        input_json = json.loads(solc_input_json_str)

        # TODO: calculate the most suitable complier version
        self._setMostSuitableVersion(versionString)

        output_json = solcx.compile_standard(input_json,
                                             allow_paths=self.allow_paths)
        # print(self.allow_paths)
        nodes: List[
            solcast.nodes.IterableNodeBase] = solcast.from_standard_output(
                output_json)
        return nodes[0]
Exemple #2
0
def _get_nodes(output_json: Dict) -> Tuple[Dict, Dict, Dict]:
    source_nodes = solcast.from_standard_output(output_json)
    stmt_nodes = _get_statement_nodes(source_nodes)
    branch_nodes = _get_branch_nodes(source_nodes)
    return source_nodes, stmt_nodes, branch_nodes
Exemple #3
0
def generate_build_json(input_json,
                        output_json,
                        compiler_data={},
                        silent=True):
    '''Formats standard compiler output to the brownie build json.

    Args:
        input_json: solc input json used to compile
        output_json: output json returned by compiler
        compiler_data: additonal data to include under 'compiler' in build json
        silent: verbose reporting

    Returns: build json dict'''
    if not silent:
        print("Generating build data...")

    compiler_data.update({
        "optimize":
        input_json['settings']['optimizer']['enabled'],
        "runs":
        input_json['settings']['optimizer']['runs']
    })
    minify = 'minify_source' in compiler_data and compiler_data['minify_source']
    build_json = {}
    path_list = list(input_json['sources'])

    source_nodes = solcast.from_standard_output(deepcopy(output_json))
    statement_nodes = get_statement_nodes(source_nodes)
    branch_nodes = get_branch_nodes(source_nodes)

    for path, contract_name in [(k, v) for k in path_list
                                for v in output_json['contracts'][k]]:

        if not silent:
            print(f" - {contract_name}...")

        evm = output_json['contracts'][path][contract_name]['evm']
        node = next(i[contract_name] for i in source_nodes if i.name == path)
        bytecode = format_link_references(evm)
        paths = sorted(
            set([node.parent().path] +
                [i.parent().path for i in node.dependencies]))

        pc_map, statement_map, branch_map = generate_coverage_data(
            evm['deployedBytecode']['sourceMap'],
            evm['deployedBytecode']['opcodes'], node, statement_nodes,
            branch_nodes)

        build_json[contract_name] = {
            'abi': output_json['contracts'][path][contract_name]['abi'],
            'allSourcePaths': paths,
            'ast': output_json['sources'][path]['ast'],
            'bytecode': bytecode,
            'bytecodeSha1': get_bytecode_hash(bytecode),
            'compiler': compiler_data,
            'contractName': contract_name,
            'coverageMap': {
                'statements': statement_map,
                'branches': branch_map
            },
            'deployedBytecode': evm['deployedBytecode']['object'],
            'deployedSourceMap': evm['deployedBytecode']['sourceMap'],
            'dependencies': [i.name for i in node.dependencies],
            # 'networks': {},
            'offset': node.offset,
            'opcodes': evm['deployedBytecode']['opcodes'],
            'pcMap': pc_map,
            'sha1': sources.get_hash(contract_name, minify),
            'source': input_json['sources'][path]['content'],
            'sourceMap': evm['bytecode']['sourceMap'],
            'sourcePath': path,
            'type': node.type
        }
    return build_json
Exemple #4
0
def get_abi(
    contract_sources: Dict[str, str],
    allow_paths: Optional[str] = None,
    remappings: Optional[list] = None,
    silent: bool = True,
) -> Dict:
    """
    Generate ABIs from contract interfaces.

    Arguments
    ---------
    contract_sources : dict
        a dictionary in the form of {'path': "source code"}
    allow_paths : str, optional
        Compiler allowed filesystem import path
    remappings : list, optional
        List of solidity path remappings
    silent : bool, optional
        Disable verbose reporting

    Returns
    -------
    dict
        Compiled ABIs in the format `{'contractName': [ABI]}`
    """

    final_output = {
        Path(k).stem: {
            "abi": json.loads(v),
            "contractName": Path(k).stem,
            "type": "interface",
            "source": None,
            "offset": None,
            "sha1": sha1(v.encode()).hexdigest(),
        }
        for k, v in contract_sources.items() if Path(k).suffix == ".json"
    }

    for path, source in [(k, v) for k, v in contract_sources.items()
                         if Path(k).suffix == ".vy"]:
        input_json = generate_input_json({path: source}, language="Vyper")
        input_json["settings"]["outputSelection"]["*"] = {"*": ["abi"]}
        try:
            output_json = compile_from_input_json(input_json, silent,
                                                  allow_paths)
        except Exception:
            # vyper interfaces do not convert to ABIs
            # https://github.com/vyperlang/vyper/issues/1944
            continue
        name = Path(path).stem
        final_output[name] = {
            "abi": output_json["contracts"][path][name]["abi"],
            "contractName": name,
            "type": "interface",
            "source": source,
            "offset": [0, len(source)],
            "sha1": sha1(contract_sources[path].encode()).hexdigest(),
        }

    solc_sources = {
        k: v
        for k, v in contract_sources.items() if Path(k).suffix == ".sol"
    }

    if not solc_sources:
        return final_output

    compiler_targets = find_solc_versions(solc_sources,
                                          install_needed=True,
                                          silent=silent)

    for version, path_list in compiler_targets.items():
        to_compile = {
            k: v
            for k, v in contract_sources.items() if k in path_list
        }

        set_solc_version(version)
        input_json = generate_input_json(to_compile,
                                         language="Solidity",
                                         remappings=remappings)
        input_json["settings"]["outputSelection"]["*"] = {
            "*": ["abi"],
            "": ["ast"]
        }

        output_json = compile_from_input_json(input_json, silent, allow_paths)
        source_nodes = solcast.from_standard_output(output_json)
        abi_json = {
            k: v
            for k, v in output_json["contracts"].items() if k in path_list
        }

        for path, name, data in [(k, x, y) for k, v in abi_json.items()
                                 for x, y in v.items()]:
            contract_node = next(i[name] for i in source_nodes
                                 if i.absolutePath == path)
            dependencies = []
            for node in [
                    i for i in contract_node.dependencies
                    if i.nodeType == "ContractDefinition"
            ]:
                dependency_name = node.name
                path_str = node.parent().absolutePath
                dependencies.append(_get_alias(dependency_name, path_str))

            final_output[name] = {
                "abi": data["abi"],
                "ast": output_json["sources"][path]["ast"],
                "contractName": name,
                "dependencies": dependencies,
                "type": "interface",
                "source": contract_sources[path],
                "offset": contract_node.offset,
                "sha1": sha1(contract_sources[path].encode()).hexdigest(),
            }

    return final_output
Exemple #5
0
def generate_build_json(input_json: Dict,
                        output_json: Dict,
                        compiler_data: Optional[Dict] = None,
                        silent: bool = True) -> Dict:
    """Formats standard compiler output to the brownie build json.

    Args:
        input_json: solc input json used to compile
        output_json: output json returned by compiler
        compiler_data: additonal data to include under 'compiler' in build json
        silent: verbose reporting

    Returns: build json dict"""
    if not silent:
        print("Generating build data...")

    if compiler_data is None:
        compiler_data = {}
    compiler_data.update({
        "optimize":
        input_json["settings"]["optimizer"]["enabled"],
        "runs":
        input_json["settings"]["optimizer"]["runs"],
        "evm_version":
        input_json["settings"]["evmVersion"],
    })
    minified = "minify_source" in compiler_data and compiler_data[
        "minify_source"]
    build_json = {}
    path_list = list(input_json["sources"])

    source_nodes = solcast.from_standard_output(deepcopy(output_json))
    statement_nodes = _get_statement_nodes(source_nodes)
    branch_nodes = _get_branch_nodes(source_nodes)

    for path, contract_name in [(k, v) for k in path_list
                                for v in output_json["contracts"][k]]:

        if not silent:
            print(f" - {contract_name}...")

        abi = output_json["contracts"][path][contract_name]["abi"]
        evm = output_json["contracts"][path][contract_name]["evm"]
        bytecode = _format_link_references(evm)
        hash_ = sources.get_hash(input_json["sources"][path]["content"],
                                 contract_name, minified)
        node = next(i[contract_name] for i in source_nodes
                    if i.absolutePath == path)
        paths = sorted(
            set([node.parent().absolutePath] +
                [i.parent().absolutePath for i in node.dependencies]))

        pc_map, statement_map, branch_map = _generate_coverage_data(
            evm["deployedBytecode"]["sourceMap"],
            evm["deployedBytecode"]["opcodes"],
            node,
            statement_nodes,
            branch_nodes,
            next((True for i in abi if i["type"] == "fallback"), False),
        )

        build_json[contract_name] = {
            "abi": abi,
            "allSourcePaths": paths,
            "ast": output_json["sources"][path]["ast"],
            "bytecode": bytecode,
            "bytecodeSha1": _get_bytecode_hash(bytecode),
            "compiler": compiler_data,
            "contractName": contract_name,
            "coverageMap": {
                "statements": statement_map,
                "branches": branch_map
            },
            "deployedBytecode": evm["deployedBytecode"]["object"],
            "deployedSourceMap": evm["deployedBytecode"]["sourceMap"],
            "dependencies": [i.name for i in node.dependencies],
            # 'networks': {},
            "offset": node.offset,
            "opcodes": evm["deployedBytecode"]["opcodes"],
            "pcMap": pc_map,
            "sha1": hash_,
            "source": input_json["sources"][path]["content"],
            "sourceMap": evm["bytecode"]["sourceMap"],
            "sourcePath": path,
            "type": node.contractKind,
        }

    if not silent:
        print("")

    return build_json
def test_mutation(path):
    with open(path) as fp:
        output_json = json.load(fp)
    original = deepcopy(output_json)
    solcast.from_standard_output(output_json)
    assert original == output_json