198 lines
3.7 KiB
Markdown
198 lines
3.7 KiB
Markdown
# PolyWeather 支付合约升级方案(V2)
|
||
|
||
最后更新:`2026-03-20`
|
||
|
||
## 1. 目标
|
||
|
||
本次 V2 方案对应三个明确目标:
|
||
|
||
1. 把 `owner` 迁到多签地址
|
||
2. 升级到 `SafeERC20 + Pausable + ReentrancyGuard`
|
||
3. 把“链上 plan 绑定”和“EIP-712 授权支付”都纳入设计,而不是只在链下校验
|
||
|
||
合约草案:
|
||
- [PolyWeatherCheckoutV2.sol](/E:/web/PolyWeather/contracts/PolyWeatherCheckoutV2.sol)
|
||
|
||
构造参数编码脚本:
|
||
- [encode_checkout_v2_constructor.py](/E:/web/PolyWeather/scripts/encode_checkout_v2_constructor.py)
|
||
|
||
## 2. V2 新增能力
|
||
|
||
### 多签 owner
|
||
|
||
V2 constructor 不再默认 `msg.sender` 作为唯一 owner,而是显式传入:
|
||
|
||
- `initialOwner`
|
||
- `initialTreasury`
|
||
- `initialSigner`
|
||
|
||
这意味着:
|
||
- 部署后可直接把多签地址设为 `owner`
|
||
- 不需要先单签部署再补 transfer
|
||
|
||
### SafeERC20
|
||
|
||
V2 内置最小 `SafeERC20` 封装:
|
||
|
||
- `safeTransferFrom`
|
||
- `safeTransfer`
|
||
|
||
相比直接依赖 `IERC20.transferFrom -> bool`:
|
||
- 对非标准 ERC20 的兼容性更稳
|
||
- 出错边界更明确
|
||
|
||
### Pausable
|
||
|
||
V2 增加:
|
||
|
||
- `pause()`
|
||
- `unpause()`
|
||
|
||
支付入口:
|
||
|
||
- `payPlan(...)`
|
||
- `payAuthorized(...)`
|
||
|
||
都受 `whenNotPaused` 保护。
|
||
|
||
一旦发现:
|
||
- treasury 配置错误
|
||
- token allowlist 配置错误
|
||
- 签名器异常
|
||
- 链上风控问题
|
||
|
||
可以直接暂停支付入口。
|
||
|
||
### ReentrancyGuard
|
||
|
||
V2 增加 `nonReentrant`,保护:
|
||
|
||
- `payPlan`
|
||
- `payAuthorized`
|
||
- `rescueToken`
|
||
|
||
虽然当前订单去重已经能挡住典型重复支付路径,但 `ReentrancyGuard` 仍然是更稳的防线。
|
||
|
||
### 链上套餐绑定
|
||
|
||
V2 新增:
|
||
|
||
- `setPlan(planId, token, amount, active)`
|
||
- `planConfig[planId][token]`
|
||
|
||
正式支付入口 `payPlan` 会:
|
||
|
||
1. 校验 token 已 allowed
|
||
2. 校验 `planId + token` 的 plan 已 active
|
||
3. 从链上读取 amount
|
||
4. 按链上配置收款
|
||
|
||
这意味着:
|
||
- `planId / amount / token` 绑定不再完全依赖链下
|
||
|
||
### EIP-712 授权支付
|
||
|
||
V2 同时保留第二条入口:
|
||
|
||
- `payAuthorized(...)`
|
||
|
||
它适合:
|
||
- 临时折扣
|
||
- 特殊活动价
|
||
- 不想每次都上链改 `setPlan`
|
||
|
||
校验字段包括:
|
||
|
||
- `orderId`
|
||
- `payer`
|
||
- `planId`
|
||
- `token`
|
||
- `amount`
|
||
- `nonce`
|
||
- `deadline`
|
||
|
||
签名人地址由:
|
||
|
||
- `signer`
|
||
|
||
统一控制。
|
||
|
||
## 3. 两条支付路径怎么选
|
||
|
||
### 路线 A:链上套餐绑定优先
|
||
|
||
优点:
|
||
- 最直观
|
||
- 合约级约束最强
|
||
- 更容易审计
|
||
|
||
缺点:
|
||
- 套餐改价需要 owner 交易
|
||
|
||
适合:
|
||
- 月付/季付/年付这类稳定商品
|
||
|
||
### 路线 B:EIP-712 授权优先
|
||
|
||
优点:
|
||
- 活动价灵活
|
||
- 不必每次改链上 plan
|
||
|
||
缺点:
|
||
- 需要管理 signer 密钥
|
||
- 风险从 owner 单点,部分转移到 signer 运维
|
||
|
||
适合:
|
||
- 促销
|
||
- 临时折扣
|
||
- 白名单价格
|
||
|
||
### 当前建议
|
||
|
||
生产建议不是二选一,而是:
|
||
|
||
1. **稳定套餐** 走 `payPlan`
|
||
2. **特殊场景** 走 `payAuthorized`
|
||
|
||
这样:
|
||
- 主流程更稳
|
||
- 特殊价仍保留灵活性
|
||
|
||
## 4. 推荐迁移步骤
|
||
|
||
1. 先部署 V2 到测试环境
|
||
2. `owner` 直接用多签地址
|
||
3. 配置 `treasury`
|
||
4. 配置 `allowedToken`
|
||
5. 配置 `planId/token/amount`
|
||
6. 仅在需要活动价时再配置 `signer`
|
||
7. 用事件重放脚本和运行态接口验证
|
||
8. 再切生产前端/后端配置到新 `receiver_contract`
|
||
|
||
## 5. 构造参数编码
|
||
|
||
示例:
|
||
|
||
```bash
|
||
python scripts/encode_checkout_v2_constructor.py \
|
||
--owner 0xYourMultiSig \
|
||
--treasury 0xYourTreasury \
|
||
--signer 0xYourBackendSigner
|
||
```
|
||
|
||
## 6. 当前判断
|
||
|
||
V2 已经把这三件事做成了明确方案:
|
||
|
||
1. 多签 owner
|
||
2. SafeERC20 + Pausable + ReentrancyGuard
|
||
3. 链上 plan 绑定 + EIP-712 授权
|
||
|
||
它现在是**升级草案**,不是现网已部署合约。
|
||
|
||
如果要真正上线,下一步就是:
|
||
|
||
1. 做一次测试网或本地链验证
|
||
2. 更新 PolygonScan 验证文档
|
||
3. 修改后端 `receiver_contract` 配置
|