Exemplo n.º 1
0
def _get_solc_version_list() -> Tuple[List, List]:
    global AVAILABLE_SOLC_VERSIONS
    installed_versions = solcx.get_installed_solc_versions()
    if AVAILABLE_SOLC_VERSIONS is None:
        try:
            AVAILABLE_SOLC_VERSIONS = solcx.get_installable_solc_versions()
        except ConnectionError:
            if not installed_versions:
                raise ConnectionError("Solc not installed and cannot connect to GitHub")
            AVAILABLE_SOLC_VERSIONS = installed_versions
    return AVAILABLE_SOLC_VERSIONS, installed_versions
Exemplo n.º 2
0
def pytest_configure(config):
    if config.getoption("--target") == "plugin" and config.getoption("numprocesses"):
        raise pytest.UsageError("Cannot use xdist with plugin tests, try adding the '-n 0' flag")

    if config.getoption("--evm"):
        # reformat evm options - only do this once to avoid repeat queries for latest solc version
        solc_versions, evm_verions, runs = [i.split(",") for i in config.option.evm]
        runs = [int(i) for i in runs]
        if "latest" in solc_versions:
            latest_version = solcx.get_installable_solc_versions()[0]
            solc_versions.remove("latest")
            solc_versions.append(latest_version)
        config.option.evm = (evm_verions, runs, solc_versions)
Exemplo n.º 3
0
def pytest_collection(session):
    global VERSIONS
    if session.config.getoption("--solc-versions"):
        VERSIONS = [
            Version(i)
            for i in session.config.getoption("--solc-versions").split(",")
        ]
    elif session.config.getoption("--no-install"):
        VERSIONS = solcx.get_installed_solc_versions()
    else:
        try:
            VERSIONS = solcx.get_installable_solc_versions()
        except ConnectionError:
            raise pytest.UsageError(
                "ConnectionError while attempting to get solc versions.\n"
                "Use the --no-install flag to only run tests against already installed versions."
            )
        for version in VERSIONS:
            solcx.install_solc(version)
def download_all(max_workers):
    """Download all versions of solc and vyper."""
    with spinner():
        solc_versions = get_installable_solc_versions()
        vyper_versions = get_installable_vyper_versions()

    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        futures = [
            executor.submit(install_solc, version) for version in solc_versions
        ]

        futures.extend([
            executor.submit(install_vyper, version)
            for version in vyper_versions
        ])

        for _f in as_completed(futures):
            # TODO: check for errors
            pass

    print("All solc and vyper versions installed")
Exemplo n.º 5
0
import solcx

versions = solcx.get_installable_solc_versions()

print(versions)

# solcx.install_solc("0.8.9")

installed = solcx.get_solc_version()

print(installed)
Exemplo n.º 6
0
 def available_versions(self) -> List[Version]:
     # NOTE: Package version should already be included in available versions
     return solcx.get_installable_solc_versions()
Exemplo n.º 7
0
def test_install_latest():
    version = solcx.get_installable_solc_versions()[0]
    assert solcx.install_solc("latest") == version
Exemplo n.º 8
0
    def from_explorer(
        cls,
        address: str,
        as_proxy_for: Optional[str] = None,
        owner: Optional[AccountsType] = None,
        silent: bool = False,
    ) -> "Contract":
        """
        Create a new `Contract` object with source code queried from a block explorer.

        Arguments
        ---------
        address : str
            Address where the contract is deployed.
        as_proxy_for : str, optional
            Address of the implementation contract, if `address` is a proxy contract.
            The generated object will send transactions to `address`, but use the ABI
            and NatSpec of `as_proxy_for`. This field is only required when the
            block explorer API does not provide an implementation address.
        owner : Account, optional
            Contract owner. If set, transactions without a `from` field will be
            performed using this account.
        """
        address = _resolve_address(address)
        data = _fetch_from_explorer(address, "getsourcecode", silent)
        is_verified = bool(data["result"][0].get("SourceCode"))

        if is_verified:
            abi = json.loads(data["result"][0]["ABI"])
            name = data["result"][0]["ContractName"]
        else:
            # if the source is not available, try to fetch only the ABI
            try:
                data_abi = _fetch_from_explorer(address, "getabi", True)
            except ValueError as exc:
                _unverified_addresses.add(address)
                raise exc
            abi = json.loads(data_abi["result"].strip())
            name = "UnknownContractName"
            warnings.warn(
                f"{address}: Was able to fetch the ABI but not the source code. "
                "Some functionality will not be available.",
                BrownieCompilerWarning,
            )

        if as_proxy_for is None and data["result"][0].get("Implementation"):
            try:
                # many proxy patterns use an `implementation()` function, so first we
                # try to determine the implementation address without trusting etherscan
                contract = cls.from_abi(name, address, abi)
                as_proxy_for = contract.implementation()
            except Exception:
                as_proxy_for = _resolve_address(data["result"][0]["Implementation"])

        if as_proxy_for == address:
            as_proxy_for = None

        # if this is a proxy, fetch information for the implementation contract
        if as_proxy_for is not None:
            implementation_contract = Contract.from_explorer(as_proxy_for)
            abi = implementation_contract._build["abi"]

        if not is_verified:
            return cls.from_abi(name, address, abi, owner)

        compiler_str = data["result"][0]["CompilerVersion"]
        if compiler_str.startswith("vyper:"):
            try:
                version = to_vyper_version(compiler_str[6:])
                is_compilable = version in get_installable_vyper_versions()
            except Exception:
                is_compilable = False
        else:
            try:
                version = Version(compiler_str.lstrip("v")).truncate()
                is_compilable = (
                    version >= Version("0.4.22")
                    and version
                    in solcx.get_installable_solc_versions() + solcx.get_installed_solc_versions()
                )
            except Exception:
                is_compilable = False

        if not is_compilable:
            if not silent:
                warnings.warn(
                    f"{address}: target compiler '{compiler_str}' cannot be installed or is not "
                    "supported by Brownie. Some debugging functionality will not be available.",
                    BrownieCompilerWarning,
                )
            return cls.from_abi(name, address, abi, owner)

        optimizer = {
            "enabled": bool(int(data["result"][0]["OptimizationUsed"])),
            "runs": int(data["result"][0]["Runs"]),
        }
        evm_version = data["result"][0].get("EVMVersion", "Default")
        if evm_version == "Default":
            evm_version = None

        source_str = "\n".join(data["result"][0]["SourceCode"].splitlines())
        if source_str.startswith("{{"):
            # source was verified using compiler standard JSON
            input_json = json.loads(source_str[1:-1])
            sources = {k: v["content"] for k, v in input_json["sources"].items()}
            evm_version = input_json["settings"].get("evmVersion", evm_version)

            compiler.set_solc_version(str(version))
            input_json.update(
                compiler.generate_input_json(sources, optimizer=optimizer, evm_version=evm_version)
            )
            output_json = compiler.compile_from_input_json(input_json)
            build_json = compiler.generate_build_json(input_json, output_json)
        else:
            if source_str.startswith("{"):
                # source was submitted as multiple files
                sources = {k: v["content"] for k, v in json.loads(source_str).items()}
            else:
                # source was submitted as a single file
                if compiler_str.startswith("vyper"):
                    path_str = f"{name}.vy"
                else:
                    path_str = f"{name}-flattened.sol"
                sources = {path_str: source_str}

            build_json = compiler.compile_and_format(
                sources,
                solc_version=str(version),
                vyper_version=str(version),
                optimizer=optimizer,
                evm_version=evm_version,
            )

        build_json = build_json[name]
        if as_proxy_for is not None:
            build_json.update(abi=abi, natspec=implementation_contract._build.get("natspec"))

        if not _verify_deployed_code(
            address, build_json["deployedBytecode"], build_json["language"]
        ):
            warnings.warn(
                f"{address}: Locally compiled and on-chain bytecode do not match!",
                BrownieCompilerWarning,
            )
            del build_json["pcMap"]

        self = cls.__new__(cls)
        _ContractBase.__init__(self, None, build_json, sources)  # type: ignore
        _DeployedContractBase.__init__(self, address, owner)
        _add_deployment(self)
        return self