Esempio n. 1
0
def test_set_solc_version():
    compiler.set_solc_version("0.5.7")
    assert solcx.get_solc_version().truncate() == compiler.solidity.get_version()
    assert solcx.get_solc_version().truncate() == Version("0.5.7")
    compiler.set_solc_version("0.4.25")
    assert solcx.get_solc_version().truncate() == compiler.solidity.get_version()
    assert solcx.get_solc_version().truncate() == Version("0.4.25")
Esempio n. 2
0
def test_unlinked_libraries(version):
    source = _solc_5_source()
    build_json = sources.compile_source(source)
    assert '__TestLib__' in build_json['TempTester']['bytecode']
    compiler.set_solc_version("v0.4.25")
    source = _solc_4_source()
    build_json = sources.compile_source(source)
    assert '__TestLib__' in build_json['TempTester']['bytecode']
Esempio n. 3
0
def test_compiler_errors(version):
    with pytest.raises(CompilerError):
        sources.compile_paths(["contracts/Token.sol"])
    sources.compile_paths(["contracts/Token.sol", "contracts/SafeMath.sol"])
    source = _solc_4_source()
    with pytest.raises(CompilerError):
        sources.compile_source(source)
    compiler.set_solc_version("v0.4.25")
    sources.compile_source(source)
Esempio n. 4
0
def test_set_solc_version():
    compiler.set_solc_version("0.5.7")
    assert solcx.get_solc_version(
        with_commit_hash=True) == compiler.solidity.get_version()
    assert solcx.get_solc_version(
        with_commit_hash=True).truncate() == Version("0.5.7")
    compiler.set_solc_version("0.4.25")
    assert solcx.get_solc_version(
        with_commit_hash=True) == compiler.solidity.get_version()
    assert solcx.get_solc_version(
        with_commit_hash=True).truncate() == Version("0.4.25")
Esempio n. 5
0
    def load(self) -> None:
        """Compiles the project contracts, creates ContractContainer objects and
        populates the namespace."""
        if self._active:
            raise ProjectAlreadyLoaded("Project is already active")

        self._compiler_config = _load_project_compiler_config(self._path, "solc")
        solc_version = self._compiler_config["version"]
        if solc_version:
            self._compiler_config["version"] = compiler.set_solc_version(solc_version)

        # compile updated sources, update build
        changed = self._get_changed_contracts()
        self._compiler_config["version"] = solc_version
        self._compile(changed, self._compiler_config, False)
        self._create_containers()
        self._load_deployments()

        # add project to namespaces, apply import blackmagic
        name = self._name
        self.__all__ = list(self._containers)
        sys.modules[f"brownie.project.{name}"] = self  # type: ignore
        sys.modules["brownie.project"].__dict__[name] = self
        sys.modules["brownie.project"].__all__.append(name)  # type: ignore
        sys.modules["brownie.project"].__console_dir__.append(name)  # type: ignore
        self._namespaces = [
            sys.modules["__main__"].__dict__,
            sys.modules["brownie.project"].__dict__,
        ]
        self._active = True
        _loaded_projects.append(self)
Esempio n. 6
0
    def load(self):
        '''Compiles the project contracts, creates ContractContainer objects and
        populates the namespace.'''
        if self._active:
            raise ProjectAlreadyLoaded("Project is already active")

        self._compiler_config = load_project_compiler_config(
            self._project_path, "solc")
        solc_version = self._compiler_config['version']
        if solc_version:
            self._compiler_config['version'] = compiler.set_solc_version(
                solc_version)

        # compile updated sources, update build
        changed = self._get_changed_contracts()
        self._compiler_config['version'] = solc_version
        self._compile(changed, self._compiler_config, False)
        self._create_containers()

        # add project to namespaces, apply import blackmagic
        name = self._name
        self.__all__ = list(self._containers)
        sys.modules[f'brownie.project.{name}'] = self
        sys.modules['brownie.project'].__dict__[name] = self
        sys.modules['brownie.project'].__all__.append(name)
        sys.modules['brownie.project'].__console_dir__.append(name)
        self._namespaces = [
            sys.modules['__main__'].__dict__,
            sys.modules['brownie.project'].__dict__
        ]
        self._active = True
        _loaded_projects.append(self)
Esempio n. 7
0
def load(project_path=None):
    '''Loads a project and instantiates various related objects.

    Args:
        project_path: Path of the project to load. If None, will attempt to
                      locate a project using check_for_project()

    Returns a list of ContractContainer objects.
    '''
    # checks
    if CONFIG['folders']['project']:
        raise ProjectAlreadyLoaded(
            f"Project already loaded at {CONFIG['folders']['project']}")
    if project_path is None:
        project_path = check_for_project('.')
    if not project_path or not Path(project_path).joinpath(
            "brownie-config.json").exists():
        raise ProjectNotFound("Could not find Brownie project")

    # paths
    project_path = Path(project_path).resolve()
    _create_folders(project_path)
    _add_to_sys_path(project_path)

    # load config
    load_project_config(project_path)
    CONFIG['solc']['version'] = compiler.set_solc_version(
        CONFIG['solc']['version'])

    # load sources and build
    sources.load(project_path)
    build.load(project_path)

    # compare build, erase as needed
    changed_paths = _get_changed_contracts()

    # compile sources, update build
    build_json = sources.compile_paths(changed_paths,
                                       optimize=CONFIG['solc']['optimize'],
                                       runs=CONFIG['solc']['runs'],
                                       minify=CONFIG['solc']['minify_source'])
    for data in build_json.values():
        build.add(data)

    # create objects, add to namespace
    return _create_objects()
Esempio n. 8
0
def solc5json(solc5source):
    compiler.set_solc_version("0.5.7")
    input_json = compiler.generate_input_json({"path": solc5source}, True, 200)
    yield compiler.compile_from_input_json(input_json)
Esempio n. 9
0
def test_min_version():
    with pytest.raises(IncompatibleSolcVersion):
        compiler.set_solc_version("v0.4.21")
Esempio n. 10
0
def solc6json(solc6source):
    compiler.set_solc_version("0.6.2")
    input_json = compiler.generate_input_json({"path.sol": solc6source}, True,
                                              200)
    yield compiler.compile_from_input_json(input_json)
Esempio n. 11
0
def test_compile_input_json_evm_translates(solc5source, original, translated):
    compiler.set_solc_version("0.5.7")
    input_json = compiler.generate_input_json({"path.sol": solc5source}, True,
                                              200, original)
    compiler.compile_from_input_json(input_json)
Esempio n. 12
0
def test_build_json_unlinked_libraries():
    build_json = compiler.compile_and_format({'path': _solc_5_source()})
    assert '__TestLib__' in build_json['TempTester']['bytecode']
    compiler.set_solc_version("v0.4.25")
    build_json = compiler.compile_and_format({'path': _solc_4_source()})
    assert '__TestLib__' in build_json['TempTester']['bytecode']
Esempio n. 13
0
def _solc_4_output_json():
    compiler.set_solc_version("0.4.25")
    source = _solc_4_source()
    input_json = compiler.generate_input_json({'path': source}, True, 200)
    return compiler.compile_from_input_json(input_json)
Esempio n. 14
0
def version():
    yield
    compiler.set_solc_version("v0.5.7")
Esempio n. 15
0
def test_set_solc_version():
    compiler.set_solc_version("0.5.7")
    assert "0.5.7" in solcx.get_solc_version_string()
    compiler.set_solc_version("0.4.25")
    assert "0.4.25" in solcx.get_solc_version_string()
Esempio n. 16
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"):
            as_proxy_for = _resolve_address(
                data["result"][0]["Implementation"])

        # 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)

        try:
            version = Version(
                data["result"][0]["CompilerVersion"].lstrip("v")).truncate()
        except Exception:
            version = Version("0.0.0")
        if version < Version("0.4.22") or (
                # special case for OSX because installing 0.4.x versions is problematic
                sys.platform == "darwin" and version < Version("0.5.0")
                and f"v{version}" not in solcx.get_installed_solc_versions()):
            if not silent:
                warnings.warn(
                    f"{address}: target compiler '{data['result'][0]['CompilerVersion']}' is "
                    "unsupported by Brownie. Some 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

        if data["result"][0]["SourceCode"].startswith("{"):
            # source was verified using compiler standard JSON
            input_json = json.loads(data["result"][0]["SourceCode"][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:
            # source was submitted as a single flattened file
            sources = {
                f"{name}-flattened.sol": data["result"][0]["SourceCode"]
            }
            build_json = compiler.compile_and_format(sources,
                                                     solc_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
Esempio n. 17
0
def solc4json(solc4source):
    compiler.set_solc_version("0.4.25")
    input_json = compiler.generate_input_json({'path': solc4source}, True, 200)
    yield compiler.compile_from_input_json(input_json)