题目
用户在多个池子里有奖励需要领取。目前实现是「一键全部领取」,把多个领取调用合并成一笔交易。
上线后出现问题:其中某个池子的领取失败,导致整笔交易回滚,用户一个都没领到,还付了手续费。请给出改进方案。
考察目标
- 能否识别原子批量与逐项失败传播的差别。
- 是否理解部分失败在业务上的可接受性。
- 能否给出对账与重试设计。
考察部分失败处理的取舍,以及状态对账与重试设计。
用户在多个池子里有奖励需要领取。目前实现是「一键全部领取」,把多个领取调用合并成一笔交易。
上线后出现问题:其中某个池子的领取失败,导致整笔交易回滚,用户一个都没领到,还付了手续费。请给出改进方案。
先确认「一键领取」实际使用的批量机制。若合约只支持原子整批,前端无法让其中一项失败后其余继续,应拆成可逐项重试的交易;若钱包或业务合约支持非原子批次,仍需逐项核对结果。不能直接把 Multicall3 的读取聚合当作替用户领取奖励的通用方案。
status 用 1 与 0 表示交易成功或失败,可作为逐笔判定的依据(依据:EIP-1474 §eth_getTransactionReceipt)。wallet_sendCalls 可以请求批量调用;未要求原子性时,钱包可以采用非原子执行,不能据此假定批次会部分成功或整批成功(依据:EIP-5792 §wallet_sendCalls)。wallet_getCallsStatus 返回批次状态,并提供原子性与收据等结果信息,前端仍需区分各调用的链上结果(依据:EIP-5792 §wallet_getCallsStatus)。aggregate3 支持按项返回失败结果,但普通账户直接调用它时,目标合约看到的 msg.sender 是 Multicall3;依赖用户地址鉴权的领取方法不能直接套用它(依据:Multicall3 README §Batch Contract Reads、§Batch Contract Writes)。aggregate3 当作所有领取合约都能使用的批量写入口,忽略 msg.sender 已变为聚合合约(依据:Multicall3 README §Batch Contract Writes)。status 反映交易成败;提交成功后直接标记全部完成会掩盖失败项(依据:EIP-1474 §eth_getTransactionReceipt)。发现这道题有问题? 反馈此题