4.1 KiB
4.1 KiB
PolyWeather 支付审计与防护说明
最后更新:2026-03-20
1. 当前已落地的防护
链下运行态
- 支付事件扫描与确认循环已把运行态写入 SQLite:
payment_runtime_statepayment_audit_events
- 关键循环现在会记录:
event_loop_startedevent_loop_cycleevent_loop_errorconfirm_loop_startedconfirm_loop_cycleconfirm_loop_error
事件确认边界
- 后端只认链上
OrderPaid事件。 - 前端提交 intent 不会直接视为支付完成。
confirm_loop会再次按链上交易与确认数校验 intent。
RPC 多节点容灾
- 支持
POLYWEATHER_PAYMENT_RPC_URLS - 格式示例:
POLYWEATHER_PAYMENT_RPC_URLS=https://polygon-rpc.com,https://polygon-bor-rpc.publicnode.com
- 启动时按顺序探活。
- 当前节点断连或收据查询失败时,会自动切换到下一个可用 RPC。
事件重放
- 已提供脚本:
用途:
- 审计某个区块范围内的
OrderPaid - 事后补查漏单
- 排查 RPC 抖动导致的监听遗漏
命令示例:
python scripts/replay_payment_events.py --from-block 10000000 --to-block 10001000
运行态检查
- 已提供接口:
GET /api/payments/runtime
可查看:
- checkout 配置摘要
- 当前活跃 RPC
- 候选 RPC 列表
- event loop 最新状态
- 最近审计事件
2. 当前合约的授权边界
合约源码:
当前边界:
owner
- 可执行:
setTreasurysetTokenAllowed
- 普通用户
- 只能调用:
pay(orderId, planId, amount, token)
- 代币边界
- 只有
allowedToken[token] == true的 token 可支付
- 订单边界
- 同一个
orderId只能成功支付一次
3. 重入与重复支付判断
当前合约的 pay 逻辑顺序是:
- 检查 token allowlist
- 检查
amount > 0 - 检查
paidOrder[orderId] == false - 先写入
paidOrder[orderId] = true - 再执行
transferFrom - 发出
OrderPaid
这意味着:
- 同一
orderId的重复支付会被拦住 - 典型“转账外部调用后再回调重复执行同订单”的路径会被
paidOrder状态挡住
但要注意:
- 当前合约没有
Pausable - 当前合约没有
SafeERC20 - 当前合约没有在链上校验
planId -> amount
所以它属于:
- 最小可用支付合约
- 不是“全功能强防护合约”
4. 当前静态审计结论
已提供脚本:
命令:
python scripts/check_payment_contract_security.py
输出会检查这些项目:
- 是否有
onlyOwner setTreasury/setTokenAllowed是否受 owner 保护- constructor / setter 是否检查零地址
- 是否校验 allowlist
- 是否校验
amount > 0 - 是否校验重复订单
- 是否在
transferFrom前写入paidOrder - 是否有 pause 开关
- 是否使用 SafeERC20
- 是否在链上绑定套餐价格
5. 当前主要剩余风险
- 单地址 owner
- 建议把
owner迁移到多签钱包
- 无暂停开关
- 发现紧急问题时,无法直接暂停
pay
- 金额校验主要在链下
- 当前
planId / amount / token绑定主要靠后端 intent 和确认逻辑
- ERC20 兼容性假设
- 当前使用
IERC20.transferFrom - 升级版合约更建议改为 OpenZeppelin
SafeERC20
6. 推荐操作
每次支付配置变更后
执行:
python scripts/check_payment_contract_security.py
python scripts/replay_payment_events.py --from-block <from> --to-block <to>
线上巡检
执行:
curl http://127.0.0.1:8000/api/payments/runtime
重点看:
rpc.active_rpc_urlrpc.configured_rpc_countevent_loop_state.last_scanned_blockrecent_audit_events
7. 下一版合约建议
如果后续升级合约,优先级建议:
Ownable-> 多签 ownerSafeERC20Pausable- 链上 plan/amount/token 绑定
- 必要时增加 rescue/sweep 能力