Ejemplo n.º 1
0
def _get_solc_version_list() -> Tuple[List, List]:
    global AVAILABLE_SOLC_VERSIONS
    installed_versions = [Version(i[1:]) for i in solcx.get_installed_solc_versions()]
    if AVAILABLE_SOLC_VERSIONS is None:
        try:
            AVAILABLE_SOLC_VERSIONS = [Version(i[1:]) for i in solcx.get_available_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
Ejemplo n.º 2
0
def pytest_configure(config):
    global VERSIONS
    if config.getoption("--no-install"):
        VERSIONS = solcx.get_installed_solc_versions()
        return
    try:
        VERSIONS = solcx.get_available_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."
        )
Ejemplo n.º 3
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_available_solc_versions()[0]
            solc_versions.remove("latest")
            solc_versions.append(latest_version)
        config.option.evm = (evm_verions, runs, solc_versions)
Ejemplo n.º 4
0
def get_supported_solc_versions():
    global _SOLC_VERSIONS
    global _SOLC_VERSIONS_LAST_UPDATE

    # Cache the result for one hour
    if len(_SOLC_VERSIONS) != 0 and _SOLC_VERSIONS_LAST_UPDATE >= time.time() - 3600:
        return _SOLC_VERSIONS

    try:
        new_versions = get_available_solc_versions()
        _SOLC_VERSIONS = sorted((SolidityVersion(v[1:]) for v in new_versions))
        _SOLC_VERSIONS_LAST_UPDATE = time.time()

    except requests.exceptions.RequestException:
        # If offline, work with installed versions
        logging.info('Fetching the latest compiler releases failed, relying on known versions.')

    return _SOLC_VERSIONS
Ejemplo n.º 5
0
import os.path
import asyncio
from time import time
from typing import Optional, Sequence
import solcx
from web3.contract import ContractConstructor, ContractFunctions
from eth_abi import decode_abi
from web3._utils.abi import get_abi_output_types
from web3._utils.contracts import prepare_transaction
from web3._utils.datatypes import PropertyCheckingFactory
from eth_utils import to_checksum_address, hexstr_if_str, to_bytes
from asynther.common import SubModule
from asynther.account import Account, NeedPrivateKey

solcx_version = solcx.get_available_solc_versions()[0]
if solcx_version not in solcx.get_installed_solc_versions():
    solcx.install_solc(solcx_version)


class Interface(dict):
    """ Contract interface
    """

    def __init__(self, source_file: str, allow_paths: Optional[Sequence[str]] = None):
        assert isinstance(source_file, str) and os.path.exists(source_file)
        assert allow_paths is None or \
               (isinstance(allow_paths, (tuple, list)) and all(os.path.exists(path) for path in allow_paths))
        allow_paths = ','.join(allow_paths) if allow_paths is not None else allow_paths
        for name, interface in solcx.compile_files([source_file], allow_paths=allow_paths).items():
            if name.startswith(source_file + ':'):
                super().__init__(interface)
Ejemplo n.º 6
0
def find_solc_versions(contracts,
                       install_needed=False,
                       install_latest=False,
                       silent=True):
    '''Analyzes contract pragmas and determines which solc version(s) to use.

    Args:
        contracts: a dictionary in the form of {'path': "source code"}
        install_needed: if True, will install when no installed version matches
                        the contract pragma
        install_latest: if True, will install when a newer version is available
                        than the installed one
        silent: enables verbose reporting

    Returns: dictionary of {'version': ['path', 'path', ..]}
    '''
    installed_versions = [
        Version(i[1:]) for i in solcx.get_installed_solc_versions()
    ]
    try:
        available_versions = [
            Version(i[1:]) for i in solcx.get_available_solc_versions()
        ]
    except ConnectionError:
        if not installed_versions:
            raise ConnectionError(
                "Solc not installed and cannot connect to GitHub")
        available_versions = installed_versions

    pragma_regex = re.compile(r"pragma +solidity([^;]*);")
    version_regex = re.compile(r"(([<>]?=?|\^)\d+\.\d+\.\d+)+")

    pragma_specs = dict((i, set()) for i in contracts)
    to_install = set()
    for path, source in contracts.items():
        try:
            pragma_string = next(pragma_regex.finditer(source))[0]
        except StopIteration:
            raise PragmaError(f"No version pragma in '{path}'") from None

        # convert pragma to Version objects
        comparator_set_range = pragma_string.replace(" ", "").split('||')
        for comparator_set in comparator_set_range:
            spec = Spec(*(i[0] for i in version_regex.findall(comparator_set)))
            spec = _standardize_spec(spec)
            pragma_specs[path].add(spec)

        # if no installed version of solc matches the pragma, find the latest available version
        if not next(
            (i for i in pragma_specs[path] if i.select(installed_versions)),
                None):
            try:
                version = _select_max(pragma_specs[path], available_versions)
                to_install.add(version)
            except ValueError:
                raise PragmaError(
                    f"No installable solc version matching '{pragma_string}' in '{path}'"
                ) from None
            if not install_needed:
                raise IncompatibleSolcVersion(
                    f"No installed solc version matching '{pragma_string}' in '{path}'"
                )

    # install new versions if needed
    if to_install:
        install_solc(*to_install)
        installed_versions = [
            Version(i[1:]) for i in solcx.get_installed_solc_versions()
        ]

    # organize source paths by latest available solc version
    compiler_versions = {}
    new_versions = set()
    for path, spec_list in pragma_specs.items():
        version = _select_max(spec_list, installed_versions)
        compiler_versions.setdefault(str(version), []).append(path)
        latest = _select_max(spec_list, available_versions)
        if latest > version:
            new_versions.add(str(latest))
    if new_versions:
        if install_latest:
            install_solc(*new_versions)
            return find_solc_versions(contracts)
        if not silent:
            print(
                f"New compatible solc version{'s' if len(new_versions) > 1 else ''}"
                f" available: {', '.join(new_versions)}")
    return compiler_versions
Ejemplo n.º 7
0
def find_solc_versions(
    contracts: Dict[str, str],
    install_needed: bool = False,
    install_latest: bool = False,
    silent: bool = True,
) -> Dict:
    """Analyzes contract pragmas and determines which solc version(s) to use.

    Args:
        contracts: a dictionary in the form of {'path': "source code"}
        install_needed: if True, will install when no installed version matches
                        the contract pragma
        install_latest: if True, will install when a newer version is available
                        than the installed one
        silent: set to False to enable verbose reporting

    Returns: dictionary of {'version': ['path', 'path', ..]}
    """
    installed_versions = [
        Version(i[1:]) for i in solcx.get_installed_solc_versions()
    ]
    try:
        available_versions = [
            Version(i[1:]) for i in solcx.get_available_solc_versions()
        ]
    except ConnectionError:
        if not installed_versions:
            raise ConnectionError(
                "Solc not installed and cannot connect to GitHub")
        available_versions = installed_versions

    pragma_regex = re.compile(r"pragma +solidity([^;]*);")
    pragma_specs: Dict = {}
    to_install = set()
    new_versions = set()

    for path, source in contracts.items():

        pragma_string = next(pragma_regex.finditer(source), None)
        if pragma_string is None:
            raise PragmaError(f"No version pragma in '{path}'")
        pragma_specs[path] = NpmSpec(pragma_string.groups()[0])
        version = pragma_specs[path].select(installed_versions)

        if not version and not (install_needed or install_latest):
            raise IncompatibleSolcVersion(
                f"No installed solc version matching '{pragma_string[0]}' in '{path}'"
            )

        # if no installed version of solc matches the pragma, find the latest available version
        latest = pragma_specs[path].select(available_versions)

        if not version and not latest:
            raise PragmaError(
                f"No installable solc version matching '{pragma_string[0]}' in '{path}'"
            )

        if not version or (install_latest and latest > version):
            to_install.add(latest)
        elif latest > version:
            new_versions.add(str(version))

    # install new versions if needed
    if to_install:
        install_solc(*to_install)
        installed_versions = [
            Version(i[1:]) for i in solcx.get_installed_solc_versions()
        ]
    elif new_versions and not silent:
        print(
            f"New compatible solc version{'s' if len(new_versions) > 1 else ''}"
            f" available: {', '.join(new_versions)}")

    # organize source paths by latest available solc version
    compiler_versions: Dict = {}
    for path, spec in pragma_specs.items():
        version = spec.select(installed_versions)
        compiler_versions.setdefault(str(version), []).append(path)

    return compiler_versions