Skip to content

cbeatty8/genlayer-linter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

genlayer-linter

Static analysis linter for GenLayer Intelligent Contracts.

Catch bugs before deploy. Like ESLint, but for GenLayer contracts.

Installation

pip install genlayer-linter

Quick Start

# Lint a single file
genlayer-lint contract.py

# Lint a directory
genlayer-lint ./contracts/

# Include INFO-level findings
genlayer-lint ./contracts/ --verbose

# JSON output
genlayer-lint contract.py --json

# List all rules
genlayer-lint --list-rules

Rules

ID Rule Severity Description
GL001 public-init ❌ Error __init__ must be private (@gl.private)
GL002 assert-in-prod ⚠️ Warning Don't use assert — use if/raise
GL003 missing-payable ❌ Error Methods accessing msg.value need @gl.payable
GL004 eval-exec ❌ Error eval()/exec() is a security risk
GL005 web-no-error-handling ⚠️ Warning gl.get_from_web() needs try/except
GL006 missing-return-type ℹ️ Info Public methods need return type hints
GL007 hardcoded-url ℹ️ Info Hardcoded URLs should be configurable
GL008 missing-docstring ℹ️ Info Public classes/methods need docstrings

Example Output

📄 contracts/weather_bet.py
──────────────────────────────────────────────────
❌ [GL001] contracts/weather_bet.py:5:4: Public __init__ in class `WeatherBet` — must be private
    💡 Add @gl.private decorator to __init__
⚠️ [GL002] contracts/weather_bet.py:12:8: assert in production code — disabled with python -O
    💡 Replace with: if not condition: raise ValueError('message')
ℹ️ [GL006] contracts/weather_bet.py:18:4: Public method `resolve` missing return type hint
    💡 Add return type annotation (e.g., -> dict, -> None)

==================================================
📊 Summary
  ❌ Errors:   1
  ⚠️  Warnings: 1
  ℹ️  Info:     1

❌ Found 1 error(s) — fix before deploying!

API Usage

from genlayer_linter import analyze_file, analyze_directory

# Lint a single file
findings = analyze_file("contract.py")
for f in findings:
    print(f"{f.severity.value}: {f.message} (line {f.line})")

# Lint a directory
results = analyze_directory("./contracts/")
for filepath, findings in results.items():
    print(f"{filepath}: {len(findings)} issues")

Why?

GenLayer contracts have unique patterns that generic linters don't catch:

  • __init__ must be private (prefixed with _ or decorated)
  • Methods accepting msg.value must be marked @gl.payable
  • assert is dangerous — can be disabled with python -O
  • Network calls (gl.get_from_web()) need error handling
  • Equivalence principle requires deterministic code paths

This linter catches these issues before you deploy to testnet.

Tested On

  • Python 3.12+
  • GenLayer Bradbury Testnet contracts

License

MIT

About

Static analysis linter for GenLayer Intelligent Contracts

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages