在以太坊转错合约地址,钱大多安静地躺在对面;在 TON 上,同样的”转给一个还没准备好的账户”,有时会自动退回,有时不会。差别由消息头里一个布尔字段决定。本文按官方文档把这套机制读一遍,TON 上的 dApp 怎么连钱包:TON Connect 的桥、会话与账号锁定 讲过钱包怎么连上 TON 生态签名,这篇讲签名之后消息在链上的物理行为。
内部消息里的两个相关字段
TON 上账户都是合约,转账是一笔”内部消息”。官方文档给出的消息结构里同时有 bounce 和 bounced:前者是发送方声明”这笔可退回”,后者标记”我就是退回件”。处理失败时,系统自动向原发送方发一条弹回消息,条件有三个:失败消息处理完后剩下的金额足够发出这条弹回;消息本身是可退回的;并且要么合约在计算阶段抛错且没有用 COMMIT 指令提交过状态,要么动作阶段启用了 +16 标记(发送动作或预留动作的”失败即弹回”选项)而出错。三个条件缺一个,钱就留下,不再退回。

弹回消息长什么样
弹回不是原样退回,官方文档列出了确定性的变换:src 与 dest 对调,bounced 置真,bounce 强制置假防止弹回再弹回形成死循环,消息体被替换成 32 位全一(0xffffffff)加原体前 256 位。旧格式的弹回体太小,连一个内部地址都装不下,因此文档又定义了新的弹回格式:靠 extra_flags 低位启用,弹回体以 0xfffffffe 打头,携带原体、原始金额与时间、失败阶段(bounced_by_phase)和 32 位 exit_code。当计算阶段被整个跳过时,exit_code 给出四种跳过原因:-1 无状态(目标账户未初始化或已冻结,消息也没带 StateInit)、-2 状态不对(带的 StateInit 哈希对不上)、-3 没有 gas、-4 账户被暂停。查一笔退回的转账,看弹回体里的这些字段就能定性是哪一种。
发送模式与钱包侧的约定
发送方的合约(钱包也是合约)用 8 位比特掩码的 send mode 决定失败怎么办:默认值 0 之下,转发动费从消息金额里扣,发送失败则整笔回滚、不发弹回;+1 是转发动费另付;+2 忽略错误因而也不会弹回;+16 是动作阶段失败即弹回;基础值 128 表示把账户全部余额发走,文档对它的警告是使用不慎会造成全部余额损失。这些是合约指令层参数,普通用户在转账界面看不到这排数字,但它在解释”为什么这笔失败没弹回”。钱包侧的配套规则写在官方地址工作流文档里:发送前应用先查询目标账户状态,若状态为未初始化,就把消息的 bounce 字段强制设为 false、忽略地址里携带的可退回标志;状态可读且非未初始化时,则按地址里的标志行事。
没弹回来的钱去哪了
弹回的前提是失败消息处理完后还剩足够的钱发出弹回消息,若原消息金额太小、被执行与转发费用吃光,即使是可退回消息也弹不出东西。合约侧同样有对应的失败面:文档在弹回条件里专门列了 COMMIT 指令——计算阶段一旦提交过状态,之后的错误不再触发弹回,这是”同一类失败,有的退有的不退”的常见来源。新弹回格式还用 extra_flags 的低位决定回收多少原体:第一位只回去掉引用的一层根单元,两位都开则把整个原始消息体带回;对接方解析弹回体时,要按新旧两种格式分别处理。
用户怎么用这套知识核对
第一,转给一个可能还没激活的 TON 地址时,别指望一定退回:按上面的约定,钱包对未初始化地址发出的就是不可退回消息,退不回来要自己找对面。第二,看到”退回”记录时,先在浏览器里核这条消息的 bounced 标志与金额,确认扣掉的手续费后到账数与预期一致,链上成功、对面入账、钱包展示仍是三件事。第三,同一把公钥在 TON 上可以开多个钱包合约,subwallet_id 不同地址就不同,资金并不互通,核对地址时要确认对方给的是哪一个钱包的地址。机制以 TON 官方文档 2026 年 10 月版本为准,本文不构成投资建议。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。