clawcontract 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/README.md +222 -0
  2. package/dist/analyzer/fallback.d.ts +28 -0
  3. package/dist/analyzer/fallback.d.ts.map +1 -0
  4. package/dist/analyzer/fallback.js +142 -0
  5. package/dist/analyzer/fallback.js.map +1 -0
  6. package/dist/analyzer/index.d.ts +24 -0
  7. package/dist/analyzer/index.d.ts.map +1 -0
  8. package/dist/analyzer/index.js +73 -0
  9. package/dist/analyzer/index.js.map +1 -0
  10. package/dist/analyzer/slither.d.ts +36 -0
  11. package/dist/analyzer/slither.d.ts.map +1 -0
  12. package/dist/analyzer/slither.js +92 -0
  13. package/dist/analyzer/slither.js.map +1 -0
  14. package/dist/cli/commands/analyze.d.ts +7 -0
  15. package/dist/cli/commands/analyze.d.ts.map +1 -0
  16. package/dist/cli/commands/analyze.js +74 -0
  17. package/dist/cli/commands/analyze.js.map +1 -0
  18. package/dist/cli/commands/delete.d.ts +5 -0
  19. package/dist/cli/commands/delete.d.ts.map +1 -0
  20. package/dist/cli/commands/delete.js +48 -0
  21. package/dist/cli/commands/delete.js.map +1 -0
  22. package/dist/cli/commands/deploy.d.ts +5 -0
  23. package/dist/cli/commands/deploy.d.ts.map +1 -0
  24. package/dist/cli/commands/deploy.js +88 -0
  25. package/dist/cli/commands/deploy.js.map +1 -0
  26. package/dist/cli/commands/full.d.ts +5 -0
  27. package/dist/cli/commands/full.d.ts.map +1 -0
  28. package/dist/cli/commands/full.js +83 -0
  29. package/dist/cli/commands/full.js.map +1 -0
  30. package/dist/cli/commands/generate.d.ts +5 -0
  31. package/dist/cli/commands/generate.d.ts.map +1 -0
  32. package/dist/cli/commands/generate.js +35 -0
  33. package/dist/cli/commands/generate.js.map +1 -0
  34. package/dist/cli/commands/interact.d.ts +6 -0
  35. package/dist/cli/commands/interact.d.ts.map +1 -0
  36. package/dist/cli/commands/interact.js +136 -0
  37. package/dist/cli/commands/interact.js.map +1 -0
  38. package/dist/cli/commands/list.d.ts +6 -0
  39. package/dist/cli/commands/list.d.ts.map +1 -0
  40. package/dist/cli/commands/list.js +37 -0
  41. package/dist/cli/commands/list.js.map +1 -0
  42. package/dist/cli/commands/setup.d.ts +8 -0
  43. package/dist/cli/commands/setup.d.ts.map +1 -0
  44. package/dist/cli/commands/setup.js +36 -0
  45. package/dist/cli/commands/setup.js.map +1 -0
  46. package/dist/cli/commands/verify.d.ts +9 -0
  47. package/dist/cli/commands/verify.d.ts.map +1 -0
  48. package/dist/cli/commands/verify.js +87 -0
  49. package/dist/cli/commands/verify.js.map +1 -0
  50. package/dist/cli/index.d.ts +3 -0
  51. package/dist/cli/index.d.ts.map +1 -0
  52. package/dist/cli/index.js +104 -0
  53. package/dist/cli/index.js.map +1 -0
  54. package/dist/cli/utils.d.ts +6 -0
  55. package/dist/cli/utils.d.ts.map +1 -0
  56. package/dist/cli/utils.js +29 -0
  57. package/dist/cli/utils.js.map +1 -0
  58. package/dist/config/chains.d.ts +18 -0
  59. package/dist/config/chains.d.ts.map +1 -0
  60. package/dist/config/chains.js +52 -0
  61. package/dist/config/chains.js.map +1 -0
  62. package/dist/config/index.d.ts +2 -0
  63. package/dist/config/index.d.ts.map +1 -0
  64. package/dist/config/index.js +2 -0
  65. package/dist/config/index.js.map +1 -0
  66. package/dist/deployer/compiler.d.ts +10 -0
  67. package/dist/deployer/compiler.d.ts.map +1 -0
  68. package/dist/deployer/compiler.js +93 -0
  69. package/dist/deployer/compiler.js.map +1 -0
  70. package/dist/deployer/deploy.d.ts +28 -0
  71. package/dist/deployer/deploy.d.ts.map +1 -0
  72. package/dist/deployer/deploy.js +60 -0
  73. package/dist/deployer/deploy.js.map +1 -0
  74. package/dist/deployer/hardhat-config-template.d.ts +2 -0
  75. package/dist/deployer/hardhat-config-template.d.ts.map +1 -0
  76. package/dist/deployer/hardhat-config-template.js +20 -0
  77. package/dist/deployer/hardhat-config-template.js.map +1 -0
  78. package/dist/deployer/index.d.ts +7 -0
  79. package/dist/deployer/index.d.ts.map +1 -0
  80. package/dist/deployer/index.js +4 -0
  81. package/dist/deployer/index.js.map +1 -0
  82. package/dist/deployer/metadata.d.ts +16 -0
  83. package/dist/deployer/metadata.d.ts.map +1 -0
  84. package/dist/deployer/metadata.js +315 -0
  85. package/dist/deployer/metadata.js.map +1 -0
  86. package/dist/deployer/wallet.d.ts +6 -0
  87. package/dist/deployer/wallet.d.ts.map +1 -0
  88. package/dist/deployer/wallet.js +21 -0
  89. package/dist/deployer/wallet.js.map +1 -0
  90. package/dist/generator/index.d.ts +19 -0
  91. package/dist/generator/index.d.ts.map +1 -0
  92. package/dist/generator/index.js +33 -0
  93. package/dist/generator/index.js.map +1 -0
  94. package/dist/generator/llm.d.ts +10 -0
  95. package/dist/generator/llm.d.ts.map +1 -0
  96. package/dist/generator/llm.js +71 -0
  97. package/dist/generator/llm.js.map +1 -0
  98. package/dist/generator/templates/erc20.d.ts +2 -0
  99. package/dist/generator/templates/erc20.d.ts.map +1 -0
  100. package/dist/generator/templates/erc20.js +106 -0
  101. package/dist/generator/templates/erc20.js.map +1 -0
  102. package/dist/generator/templates/erc20.sol.d.ts +2 -0
  103. package/dist/generator/templates/erc20.sol.d.ts.map +1 -0
  104. package/dist/generator/templates/erc20.sol.js +106 -0
  105. package/dist/generator/templates/erc20.sol.js.map +1 -0
  106. package/dist/generator/templates/erc721.d.ts +2 -0
  107. package/dist/generator/templates/erc721.d.ts.map +1 -0
  108. package/dist/generator/templates/erc721.js +168 -0
  109. package/dist/generator/templates/erc721.js.map +1 -0
  110. package/dist/generator/templates/erc721.sol.d.ts +2 -0
  111. package/dist/generator/templates/erc721.sol.d.ts.map +1 -0
  112. package/dist/generator/templates/erc721.sol.js +168 -0
  113. package/dist/generator/templates/erc721.sol.js.map +1 -0
  114. package/dist/generator/templates/index.d.ts +21 -0
  115. package/dist/generator/templates/index.d.ts.map +1 -0
  116. package/dist/generator/templates/index.js +157 -0
  117. package/dist/generator/templates/index.js.map +1 -0
  118. package/dist/generator/templates/multisig.d.ts +2 -0
  119. package/dist/generator/templates/multisig.d.ts.map +1 -0
  120. package/dist/generator/templates/multisig.js +136 -0
  121. package/dist/generator/templates/multisig.js.map +1 -0
  122. package/dist/generator/templates/multisig.sol.d.ts +2 -0
  123. package/dist/generator/templates/multisig.sol.d.ts.map +1 -0
  124. package/dist/generator/templates/multisig.sol.js +136 -0
  125. package/dist/generator/templates/multisig.sol.js.map +1 -0
  126. package/dist/generator/templates/staking.d.ts +2 -0
  127. package/dist/generator/templates/staking.d.ts.map +1 -0
  128. package/dist/generator/templates/staking.js +119 -0
  129. package/dist/generator/templates/staking.js.map +1 -0
  130. package/dist/generator/templates/staking.sol.d.ts +2 -0
  131. package/dist/generator/templates/staking.sol.d.ts.map +1 -0
  132. package/dist/generator/templates/staking.sol.js +119 -0
  133. package/dist/generator/templates/staking.sol.js.map +1 -0
  134. package/dist/generator/templates/vesting.d.ts +2 -0
  135. package/dist/generator/templates/vesting.d.ts.map +1 -0
  136. package/dist/generator/templates/vesting.js +133 -0
  137. package/dist/generator/templates/vesting.js.map +1 -0
  138. package/dist/generator/templates/vesting.sol.d.ts +2 -0
  139. package/dist/generator/templates/vesting.sol.d.ts.map +1 -0
  140. package/dist/generator/templates/vesting.sol.js +133 -0
  141. package/dist/generator/templates/vesting.sol.js.map +1 -0
  142. package/dist/generator/utils.d.ts +5 -0
  143. package/dist/generator/utils.d.ts.map +1 -0
  144. package/dist/generator/utils.js +49 -0
  145. package/dist/generator/utils.js.map +1 -0
  146. package/dist/index.d.ts +2 -0
  147. package/dist/index.d.ts.map +1 -0
  148. package/dist/index.js +2 -0
  149. package/dist/index.js.map +1 -0
  150. package/dist/verifier/explorer-api.d.ts +21 -0
  151. package/dist/verifier/explorer-api.d.ts.map +1 -0
  152. package/dist/verifier/explorer-api.js +92 -0
  153. package/dist/verifier/explorer-api.js.map +1 -0
  154. package/dist/verifier/index.d.ts +20 -0
  155. package/dist/verifier/index.d.ts.map +1 -0
  156. package/dist/verifier/index.js +31 -0
  157. package/dist/verifier/index.js.map +1 -0
  158. package/package.json +53 -0
package/README.md ADDED
@@ -0,0 +1,222 @@
1
+ # ClawContract 🦞
2
+
3
+ **AI-powered smart contract generator, analyzer, and deployer for BNB Chain**
4
+
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
+ [![Node.js 20+](https://img.shields.io/badge/Node.js-20%2B-green.svg)](https://nodejs.org)
7
+ [![BNB Chain](https://img.shields.io/badge/BNB%20Chain-BSC%20%7C%20opBNB-F0B90B.svg)](https://www.bnbchain.org)
8
+ [![Hackathon](https://img.shields.io/badge/Hackathon-Good%20Vibes%20Only-blueviolet.svg)](#hackathon)
9
+
10
+ ---
11
+
12
+ ## Overview
13
+
14
+ ClawContract turns natural language into production-ready, deployed, and verified smart contracts on BNB Chain. Describe what you want in plain English — ClawContract generates the Solidity code using AI, runs security analysis, deploys to BSC or opBNB, and verifies the source on BscScan — all in a single command.
15
+
16
+ ## Features
17
+
18
+ - **Security analysis** — runs Slither static analysis with an automatic regex-based fallback for environments without Python
19
+ - **One-command deployment** — deploy to BSC and opBNB (mainnet + testnet) with gas estimation
20
+ - **Automatic verification** — verify source code on BscScan and opBNBScan immediately after deployment
21
+ - **Non-interactive CLI** — fully automated pipeline with gas estimates, no user prompts required
22
+ - **OpenClaw skill integration** — register as an OpenClaw skill for chat-based contract generation and deployment
23
+
24
+ ## Quick Start
25
+
26
+ ```bash
27
+ git clone https://github.com/your-username/ClawContract.git
28
+ cd ClawContract
29
+ pnpm install
30
+ pnpm run build
31
+ ```
32
+
33
+ Then set up your environment:
34
+
35
+ ```bash
36
+ clawcontract setup
37
+ clawcontract setup --openrouter-key sk-or-... --bscscan-key ABC123
38
+ clawcontract setup --private-key 0xabc... --openrouter-key sk-or-... --openrouter-model anthropic/claude-sonnet-4-20250514
39
+ ```
40
+
41
+ This writes a `.env` file non-interactively. A wallet is auto-generated if `--private-key` is not provided.
42
+
43
+ ## Usage
44
+
45
+ ### Generate a contract
46
+
47
+ ```bash
48
+ clawcontract generate "ERC-20 token called VibeToken with 1M supply"
49
+ ```
50
+
51
+ ### Analyze a contract for vulnerabilities
52
+
53
+ ```bash
54
+ clawcontract analyze ./contracts/VibeToken.sol
55
+ ```
56
+
57
+ ### Deploy to a chain
58
+
59
+ ```bash
60
+ clawcontract deploy ./contracts/VibeToken.sol --chain bsc-testnet
61
+ ```
62
+
63
+ ### Verify on block explorer
64
+
65
+ ```bash
66
+ clawcontract verify 0xYourContractAddress --chain bsc-testnet --file ./contracts/VibeToken.sol
67
+ ```
68
+
69
+ ### Interact with a deployed contract
70
+
71
+ ```bash
72
+ clawcontract interact 0xYourContractAddress name --chain bsc-testnet
73
+ ```
74
+
75
+ Call any function on a deployed contract. Read-only functions (`view`/`pure`) are called without gas. State-changing functions are sent as signed transactions.
76
+
77
+ ```bash
78
+ # Read-only call
79
+ clawcontract interact 0xABC... balanceOf 0xDEF... --chain bsc-testnet
80
+
81
+ # State-changing call
82
+ clawcontract interact 0xABC... transfer 0xDEF... 1000 --chain bsc-testnet
83
+
84
+ # Payable call (send BNB value in wei)
85
+ clawcontract interact 0xABC... fundTrade 1 --value 100000000000000 --chain bsc-testnet
86
+
87
+ # Use ABI from source file instead of stored metadata
88
+ clawcontract interact 0xABC... name --chain bsc-testnet --file ./contracts/VibeToken.sol
89
+ ```
90
+
91
+ ### List deployments
92
+
93
+ ```bash
94
+ clawcontract list
95
+ ```
96
+
97
+ List all stored deployment records. Shows address, contract name, chain, deployer, and deployment date.
98
+
99
+ ```bash
100
+ # List all deployments
101
+ clawcontract list
102
+
103
+ # Filter by chain
104
+ clawcontract list --chain bsc-testnet
105
+
106
+ # Output as JSON (for scripting)
107
+ clawcontract list --json
108
+ ```
109
+
110
+ ### Delete a deployment record
111
+
112
+ ```bash
113
+ clawcontract delete <address>
114
+ ```
115
+
116
+ Remove a deployment record from the local store. Shows deployment details and asks for confirmation before deleting. Orphaned ABI files are automatically cleaned up.
117
+
118
+ ```bash
119
+ # Delete with confirmation prompt
120
+ clawcontract delete 0xYourContractAddress
121
+
122
+ # Skip confirmation
123
+ clawcontract delete 0xYourContractAddress --force
124
+ ```
125
+
126
+ ### Full pipeline (generate → analyze → deploy → verify)
127
+
128
+ ```bash
129
+ clawcontract full "staking contract for BNB with 10% APY" --chain bsc-testnet
130
+ ```
131
+
132
+ ### Global options
133
+
134
+ | Option | Description | Default |
135
+ |---|---|---|
136
+ | `--chain <chain>` | Target blockchain | `bsc-testnet` |
137
+ | `--output <dir>` | Output directory for generated contracts | `./contracts` |
138
+
139
+ ## Supported Chains
140
+
141
+ | Chain | Chain ID | RPC | Explorer |
142
+ |---|---|---|---|
143
+ | BNB Smart Chain | 56 | `https://bsc-dataseed.binance.org` | [bscscan.com](https://bscscan.com) |
144
+ | BNB Smart Chain Testnet | 97 | `https://data-seed-prebsc-1-s1.binance.org:8545` | [testnet.bscscan.com](https://testnet.bscscan.com) |
145
+ | opBNB | 204 | `https://opbnb-mainnet-rpc.bnbchain.org` | [opbnbscan.com](https://opbnbscan.com) |
146
+ | opBNB Testnet | 5611 | `https://opbnb-testnet-rpc.bnbchain.org` | [testnet.opbnbscan.com](https://testnet.opbnbscan.com) |
147
+
148
+ ## Architecture
149
+
150
+ ```
151
+ src/
152
+ ├── cli/ # Commander.js CLI entry point + command handlers
153
+ ├── generator/ # Contract generation (template matching + Claude LLM)
154
+ ├── analyzer/ # Security analysis (Slither + regex fallback)
155
+ ├── deployer/ # Compilation + deployment via Hardhat + ethers.js (saves metadata)
156
+ ├── verifier/ # BscScan / opBNBScan source verification
157
+ ├── config/ # Chain configurations and constants
158
+ └── openclaw/ # OpenClaw skill definition for chat integration
159
+ ```
160
+
161
+ ## Pipeline Flow
162
+
163
+ The `full` command runs the entire pipeline end-to-end. If high-severity issues are found during analysis, the AI will automatically attempt to fix them (up to 3 attempts) before proceeding to deployment.
164
+
165
+ ```
166
+ Natural Language
167
+
168
+ AI Generation ─── template matching + Claude LLM
169
+
170
+ Security Analysis ── Slither / regex checks
171
+ ↓ ↑
172
+ AI Auto-Fix ────────┘ (up to 3 attempts if high-severity issues found)
173
+
174
+ Compilation ────── Hardhat + solc
175
+
176
+ Deployment ─────── ethers.js → BSC / opBNB
177
+
178
+ Verification ───── BscScan / opBNBScan API
179
+
180
+ Interaction ────── ethers.js read/write calls
181
+ ```
182
+
183
+ ## OpenClaw Integration
184
+
185
+ ClawContract ships with an [OpenClaw skill](src/openclaw/SKILL.md) that teaches OpenClaw agents how to use the CLI for chat-based contract generation and deployment. Copy or symlink `src/openclaw/` into your OpenClaw workspace `skills/` directory to enable it.
186
+
187
+ ## Configuration
188
+
189
+ Run `clawcontract setup` to generate a `.env` file, or copy the example and fill in manually:
190
+
191
+ ```bash
192
+ cp .env.example .env
193
+ ```
194
+
195
+ | Variable | Description | Required |
196
+ |---|---|---|
197
+ | `PRIVATE_KEY` | Wallet private key for deployment (auto-generated if not set) | No |
198
+ | `OPENROUTER_API_KEY` | OpenRouter API key for AI contract generation | Yes |
199
+ | `OPENROUTER_MODEL` | OpenRouter model (default: `anthropic/claude-sonnet-4-20250514`) | No |
200
+ | `BSCSCAN_API_KEY` | BscScan / opBNBScan API key for contract verification | No |
201
+
202
+ > **Security:** Never commit your `.env` file. The `.env.example` file is provided as a reference.
203
+
204
+ > **Data:** Deployment metadata is saved to `contracts/.deployments/` using a directory-based store with deduplicated ABIs and an index for fast lookups. Legacy `.deployments.json` files are auto-migrated on first access. This directory is local and should not be committed.
205
+
206
+ ## Requirements
207
+
208
+ - **Node.js** 20.0.0 or later
209
+ - **pnpm** (recommended package manager)
210
+ - **Python 3.8+** (optional — required for Slither static analysis; regex fallback is used if unavailable)
211
+
212
+ ## Hackathon
213
+
214
+ Built for the **Good Vibes Only: OpenClaw Edition** hackathon.
215
+
216
+ - **Track:** Builders' Tools
217
+ - **Chain:** BNB Chain (BSC + opBNB)
218
+ - **Goal:** Make smart contract development accessible to everyone through AI and natural language
219
+
220
+ ## License
221
+
222
+ [MIT](LICENSE)
@@ -0,0 +1,28 @@
1
+ export interface Finding {
2
+ severity: 'High' | 'Medium' | 'Low' | 'Informational' | 'Optimization';
3
+ title: string;
4
+ description: string;
5
+ location: string;
6
+ recommendation: string;
7
+ }
8
+ export interface AnalysisSummary {
9
+ high: number;
10
+ medium: number;
11
+ low: number;
12
+ informational: number;
13
+ optimization: number;
14
+ total: number;
15
+ }
16
+ export interface AnalysisResult {
17
+ findings: Finding[];
18
+ summary: AnalysisSummary;
19
+ passed: boolean;
20
+ }
21
+ export declare function checkReentrancy(source: string): Finding[];
22
+ export declare function checkUncheckedReturn(source: string): Finding[];
23
+ export declare function checkTxOrigin(source: string): Finding[];
24
+ export declare function checkSelfDestruct(source: string): Finding[];
25
+ export declare function checkFloatingPragma(source: string): Finding[];
26
+ export declare function runFallbackAnalysis(source: string): AnalysisResult;
27
+ export declare function runFallbackAnalysisFromFile(filePath: string): AnalysisResult;
28
+ //# sourceMappingURL=fallback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback.d.ts","sourceRoot":"","sources":["../../src/analyzer/fallback.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,OAAO;IACtB,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,eAAe,GAAG,cAAc,CAAC;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,EAAE,eAAe,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,EAAE,CA2BzD;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,EAAE,CAoB9D;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,EAAE,CAkBvD;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,EAAE,CAkB3D;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,EAAE,CAkB7D;AAyBD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAalE;AAED,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CAG5E"}
@@ -0,0 +1,142 @@
1
+ import { readFileSync } from 'node:fs';
2
+ export function checkReentrancy(source) {
3
+ const findings = [];
4
+ const lines = source.split('\n');
5
+ for (let i = 0; i < lines.length; i++) {
6
+ const line = lines[i].trim();
7
+ if ((line.includes('.call{') || line.includes('.call(') || line.includes('.send(') || line.includes('.transfer(')) &&
8
+ !line.startsWith('//')) {
9
+ for (let j = i + 1; j < Math.min(i + 10, lines.length); j++) {
10
+ const subsequent = lines[j].trim();
11
+ if (subsequent.includes('=') && !subsequent.startsWith('//') && !subsequent.startsWith('require') && !subsequent.startsWith('if')) {
12
+ findings.push({
13
+ severity: 'High',
14
+ title: '[Basic Check] Potential Reentrancy',
15
+ description: `External call at line ${i + 1} is followed by a state change at line ${j + 1}. This could be vulnerable to reentrancy attacks.`,
16
+ location: `Line ${i + 1}`,
17
+ recommendation: 'Use the checks-effects-interactions pattern or a reentrancy guard. Update state variables before making external calls.',
18
+ });
19
+ break;
20
+ }
21
+ }
22
+ }
23
+ }
24
+ return findings;
25
+ }
26
+ export function checkUncheckedReturn(source) {
27
+ const findings = [];
28
+ const lines = source.split('\n');
29
+ for (let i = 0; i < lines.length; i++) {
30
+ const line = lines[i].trim();
31
+ if (line.includes('.call{') || line.includes('.call(')) {
32
+ if (!line.includes('(bool') && !line.includes('require') && !line.includes('if')) {
33
+ findings.push({
34
+ severity: 'Medium',
35
+ title: '[Basic Check] Unchecked Return Value',
36
+ description: `Low-level call at line ${i + 1} does not check the return value. The call could silently fail.`,
37
+ location: `Line ${i + 1}`,
38
+ recommendation: 'Check the return value of low-level calls: (bool success, ) = addr.call{...}(...); require(success);',
39
+ });
40
+ }
41
+ }
42
+ }
43
+ return findings;
44
+ }
45
+ export function checkTxOrigin(source) {
46
+ const findings = [];
47
+ const lines = source.split('\n');
48
+ for (let i = 0; i < lines.length; i++) {
49
+ const line = lines[i].trim();
50
+ if (line.includes('tx.origin') && !line.startsWith('//')) {
51
+ findings.push({
52
+ severity: 'Medium',
53
+ title: '[Basic Check] tx.origin Usage',
54
+ description: `tx.origin used at line ${i + 1}. Using tx.origin for authorization is vulnerable to phishing attacks.`,
55
+ location: `Line ${i + 1}`,
56
+ recommendation: 'Use msg.sender instead of tx.origin for authorization checks.',
57
+ });
58
+ }
59
+ }
60
+ return findings;
61
+ }
62
+ export function checkSelfDestruct(source) {
63
+ const findings = [];
64
+ const lines = source.split('\n');
65
+ for (let i = 0; i < lines.length; i++) {
66
+ const line = lines[i].trim();
67
+ if ((line.includes('selfdestruct(') || line.includes('selfdestruct (')) && !line.startsWith('//')) {
68
+ findings.push({
69
+ severity: 'High',
70
+ title: '[Basic Check] selfdestruct Usage',
71
+ description: `selfdestruct found at line ${i + 1}. This can permanently destroy the contract and send remaining Ether to an address.`,
72
+ location: `Line ${i + 1}`,
73
+ recommendation: 'Remove selfdestruct or protect it with strict access control. Note: selfdestruct is deprecated in newer Solidity versions.',
74
+ });
75
+ }
76
+ }
77
+ return findings;
78
+ }
79
+ export function checkFloatingPragma(source) {
80
+ const findings = [];
81
+ const lines = source.split('\n');
82
+ for (let i = 0; i < lines.length; i++) {
83
+ const line = lines[i].trim();
84
+ if (line.startsWith('pragma solidity') && line.includes('^')) {
85
+ findings.push({
86
+ severity: 'Informational',
87
+ title: '[Basic Check] Floating Pragma',
88
+ description: `Floating pragma found at line ${i + 1}: "${line}". Contracts should be deployed with the same compiler version they were tested with.`,
89
+ location: `Line ${i + 1}`,
90
+ recommendation: 'Lock the pragma to a specific version, e.g., "pragma solidity 0.8.20;" instead of "pragma solidity ^0.8.20;".',
91
+ });
92
+ }
93
+ }
94
+ return findings;
95
+ }
96
+ function buildSummary(findings) {
97
+ const summary = {
98
+ high: 0,
99
+ medium: 0,
100
+ low: 0,
101
+ informational: 0,
102
+ optimization: 0,
103
+ total: findings.length,
104
+ };
105
+ for (const finding of findings) {
106
+ switch (finding.severity) {
107
+ case 'High':
108
+ summary.high++;
109
+ break;
110
+ case 'Medium':
111
+ summary.medium++;
112
+ break;
113
+ case 'Low':
114
+ summary.low++;
115
+ break;
116
+ case 'Informational':
117
+ summary.informational++;
118
+ break;
119
+ case 'Optimization':
120
+ summary.optimization++;
121
+ break;
122
+ }
123
+ }
124
+ return summary;
125
+ }
126
+ export function runFallbackAnalysis(source) {
127
+ const findings = [
128
+ ...checkReentrancy(source),
129
+ ...checkUncheckedReturn(source),
130
+ ...checkTxOrigin(source),
131
+ ...checkSelfDestruct(source),
132
+ ...checkFloatingPragma(source),
133
+ ];
134
+ const summary = buildSummary(findings);
135
+ const passed = summary.high === 0;
136
+ return { findings, summary, passed };
137
+ }
138
+ export function runFallbackAnalysisFromFile(filePath) {
139
+ const source = readFileSync(filePath, 'utf-8');
140
+ return runFallbackAnalysis(source);
141
+ }
142
+ //# sourceMappingURL=fallback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback.js","sourceRoot":"","sources":["../../src/analyzer/fallback.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export interface Finding {
2
+ severity: 'High' | 'Medium' | 'Low' | 'Informational' | 'Optimization';
3
+ title: string;
4
+ description: string;
5
+ location: string;
6
+ recommendation: string;
7
+ }
8
+ export interface AnalysisSummary {
9
+ high: number;
10
+ medium: number;
11
+ low: number;
12
+ informational: number;
13
+ optimization: number;
14
+ total: number;
15
+ }
16
+ export interface AnalysisResult {
17
+ findings: Finding[];
18
+ summary: AnalysisSummary;
19
+ passed: boolean;
20
+ }
21
+ export declare function analyzeContract(filePath: string): Promise<AnalysisResult>;
22
+ export declare function isSlitherAvailable(): boolean;
23
+ export declare function getSlitherInstallInstructions(): string;
24
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analyzer/index.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,OAAO;IACtB,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,eAAe,GAAG,cAAc,CAAC;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,EAAE,eAAe,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;CACjB;AAyBD,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CA4B/E;AAED,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C;AAED,wBAAgB,6BAA6B,IAAI,MAAM,CAWtD"}
@@ -0,0 +1,73 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { isSlitherInstalled, runSlither, mapSlitherResults } from './slither.js';
3
+ import { runFallbackAnalysis } from './fallback.js';
4
+ function buildSummary(findings) {
5
+ const summary = {
6
+ high: 0,
7
+ medium: 0,
8
+ low: 0,
9
+ informational: 0,
10
+ optimization: 0,
11
+ total: findings.length,
12
+ };
13
+ for (const finding of findings) {
14
+ switch (finding.severity) {
15
+ case 'High':
16
+ summary.high++;
17
+ break;
18
+ case 'Medium':
19
+ summary.medium++;
20
+ break;
21
+ case 'Low':
22
+ summary.low++;
23
+ break;
24
+ case 'Informational':
25
+ summary.informational++;
26
+ break;
27
+ case 'Optimization':
28
+ summary.optimization++;
29
+ break;
30
+ }
31
+ }
32
+ return summary;
33
+ }
34
+ export async function analyzeContract(filePath) {
35
+ if (!existsSync(filePath)) {
36
+ throw new Error(`Contract file not found: ${filePath}`);
37
+ }
38
+ if (isSlitherAvailable()) {
39
+ const output = runSlither(filePath);
40
+ const findings = mapSlitherResults(output);
41
+ const summary = buildSummary(findings);
42
+ const passed = summary.high === 0;
43
+ return { findings, summary, passed };
44
+ }
45
+ const source = readFileSync(filePath, 'utf-8');
46
+ const result = runFallbackAnalysis(source);
47
+ result.findings.unshift({
48
+ severity: 'Informational',
49
+ title: '[Basic Check] Slither Not Installed',
50
+ description: 'Slither is not installed. Only basic regex-based checks were performed. Install Slither for comprehensive analysis.',
51
+ location: 'N/A',
52
+ recommendation: getSlitherInstallInstructions(),
53
+ });
54
+ result.summary.informational++;
55
+ result.summary.total++;
56
+ return result;
57
+ }
58
+ export function isSlitherAvailable() {
59
+ return isSlitherInstalled();
60
+ }
61
+ export function getSlitherInstallInstructions() {
62
+ return [
63
+ 'Install Slither for comprehensive smart contract analysis:',
64
+ ' pip3 install slither-analyzer',
65
+ '',
66
+ 'Or with pipx:',
67
+ ' pipx install slither-analyzer',
68
+ '',
69
+ 'Requires Python 3.8+ and solc (Solidity compiler).',
70
+ 'More info: https://github.com/crytic/slither',
71
+ ].join('\n');
72
+ }
73
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/analyzer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AA0BpD,SAAS,YAAY,CAAC,QAAmB;IACvC,MAAM,OAAO,GAAoB;QAC/B,IAAI,EAAE,CAAC;QACP,MAAM,EAAE,CAAC;QACT,GAAG,EAAE,CAAC;QACN,aAAa,EAAE,CAAC;QAChB,YAAY,EAAE,CAAC;QACf,KAAK,EAAE,QAAQ,CAAC,MAAM;KACvB,CAAC;IAEF,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,QAAQ,OAAO,CAAC,QAAQ,EAAE,CAAC;YACzB,KAAK,MAAM;gBAAE,OAAO,CAAC,IAAI,EAAE,CAAC;gBAAC,MAAM;YACnC,KAAK,QAAQ;gBAAE,OAAO,CAAC,MAAM,EAAE,CAAC;gBAAC,MAAM;YACvC,KAAK,KAAK;gBAAE,OAAO,CAAC,GAAG,EAAE,CAAC;gBAAC,MAAM;YACjC,KAAK,eAAe;gBAAE,OAAO,CAAC,aAAa,EAAE,CAAC;gBAAC,MAAM;YACrD,KAAK,cAAc;gBAAE,OAAO,CAAC,YAAY,EAAE,CAAC;gBAAC,MAAM;QACrD,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,QAAgB;IACpD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,4BAA4B,QAAQ,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,IAAI,kBAAkB,EAAE,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAc,iBAAiB,CAAC,MAAM,CAAC,CAAC;QACtD,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC;QAClC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IACvC,CAAC;IAED,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAE3C,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;QACtB,QAAQ,EAAE,eAAe;QACzB,KAAK,EAAE,qCAAqC;QAC5C,WAAW,EAAE,qHAAqH;QAClI,QAAQ,EAAE,KAAK;QACf,cAAc,EAAE,6BAA6B,EAAE;KAChD,CAAC,CAAC;IAEH,MAAM,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;IAC/B,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IAEvB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,kBAAkB,EAAE,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,6BAA6B;IAC3C,OAAO;QACL,4DAA4D;QAC5D,iCAAiC;QACjC,EAAE;QACF,eAAe;QACf,iCAAiC;QACjC,EAAE;QACF,oDAAoD;QACpD,8CAA8C;KAC/C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,36 @@
1
+ export interface SlitherDetector {
2
+ check: string;
3
+ impact: string;
4
+ confidence: string;
5
+ description: string;
6
+ elements: SlitherElement[];
7
+ first_markdown_element: string;
8
+ }
9
+ export interface SlitherElement {
10
+ type: string;
11
+ name: string;
12
+ source_mapping: {
13
+ filename_relative: string;
14
+ lines: number[];
15
+ starting_column: number;
16
+ ending_column: number;
17
+ };
18
+ }
19
+ export interface SlitherOutput {
20
+ success: boolean;
21
+ error: string | null;
22
+ results: {
23
+ detectors: SlitherDetector[];
24
+ } | null;
25
+ }
26
+ export interface Finding {
27
+ severity: 'High' | 'Medium' | 'Low' | 'Informational' | 'Optimization';
28
+ title: string;
29
+ description: string;
30
+ location: string;
31
+ recommendation: string;
32
+ }
33
+ export declare function isSlitherInstalled(): boolean;
34
+ export declare function runSlither(filePath: string): SlitherOutput;
35
+ export declare function mapSlitherResults(output: SlitherOutput): Finding[];
36
+ //# sourceMappingURL=slither.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slither.d.ts","sourceRoot":"","sources":["../../src/analyzer/slither.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE;QACd,iBAAiB,EAAE,MAAM,CAAC;QAC1B,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,eAAe,EAAE,MAAM,CAAC;QACxB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;CACH;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE;QACP,SAAS,EAAE,eAAe,EAAE,CAAC;KAC9B,GAAG,IAAI,CAAC;CACV;AAED,MAAM,WAAW,OAAO;IACtB,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,eAAe,GAAG,cAAc,CAAC;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;CACxB;AAcD,wBAAgB,kBAAkB,IAAI,OAAO,CAQ5C;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CA6B1D;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,EAAE,CAkBlE"}
@@ -0,0 +1,92 @@
1
+ import { execSync } from 'node:child_process';
2
+ import { platform } from 'node:os';
3
+ const IMPACT_MAP = {
4
+ High: 'High',
5
+ Medium: 'Medium',
6
+ Low: 'Low',
7
+ Informational: 'Informational',
8
+ Optimization: 'Optimization',
9
+ };
10
+ function mapImpact(impact) {
11
+ return IMPACT_MAP[impact] ?? 'Informational';
12
+ }
13
+ export function isSlitherInstalled() {
14
+ try {
15
+ const cmd = platform() === 'win32' ? 'where slither' : 'which slither';
16
+ execSync(cmd, { stdio: 'pipe' });
17
+ return true;
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }
23
+ export function runSlither(filePath) {
24
+ try {
25
+ const stdout = execSync(`slither ${filePath} --json -`, {
26
+ encoding: 'utf-8',
27
+ stdio: ['pipe', 'pipe', 'pipe'],
28
+ timeout: 120_000,
29
+ });
30
+ const parsed = JSON.parse(stdout);
31
+ return parsed;
32
+ }
33
+ catch (err) {
34
+ if (err && typeof err === 'object' && 'stdout' in err) {
35
+ const stdout = err.stdout;
36
+ if (stdout && typeof stdout === 'string') {
37
+ try {
38
+ const parsed = JSON.parse(stdout);
39
+ return parsed;
40
+ }
41
+ catch {
42
+ // JSON parse failed, fall through
43
+ }
44
+ }
45
+ }
46
+ return {
47
+ success: false,
48
+ error: err instanceof Error ? err.message : String(err),
49
+ results: null,
50
+ };
51
+ }
52
+ }
53
+ export function mapSlitherResults(output) {
54
+ if (!output.results?.detectors) {
55
+ return [];
56
+ }
57
+ return output.results.detectors.map((detector) => {
58
+ const location = detector.elements.length > 0
59
+ ? formatLocation(detector.elements[0])
60
+ : 'Unknown';
61
+ return {
62
+ severity: mapImpact(detector.impact),
63
+ title: detector.check,
64
+ description: detector.description,
65
+ location,
66
+ recommendation: getRecommendation(detector.check),
67
+ };
68
+ });
69
+ }
70
+ function formatLocation(element) {
71
+ const file = element.source_mapping.filename_relative;
72
+ const lines = element.source_mapping.lines;
73
+ if (lines.length > 0) {
74
+ return `${file}#L${lines[0]}`;
75
+ }
76
+ return file;
77
+ }
78
+ function getRecommendation(check) {
79
+ const recommendations = {
80
+ 'reentrancy-eth': 'Use the checks-effects-interactions pattern or a reentrancy guard.',
81
+ 'reentrancy-no-eth': 'Use the checks-effects-interactions pattern or a reentrancy guard.',
82
+ 'unchecked-lowlevel': 'Check the return value of low-level calls.',
83
+ 'unchecked-send': 'Check the return value of send().',
84
+ 'tx-origin': 'Use msg.sender instead of tx.origin for authorization.',
85
+ 'suicidal': 'Remove or protect selfdestruct with access control.',
86
+ 'arbitrary-send': 'Restrict who can call functions that send Ether.',
87
+ 'locked-ether': 'Add a withdrawal function for locked Ether.',
88
+ 'solc-version': 'Use a fixed Solidity version pragma.',
89
+ };
90
+ return recommendations[check] ?? 'Review and address this finding.';
91
+ }
92
+ //# sourceMappingURL=slither.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slither.js","sourceRoot":"","sources":["../../src/analyzer/slither.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Finding } from '../../analyzer/index.js';
2
+ export interface AnalyzeCommandResult {
3
+ passed: boolean;
4
+ findings: Finding[];
5
+ }
6
+ export declare function analyzeCommand(file: string): Promise<AnalyzeCommandResult>;
7
+ //# sourceMappingURL=analyze.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/analyze.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAUvD,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAgEhF"}