Skip to content

Commit

Permalink
Formating prints according to CERT-7899 (#61)
Browse files Browse the repository at this point in the history
* changes

* Update execution.json

* Update price_feed.py

* Update test_price_feed.py

* Update Quorum/check_proposal.py

Co-authored-by: yoav-el-certora <[email protected]>

* .

* Update price_feed.py

* .

* more formatting.

* more formatting (live with michael)

* Update create_report.py

* .

* Finish splitting refactor

* Fix test

---------

Co-authored-by: yoav-el-certora <[email protected]>
Co-authored-by: niv vaknin <[email protected]>
  • Loading branch information
3 people authored Jan 7, 2025
1 parent 7fc44dd commit 4ccd1f7
Show file tree
Hide file tree
Showing 21 changed files with 273 additions and 178 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ CustomerClones/
**cache**
**.DS_Store
!**cached_llm.py
quorum_project/
quorum_project/
dist/
2 changes: 1 addition & 1 deletion Quorum/apis/block_explorers/source_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def _parse_source_code(self) -> None:
self._parsed_contract = contract_ast[contract_name]['ast']

except Exception as e:
pp.pretty_print(f"Error parsing source code for {self.file_name}: {e}\n"
pp.pprint(f"Error parsing source code for {self.file_name}: {e}\n"
f"Some of the checks will not apply to this contract!!!",
pp.Colors.FAILURE)
finally:
Expand Down
6 changes: 3 additions & 3 deletions Quorum/apis/git_api/git_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ def _load_repos_from_file(self, gt_config: dict[str, any]) -> tuple[dict[str, st
def __clone_or_update_for_repo(repo_name: str, repo_url: str, to_path: Path):
repo_path = to_path / repo_name
if repo_path.exists():
pp.pretty_print(f"Repository {repo_name} already exists at {repo_path}. Updating repo and submodules.", pp.Colors.INFO)
pp.pprint(f"Repository {repo_name} already exists at {repo_path}. Updating repo and submodules.", pp.Colors.INFO)
repo = Repo(repo_path)
repo.git.pull()
repo.git.submodule('update', '--init', '--recursive')
else:
pp.pretty_print(f"Cloning {repo_name} from URL: {repo_url} to {repo_path}...", pp.Colors.INFO)
pp.pprint(f'Cloning {repo_name} from URL: {repo_url} to {repo_path}...', pp.Colors.INFO)
Repo.clone_from(repo_url, repo_path, multi_options=["--recurse-submodules"])


Expand All @@ -68,7 +68,7 @@ def clone_or_update(self) -> None:
If the repository already exists locally, it will update the repository and its submodules.
Otherwise, it will clone the repository and initialize submodules.
"""

pp.pprint('Cloning and updating preliminaries', pp.Colors.INFO, pp.Heading.HEADING_2)
for repo_name, repo_url in self.repos.items():
GitManager.__clone_or_update_for_repo(repo_name, repo_url, self.modules_path)

Expand Down
6 changes: 3 additions & 3 deletions Quorum/apis/governance/data_models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List, Optional
from typing import Optional
from pydantic import BaseModel, Field

from Quorum.utils.chain_enum import Chain
Expand Down Expand Up @@ -49,9 +49,9 @@ class BGDProposalData(BaseModel):
"""
ipfs: Optional[IPFSData] = None
proposal: Optional[ProposalData] = None
events: List[EventData] = Field(default_factory=list)
events: list[EventData] = Field(default_factory=list)


class PayloadAddresses(BaseModel):
chain: Chain
addresses: List[str]
addresses: list[str]
44 changes: 26 additions & 18 deletions Quorum/checks/diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,21 +123,29 @@ def __print_diffs_results(self, missing_files: list[SourceCode], files_with_diff
missing_files (list[SourceCode]): A list of SourceCode objects representing missing files.
files_with_diffs (list[Compared]): A list of Compared objects representing files with differences.
"""
total_number_of_files = len(self.source_codes)
number_of_missing_files = len(missing_files)
number_of_files_with_diffs = len(files_with_diffs)

msg = f"Compared {total_number_of_files - number_of_missing_files}/{total_number_of_files} files for proposal {self.proposal_address}"
if number_of_missing_files == 0:
pp.pretty_print(msg, pp.Colors.SUCCESS)
else:
pp.pretty_print(msg, pp.Colors.WARNING)
for source_code in missing_files:
pp.pretty_print(f"Missing file: {source_code.file_name} in local repo", pp.Colors.WARNING)

if number_of_files_with_diffs == 0:
pp.pretty_print("No differences found.", pp.Colors.SUCCESS)
else:
pp.pretty_print(f"Found differences in {number_of_files_with_diffs} files", pp.Colors.FAILURE)
for compared_pair in files_with_diffs:
pp.pretty_print(f"Local: {compared_pair.local_file}\nProposal: {compared_pair.proposal_file}\nDiff: {compared_pair.diff}", pp.Colors.FAILURE)
num_total_files = len(self.source_codes)
num_missing_files = len(missing_files)
num_diff_files = len(files_with_diffs)
num_identical = num_total_files - num_missing_files - num_diff_files

# Identical files message.
pp.pprint(f'Files found identical: {num_identical}/{num_total_files}\n', pp.Colors.SUCCESS)

# Diffs files message.
if num_diff_files > 0:
diffs_msg = ('Proposal files found to deviate from their source of truth counterpart: '
f'{num_diff_files}/{num_total_files}\n')
for i, compared_pair in enumerate(files_with_diffs, 1):
diffs_msg += (f'\t{i}. Proposal file: {compared_pair.proposal_file}\n'
f'\t Source of truth file: {compared_pair.local_file}\n'
f'\t Diff can be found here: {compared_pair.diff}\n')
pp.pprint(diffs_msg, pp.Colors.FAILURE)

# Missing files message.
if num_missing_files > 0:
missing_msg = ('Proposal files missing from source of truth: '
f'{num_missing_files}/{num_total_files}\n')
for i, source_code in enumerate(missing_files, 1):
missing_msg += f'\t{i}. File: {source_code.file_name}\n'
pp.pprint(missing_msg, pp.Colors.WARNING)

21 changes: 12 additions & 9 deletions Quorum/checks/global_variables.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import re
from pathlib import Path


from Quorum.checks.check import Check
from Quorum.apis.block_explorers.source_code import SourceCode
import Quorum.utils.pretty_printer as pp
Expand Down Expand Up @@ -75,11 +73,16 @@ def __process_results(self, source_code_to_violated_variables: dict[str, list[di
to lists of violated variables.
"""
if not source_code_to_violated_variables:
pp.pretty_print("All global variables are constant or immutable.", pp.Colors.SUCCESS)
else:
pp.pretty_print("Global variable checks failed:", pp.Colors.FAILURE)
for file_name, violated_variables in source_code_to_violated_variables.items():
pp.pretty_print(f"File {file_name} contains variables that are not constant or immutable"
,pp.Colors.FAILURE)
self._write_to_file(Path(file_name).stem.removesuffix(".sol"), violated_variables)
pp.pprint('All global variables are constant or immutable.', pp.Colors.SUCCESS)
return

msg = ("Some global variables aren't constant or immutable. A storage collision may occur!\n"
f'The following variables found to be storage variables: ')
i = 1
for file_name, violated_variables in source_code_to_violated_variables.items():
for var in violated_variables:
msg += f"\t{i}. File {file_name}: {var['name']}"
i += 1
self._write_to_file(Path(file_name).stem.removesuffix('.sol'), violated_variables)
pp.pprint(msg, pp.Colors.FAILURE)

49 changes: 27 additions & 22 deletions Quorum/checks/new_listing.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@


class NewListingCheck(Check):

def new_listing_check(self) -> None:
"""
Checks if the proposal address is a new listing on the blockchain.
Expand All @@ -14,35 +13,41 @@ def new_listing_check(self) -> None:
no new listings were found.
"""
functions = self._get_functions_from_source_codes()
if functions.get("newListings", functions.get("newListingsCustom")):
pp.pretty_print(f"New listings detected for {self.proposal_address}", pp.Colors.WARNING)
if functions.get('newListings', functions.get('newListingsCustom')):
pp.pprint(f'New listings detected for payload {self.proposal_address}', pp.Colors.WARNING)

# Check if Anthropic API key is configured
if not config.ANTHROPIC_API_KEY:
pp.pretty_print(
"First deposit check is skipped. If you have a LLM API key, you can add it to your environment variables to enable this check",
proposal_code = self.source_codes[0].file_content
proposal_code_str = '\n'.join(proposal_code)
try:
listings: ListingArray | None = FirstDepositChain().execute(proposal_code_str)
except:
pp.pprint(
'New listings were detected in payload but first deposit check is skipped.\n'
'If you have a LLM API key, you can add it to your environment variables to enable this check',
pp.Colors.WARNING
)
return

proposal_code = self.source_codes[0].file_content
proposal_code_str = '\n'.join(proposal_code)
listings: ListingArray | None = FirstDepositChain().execute(proposal_code_str)
if listings is None:
pp.pretty_print(f"Failed to retrieve new listings for {self.proposal_address}", pp.Colors.FAILURE)
pp.pprint('New listings were detected in payload but LLM failed to retrieve them.',
pp.Colors.FAILURE)
return
for listing in listings.listings:
if listing.approve_indicator and listing.supply_indicator:
pp.pretty_print(
f"New listing detected for {listing}", pp.Colors.SUCCESS
)
else:
pp.pretty_print(f"New listing detected for {listing.asset_symbol} but no approval or supply detected", pp.Colors.FAILURE)
self._write_to_file("new_listings.json", listings.model_dump())


pp.pprint(f'{len(listings.listings)} new asset listings were detected:', pp.Colors.INFO)
for i, listing in enumerate(listings.listings, 1):
pp.pprint(f'\t{i}. Variable: {listing.asset_symbol}\n'
f'\t Asset address: {listing.asset_address}\n'
f'\t Approve indicator: {listing.approve_indicator}\n'
f'\t Supply seed amount: {listing.supply_seed_amount}\n'
f'\t Supply indicator: {listing.supply_indicator}',
(pp.Colors.SUCCESS if listing.approve_indicator and listing.supply_indicator
else pp.Colors.FAILURE))

self._write_to_file('new_listings.json', listings.model_dump())

else:
pp.pretty_print(f"No new listings detected for {self.proposal_address}", pp.Colors.INFO)
pp.pprint(f'No new listings detected for {self.proposal_address}', pp.Colors.INFO)

def _get_functions_from_source_codes(self) -> dict:
"""
Retrieves functions from the source codes.
Expand Down
Loading

0 comments on commit 4ccd1f7

Please sign in to comment.