Juicebox 分配回执成功但少到账:核额度、split 目标与局部失败
链小知 · 进阶 · 核验 · 依官方文档整理
对已有 sendPayoutsOf 记录拆开请求金额、实际gross、额度截断、各split净额及失败回补,避免把总回执当全部收款成功。
开始前准备
- 准备既有payout解码/回执及同一版本快照:network/projectId、terminal/token、amount/currency/minTokensPaidOut、ruleset/cycle、limits、splits和转账事件;不新发payout或查询业务/RPC。
- 按固定V6核心53914d2与当前官方说明;具体部署不匹配时不能套错误/事件,资金和fees均需原记录,权限/实时Gas未实测。
1. 辨认分的是资金还是保留token
解码已有方法:JBMultiTerminal.sendPayoutsOf分发项目资金;JBController.sendReservedTokensToSplitsOf分发累计保留项目tokens。看到Split或Distribution标签不足以认定是同一币种流程。
对资金记录保存projectId、token、terminal、amount、currency及minTokensPaidOut原整数。实际currency可能与token记账货币不同;用该token accounting context精度,native token sentinel也不等任意ERC20地址。
检查结果:原方法、输入币/货币和单位确定,保留token与资金分配未混淆。
2. 核当前周期剩余额度和实际gross
按已有状态对照payoutLimitOf(projectId,rulesetId,terminal,token,currency)与usedPayoutLimitOf中cycleNumber。固定V6 recordPayoutFor实际把请求cap到remaining limit;超额不必revert,与该函数旧注释不同。无剩余可返回0,跨货币换算舍入0也不消耗额度。
再核terminal token balance;不足实际gross可报InadequateTerminalStoreBalance。记录请求amount与回执amountPaidOut的差异。minTokensPaidOut最终检查总gross amountPaidOut,不保证每个收款人净额;不能依据官网概略注释把它当所有recipient minimum。
检查结果:requested、remaining limit、gross与minimum明确,额度cap/0/余额不足分别解释。
3. 按正确 ruleset 与组查接收目标
对已有splits使用(projectId,rulesetId,groupId),资金组groupId为uint256(uint160(token));固定splitsOf无该ruleset数组会回退ruleset0,不可拿保留token组替代。percent分母1e9,未分配余量通常给project owner。
逐项读hook、projectId、beneficiary、preferAddToBalance:hook优先,其次目标project,最后直接地址。project split的beneficiary可能收到目标项目token而非资金;零beneficiary分支可用originalcaller。当前代码目标project无terminal会失败,不沿用struct旧“送owner”注释。
检查结果:资金group和实际目标路径明确,beneficiary字段未被一概解释成资金地址。
4. 分别核权限与锁表范围
常规分配可由任何人触发,但当前规则ownerMustSendPayouts时检查owner或SEND_PAYOUTS operator;触发者不等资金recipient,也不因发起交易就取得项目ownership。查看已有权限记录即可,不新授ROOT或修改接收人。
lockedUntil是Unix秒,固定JBSplits锁保留针对同project/ruleset/group表。后继规则使用不同rulesetId时不自动继承该锁;要核未来规则的表,不能将“当前split锁至某日”写成所有未来资金都保证送同地址。
检查结果:触发权限、实际接收人与同表锁分开,未将锁扩成跨规则资金保证。
5. 拆开各split费用、gross和net
匹配token精度后按实际fee eligibility拆分:固定标准费25/1000=2.5%,gross100个token、全部适用该费且无其他扩展时理论net97.5;豁免、项目同terminal、hook部分消耗和逐笔舍入会改变结果。不要统一从每笔gross再扣一次总fee。
同terminal项目支付可免core fee,但转发到非豁免hook仍有条件;fee支付返回的JBP6 token不等现金退款。holdFees/后续处理和Gas独立,原记录缺这些字段时保留未知,不从营销零fee或总余额硬算最终到账。
检查结果:原gross/net/fee basis和豁免可复核,链费与返token未误算成同币净额。
6. 逐收款人查局部失败而不只看总回执
在匹配合约日志里核SendPayouts以及每项SendPayoutToSplit的amount/netAmount,另找PayoutReverted、owner转账PayoutTransferReverted、FeeReverted等原错误并对照实际token转移。固定split库捕获失败、回补project balance但仍消耗payout limit,SendPayoutToSplit也可能伴失败且netAmount=0。
交易status成功或总gross非零不代表每recipient已收到。把额度已用、余额回补、成功split、失败split和fee处理状态分列;没有原转账证据就写收款未证实,不重复payout“试一下”。源码只说明该版本分支,不证明个人回执或实时余额。
检查结果:各recipient和费用处理都有独立结果/未知,总成功未升级为全体到账。
怎样确认完成
- 已列请求、gross、limits、各split净额/失败与回补阶段。
- 只有原结果充分才判断已有执行;未分发资金、签名、调RPC或改变权限。
常见错误与边界
- recordPayoutFor注释与实际cap行为不同;min检查gross,不保证各recipient净额。
- partial failure可恢复余额但消耗额度;同名事件、成功回执不替代实际资金路径。