Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
jhfnetboy
left a comment
There was a problem hiding this comment.
代码审查 — PR #281 Fix/pr278 clean onto master
审查范围:Task Market UI (M6-M9)、Social Recovery、x402 payment flow、MetaMask guardian signing
🔴 严重问题(必须修复)
1. myAddress 角色判断不一致(功能性 Bug)
tasks/page.tsx 中 TaskCard 使用智能账户地址判断归属:
const myAddress = data.account?.address?.toLowerCase(); // YAA 智能账户但 tasks/[taskId]/page.tsx 用 EOA 地址判断角色:
const myAddress = (eoaAddress || (data.account?.address ?? "")).toLowerCase();合约存储的是 EOA 地址,所以任务列表页面 "(you)" 标签会始终不显示,或在 EOA = 智能账户时误显示。需统一用 EOA。
2. guardian-sign 中 acceptanceHash 校验被删除(安全问题)
原 passkey 路径有 if (!acceptanceHash) 守卫,这次重构时被删掉了。MetaMask 路径也没有这个守卫。isValidParams 仅控制按钮渲染,不阻止函数内部执行。URL 参数缺失时用户会对空 hash 签名,这是一个安全漏洞。
🟡 中等问题(建议本 PR 内修复)
3. EIP-2612 permit domain version 写死为 "2"
tasks/create/page.tsx 中 version: "2" 是硬编码,但 task-config.ts 已暴露 REWARD_TOKEN_VERSION 环境变量。USDC 在不同网络 version 不同,应使用配置值。
4. getPublicClient() 重复定义
task-config.ts 中已导出 getPublicClient(),但 TaskContext.tsx 又定义了同名本地函数且从未导入 task-config 版本。请删除本地版本,统一使用导出版本。
5. 任务加载只扫描最近 50,000 个区块
const fromBlock = latestBlock > 50000n ? latestBlock - 50000n : 0n;Sepolia ~12s/块,50,000 块约 7 天。更早的任务对用户不可见,且无分页。建议改用 subgraph 或后端索引。
6. TaskCreated 事件 topic 魔术字符串
topics: ["0xc703eeeb92d845b735c767a95c30a380646ad4c4824a3a100253d4bec0294e9e"],ABI 任何变动都会静默失效,应用 viem 的 encodeEventTopics 从 ABI 推导。
7. 手动关联 receipt 时同一值传入两个参数
await linkReceipt(task!.taskId, receiptInput.trim(), receiptInput.trim(), walletClient);
// ^ receiptId ^ receiptUri (同一值)receiptId 是 bytes32 标识符,receiptUri 是 URI 字符串,两者应该不同。
⚪ 轻微问题(可后续跟进)
8. TaskContext 所有 catch 块静默吞错 — 空 catch 导致链上错误完全不可调试,建议至少 console.error。
9. recovery/page.tsx 使用 confirm() — 阻塞浏览器 API,移动端 WebView 可能禁用,应换成 UI 内确认组件。
10. pendingRecovery: any 类型 — 应根据后端响应定义接口类型。
11. Recovery 多 guardian UX 假设同一浏览器 — Guardian 1 发起和 Guardian 2 支持都在同一 session,现实中是两个不同的人,缺少分享通知机制。
总结
| 级别 | 数量 |
|---|---|
| 🔴 严重(必须修复) | 2 |
| 🟡 中等(建议修复) | 5 |
| ⚪ 轻微(可后续跟进) | 4 |
请至少修复两个严重问题(EOA/智能账户角色判断不一致 + acceptanceHash 空签名漏洞)再 merge。
Integrate MyTask task market into YAA frontend under /tasks route. - Add TaskContext with contract read/write (createTask, acceptTask, submitWork, approveWork, finalizeTask, cancelTask) - Add task list page with All/Open/Mine/Claimed filter tabs and search - Add create task form with ERC-20 approve + createTask two-step flow - Add task detail page with role-based action buttons (Community/Taskor) - Add TaskEscrowV2 ABI and contract config (viem, env-driven chain) - Add task-types.ts (TaskStatus enum, ParsedTask), date-utils.ts - Inject TaskProvider in app layout; add Tasks nav (desktop + mobile) - Upgrade tsconfig target to ES2020 (BigInt literal support)
- Add /recovery page for on-chain social recovery flow (propose + execute) - Update guardian-sign page for QR-based guardian signature - Add social recovery E2E test docs and HTML test pages
…ipts T01: 积分余额展示 - TaskContext 新增 taskTokenBalance / loadTaskTokenBalance - Dashboard 新增 Task Reward Balance 卡片,实时读取 ERC-20 余额 T02: createTaskWithPermit - TASK_ESCROW_ABI 补充 createTaskWithPermit / ERC20 nonces / name / permit - 创建任务时优先走 EIP-2612 permit(单 tx 无需 approve) - permit 失败自动降级为 approve + createTask T06: linkReceipt 前端 - ABI 补充 linkReceipt / getTaskReceipts - TaskContext 新增 getTaskReceipts / linkReceipt - 任务详情页新增 x402 Receipts 区域:显示已绑定收据,参与方可手动 link
T05 — X402Client integration (lib/x402-client.ts): - postTaskWithX402: POST /tasks → 402 → sign EIP-3009 → retry → receiptId - fetchReceiptDetails: GET /receipts/:id for richer display - Graceful degradation when NEXT_PUBLIC_X402_API_URL not set T06 — Receipt display & auto-link: - create/page.tsx: x402 sign → createTaskWithPermit → auto linkReceipt (3-step) - [taskId]/page.tsx: show payer + timestamp per receipt, fetched from API - task-config.ts: add X402_API_URL, REWARD_TOKEN_NAME/VERSION, isX402Configured()
- Run prettier on all 11 frontend files (task pages, contexts, lib) - Remove unused imports: IsPositive, IsNumberString, EnvConfigService, AnalyzeTransactionDto - Rename catch (error) → catch (_error) in user-nft and user-token services where the error variable was not used (per @typescript-eslint/no-unused-vars)
- Reformat guardian-setup.dto.ts with prettier after import cleanup - Remove unused `data` destructure from useDashboard() call - Remove unused DEFAULT_REWARD_TOKEN_SYMBOL and getStoredAuth imports
- tasks/page.tsx: use signerAddress (EOA) instead of smart account address for "(you)" label; contracts store EOA so the label was never shown - guardian-sign/page.tsx: add acceptanceHash guard at the top of both handleSignWithPasskey and handleSignWithMetaMask to prevent signing an empty hash when URL params are missing
c8b3876 to
c00a793
Compare
jhfnetboy
left a comment
There was a problem hiding this comment.
Re-review — 严重问题已修复 ✅,中等问题待处理
感谢快速响应。两个严重问题已正确修复:
- ✅ EOA 角色判断:
tasks/page.tsx改用data.account?.signerAddress— 正确,Account类型中该字段存在。 - ✅
acceptanceHash空签名漏洞:在handleSignWithPasskey和handleSignWithMetaMask顶部都加了守卫 — 正确。
以下 5 个中等问题仍未处理,请跟进:
[未修复] permit domain version 仍写死为 "2"
tasks/create/page.tsx:172:
version: "2", // ← 仍然硬编码REWARD_TOKEN_VERSION 已经 import 进来(第 16 行)并在 x402 path 里用了(第 131 行),但 EIP-2612 permit 的 domain 里忘了替换。改一行即可:
version: REWARD_TOKEN_VERSION,[未修复] getPublicClient() 在 TaskContext.tsx 中重复定义
TaskContext.tsx:110 有一个本地 getPublicClient(),与 task-config.ts 导出的同名函数完全相同。删掉本地版本,改为:
import { getPublicClient } from "@/lib/contracts/task-config";[未修复] 任务加载只扫描最近 50,000 个区块
TaskContext.tsx:153:
const fromBlock = latestBlock > 50000n ? latestBlock - 50000n : 0n;Sepolia ~12s/块,50,000 块约 7 天,更早的任务用户不可见。短期可以调大到 200000n,长期建议改用 subgraph 或后端索引。
[未修复] TaskCreated 事件 topic 魔术字符串
TaskContext.tsx:159:
topics: ["0xc703eeeb92d845b735c767a95c30a380646ad4c4824a3a100253d4bec0294e9e"],建议改为:
import { keccak256, toHex, toBytes } from "viem";
// 或直接用 viem 的 parseAbiItem + encodeEventTopics
const topic = keccak256(toBytes("TaskCreated(bytes32,address,address,uint256)"));这样 ABI 改动时不会静默失效。
[未修复] 手动关联 receipt 同一值传两个参数
tasks/[taskId]/page.tsx:418-421:
await linkReceipt(
task!.taskId,
receiptInput.trim(), // receiptId (bytes32)
receiptInput.trim(), // receiptUri (URI string) ← 同一值
walletClient
);如果用户粘贴的是 receipt URI(字符串),linkReceipt 内部会对它 keccak256 再传给合约;如果粘贴的是已有的 bytes32 id,则 URI 字段应该是别的值。建议将输入框拆为两个字段,或在 UI 上明确说明只接受哪种格式,并在 receiptUri 字段填入有意义的值。
总结
| 问题 | 状态 |
|---|---|
| EOA 角色判断 | ✅ 已修复 |
| acceptanceHash 空签名 | ✅ 已修复 |
| permit version 写死 | ❌ 未修复 |
| getPublicClient 重复 | ❌ 未修复 |
| 50k 块扫描上限 | ❌ 未修复 |
| topic 魔术字符串 | ❌ 未修复 |
| linkReceipt 双参数 | ❌ 未修复 |
前两个(permit version + getPublicClient 重复)是 1 行的改动,建议顺手修掉再 merge。
Summary
Clean rebase onto master — supersedes #278 and #279. Excludes SDK work already merged via #237/#250/#251/#272.
4 commits, ~6000 additions:
feat(tasks): add MyTask M6-M8 task market UIfeat(recovery): add social recovery UI and guardian-sign pagefeat(tasks): Sprint 1 M9 — ERC-20 balance, EIP-2612 permit, x402 receiptsfeat(tasks): Sprint 1 T05/T06 — x402 payment flow + receipt displayCloses
Supersedes #278 and #279 (both can be closed after this merges)
Test plan
M6-M8 Task market:
/tasks→ Post Task → Approve USDC → CreateSprint 1 x402:
NEXT_PUBLIC_X402_API_URL=http://localhost:3401in.env.localcd MyTask/packages/api-server && pnpm startNEXT_PUBLIC_X402_API_URL→ task still creates (graceful degradation)Social recovery:
/recoverypage: propose + execute social recovery flow