Skip to content

Commit

Permalink
feat: extract version detection code into separate method and make te…
Browse files Browse the repository at this point in the history
…sts more explicit.
  • Loading branch information
mariuspod committed Jan 7, 2022
1 parent 01ec018 commit b4c271c
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 35 deletions.
38 changes: 28 additions & 10 deletions brownie/network/contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -1088,16 +1088,7 @@ def from_explorer(
is_compilable = False
else:
try:
version = Version(compiler_str.lstrip("v")).truncate()
compiler_config = _load_project_compiler_config(Path(os.getcwd()))
solc_config = compiler_config["solc"]
if "use_latest_patch" in solc_config:
use_latest_patch = solc_config["use_latest_patch"]
if use_latest_patch is True or address in use_latest_patch:
versions = [Version(str(i)) for i in solcx.get_installable_solc_versions()]
for v in filter(lambda l: l < version.next_minor(), versions):
if v > version:
version = v
version = cls.get_solc_version(compiler_str, address)

is_compilable = (
version >= Version("0.4.22")
Expand Down Expand Up @@ -1184,6 +1175,33 @@ def from_explorer(
_add_deployment(self)
return self

@classmethod
def get_solc_version(cls, compiler_str, address) -> Version:
"""
Return the solc compiler version either from the passed compiler string
or try to find the latest available patch semver compiler version.
Arguments
---------
compiler_str: str
The compiler string passed from the contract metadata.
address: str
The contract address to check for.
"""
version = Version(compiler_str.lstrip("v")).truncate()

compiler_config = _load_project_compiler_config(Path(os.getcwd()))
solc_config = compiler_config["solc"]
if "use_latest_patch" in solc_config:
use_latest_patch = solc_config["use_latest_patch"]
if use_latest_patch is True or address in use_latest_patch:
versions = [Version(str(i)) for i in solcx.get_installable_solc_versions()]
for v in filter(lambda l: l < version.next_minor(), versions):
if v > version:
version = v

return version

def set_alias(self, alias: Optional[str]) -> None:
"""
Apply a unique alias this object. The alias can be used to restore the
Expand Down
41 changes: 16 additions & 25 deletions tests/network/contract/test_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import pytest
import requests
import yaml
from semantic_version import Version

from brownie import Wei
from brownie.exceptions import BrownieCompilerWarning, BrownieEnvironmentWarning, ContractNotFound
Expand Down Expand Up @@ -315,11 +316,9 @@ def test_solc_use_latest_patch_true(testproject, network):
with testproject._path.joinpath("brownie-config.yaml").open("w") as fp:
yaml.dump(solc_config, fp)

# chainlink contract specifies version pragma ^0.4.16 which doesn't support overloaded
# events (>= 0.4.17)
c = Contract.from_explorer("0x514910771AF9Ca656af840dff83E8264EcF986CA")
transfer_events = list(filter(lambda l: "name" in l and l["name"] == "Transfer", c.abi))
assert len(transfer_events) == 2
assert Contract.get_solc_version(
"v0.4.16", "0x514910771AF9Ca656af840dff83E8264EcF986CA"
) == Version("0.4.26")


def test_solc_use_latest_patch_false(testproject, network):
Expand All @@ -328,11 +327,9 @@ def test_solc_use_latest_patch_false(testproject, network):
with testproject._path.joinpath("brownie-config.yaml").open("w") as fp:
yaml.dump(solc_config, fp)

# chainlink contract specifies version pragma ^0.4.16 which doesn't support overloaded
# events (>= 0.4.17)
c = Contract.from_explorer("0x514910771AF9Ca656af840dff83E8264EcF986CA")
transfer_events = list(filter(lambda l: "name" in l and l["name"] == "Transfer", c.abi))
assert len(transfer_events) == 1
assert Contract.get_solc_version(
"v0.4.16", "0x514910771AF9Ca656af840dff83E8264EcF986CA"
) == Version("0.4.16")


def test_solc_use_latest_patch_missing(testproject, network):
Expand All @@ -341,11 +338,9 @@ def test_solc_use_latest_patch_missing(testproject, network):
with testproject._path.joinpath("brownie-config.yaml").open("w") as fp:
yaml.dump(solc_config, fp)

# chainlink contract specifies version pragma ^0.4.16 which doesn't support overloaded
# events (>= 0.4.17)
c = Contract.from_explorer("0x514910771AF9Ca656af840dff83E8264EcF986CA")
transfer_events = list(filter(lambda l: "name" in l and l["name"] == "Transfer", c.abi))
assert len(transfer_events) == 1
assert Contract.get_solc_version(
"v0.4.16", "0x514910771AF9Ca656af840dff83E8264EcF986CA"
) == Version("0.4.16")


def test_solc_use_latest_patch_specific_not_included(testproject, network):
Expand All @@ -356,11 +351,9 @@ def test_solc_use_latest_patch_specific_not_included(testproject, network):
with testproject._path.joinpath("brownie-config.yaml").open("w") as fp:
yaml.dump(solc_config, fp)

# chainlink contract specifies version pragma ^0.4.16 which doesn't support overloaded
# events (>= 0.4.17)
c = Contract.from_explorer("0x514910771AF9Ca656af840dff83E8264EcF986CA")
transfer_events = list(filter(lambda l: "name" in l and l["name"] == "Transfer", c.abi))
assert len(transfer_events) == 1
assert Contract.get_solc_version(
"v0.4.16", "0x514910771AF9Ca656af840dff83E8264EcF986CA"
) == Version("0.4.16")


def test_solc_use_latest_patch_specific_included(testproject, network):
Expand All @@ -371,11 +364,9 @@ def test_solc_use_latest_patch_specific_included(testproject, network):
with testproject._path.joinpath("brownie-config.yaml").open("w") as fp:
yaml.dump(solc_config, fp)

# chainlink contract specifies version pragma ^0.4.16 which doesn't support overloaded
# events (>= 0.4.17)
c = Contract.from_explorer("0x514910771AF9Ca656af840dff83E8264EcF986CA")
transfer_events = list(filter(lambda l: "name" in l and l["name"] == "Transfer", c.abi))
assert len(transfer_events) == 2
assert Contract.get_solc_version(
"v0.4.16", "0x514910771AF9Ca656af840dff83E8264EcF986CA"
) == Version("0.4.26")


# @pytest.mark.parametrize(
Expand Down

0 comments on commit b4c271c

Please sign in to comment.