示例#1
0
def compile_and_format(
    contract_sources: Dict[str, str],
    solc_version: Optional[str] = None,
    vyper_version: Optional[str] = None,
    optimize: bool = True,
    runs: int = 200,
    evm_version: Optional[str] = None,
    silent: bool = True,
    allow_paths: Optional[str] = None,
    interface_sources: Optional[Dict[str, str]] = None,
    remappings: Optional[list] = None,
    optimizer: Optional[Dict] = None,
) -> Dict:
    """Compiles contracts and returns build data.

    Args:
        contract_sources: a dictionary in the form of {'path': "source code"}
        solc_version: solc version to compile with (use None to set via pragmas)
        optimize: (deprecated) enable solc optimizer
        runs: (deprecated) optimizer runs
        evm_version: evm version to compile for
        silent: verbose reporting
        allow_paths: compiler allowed filesystem import path
        interface_sources: dictionary of interfaces as {'path': "source code"}
        remappings: list of solidity path remappings
        optimizer: dictionary of solidity optimizer settings

    Returns:
        build data dict
    """
    if not contract_sources:
        return {}
    if interface_sources is None:
        interface_sources = {}

    if [i for i in contract_sources if Path(i).suffix not in (".sol", ".vy")]:
        raise UnsupportedLanguage(
            "Source suffixes must be one of ('.sol', '.vy')")
    if [
            i for i in interface_sources
            if Path(i).suffix not in (".sol", ".vy", ".json")
    ]:
        raise UnsupportedLanguage(
            "Interface suffixes must be one of ('.sol', '.vy', '.json')")

    build_json: Dict = {}
    compiler_targets = {}

    vyper_sources = {
        k: v
        for k, v in contract_sources.items() if Path(k).suffix == ".vy"
    }
    if vyper_sources:
        # TODO add `vyper_version` input arg to manually specify, support in config file
        if vyper_version is None:
            compiler_targets.update(
                find_vyper_versions(vyper_sources,
                                    install_needed=True,
                                    silent=silent))
        else:
            compiler_targets[vyper_version] = list(vyper_sources)
    solc_sources = {
        k: v
        for k, v in contract_sources.items() if Path(k).suffix == ".sol"
    }
    if solc_sources:
        if solc_version is None:
            compiler_targets.update(
                find_solc_versions(solc_sources,
                                   install_needed=True,
                                   silent=silent))
        else:
            compiler_targets[solc_version] = list(solc_sources)

        if optimizer is None:
            optimizer = {"enabled": optimize, "runs": runs if optimize else 0}

    for version, path_list in compiler_targets.items():
        compiler_data: Dict = {}
        if path_list[0].endswith(".vy"):
            set_vyper_version(version)
            language = "Vyper"
            compiler_data["version"] = str(vyper.get_version())
            interfaces = {
                k: v
                for k, v in interface_sources.items()
                if Path(k).suffix != ".sol"
            }
        else:
            set_solc_version(version)
            language = "Solidity"
            compiler_data["version"] = str(solidity.get_version())
            interfaces = {
                k: v
                for k, v in interface_sources.items()
                if Path(k).suffix == ".sol"
                and Version(version) in sources.get_pragma_spec(v, k)
            }

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

        input_json = generate_input_json(
            to_compile,
            evm_version=evm_version,
            language=language,
            interface_sources=interfaces,
            remappings=remappings,
            optimizer=optimizer,
        )

        output_json = compile_from_input_json(input_json, silent, allow_paths)

        output_json["contracts"] = {
            k: v
            for k, v in output_json["contracts"].items() if k in path_list
        }

        build_json.update(
            generate_build_json(input_json, output_json, compiler_data,
                                silent))
    return build_json
示例#2
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",
            "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],
            "contractName": name,
            "type": "interface",
            "sha1": sha1(contract_sources[path].encode()).hexdigest(),
        }

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

    if solc_sources:

        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="Vyper" if version == "vyper" else "Solidity",
                remappings=remappings,
            )
            input_json["settings"]["outputSelection"]["*"] = {"*": ["abi"]}

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

            final_output.update({
                name: {
                    "abi": data["abi"],
                    "contractName": name,
                    "type": "interface",
                    "sha1": sha1(contract_sources[path].encode()).hexdigest(),
                }
                for path, v in output_json.items() for name, data in v.items()
            })

    return final_output
示例#3
0
def compile_and_format(
    contract_sources: Dict[str, str],
    solc_version: Optional[str] = None,
    optimize: bool = True,
    runs: int = 200,
    evm_version: int = None,
    minify: bool = False,
    silent: bool = True,
    allow_paths: Optional[str] = None,
    interface_sources: Optional[Dict[str, str]] = None,
) -> Dict:
    """Compiles contracts and returns build data.

    Args:
        contracts: a dictionary in the form of {'path': "source code"}
        solc_version: solc version to compile with (use None to set via pragmas)
        optimize: enable solc optimizer
        runs: optimizer runs
        evm_version: evm version to compile for
        minify: minify source files
        silent: verbose reporting
        allow_paths: compiler allowed filesystem import path

    Returns:
        build data dict
    """
    if not contract_sources:
        return {}
    if interface_sources is None:
        interface_sources = {}

    if [i for i in contract_sources if Path(i).suffix not in (".sol", ".vy")]:
        raise UnsupportedLanguage(
            "Source suffixes must be one of ('.sol', '.vy')")
    if [
            i for i in interface_sources
            if Path(i).suffix not in (".sol", ".vy", ".json")
    ]:
        raise UnsupportedLanguage(
            "Interface suffixes must be one of ('.sol', '.vy', '.json')")

    build_json: Dict = {}
    compiler_targets = {}

    vyper_paths = [i for i in contract_sources if Path(i).suffix == ".vy"]
    if vyper_paths:
        compiler_targets["vyper"] = vyper_paths

    solc_sources = {
        k: v
        for k, v in contract_sources.items() if Path(k).suffix == ".sol"
    }
    if solc_sources:
        if solc_version is None:
            compiler_targets.update(
                find_solc_versions(solc_sources,
                                   install_needed=True,
                                   silent=silent))
        else:
            compiler_targets[solc_version] = list(solc_sources)

    for version, path_list in compiler_targets.items():
        compiler_data: Dict = {"minify_source": minify}
        if version == "vyper":
            language = "Vyper"
            compiler_data["version"] = str(vyper.get_version())
            interfaces = {
                k: v
                for k, v in interface_sources.items()
                if Path(k).suffix != ".sol"
            }
        else:
            set_solc_version(version)
            language = "Solidity"
            compiler_data["version"] = str(solidity.get_version())
            interfaces = {
                k: v
                for k, v in interface_sources.items()
                if Path(k).suffix == ".sol"
                and Version(version) in sources.get_pragma_spec(v, k)
            }

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

        input_json = generate_input_json(to_compile, optimize, runs,
                                         evm_version, minify, language,
                                         interfaces)
        output_json = compile_from_input_json(input_json, silent, allow_paths)

        output_json["contracts"] = {
            k: v
            for k, v in output_json["contracts"].items() if k in path_list
        }

        build_json.update(
            generate_build_json(input_json, output_json, compiler_data,
                                silent))
    return build_json
示例#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
示例#5
0
def compile_and_format(
    contract_sources: Dict[str, str],
    solc_version: Optional[str] = None,
    optimize: bool = True,
    runs: int = 200,
    evm_version: int = None,
    minify: bool = False,
    silent: bool = True,
    allow_paths: Optional[str] = None,
) -> Dict:
    """Compiles contracts and returns build data.

    Args:
        contracts: a dictionary in the form of {'path': "source code"}
        solc_version: solc version to compile with (use None to set via pragmas)
        optimize: enable solc optimizer
        runs: optimizer runs
        evm_version: evm version to compile for
        minify: minify source files
        silent: verbose reporting
        allow_paths: compiler allowed filesystem import path

    Returns:
        build data dict
    """
    if not contract_sources:
        return {}

    if [
            i for i in contract_sources
            if not i.endswith(".sol") and not i.endswith(".vy")
    ]:
        raise UnsupportedLanguage("Source filenames must end in .sol or .vy")

    build_json: Dict = {}
    compiler_targets = {}

    vyper_paths = [i for i in contract_sources if i.endswith(".vy")]
    if vyper_paths:
        compiler_targets["vyper"] = vyper_paths

    solc_sources = dict(
        (k, v) for k, v in contract_sources.items() if k.endswith(".sol"))
    if solc_sources:
        if solc_version is None:
            compiler_targets.update(
                find_solc_versions(solc_sources,
                                   install_needed=True,
                                   silent=silent))
        else:
            compiler_targets[solc_version] = list(solc_sources)

    compiler_data: Dict = {"minify_source": minify}
    for version, path_list in compiler_targets.items():
        if version == "vyper":
            language = "Vyper"
            compiler_data["version"] = str(vyper.get_version())
        else:
            set_solc_version(version)
            language = "Solidity"
            compiler_data["version"] = str(solidity.get_version())

        to_compile = dict(
            (k, v) for k, v in contract_sources.items() if k in path_list)

        input_json = generate_input_json(to_compile, optimize, runs,
                                         evm_version, minify, language)
        output_json = compile_from_input_json(input_json, silent, allow_paths)
        build_json.update(
            generate_build_json(input_json, output_json, compiler_data,
                                silent))
    return build_json