---
name: agentminer
description: "AgentMiner v8 (vault source v8): Agent ID gate + PoW ritual; solveAndMine with Trigger fee; mult via Flap Trigger; 1%/10min release; 25% per-period distribution cap. For Binance Agentic Wallet agents."
---

# AgentMiner Skill（币安 Agentic Wallet）

**AgentMiner** 是 Flap 金库玩法：持有 **Agent ID** 的 EOA 完成 PoW「仪式」后烧税币换衰减算力，从税池 BNB 中按算力比例领取（每 10 分钟释放约 1%；单地址每期最多拿该期释放量的 25%，超出留池）。

用户只会说「帮我挖矿」时：按下列步骤自动做完，**每笔签名前用中文向用户确认烧币数量与 Trigger 费用**；不要索取私钥/助记词。

---

## 配置（部署后填写）

```
VAULT_ADDRESS=0x…          # AgentMinerVault 代理地址
TOKEN_ADDRESS=0x…          # 税币 taxToken（vault.taxToken()）
TRIGGER_ADDRESS=0xcf4EE25035CF883895110f367F5BA8172416a7F9  # 主网不可变；亦可 vault.triggerService()
CHAIN_ID=56                # BSC
```

依赖：求解器 `solve.js` 和 `package.json` 与本文件放在同一个公开目录（把本文件链接末尾的 `skill.md` 换成 `solve.js` / `package.json` 即可下载）。下载到同一个本地文件夹后执行 `npm install`（只依赖 ethers，版本锁定为 6.17.0）。

---

## 前提条件

1. **币安 Agentic Wallet**，且 `tx.origin == msg.sender`（必须是 EOA 亲自签，不能合约代签）。
2. 该地址已有 **Agent ID**（`.ai` / SPACE ID 体系；`vault.isAgent(wallet)` 为 true）。
3. 钱包里有：
   - 税币 ≥ 计划烧币量（从任何市场买入即可，不必本金库内盘）；
   - **BNB**：普通 gas + **Trigger 费**（约 0.0002 BNB，以 `getFee()` 为准）。
4. 金库未 `paused`；若冷启动未开，等 `releasesUnlocked()` 或凑够矿工数（不影响先挖，只影响释放）。

---

## 端到端步骤

### 0) 读状态（给用户一句中文摘要）

- `vault.paused()` / `vault.releasesUnlocked()` / `vault.stats()`
- `vault.minMine()` / `vault.maxMine()` / `vault.taxToken()`
- `vault.isAgent(user)`；可选 `vault.verifier()`

若 `!isAgent`：告知「请先在币安 Agentic Wallet 领取/绑定 Agent ID」，停止。

### 1) 定烧币量 `amount`

- 默认建议：`max(minMine, 用户指定)`，且 `amount <= maxMine`、`amount <= token.balanceOf(user)`。
- **首次**建议只烧 `minMine`（或用户同意的小额）。
- 用中文展示：`将烧 {amount} 枚税币（不可逆）+ Trigger 费约 {fee} BNB + gas`，等用户同意再继续。

### 2) Approve（只授权本次烧币数量）

```
token.approve(VAULT_ADDRESS, amount)   // amount = 本次 solveAndMine 要烧的数量，精确等于，不多给
```

- **只授权本次要烧的数量**：不要 approve 无限额度（`MaxUint256`），也不要为了「以后不用再 approve」而授权比本次更多的数量。
- 每次挖矿前读 `allowance(user, VAULT_ADDRESS)`：若正好 `>= amount`（例如上次授权后没用掉）可跳过；若不足，就 `approve(VAULT_ADDRESS, amount)` 设成本次数量。
- 若发现现有 allowance 明显大于本次数量（例如以前授权过无限额度），告诉用户，并建议先 `approve(VAULT_ADDRESS, amount)` 把授权降到本次数量。
- `solveAndMine` 成功后，本次授权会被 `transferFrom` 用掉。

### 3) 读题 `challengeOf(user)`

返回：`(round, seed, diff, alreadySolved, hasUnusedPermit, permitRound)`

- `diff` = 当前难度（通常 12–24）。**位数以返回值为准，不要写死 16。**
- 若 `alreadySolved && !hasUnusedPermit`：本轮已用过，**等下一轮**（约 `roundBlocks` 块，默认 ~200 块 / ~90s）或用上一轮未用许可。
- `seed` 来自链上 `blockhash`；若报错 `Seed unavailable / 种子不可用`：等几块再读。

### 4) 解 PoW nonce（Worker / Node）

合约校验（与 `checkProof` 一致）：

```solidity
uint256(keccak256(abi.encode(seed, agent, nonce))) >> (256 - difficulty) == 0;
```

使用同目录的 `solve.js`（推荐 Web Worker 同逻辑）：

```bash
# 先把 solve.js 和 package.json 下载到同一个文件夹
npm install
node solve.js <seed> <userAddress> <diff>
# 只 stdout 打印十进制 nonce
```

约束：

- 时间预算建议 10–30s；超时或轮次变化则 **重新 `challengeOf`**。
- 许可可覆盖 **本轮 + 上一轮**；若解题中 `currentRound` 已超过 `round+1`，丢弃 nonce 重解。
- **禁止**把 nonce 混进倍数随机（倍数只由 Trigger 回调的 `blockhash` 决定）。

自检向量（`node solve.js --selftest`，并由 `forge test --match-path test/SolveJsVector.t.sol` 对照合约）：

- seed `0x1111…1111`，agent `0x…00A1`，diff `12` → nonce `2267`。

### 5) 读 Trigger 费并一键挖矿

```
fee = IFlapTriggerService(vault.triggerService()).getFee()
# 切勿写死；合约侧还有 MAX_TRIGGER_FEE 上限裁剪
ticketId = vault.solveAndMine{value: fee}(nonce, amount)
```

- 多余 `msg.value` 会退回用户。
- **Gas**：每笔交易（approve / solveAndMine / claim）发送前先 `estimateGas`，在估算值上加约 20% 余量作为 gasLimit，**不要写死 gasLimit**。票积压时，第一个碰到合约的交易要顺带激活到期票，gas 会明显变高；若估算失败或交易因 gas 不足失败，重新估算后再发，不要盲目重试同一 gasLimit。
- 成功后票先按 **1x**；`startPeriod = 当前周期+1`，**从下一释放周期起计收益**。
- 倍数由 Flap Trigger 回调揭晓（约延迟 `TRIGGER_DELAY` 秒级）；迟迟未揭晓时可 `finalizeTimedOut` → 锁 1x：**只对自己的票**，满 1 小时（`FINALIZE_TIMEOUT`）即可调用；别人的票要满 24 小时（`PUBLIC_FINALIZE_TIMEOUT`）才能调用（未满 24 小时去调会报 `Not timed out / 未超时`）。

### 6) 查倍数 / 可领

- `vault.multiplierOf(ticketId)`：`0` = 未揭晓；否则为 `multX100`（100=1x … 200=2x）。
- `vault.getTicket(id)`：`finalized` / `activated` / `burned` / `multX100`。
- `vault.pendingOf(id)` / `vault.pendingOfOwner(user)`：可领 BNB（视图会模拟 catch-up，与 poke 后一致）。
- `vault.capWithheld()`：因 25% 上限留池的 last/total。

### 7) 领取 `claim`

```
vault.claim([id1, id2, ...])   // 仅校验票归属，不要求当前仍是 Agent
```

先展示 `pendingOfOwner`，用户同意再发交易。

---

## 报错信息 → 中文动作

合约用 require 报错字符串（中英双语），按字符串匹配：

| 错误 | 含义 | 建议动作 |
|------|------|----------|
| `Not agent / 非 Agent 钱包` | 无 Agent ID | 引导去币安 Agentic Wallet 领 ID |
| `Not EOA / 非 EOA` | 非 EOA / 被合约转发 | 用钱包本体直接签 |
| `Paused / 已暂停` | 金库暂停 | 告知稍后再试（Guardian 暂停中） |
| `Bad amount / 数量不合法` | 烧币量越界 | 改到 `[minMine, maxMine]` |
| `Seed unavailable / 种子不可用` | 题目 seed 块哈希不可用 | 等 1–2 块再 `challengeOf` |
| `Bad proof / 证明无效` | nonce 错或轮次不对 | 重读题目重解 |
| `Already solved / 本轮已解` | 本轮已解过 | 等下一轮 |
| `No permit / 无许可` / `Permit used / 许可已用` | 无可用许可 | 先 solve 或等新轮 |
| `Permit expired / 许可过期` | 许可超出本轮+上轮 | 重解当前轮 |
| `Insufficient trigger fee / 手续费不足` | `msg.value` < getFee() | 按最新 `getFee()` 重发 |
| `Nothing to claim / 无可领` | 无可领 | 等释放或 poke 后再查 pending |
| `Transfer failed / 转账失败` | 转账/退款失败 | 查余额与代币是否打到死地址异常 |
| `Not your ticket / 非你的票` | 票不属于你 | 检查 ticketsOf(user) |
| `Already finalized / 已揭晓` | 倍数已揭晓 | 无需再 finalize |
| `Not timed out / 未超时` | 未到超时时间（自己的票 1h，别人的票 24h） | 等 Trigger，或自己的票满 1h 后再 finalizeTimedOut |

ERC20 `transferFrom` 失败：检查 approve/余额。用户拒签：停止并说明。

---

## 向用户汇报（白话中文模板）

挖矿成功：
> 已烧 {amount} 枚税币，票号 #{id}。当前倍数：{未揭晓 / X.xx x}。预计从下一 10 分钟周期起计收益；单地址每期最多拿该期释放的 25%。可领约 {pending} BNB。需要我帮你领取吗？

失败：
> 失败原因：{上表中文}。下一步：{动作}。

---

## 安全规则（必须遵守）

1. **永不**索取或转发私钥、助记词、Seed Phrase、Keystore。
2. 签名前展示：**烧币量、Trigger 费、金库地址、代币地址**；用户明确同意再发。
3. 首次只建议小额（≥ `minMine` 的最小档）；**禁止**未经同意自动循环烧币。
4. 说明：烧币不可逆；算力随时间衰减（配置约 **每小时量级衰减 1%** 档，以 `decayKeepPpm`/`decayPeriods` 为准）；**每期分配有 25% 地址上限**，大户触发时他人当期份额也可能同比缩小，差额留池。
5. `solveAndMine` 的 `msg.value` 只用于 Trigger 费，不是「加仓 BNB」。
6. 发任何交易前先 `estimateGas`（加约 20% 余量），不要写死 gas limit。

---

## 常用只读 ABI（名称保持英文）

```
isAgent(address) → bool
challengeOf(address) → (round, seed, diff, alreadySolved, hasUnusedPermit, permitRound)
checkProof(bytes32 seed, address agent, uint256 nonce) → bool
minMine() / maxMine() / taxToken() / triggerService() / paused() / releasesUnlocked()
pendingOf(uint256) / pendingOfOwner(address) / ticketsOf(address) / getTicket(uint256)
multiplierOf(uint256) / capWithheld() / pendingCapWithheld() / stats()
```

写入：

```
solveAndMine(uint256 nonce, uint256 amount) payable → uint256 id
claim(uint256[] ids) → uint256 amount
requestFinalizeTrigger() payable   // 揭晓卡住时可自费重约；揭晓队列为空时不预约，费用全额退回
finalizeTimedOut(uint256 id)      // 超时锁 1x：票主本人满 1h，其他人满 24h
```

Trigger：`IFlapTriggerService.getFee() → uint256`（地址 = `triggerService()`）。

---

## 求解器文件

- `solve.js`（与本文件同目录）— Node / Worker 可用；`npm run selftest` 自检。
- 开发者合约对照测试：`forge test --match-path test/SolveJsVector.t.sol`（金库源码仓库内）。
