dmustapha/backstop
GitHub: dmustapha/backstop
Backstop 是一个面向自主 AI agent 的仅限否决的链上共同签名者,通过实时交易模拟和分级判决引擎在资金离开前拦截恶意抽水交易。
Stars: 0 | Forks: 0
# Backstop:一个链上共同签名者,用于否决你的 AI agent 不应该执行的交易
Backstop 是一个位于自主 agent 和链之间的守护者。agent 钱包即将执行的每一笔交易都会被拦截,并根据实时的 Mantle 状态进行模拟,然后在哪怕一个 wei 离开之前,对其进行共同签名或否决。确定性规则可以在一秒钟内阻止已知的恶意抽水合约;灰色地带的调用则升级到撰写意见书的 LLM。每一次否决和共同签名都会作为真实的链上事件进行结算,因此整个决策轨迹都是可审计的。
[](https://www.typescriptlang.org/)
[](https://nextjs.org/)
[](https://soliditylang.org/)
[](LICENSE)
[]()
**在线演示:** [backstop-alpha.vercel.app](https://backstop-alpha.vercel.app)

## 在线演示
**[backstop-alpha.vercel.app](https://backstop-alpha.vercel.app)**
打开实时控制台查看判决流,然后前往沙盒并粘贴任何 Mantle Sepolia 交易即可获得真实的模拟判决。验证页面上的每一张卡片都直接链接到区块浏览器。
## 什么是 Backstop?
自主 agent 已经在转移真实的资金。危险的失败不在于系统崩溃,而在于 agent 因为被注入了指令而自信地批准了一个恶意抽水合约。Backstop 是一个仅限否决的记录共同签名者:它像公证人阅读文件一样阅读交易,模拟真实的余额和授权额度变动,将 agent 陈述的意图与实际的 calldata 进行权衡,并拒绝为伪造内容签名。
守护者本身不持有任何消费能力。它只能共同签名或否决,因此它最坏的情况也只是阻止交易,绝不会转移资金。桌面的双方都具有链上身份:守护者(ERC-8004 agentId 182)和被守护的账户(agentId 183)。
## 截图
| 实时控制台 | 交易沙盒 |
|------|------|
|  |  |
| **记录证据** | |
|  | |
## 功能
- **仅限否决的共同签名者**:守护者只能阻止或共同签名,绝不能消费。被攻陷的守护者无法抽干其保护的账户。
- **实时模拟,零部署**:在签署任何内容之前,使用带有代码覆盖的 `eth_call` 来追踪针对当前链状态的实时余额和授权额度变动。
- **分级判决引擎**:确定性底线为正常流量共同签名,静态已知恶意抽水合约列表在一秒钟内否决被标记的授权,只有真正的灰色地带调用才会到达 LLM。
- **意图与 calldata 校验**:将 agent 陈述的意图与 calldata 的实际执行操作进行权衡,从而捕获意图注入,即自信的 agent 批准了它被诱骗执行的恶意抽水合约。
- **可插拔 LLM**:Tier-B 裁决器可通过任何兼容 OpenAI 的 endpoint 运行,并具有经验证的直接 Anthropic 路径作为备选。
- **一切皆留痕**:每次否决都会触发链上 `Blocked` 事件,每次批准都会触发 `CoSigned` 事件。控制台显示的是真实事件,绝不是仅限于 UI 的标签。
- **三行代码集成**:`backstop.wrap(account)` 可将现有的 agent 钱包置于共同签名者之后。
## 工作原理
```
agent wallet Backstop keeper Mantle Sepolia
──────────── ─────────────── ──────────────
│ proposes tx │ │
├─────────────────────────────▶│ │
│ │ eth_call sim (code override) │
│ ├──────────────────────────────────▶│
│ │◀── balance + allowance deltas ────┤
│ │ │
│ ┌────────────┴────────────┐ │
│ │ FLOOR: clean → cosign │ │
│ │ TIER-A: drainer → veto │ (deterministic) │
│ │ TIER-B: gray → LLM │ (intent vs calldata)│
│ └────────────┬────────────┘ │
│ │ COSIGN → EIP-712 guardian sig │
│ ├──────────────────────────────────▶│ CoSigned event
│ │ VETO → on-chain block │
│ ├──────────────────────────────────▶│ Blocked event
│◀───── verdict (SSE) ──────────┤ │
```
**分级决策。** 判决引擎按顺序解析:确定性底线为仅涉及允许列目标且不转移任何资金的交易共同签名;Tier-A 否决任何向已知恶意抽水合约列表上的地址进行的授权或转账;Tier-B 将所有模棱两可的内容升级到 LLM,后者会返回带有置信度和书面理由的结构化 COSIGN/VETO。当 LLM 不可用时,Tier-B 会倒向审查(VETO),绝不倒向签署。
**共同签名机制。** COSIGN 是守护者密钥对确切调用生成的 EIP-712 签名。链上的 `BackstopAccount` 仅执行带有针对该精确 `(to, value, data, nonce)` 元组的有效、未过期的守护者签名的调用,因此重放或篡改的调用将回滚。守护者密钥可以签名和否决,但合约没有为其提供任何转移资金的路径。
## 技术栈
| 层级 | 技术 |
|-------|-----------|
| 合约 | Solidity 0.8, Foundry, ERC-8004 identity |
| Keeper | Node + TypeScript, viem, 原生 `http` (REST + SSE) |
| 模拟 | Mantle Sepolia 上带有状态/代码覆盖的 `eth_call` |
| LLM | 兼容 OpenAI 的 endpoint (主要) + Anthropic SDK (备选) |
| 仪表盘 | Next.js 15, React 19, Tailwind v4 |
| 链 | Mantle Sepolia (chainId 5003) |
## 测试
```
# Contracts
cd contracts && forge test
# 结果: 9/9 通过
# Keeper verdict engine
npm run test:keeper
# 结果: 7/7 通过
```
合约测试涵盖了共同签名执行路径、仅限守护者的否决、重放拒绝、恢复超时,以及一个模糊测试证明,该证明表明只有有效的守护者签名才能执行,且守护者本身无法转移资金。Keeper 测试涵盖了确定性底线、Tier-A 恶意抽水合约否决、意图与 calldata 比对路径,以及 LLM 宕机时倒向审查的行为。
## 体验一下(3 分钟)
1. 打开 **实时控制台** 观看判决流。每张卡片都是一个真实的链上 `Blocked` 或 `CoSigned` 事件,包含层级、理由及其测量的授权额度变动。
2. 打开 **沙盒** 并粘贴任何 Mantle Sepolia 交易(`to`、`value`、`data`),或使用预填的被守护账户。添加一行意图说明。
3. 提交。Backstop 会在实时 Mantle 上模拟调用并返回判决。在允许列出的 DEX 上进行的干净兑换会在底层得到共同签名;对已知恶意抽水合约列表的授权会在一秒钟内被 Tier-A 否决;未知合约调用会升级到 LLM,这需要几秒钟的时间来撰写意见。
4. 打开 **证据** 页面,跟随每一个判决直达区块浏览器。
### 网络
| 字段 | 值 |
|-------|-------|
| 网络 | Mantle Sepolia |
| Chain ID | 5003 |
| RPC URL | `https://rpc.sepolia.mantle.xyz` |
| 浏览器 | `https://sepolia.mantlescan.xyz` |
| 水龙头 | `https://faucet.sepolia.mantle.xyz` |
## API 参考
Keeper 暴露了一个小型的 HTTP 接口。CORS 是开放的,因此仪表盘可以直接从浏览器与它通信。
| 方法 | Endpoint | 描述 |
|--------|----------|-------------|
| `GET` | `/verdicts?limit=N` | 最近的判决,最新优先 |
| `GET` | `/events` | Server-Sent Events 流;每个新判决一条消息 |
| `POST` | `/simulate` | 用于调用的只读判决。模拟并裁决,从不广播(`txHash: null`) |
| `POST` | `/propose` | 真实提交一个调用。VETO 会触发链上的 `Blocked` 事件;COSIGN 将共同签名并执行 |
**请求体**(`/simulate` 和 `/propose`):
```
{
"to": "0x18bf06FB248Bd12D80734F4E49b0Ef743Bd151B8",
"value": "0",
"data": "0x095ea7b3...",
"intent": "approve the router to swap 2 WMNT"
}
```
**判决响应:**
```
{
"id": "v_19",
"decision": "VETO",
"tier": "B",
"reasons": ["intent says swap, calldata approves an unknown spender"],
"deltas": {
"nativeSelfDelta": "0",
"tokenSelfDeltas": ["-2000000000000000000"],
"allowanceDeltas": ["+115792089237316195423570985008687907853269984665640564039457584007913129639935"],
"execOk": true
},
"llm": { "decision": "VETO", "confidence": 0.99, "reason": "...", "provider": "altllm" },
"confidence": 0.99,
"txHash": null,
"createdAt": 1718370000000
}
```
## 智能合约
| 合约 | 地址 | 描述 |
|----------|---------|-------------|
| `BackstopAccountFactory` | `0x46BA593Cd94a96ba6B6cbfA90681e8952935bEd7` | 部署一个被守护的账户并在一次调用中注册其 ERC-8004 身份 |
| `BackstopAccount` | `0x42D7bb229f0aB8BBEd38C7B2Fd974892F6B28919` | 被守护的智能账户;仅执行带有有效守护者共同签名的调用 |
| `IdentityRegistry` (ERC-8004) | `0x8004A818BFB912233c491871b3d84c89A494BD9e` | 守护者和被守护账户的链上身份 |
## 链上验证
下面的每个地址和哈希都在 Mantle Sepolia 上实时存在,并且可独立验证。该工厂已通过 Sourcify 验证。
| 项目 | 链接 |
|------|------|
| 工厂(Sourcify 已验证) | [`0x46BA…bEd7`](https://sepolia.mantlescan.xyz/address/0x46BA593Cd94a96ba6B6cbfA90681e8952935bEd7) |
| 被守护的账户(agentId 183) | [`0x42D7…8919`](https://sepolia.mantlescan.xyz/address/0x42D7bb229f0aB8BBEd38C7B2Fd974892F6B28919) |
| ERC-8004 IdentityRegistry | [`0x8004…BD9e`](https://sepolia.mantlescan.xyz/address/0x8004A818BFB912233c491871b3d84c89A494BD9e) |
| 否决:向被标记的恶意抽水合约进行恶意授权 | [Blocked 交易](https://sepolia.mantlescan.xyz/tx/0x53e43348a74799c7aedf717991b56e94e8a9766ee3941eeee3a1218b5f549b63) |
| 共同签名:在允许列出的 DEX 上的已结算兑换 | [CoSigned 交易](https://sepolia.mantlescan.xyz/tx/0x37f8ef0eae66edd62353012e4b3ea8b1cb9030d7112b4180fb8d363588ae5f74) |
| 否决:未知合约意图(LLM 层级) | [Blocked 交易](https://sepolia.mantlescan.xyz/tx/0xf83a34f4ea3fee884df8125f5b6788c140a4d6a3951483e87c965bc9d223673a) |
| 否决:意图与 calldata 不匹配(LLM 层级) | [Blocked 交易](https://sepolia.mantlescan.xyz/tx/0xca732869fc64ca229f4f424a55953a0613ac8db49f3675e2cfe22a50b363098d) |
## 本地运行
```
git clone https://github.com/dmustapha/backstop.git
cd backstop
npm install
# 1. 配置
cp .env.example .env # fill in RPC, keys, and deployed addresses
# 2. Contracts (可选: 上面的地址已经生效)
cd contracts && forge test && cd ..
# 3. 启动 keeper (REST + SSE 在 :8787)
npm run keeper
# 4. 初始化少量 verdict 历史 (真实的链上事件)
npm run seed
# 5. Dashboard
cd dashboard && npm install && npm run dev # http://localhost:3000
```
### 必需的环境变量
| 变量 | 描述 |
|----------|-------------|
| `MANTLE_RPC_URL` | Mantle Sepolia RPC(第三方用于写入;公共 RPC 用于模拟) |
| `GUARDIAN_KEY` / `GUARDIAN_ADDRESS` | Keeper 共同签名/否决密钥及其地址 |
| `DEMO_AGENT_KEY` / `DEMO_AGENT_ADDRESS` | 演示 agent 所有者密钥和地址 |
| `FACTORY_ADDRESS` | 已部署的 `BackstopAccountFactory` |
| `LLM_BASE_URL` / `LLM_API_KEY` / `LLM_MODEL` | 兼容 OpenAI 的 Tier-B 提供商 |
| `LLM_FALLBACK` / `ANTHROPIC_API_KEY` / `ANTHROPIC_MODEL` | 备选 LLM 路径 |
| `STATIC_DRAINERS` | 逗号分隔的已知恶意抽水合约地址 |
| `THREATINTEL_API_KEY` | 可选。留空将回退到已知恶意抽水合约列表(ethereum-lists) |
| `NEXT_PUBLIC_KEEPER_URL` | 仪表盘调用的 Keeper URL(在生产环境中设置为托管的 Keeper) |
有关完整的带注释列表,请参见 `.env.example`。
## 项目结构
```
backstop/
├── contracts/ Solidity: BackstopAccount, Factory, ERC-8004 interface, Foundry tests
├── keeper/ Verdict engine: simulator, classifier, tiered veto/cosign, LLM, REST + SSE server
├── dashboard/ Next.js 15 app: landing, live console, sandbox, evidence, agent history
├── agent/ Demo autonomous agent that proposes the transactions
├── sdk/ backstop.wrap() integration + ERC-8004 helpers
├── shared/ Chain config, addresses, ABIs, shared types
└── scripts/ Deploy, guardian registration, demo seeding
```
## 许可证
MIT。详见 [LICENSE](LICENSE)。
标签:AI代理, Web3安全, 交易模拟, 区块链, 智能合约, 自动化攻击, 资金安全