1Do App

Will

钱包签署受益人、权重、触发模式、版本与执行费;首次激活锁定计划,之后可按资产分批结算。

7 个章节onedo-will
01

计划结构与签名

WillPlan 用 EIP-712 domain Will Plan on 1Do / 1 签署,verifyingContract 是钱包地址,签名通过钱包 ERC-1271 验证。受益人顺序也参与哈希。

tokens 数组不属于签名计划,而是在每次 executeWill 时由执行者提供。计划固定分配规则,但不固定资产列表、签署时余额或未来结算金额。

  • beneficiaries 包含非零地址与相对权重;零权重条目允许,但全部权重之和必须大于 0。
  • triggerMode 0 是固定时间,triggerMode 1 是钱包不活跃;不活跃模式也可以额外设置 timeUnlock。
  • expiresAt 是首次激活截止时间;当前时间等于 expiresAt 时仍可激活,但 expiresAt = 0 会立即被视为过期,并不表示无限期。
  • willVersion 初始为 1,resetWill 后递增,使旧版本签名失效。
  • executorFeeBps 最高 100 bps,即每项资产余额的 1%。
Signed WillPlan fields
struct Beneficiary {
  address addr;
  uint256 weight;
}

struct WillPlan {
  uint256 expiresAt;
  uint256 timeUnlock;
  uint256 executorFeeBps;
  uint8 triggerMode;
  uint256 willVersion;
  Beneficiary[] beneficiaries;
}
02

触发配置

configureInactivity(delay, grace) 设置 inactiveDelay 与 gracePeriod,并立即把 lastAlive 更新为当前时间;之后 ping() 可刷新 lastAlive。达到 lastAlive + inactiveDelay + gracePeriod 后,不活跃条件成立。

不活跃配置不在签名计划中,钱包可以在签名后修改它。configureInactivity、ping、setPaused 与 resetWill 都只能由钱包 self-call。

  • 固定时间模式要求 block.timestamp >= timeUnlock。
  • 不活跃模式要求已配置 lastAlive、没有暂停且到达 delay + grace;若 timeUnlock 非零,还必须同时达到该时间。
  • setPaused(true) 只让不活跃判断返回 false,不会暂停固定时间计划,也不会阻止已经激活的计划继续结算。
  • 暂停与恢复不会刷新 lastAlive;如果截止时间已在暂停期间经过,恢复后可能立即满足不活跃条件。
03

首次激活

步骤 1

提交计划与签名

任何执行者都可以提交 executeWill,但计划版本、费用、有效期、触发条件和钱包签名都必须有效。

步骤 2

选择可执行资产

执行者传入原生币或 ERC-20 地址;至少一项资产必须有非零余额且尚未在当前版本结算。

步骤 3

锁定计划

首次成功执行会保存 activePlanHash。它是 WillPlan 的 struct hash,不是加入 domain 后的完整 EIP-712 digest。

步骤 4

完成首批分配

同一交易结算传入的可执行资产并发出 WillActivated 与 TokenSettled 事件。任一转账失败会整体回滚。

同一版本只能激活一个计划

链下可能同时存在多个同版本有效签名,第一个成功执行的计划会锁定该版本。要替换计划,应先由钱包 resetWill,再签署新版本。

04

分批资产结算

  • 计划激活后,后续调用必须重传完全相同的 plan;不再检查 selfSig、expiresAt 或触发条件,selfSig 可以为空。
  • address(0) 表示原生币,其他地址表示 ERC-20。当前不支持 NFT。
  • 每个资产在当前 willVersion 最多结算一次。重复地址会跳过;零余额资产不会被标记,未来收到余额后仍可结算。
  • 如果一批中的资产全部为零余额或已经结算,调用以 NoExecutableToken 回滚。多资产批次是原子的。
  • 某资产结算后新进入的钱不能在同一版本再次分配;需要 resetWill 并签署新版本计划。
  • expiresAt 只限制首次激活。计划一旦激活,后续资产可以在 expiresAt 之后继续结算。
05

权重、尾差与执行费

每项资产都按执行时钱包的完整实时余额独立计算。执行费先支付给本次调用者,剩余部分再按权重分配;不同批次可以由不同执行者领取对应费用。

  • 整数除法产生的尾差全部给最后一个正权重受益人,确保可分配余额完整结算。
  • 计划不会冻结、预留或迁移资产;签名后到执行前,钱包余额仍可变化。
executor fee = floor(balance × executorFeeBps / 10,000)
remaining    = balance - executor fee
share        = floor(remaining × weight / totalWeight)
06

状态读取与事件

  • inactivityState() 返回 lastPing、inactiveDelay、gracePeriod、paused 与当前 inactive 判断。
  • willState() 返回 currentWillVersion 与 activePlanHash;isTokenSettled(token) 只反映当前版本。
  • 链上不保存完整计划、受益人列表或签名,只保存计划哈希、版本、心跳配置与逐资产结算版本。客户端需要安全保存原始计划。
  • InactivityConfigUpdated、PingRecorded、PausedSet、WillReset、WillActivated 与 TokenSettled 都由钱包地址发出。
07

生命周期与边界

  • resetWill 通过切换版本让旧 settled 标记失效,不需要逐项清空映射;同时清除 activePlanHash,但不会清除心跳配置或 paused 状态。
  • 禁用应用、Registry 阻断或 Runtime 版本变化都可能影响未来执行;Will 不是独立托管金库。
  • 执行能分配的只是结算时实际存在且可转移的资产,不保证签名时或未来的余额。

链上资产分配,不是法律效力保证

Will 实现的是满足条件后的链上资产执行规则。法律遗嘱、身份、税务和司法辖区要求不由合约验证,用户应按自身情况另行处理。