Hovibby/REPORT-CARD
GitHub: Hovibby/REPORT-CARD
面向 Soroban 智能合约的安全评级注册表,融合审计证明、WASM 分析与源码验证生成 A–F 评级,供钱包在签名前进行安全预警。
Stars: 0 | Forks: 0
# 📋 成绩单
[](LICENSE)
[](LICENSE)
[](https://stellar.org)
[]()
在你的钱包签名之前,它会询问一个问题:
```
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, 云安全监控, 区块链安全, 可视化界面, 智能合约, 自动化攻击, 请求拦截, 静态分析