Skip to content

Commit

Permalink
update strategy to find the best version based on minor version
Browse files Browse the repository at this point in the history
  • Loading branch information
taquangtrung committed Apr 18, 2023
1 parent c791b2e commit 76212b7
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 41 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "solc_detect"
version = "0.0.6"
version = "0.0.7"
authors = [{name="Ta Quang Trung"},]
description = "A tool to detect Solidity compiler version required by smart contracts"
dynamic = ["dependencies"]
Expand Down
10 changes: 5 additions & 5 deletions solc_detect/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ def configure_cli_arguments():
help="",
)

# Print verbose
# Quiet mode, print only the best version.
arg_parser.add_argument(
"-v",
"--verbose",
"-q",
"--quiet",
action="store_true",
default=False,
help="",
Expand Down Expand Up @@ -74,11 +74,11 @@ def main():
arg_parser.exit()

pragma_version = solc_detect.find_pragma_solc_version(input_file)
if args.verbose:
if not args.quiet:
print("Detected pragmas:", pragma_version)

best_version = solc_detect.find_best_solc_version_for_pragma(pragma_version)
if args.verbose:
if not args.quiet:
print("Best version:", best_version)
else:
print(best_version)
Expand Down
80 changes: 45 additions & 35 deletions solc_detect/solc_detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,33 @@
Module define some utility variables and functions.
"""

from typing import List, Union
from typing import List, Optional

import nodesemver
import semantic_version

from solc_detect import pragma_parser

# from semantic_version import NpmSpec, Version
# Enumerate all Solidity versions based on information in:
# https://blog.soliditylang.org/category/release
solc_0_4 = ["0.4.%d" % i for i in range(27)] # 0.4.0 --> 0.4.26
solc_0_5 = ["0.5.%d" % i for i in range(18)] # 0.5.0 --> 0.5.17
solc_0_6 = ["0.6.%d" % i for i in range(13)] # 0.6.0 --> 0.6.12
solc_0_7 = ["0.7.%d" % i for i in range(7)] # 0.7.0 --> 0.7.6
solc_0_8 = ["0.8.%d" % i for i in range(20)] # 0.8.0 --> 0.8.19


def init_all_solidity_versions() -> List[str]:
"""Enumerate all Solidity versions.
All Solidity releases: https://blog.soliditylang.org/category/releases/"""

solidity_0_4 = ["0.4.%d" % i for i in range(27)] # 0.4.0 --> 0.4.26
solidity_0_5 = ["0.5.%d" % i for i in range(18)] # 0.5.0 --> 0.5.17
solidity_0_6 = ["0.6.%d" % i for i in range(13)] # 0.6.0 --> 0.6.12
solidity_0_7 = ["0.7.%d" % i for i in range(7)] # 0.7.0 --> 0.7.6
solidity_0_8 = ["0.8.%d" % i for i in range(20)] # 0.8.0 --> 0.8.19

all_versions = (
solidity_0_4 + solidity_0_5 + solidity_0_6 + solidity_0_7 + solidity_0_8
)

return all_versions
def enumerate_and_group_solc_version_by_minor_version() -> List[List[str]]:
"""Enumerate all Solc versions, group by MINOR version, in each group, sort
by PATCH version, according to semantic versioning: https://semver.org/."""
solc_versions = [
solc_0_4,
solc_0_5,
solc_0_6,
solc_0_7,
solc_0_8,
]
return solc_versions


def find_pragma_solc_version(input_file) -> List[str]:
Expand All @@ -38,23 +39,32 @@ def find_pragma_solc_version(input_file) -> List[str]:
return pragma_versions


def find_best_solc_version_for_pragma(pragma_versions) -> Union[str, None]:
"""Find the best version of Solc compiler for a pragma version."""
all_versions = init_all_solidity_versions()
def find_best_solc_version_for_pragma(pragma_versions) -> Optional[str]:
"""Find the best version of Solc compiler for a pragma version. This version
is the latest patch of the lowest minor version satisfying the required
pragmas."""

version_groups = enumerate_and_group_solc_version_by_minor_version()
constraint = " ".join(pragma_versions)
try:
# Use `semantic_version` to find the best version first
all_semvers = [semantic_version.Version(v) for v in all_versions]
version_spec = semantic_version.NpmSpec(constraint)
best_version = version_spec.select(all_semvers)
return str(best_version)
except ValueError:
# If errors occur, use `node_semver` to find the best version
best_version = nodesemver.max_satisfying(all_versions, constraint)
return str(best_version)


def find_best_solc_version(input_file) -> Union[str, None]:
"""Find the best version of Solc compiler for a smart contract."""
for group in version_groups:
try:
# First, use `semantic_version` module to find the best version
all_semvers = [semantic_version.Version(v) for v in group]
version_spec = semantic_version.NpmSpec(constraint)
if (best_version := version_spec.select(all_semvers)):
return str(best_version)
except ValueError:
# If errors occur, then use `node_semver` module to find it
if (best_version := nodesemver.max_satisfying(group, constraint)):
return str(best_version)

# Unable to find a suitable version
return None


def find_best_solc_version(input_file) -> Optional[str]:
"""Find the best version of Solc compiler for a smart contract. This version
is the latest patch of the lowest minor version satisfying the required
pragmas."""
pragma_versions = find_pragma_solc_version(input_file)
return find_best_solc_version_for_pragma(pragma_versions)

0 comments on commit 76212b7

Please sign in to comment.