Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

handle solidity files with no contracts #333

Merged
merged 1 commit into from
Jul 29, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 30 additions & 19 deletions src/halmos/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1300,6 +1300,19 @@ def mk_arrlen(args: HalmosConfig) -> Dict[str, int]:
return arrlen


def get_contract_type(
ast_nodes: Dict, contract_name: str
) -> Tuple[str | None, str | None]:
for node in ast_nodes:
if node["nodeType"] == "ContractDefinition" and node["name"] == contract_name:
abstract = "abstract " if node.get("abstract") else ""
contract_type = abstract + node["contractKind"]
natspec = node.get("documentation")
return contract_type, natspec

return None, None


def parse_build_out(args: HalmosConfig) -> Dict:
result = {} # compiler version -> source filename -> contract name -> (json, type)

Expand Down Expand Up @@ -1328,35 +1341,33 @@ def parse_build_out(args: HalmosConfig) -> Dict:
with open(json_path, encoding="utf8") as f:
json_out = json.load(f)

compiler_version = json_out["metadata"]["compiler"]["version"]
if compiler_version not in result:
result[compiler_version] = {}
if sol_dirname not in result[compiler_version]:
result[compiler_version][sol_dirname] = {}
contract_map = result[compiler_version][sol_dirname]

# cut off compiler version number as well
contract_name = json_filename.split(".")[0]

contract_type = None
for node in json_out["ast"]["nodes"]:
if (
node["nodeType"] == "ContractDefinition"
and node["name"] == contract_name
):
abstract = "abstract " if node.get("abstract") else ""
contract_type = abstract + node["contractKind"]
natspec = node.get("documentation")
break
ast_nodes = json_out["ast"]["nodes"]
contract_type, natspec = get_contract_type(ast_nodes, contract_name)

# can happen to solidity files for multiple reasons:
# - import only (like console2.log)
# - defines only structs or enums
# - defines only free functions
# - ...
if contract_type is None:
raise ValueError("no contract type", contract_name)
if args.debug:
debug(f"Skipped {json_filename}, no contract definition found")
continue

compiler_version = json_out["metadata"]["compiler"]["version"]
result.setdefault(compiler_version, {})
result[compiler_version].setdefault(sol_dirname, {})
contract_map = result[compiler_version][sol_dirname]

if contract_name in contract_map:
raise ValueError(
"duplicate contract names in the same file",
contract_name,
sol_dirname,
)

contract_map[contract_name] = (json_out, contract_type, natspec)

try:
Expand Down