Skip to content
Open
Show file tree
Hide file tree
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
Binary file added .DS_Store
Binary file not shown.
48 changes: 42 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,47 @@
/venv
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg

# Virtual Environment
venv/
.venv/
ENV/
env/

# IDE
.idea/
.vscode/
*.swp
*.swo
.cursor/

# Environment variables
.env
src/__pycache__
/crytic-export

# Project specific
/crytic-export
/contracts.json
/permissions.json
/results
# markdown generation outputs
results/
*.md
*.json
logs/
temp/
.DS_Store
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.11
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ Create and activate a virtual Python environment, and install the required Pytho
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
pip install -e . # to install the this repo as a package name permission_scanner
```

Or use uv

```shell
uv venv
uv pip install -r requirements.txt
```

Copy the `.env.example` file to `.env` and, depending on the network where the contracts are deployed on, fill in your RPC provider's url and a valid block explorer api key. Then load the variables with
Expand All @@ -49,7 +57,13 @@ source .env
Then execute the scanner script with 🚀

```shell
python src/main.py
python example/run_scanner.py
```

Or use uv

```shell
uv run example/run_scanner.py
```

### Results
Expand Down
90 changes: 90 additions & 0 deletions example/run_scanner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import os
import json
import logging
from dotenv import load_dotenv
from permission_scanner import ContractScanner
from permission_scanner.utils.markdown_generator import generate_full_markdown


def load_config_from_file(file_path: str) -> dict:
"""Load configuration from a JSON file.

Args:
file_path (str): Path to the configuration file

Returns:
dict: Configuration data

Raises:
FileNotFoundError: If the config file doesn't exist
json.JSONDecodeError: If the config file is not valid JSON
"""
try:
with open(file_path, "r") as file:
return json.load(file)
except FileNotFoundError:
raise
except json.JSONDecodeError as e:
raise


def main():
"""Main function to run the contract scanner."""
try:
# Load environment variables
load_dotenv()

# Load contracts from json
config_json = load_config_from_file("temp/contracts_kodiak_error.json")
contracts_addresses = config_json["Contracts"]
project_name = config_json["Project_Name"]
chain_name = config_json["Chain_Name"]

# Setup environment variables
block_explorer_api_key = os.getenv("BERASCAN_API_KEY")
rpc_url = os.getenv("RPC_URL")

if not block_explorer_api_key or not rpc_url:
raise ValueError("Missing required environment variables")

export_dir = f"temp/kodiak_error"

# Scan each contract
all_scan_results = {}
all_contract_data_for_markdown = []

for address in contracts_addresses:
# initiate scanner for each address
scanner = ContractScanner(
project_name=project_name,
address=address,
chain_name=chain_name,
block_explorer_api_key=block_explorer_api_key,
rpc_url=rpc_url,
export_dir=export_dir,
)
final_result, contract_data_for_markdown = scanner.scan()
all_scan_results.update(final_result)
all_contract_data_for_markdown += contract_data_for_markdown

report_dir = f"{export_dir}/{project_name}-reports"
os.makedirs(report_dir, exist_ok=True)
permissions_json_path = os.path.join(report_dir, "permissions.json")
markdown_path = os.path.join(report_dir, "markdown.md")

# save permissions.json
with open(permissions_json_path, "w") as f:
json.dump(all_scan_results, f, indent=4)

# save markdown.md
markdown_content = generate_full_markdown(
project_name, all_contract_data_for_markdown, all_scan_results
)
with open(markdown_path, "w") as f:
f.write(markdown_content)
except Exception as e:
raise


if __name__ == "__main__":
main()
14 changes: 14 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[project]
name = "permission_scanner"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/permission_scanner"]
47 changes: 0 additions & 47 deletions src/etherscan.py

This file was deleted.

76 changes: 0 additions & 76 deletions src/get_rpc_url.py

This file was deleted.

Loading