Hovibby/REPORT-CARD

GitHub: Hovibby/REPORT-CARD

面向 Soroban 智能合约的安全评级注册表,融合审计证明、WASM 分析与源码验证生成 A–F 评级,供钱包在签名前进行安全预警。

Stars: 0 | Forks: 0

# 📋 成绩单 [![License: Apache-2.0](https://img.shields.io/badge/License-Apache--2.0-blue.svg)](LICENSE) [![Data: CC-BY-4.0](https://img.shields.io/badge/Data-CC--BY--4.0-green.svg)](LICENSE) [![Stellar Network](https://img.shields.io/badge/Network-Stellar%20Testnet-purple.svg)](https://stellar.org) [![Project](https://img.shields.io/badge/Suite-Trust--Oracle%20%233%20of%205-orange.svg)]() 在你的钱包签名之前,它会询问一个问题: ``` is_safe(contract_id) → { grade: "A", upgradeable: false, attestation_count: 2, … } ``` 审计证明 + WASM 静态分析 + 可复现构建源码验证 —— 融合为一个单一的 **A–F 评级**,任何钱包、合约或 dApp 都能通过一次调用读取。 ## 为什么需要它 Soroban 尚处于早期阶段。用户经常对无法阅读的合约签署交易。合约可能被悄悄升级、隐藏管理员后门,或者完全未经审计 —— 并且没有一个共享的地方来回答*“与之交互安全吗?”* Report Card 就是这个共享的地方。它是基础设施,而不是一个应用。 ## 10 秒演示 | 场景 | 评级 | 你将看到 | |---|---|---| | 粘贴一个暗中可升级的合约 | **D** | 🔴 “管理员可以随时替换此代码。” | | 粘贴一个完全审计过且验证了源码的合约 | **A** | ✅ 审计员名称 · WASM hash · 置信度 95% | ## 架构 三个严格解耦的层级。每一层都可以独立替换。 ``` ┌──────────────────────────────────────────────────────────────────┐ │ LAYER 3 — Dashboard (Next.js 14 · Tailwind · app router) │ │ │ │ / Homepage — search bar + recent contracts │ │ /contract/[id] Full report: grade · evidence · attest. │ │ /auditor Wallet-connected attestation portal │ │ /api/safety?id= CORS-open JSON endpoint for wallets │ └──────────────────────────┬───────────────────────────────────────┘ │ fetchSafetyRecord() / /api/safety ┌──────────────────────────▼───────────────────────────────────────┐ │ LAYER 2 — Engine (Node.js 20 · TypeScript · ESM) │ │ │ │ ingest.ts Pull WASM via Soroban RPC getLedgerEntries │ │ scoring.ts 5-signal weighted rubric → A–F grade │ │ verify.ts Reproducible Docker build → hash comparison │ │ relayer.ts Sign & submit set_flags() on-chain │ │ index.ts Scheduler (cron) + CLI entry-point │ └──────────────────────────┬───────────────────────────────────────┘ │ set_flags() · submit_attestation() ┌──────────────────────────▼───────────────────────────────────────┐ │ LAYER 1 — Contract (Rust · Soroban SDK 21 · WASM) │ │ │ │ initialize() Bootstrap admin + relayer │ │ is_safe() ← READ Returns SafetyRecord (grade + evidence) │ │ register_auditor() Admin onboards auditor with reputation │ │ deactivate_auditor() Admin slashes / removes auditor │ │ submit_attestation() Auditor signs verdict bound to WASM hash │ │ set_flags() Relayer writes WASM analysis flags │ │ event: graded Emitted on every grade change │ └──────────────────────────────────────────────────────────────────┘ ``` ## 评分标准 每个评级都是确定性的,并且可以从公开的链上数据中得到充分解释。 | 信号 | 权重 | 衡量内容 | |---|:---:|---| | 已签名的审计证明 | **30%** | 受认可的审计员对精确的 WASM hash 进行签名;按声誉加权 | | 源码验证 | **25%** | 所声明仓库的可复现构建与链上 WASM hash 相匹配 | | 可升级性暴露 | **20%** | 在 WASM 字节码中检测到由管理员控制的代码替换路径 | | 管理员权力范围 | **15%** | 由单一密钥控制的无限制铸造 / 冻结 / 抽离权限 | | 成熟度与使用情况 | **10%** | 合约年龄 · 独立用户数 · 原生 XLM TVL 代理指标 | **评级阈值:** A ≥ 80 · B ≥ 65 · C ≥ 50 · D ≥ 35 · F < 35 ## 仓库结构 ``` report_card/ │ ├── packages/ │ └── types/ ← @reportcard/types (shared source of truth) │ └── src/index.ts GradeLetter, SafetyRecord, WalletKit, │ NetworkConfig, SIGNAL_WEIGHTS, helpers │ ├── contracts/ │ └── report_card/ ← @reportcard/contract (Soroban / Rust) │ ├── src/ │ │ ├── lib.rs Registry contract (all 6 functions) │ │ └── test.rs 14 unit + integration tests │ └── Cargo.toml │ ├── engine/ ← @reportcard/engine (Node.js / TypeScript) │ ├── src/ │ │ ├── index.ts Scheduler + CLI entry-point │ │ ├── ingest.ts Soroban RPC WASM pull + Horizon metadata │ │ ├── scoring.ts 5-signal weighted rubric │ │ ├── verify.ts Reproducible-build source verification │ │ └── relayer.ts On-chain verdict submission │ ├── .env.example │ └── package.json │ ├── web/ ← @reportcard/web (Next.js 14) │ ├── app/ │ │ ├── page.tsx Homepage (search + stats + recent) │ │ ├── contract/[id]/ Full safety report │ │ ├── auditor/ Wallet-connected attestation portal │ │ └── api/safety/ REST endpoint for wallets │ ├── components/ │ │ ├── GradeCard.tsx Big letter + flag pills + upgrade warning │ │ ├── EvidenceChecklist.tsx Pass/fail per signal with weights │ │ ├── AttestationList.tsx On-chain auditor attestations │ │ ├── SearchBar.tsx Contract ID lookup │ │ ├── HeroStats.tsx Registry aggregate stats │ │ ├── RecentContracts.tsx Grade grid from seed data │ │ └── WalletButton.tsx Freighter connect/disconnect │ ├── lib/ │ │ ├── registry.ts Soroban RPC view calls + write tx │ │ ├── useWallet.ts Wallet kit React hook (typed WalletKit) │ │ ├── gradeUtils.ts Tailwind colour helpers per grade │ │ ├── seedContracts.ts Demo contracts for homepage │ │ ├── seedAttestations.ts Demo attestations for AttestationList │ │ └── knownAuditors.ts Demo auditor identities │ ├── .env.local.example │ └── package.json │ ├── sdk/ ← @reportcard/sdk (isomorphic client) │ ├── index.ts ReportCard class · isSafe() · http+rpc │ ├── package.json │ └── tsconfig.json │ ├── data/ ← CC-BY-4.0 open dataset │ ├── contracts.json Contracts processed by the engine │ └── README.md │ ├── scripts/ │ └── deploy.sh 5-step Testnet build + deploy + init │ ├── package.json ← npm workspaces root ├── .gitignore ├── LICENSE ← Apache-2.0 (code) / CC-BY-4.0 (data) └── README.md ``` ## 快速开始 ### 前置条件 ``` # Rust + WASM target rustup target add wasm32-unknown-unknown # Stellar CLI cargo install --locked stellar-cli # Node.js 20+ (检查: node --version) # npm 10+ (检查: npm --version) ``` ### 1 — 为 Testnet 身份充值 ``` stellar keys generate me --network testnet stellar keys fund me --network testnet ``` ### 2 — 部署 registry 合约 ``` bash scripts/deploy.sh # 打印: CONTRACT_ID = C… ``` ### 3 — 配置环境 ``` # Dashboard cp web/.env.local.example web/.env.local # 填写: NEXT_PUBLIC_REGISTRY_CONTRACT_ID= # Engine cp engine/.env.example engine/.env # 填写: REGISTRY_CONTRACT_ID= # RELAYER_SECRET= ``` ### 4 — 安装依赖项 ``` npm install --legacy-peer-deps # installs all workspaces at once ``` ### 5 — 启动仪表板 ``` npm run dev:web # → http://localhost:3000 ``` ### 6 — 运行引擎(演示可选) ``` npm run dev:engine -- --once # analyse data/contracts.json once and exit npm run dev:engine # start the 5-minute scheduler ``` ## Smart-contract API 参考 所有函数均位于已部署的 registry 合约上。 ### 读取(pure,无费用) #### `is_safe(contract_id: Address) → SafetyRecord` 返回任何 Soroban 合约的完整安全记录。 对于从未被分析过的合约,返回默认的 **F** 记录。 ``` { "grade": { "letter": "A", "score": 87, "numeric": 5 }, "upgradeable": false, "source_verified": true, "wasm_hash": "aa…aa", "attestation_count": 2, "admin_power": false, "maturity_score": 8 } ``` #### `get_auditor(auditor: Address) → Option` 返回审计员记录(reputation、meta_hash、active 状态)或 `None`。 #### `get_attestation(contract_id, auditor) → Option` 返回特定审计员对某合约的证明,或 `None`。 ### 写入(受限) | 函数 | 授权 | 目的 | |---|---|---| | `initialize(admin, relayer)` | admin(仅一次) | 初始化 registry | | `register_auditor(auditor, reputation, meta_hash)` | admin | 接入审计员(rep 1–100) | | `deactivate_auditor(auditor)` | admin | 削减 / 禁用审计员 | | `submit_attestation(auditor, contract_id, wasm_hash, verdict, confidence, sig)` | auditor (`require_auth`) | 绑定至 WASM hash 的签名结论 | | `set_flags(contract_id, wasm_hash, upgradeable, source_verified, admin_power, maturity_score)` | relayer | 写入客观的 WASM 分析标志 | ## SDK — 单行集成 安装: ``` npm install @reportcard/sdk ``` ### TypeScript / JavaScript(HTTP 传输 —— 零额外依赖) ``` import { ReportCard } from '@reportcard/sdk'; const rc = new ReportCard({ transport: 'http', apiUrl: 'https://your-dashboard.example.com', }); const g = await rc.isSafe(contractId); if (g.gradeNumeric <= 2 || g.upgradeable) { showWarning(`Grade ${g.grade}: ${g.explanation}`); } ``` ### TypeScript / JavaScript(RPC 传输 —— 直连 Soroban) ``` import { ReportCard } from '@reportcard/sdk'; const rc = new ReportCard({ transport: 'rpc', network: 'testnet', registryContractId: 'C…', }); const g = await rc.isSafe(contractId); ``` ### Soroban 跨合约守卫(Rust) ``` // Only call contracts that are sufficiently safe. let g = reportcard::Client::new(&env, ®ISTRY_ID).is_safe(&target_contract); assert!(g.grade.numeric >= 4, "target contract is below grade B"); ``` ### HTTP endpoint(钱包、脚本、curl) ``` curl "https://your-dashboard.example.com/api/safety?id=CXXXXX…" ``` ``` { "contractId": "CXXXXX…", "record": { "grade": { "letter": "B", "score": 71, "numeric": 4 }, "upgradeable": false, "source_verified": true, "attestation_count": 1, "admin_power": false, "maturity_score": 6 } } ``` ## 引擎环境变量 | 变量 | 必需 | 默认值 | 描述 | |---|:---:|---|---| | `STELLAR_NETWORK` | | `testnet` | `testnet` \| `mainnet` \| `futurenet` | | `REGISTRY_CONTRACT_ID` | ✓ | — | 已部署的 registry 合约 ID | | `RELAYER_SECRET` | ✓ | — | Relayer 的 Stellar 密钥 | | `SOROBAN_RPC_URL` | | SDF testnet | Soroban RPC endpoint | | `HORIZON_URL` | | SDF testnet | Horizon API endpoint | | `ENGINE_INTERVAL_MS` | | `300000` | 重新扫描间隔(毫秒,5 分钟) | | `ENABLE_DOCKER_VERIFY` | | `true` | 使用 Docker 进行可复现构建 | | `LOG_LEVEL` | | `info` | `error` \| `warn` \| `info` \| `debug` | 复制 `engine/.env.example` → `engine/.env` 并填入所需的值。 ## 仪表板环境变量 | 变量 | 必需 | 默认值 | 描述 | |---|:---:|---|---| | `NEXT_PUBLIC_REGISTRY_CONTRACT_ID` | ✓ | — | 已部署的 registry 合约 ID | | `NEXT_PUBLIC_NETWORK` | | `testnet` | `testnet` \| `mainnet` | | `NEXT_PUBLIC_SOROBAN_RPC_URL` | | SDF testnet | Soroban RPC endpoint | | `NEXT_PUBLIC_HORIZON_URL` | | SDF testnet | Horizon API endpoint | 复制 `web/.env.local.example` → `web/.env.local` 并填入所需的值。 ## 威胁模型与反滥用 | 攻击向量 | 缓解措施 | |---|---| | **伪造审计员身份** | 审计员由管理员以声誉权重接入。低声誉证明几乎不会影响评级。 | | **证明哈希篡改** | 证明在加密层面绑定到精确的 WASM hash。使用新代码重新部署会使旧评级失效。 | | **检查时/使用时升级** | 可升级合约将被永久标记为红旗并在评级中设限,无论其审计状态如何。 | | **源码仓库不匹配作弊** | 可复现构建必须在字节层面匹配链上 WASM hash,否则 `source_verified` 将保持为 `false`。 | | **走过场式审计** | 需要多个独立的证明才能达到 A 级。声誉可以通过 `deactivate_auditor` 被削减。 | ## 去中心化路线 目前的设计为简便起见使用了单一的 relayer 密钥。该授权模型旨在进行扩展: 1. **现在** —— 在 `initialize()` 时设置单一的 relayer 密钥。 2. **下一步** —— 通过更新 relayer 地址,替换为多签账户(例如 3-of-5 验证者集合)。 3. **未来** —— 由 Auditor DAO 管理声誉权重和争议解决。 ## 开源与公共物品原则 - **可解释** —— 每一个评级都可以从公开的链上数据中复现。仪表板展示了每个信号背后的确切证据。 - **组合优先** —— 全部的价值都在 `is_safe()` 调用中。SDK 和 HTTP endpoint 让集成只需一行代码。 - **非黑名单** —— 评分是透明、可争议且可申诉的。它是基础设施,而不是监控工具。 - **双重许可** —— 代码采用 Apache-2.0 许可;种子数据集采用 CC-BY-4.0 许可。两者的设计初衷都是为赠款周期之后持续服务。 ## 路线图 - [ ] 管理 reputation 权重和争议解决的 Auditor DAO - [ ] 自动为评级提供输入的形式化属性检查(拒绝无限制的铸造) - [ ] Wallet-SDK 合作伙伴关系,让 `is_safe()` 成为默认的签名前检查 - [ ] 面向 dApp 前端的评级徽章组件 - [ ] 削减机制:链上证明“安全”结论是错误的 ## 贡献 1. Fork 本仓库并基于 `main` 创建分支。 2. 将你的合约添加到 `data/contracts.json`(见 `data/README.md`)。 3. 对于 Rust 合约:在 `contracts/report_card/` 中运行 `cargo test` 后再提交 PR。 4. 对于 TypeScript:从根目录运行 `npm run lint --workspaces --if-present`。 5. 提交 PR —— 描述应说明修改了什么以及测试了什么。 ## 许可证 | 范围 | 许可证 | |---|---| | 所有源代码 (`contracts/`, `engine/`, `web/`, `sdk/`, `packages/`, `scripts/`) | [Apache-2.0](LICENSE) | | 开放数据集 (`data/`) | [CC-BY-4.0](LICENSE) |
标签:MITM代理, Soroban, Stellar, 云安全监控, 区块链安全, 可视化界面, 智能合约, 自动化攻击, 请求拦截, 静态分析