Parsa2025AI commited on
Commit
f8708fc
Β·
verified Β·
1 Parent(s): bdee7cf

gradio app

Browse files
Files changed (1) hide show
  1. app.py +145 -107
app.py CHANGED
@@ -1,108 +1,146 @@
1
- """
2
- Hugging Face Spaces entry point.
3
- Deploy this file as app.py in your HF Space (SDK: gradio).
4
- """
5
- import os
6
- import json
7
- import gradio as gr
8
- from app.models.analyzer import analyze_contract
9
-
10
- # ------------------------------------------------------------------ helpers --
11
-
12
- def _fmt_vulns(vulns: list) -> str:
13
- if not vulns:
14
- return "βœ… No vulnerabilities detected."
15
- icons = {"HIGH": "🚨", "MEDIUM": "⚠️", "LOW": "ℹ️"}
16
- lines = []
17
- for v in vulns:
18
- icon = icons.get(v["severity"], "β€’")
19
- name = v["name"].replace("_", " ").title()
20
- lines.append(f"{icon} **{name}** [{v['severity']}]")
21
- lines.append(f" {v['description']}")
22
- if v.get("line_numbers"):
23
- lines.append(f" Lines: {', '.join(map(str, v['line_numbers'][:8]))}")
24
- if v.get("recommendation"):
25
- lines.append(f" πŸ’‘ {v['recommendation']}")
26
- lines.append("")
27
- return "\n".join(lines)
28
-
29
-
30
- def audit(solidity_code: str):
31
- if not solidity_code.strip():
32
- return "⚠️ Please paste some Solidity code.", "{}", ""
33
-
34
- result = analyze_contract(solidity_code)
35
-
36
- # Summary block
37
- risk_icons = {"CRITICAL": "🚨", "MEDIUM": "⚠️", "LOW": "ℹ️", "SAFE": "βœ…"}
38
- icon = risk_icons.get(result["risk_level"], "β€’")
39
- summary = (
40
- f"## {icon} Risk Level: {result['risk_level']}\n\n"
41
- f"- **Solidity Version:** {result['solidity_version']}\n"
42
- f"- **Lines:** {result['total_lines']}\n"
43
- f"- **Severity Score:** {result['severity_score']}\n"
44
- f"- **Analysis type:** {result['analysis_type']}\n\n"
45
- f"| HIGH | MEDIUM | LOW |\n|------|--------|-----|\n"
46
- f"| {result['high_count']} | {result['medium_count']} | {result['low_count']} |"
47
- )
48
-
49
- vuln_text = _fmt_vulns(result["vulnerabilities"])
50
- llm_text = result.get("llm_analysis") or "_LLM model not loaded – showing pattern analysis only._"
51
-
52
- return summary, vuln_text, llm_text
53
-
54
-
55
- # ------------------------------------------------------------------- UI ------
56
-
57
- EXAMPLES = [
58
- [
59
- """pragma solidity ^0.4.24;
60
- contract VulnerableBank {
61
- mapping(address => uint256) public balances;
62
- function withdraw(uint256 _amount) public {
63
- require(balances[msg.sender] >= _amount);
64
- msg.sender.call.value(_amount)();
65
- balances[msg.sender] -= _amount;
66
- }
67
- }"""
68
- ],
69
- [
70
- """// SPDX-License-Identifier: MIT
71
- pragma solidity ^0.8.0;
72
- import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
73
- import "@openzeppelin/contracts/access/Ownable.sol";
74
- contract SafeVault is ReentrancyGuard, Ownable {
75
- mapping(address => uint256) private balances;
76
- function withdraw(uint256 amount) external nonReentrant {
77
- require(balances[msg.sender] >= amount);
78
- balances[msg.sender] -= amount;
79
- (bool ok,) = payable(msg.sender).call{value: amount}("");
80
- require(ok);
81
- }
82
- }"""
83
- ],
84
- ]
85
-
86
- with gr.Blocks(title="πŸ›‘οΈ Smart Contract Auditor", theme=gr.themes.Soft()) as demo:
87
- gr.Markdown("# πŸ›‘οΈ Smart Contract Security Auditor\nPaste Solidity code to detect security vulnerabilities using LLM + pattern analysis.")
88
-
89
- with gr.Row():
90
- with gr.Column():
91
- code_input = gr.Code(label="Solidity Contract", language="javascript", lines=20)
92
- analyze_btn = gr.Button("πŸ” Analyze", variant="primary")
93
-
94
- with gr.Column():
95
- summary_out = gr.Markdown(label="Summary")
96
- vuln_out = gr.Markdown(label="Vulnerabilities")
97
- llm_out = gr.Markdown(label="LLM Analysis")
98
-
99
- gr.Examples(examples=EXAMPLES, inputs=[code_input])
100
-
101
- analyze_btn.click(
102
- fn=audit,
103
- inputs=[code_input],
104
- outputs=[summary_out, vuln_out, llm_out],
105
- )
106
-
107
- if __name__ == "__main__":
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  demo.launch()
 
1
+ """
2
+ Hugging Face Spaces entry point.
3
+ Deploy this file as app.py in your HF Space (SDK: gradio).
4
+ """
5
+ import os
6
+ import logging
7
+ import gradio as gr
8
+ from app.models.analyzer import analyze_contract
9
+
10
+ logging.basicConfig(level=logging.INFO)
11
+ logger = logging.getLogger(__name__)
12
+
13
+ # ── Startup diagnostics ───────────────────────────────────────────────────────
14
+ HF_MODEL_ID = os.getenv("HF_MODEL_ID", "")
15
+ HF_TOKEN = os.getenv("HF_TOKEN", "")
16
+
17
+ logger.info("=" * 50)
18
+ if HF_MODEL_ID:
19
+ logger.info(f"βœ… HF_MODEL_ID set: {HF_MODEL_ID}")
20
+ else:
21
+ logger.warning("⚠️ HF_MODEL_ID not set – LLM analysis disabled")
22
+
23
+ if HF_TOKEN:
24
+ logger.info("βœ… HF_TOKEN set")
25
+ else:
26
+ logger.warning("⚠️ HF_TOKEN not set")
27
+ logger.info("=" * 50)
28
+
29
+
30
+ # ── Helpers ────────────────────────────────────────────────────────────────��──
31
+
32
+ def _fmt_vulns(vulns: list) -> str:
33
+ if not vulns:
34
+ return "βœ… No vulnerabilities detected."
35
+ icons = {"HIGH": "🚨", "MEDIUM": "⚠️", "LOW": "ℹ️"}
36
+ lines = []
37
+ for v in vulns:
38
+ icon = icons.get(v["severity"], "β€’")
39
+ name = v["name"].replace("_", " ").title()
40
+ lines.append(f"{icon} **{name}** [{v['severity']}]")
41
+ lines.append(f" {v['description']}")
42
+ if v.get("line_numbers"):
43
+ lines.append(f" Lines: {', '.join(map(str, v['line_numbers'][:8]))}")
44
+ if v.get("recommendation"):
45
+ lines.append(f" πŸ’‘ {v['recommendation']}")
46
+ lines.append("")
47
+ return "\n".join(lines)
48
+
49
+
50
+ def get_status() -> str:
51
+ """Show current config – useful for debugging."""
52
+ model_id = os.getenv("HF_MODEL_ID", "")
53
+ token = os.getenv("HF_TOKEN", "")
54
+ if model_id and token:
55
+ return f"🟒 **LLM ready** β€” `{model_id}`"
56
+ elif model_id and not token:
57
+ return f"🟑 **HF_MODEL_ID set** but no HF_TOKEN β€” may fail on private models"
58
+ else:
59
+ return "πŸ”΄ **HF_MODEL_ID not set** β€” pattern analysis only"
60
+
61
+
62
+ def audit(solidity_code: str):
63
+ if not solidity_code.strip():
64
+ return "⚠️ Please paste some Solidity code.", "", ""
65
+
66
+ logger.info("Running analysis...")
67
+ result = analyze_contract(solidity_code)
68
+ logger.info(f"Analysis type: {result['analysis_type']}, risk: {result['risk_level']}")
69
+
70
+ risk_icons = {"CRITICAL": "🚨", "MEDIUM": "⚠️", "LOW": "ℹ️", "SAFE": "βœ…"}
71
+ icon = risk_icons.get(result["risk_level"], "β€’")
72
+ summary = (
73
+ f"## {icon} Risk Level: {result['risk_level']}\n\n"
74
+ f"- **Solidity Version:** {result['solidity_version']}\n"
75
+ f"- **Lines analyzed:** {result['total_lines']}\n"
76
+ f"- **Severity Score:** {result['severity_score']}\n"
77
+ f"- **Analysis type:** `{result['analysis_type']}`\n\n"
78
+ f"| 🚨 HIGH | ⚠️ MEDIUM | ℹ️ LOW |\n|---------|----------|-------|\n"
79
+ f"| {result['high_count']} | {result['medium_count']} | {result['low_count']} |"
80
+ )
81
+
82
+ vuln_text = _fmt_vulns(result["vulnerabilities"])
83
+
84
+ if result.get("llm_analysis"):
85
+ llm_text = result["llm_analysis"]
86
+ else:
87
+ llm_text = (
88
+ "_LLM analysis not available._\n\n"
89
+ f"**Current status:** {get_status()}\n\n"
90
+ "Make sure `HF_MODEL_ID` and `HF_TOKEN` are set in Space **Settings β†’ Repository secrets**."
91
+ )
92
+
93
+ return summary, vuln_text, llm_text
94
+
95
+
96
+ # ── UI ────────────────────────────────────────────────────────────────────────
97
+
98
+ EXAMPLES = [
99
+ ["""pragma solidity ^0.4.24;
100
+ contract VulnerableBank {
101
+ mapping(address => uint256) public balances;
102
+ function withdraw(uint256 _amount) public {
103
+ require(balances[msg.sender] >= _amount);
104
+ msg.sender.call.value(_amount)();
105
+ balances[msg.sender] -= _amount;
106
+ }
107
+ }"""],
108
+ ["""// SPDX-License-Identifier: MIT
109
+ pragma solidity ^0.8.0;
110
+ import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
111
+ import "@openzeppelin/contracts/access/Ownable.sol";
112
+ contract SafeVault is ReentrancyGuard, Ownable {
113
+ mapping(address => uint256) private balances;
114
+ function withdraw(uint256 amount) external nonReentrant {
115
+ require(balances[msg.sender] >= amount);
116
+ balances[msg.sender] -= amount;
117
+ (bool ok,) = payable(msg.sender).call{value: amount}("");
118
+ require(ok);
119
+ }
120
+ }"""],
121
+ ]
122
+
123
+ with gr.Blocks(title="πŸ›‘οΈ Smart Contract Auditor") as demo:
124
+ gr.Markdown("# πŸ›‘οΈ Smart Contract Security Auditor")
125
+ gr.Markdown(get_status) # live status banner – refreshes on load
126
+
127
+ with gr.Row():
128
+ with gr.Column():
129
+ code_input = gr.Code(label="Solidity Contract", language="javascript", lines=22)
130
+ analyze_btn = gr.Button("πŸ” Analyze Contract", variant="primary")
131
+
132
+ with gr.Column():
133
+ summary_out = gr.Markdown(label="πŸ“Š Summary")
134
+ vuln_out = gr.Markdown(label="πŸ” Vulnerabilities")
135
+ llm_out = gr.Markdown(label="πŸ€– LLM Analysis")
136
+
137
+ gr.Examples(examples=EXAMPLES, inputs=[code_input])
138
+
139
+ analyze_btn.click(
140
+ fn=audit,
141
+ inputs=[code_input],
142
+ outputs=[summary_out, vuln_out, llm_out],
143
+ )
144
+
145
+ if __name__ == "__main__":
146
  demo.launch()