Appearance
L1-4: Custom Stream(高级流支付)
1. 问题
在 ETH Streaming 基础上创建更高级的流支付系统,支持多接收者、多流管理、流取消等功能。
2. 原因
基本 ETH Streaming 只支持单一 ETH 流。实际应用中需要:
- 管理多个并发流
- 支持 ERC20 代币流(不仅是 ETH)
- 流生命周期管理(创建、取消、资金回收)
3. 方案
架构设计
solidity
struct Stream {
address token; // ERC20 代币地址 (address(0) = ETH)
uint256 cap; // 单次最大可提取量
uint256 unlockTime; // 完整解锁周期
uint256 timeOfLastWithdrawal;
uint256 remainingBalance; // 该流剩余总预算
}
多流管理
streamId标识每个流streamId → recipient → Stream双层映射- 每个流独立追踪预算和解锁状态
流生命周期
createStream(token, totalBudget)— 创建并注资addRecipient(streamId, recipient, cap, unlockTime)— 添加接收者withdraw(streamId, amount)— 接收者提取cancelStream(streamId)— 所有者取消流
4. 遇到的陷阱
4.1 remainingBalance 和 cap 的混淆
cap 是每次解锁周期的最大可提取量(会随时间恢复),remainingBalance 是该接收者的总预算(不会恢复)。
4.2 取消后未阻止提款
流取消后如果不清除 activeStreams 标记,接收者仍可能提款。
5. 陷阱的原因
5.1
cap 按时间解锁模型运作(同 L1-3),而 remainingBalance 是固定预算上限。两者需要分别处理:withdraw 中先检查 unlocked(时间维度),再检查 remainingBalance(预算维度)。
5.2
流取消修改内部状态后,需要在 withdraw 入口检查 activeStreams[streamId]。
6. 如何解决陷阱
solidity
if (amount > unlocked) revert InsufficientUnlockedBalance();
if (amount > stream.remainingBalance) revert InsufficientStreamBalance();
7. 技术要点
| 要点 | 说明 |
|---|---|
| 多流架构 | streamId + 双层映射 |
| 预算 vs 速率 | remainingBalance (总量) vs cap (速率) |
| 流生命周期 | create → fund → addRecipient → withdraw → cancel |
| 可扩展性 | 每种流可配置独立的 unlockTime |