跳到正文
fevou.独立加密知识站

带税代币怎么查:买入税、卖出税和到账变少的原因

到账比报价少或卖出失败,代币转账扣费是需要排查的一项。先查当前买入税、卖出税,再核对自己的交易记录与费率修改权限;这些结果能帮助你判断差额来自哪里。

编辑图解:标题文字为“到账比报价少,先查代币自己扣了多少”,下方三格分别写着“买入扣多少”“卖出扣多少”“谁能改费率”
买入扣多少、卖出扣多少、谁能改费率,到账对不上时按这三格查。

在 DEX 上买一个陌生代币,到手数量比报价少了一截,第一个要排查的是这个代币的合约有没有自己扣一笔。圈里叫它“税”,官方文档叫 token fee,或者 fee on transfer。它跟报税没有关系,也不是 DEX 收的兑换手续费,更不是 gas。

这笔钱扣多少,先读代币警告和合约的当前费率;已经成交的,再核对那笔交易的转账记录。日志能完整对应池子与钱包时,才用转出量和实收量倒算。这两种查法下面分别讲,卖不出去和滑点报错也一起查。

买币到账比报价少,是谁扣的

如果确认少掉的数量来自代币税,扣费发生在代币的转账逻辑里,费率和分配方式由合约规则决定。仅凭“到账少了”,还不能排除报价变化或其他费用。

Uniswap 帮助中心的 What is a token fee? 把这笔钱定义为代币在买入、卖出或转账时收取的费用,并说明由代币发行方设定和收取,该平台不参与分成。本文所用官方说明查阅于 2026 年 10 月;警告标签与界面提示以页面实时显示为准。

要追这笔差额,得先确认币从池子转出后经过哪些地址,再查合约在哪一步扣费。DEX 的报价、成交记录和代币的转账记录要放在一起看。

截走的部分去了哪,每个合约写法不同,得看它自己的代码。PancakeSwap 文档举过一个例子:某代币每笔交易收 10%,其中 5% 分给全体持有人,5% 拿去加流动性。这只说明“可以这样设计”,换一个合约,钱可能直接进发行方指定的地址。

该帮助页也说明,合约要求的买入费或卖出费未支付时,兑换就不能发生。由此可见,只换一个下单界面不能保证免税;合约若对某些地址或池子设有豁免,实际扣费才可能不同,仍要回到代码确认。

代币税、兑换手续费、gas:三笔钱别算混

一笔链上兑换里,你可能同时付三种钱。算损耗之前把它们分开,不然倒算出来的数字没有意义。

扣的是什么谁定的钱给谁去哪里看
代币税(token fee)代币发行方,写在代币合约里按代币合约代码分配界面的代币警告、合约源码、自己那笔交易的转账记录
DEX 兑换手续费DEX 协议与池子的设置按该 DEX 的规则分配,查它的文档该 DEX 的官方文档
gas(网络费)链的网络状况付给网络,用链的原生币结算钱包的确认弹窗、区块浏览器的交易详情

gas 通常另用 ETH、BNB、SOL 等原生币支付;钱包或聚合器若提供代付并另收服务费,还要核对它列出的费用。DEX 兑换费可能已经计入报价。“报价 1000、到手 950”只说明数量有差异,不能直接把这 50 枚全算成代币税。

报价之后价格变了、订单本身推动了池子价格,也会影响实收。排除这些因素后,再查转账扣费。

买之前,去哪里查买入税和卖出税

以太坊和它的 Layer 2:先看 Uniswap 的代币警告

在这个界面里选中一个代币,如果它被标了费用相关的警告,界面可能给出提示。What are token warnings? 一页的标签表里,和税直接相关的有两条:“High Buy or Sell fee”(买入或卖出收取高额费用)和“100% Sell Fee Detected”(检测到 100% 卖出费)。另有一条“Honeypot”,写的是被 Blockaid 标记为疑似蜜罐。

使用这个警告时,有三件事要知道:

  • 覆盖范围是以太坊 ERC-20 和受支持的 Layer 2 代币。
  • 数据来源是第三方 Blockaid,平台声明不保证其准确性,也不独立核实。
  • 较新或冷门的代币可能没有数据。

第三条最要紧。如果你碰到的陌生币正好属于“较新或冷门”那一类,没有警告就不等于没有税。该页也没有写“高”的门槛是多少,单凭 High Buy or Sell fee 这个标签得不到一个数字。界面上如果另外标出了买入、卖出费率,先记下来,再用下面的办法对一遍。

EVM 链通用:读合约源码

ERC-20 标准(EIP-20)列出的九个方法里,没有统一的费率查询方法;其中 name、symbol、decimals 还是可选的。转账扣费需要合约另写逻辑,变量名、计费单位、买卖是否分别收费,都得看具体实现。

所以没有一个固定的格子能让你直接读到“卖出税 = X%”。能做的是:

  1. 确认你手里的合约地址是对的,名字谁都能起,核对方法在 同名代币怎么认合约地址。
  2. 在区块浏览器打开合约,查看源码验证状态。这家浏览器未验证,不代表源码从未公开;可以再核其他验证服务,但要确认源码与当前链上代码匹配。仍找不到对应源码时,先把源码查费率这一步记为未确认,见 合约源码验证怎么看。
  3. 在源码里搜 fee、tax 这类关键词,找到转账函数里做减法的那一段,看被减掉的比例来自哪个变量。搜不到这类词不等于没有扣费,名字是发行方自己起的。
  4. 在合约页的读取功能(Etherscan 上的 Read Contract)找公开的费率查询项,确认单位和分母再读数。若是代理合约,先确认当前实现,再通过代理地址的 Read as Proxy 读取当前状态,不能拿实现地址自身的存储值当代币当前值。没有公开查询项就记“费率未读出”。

读不懂代码也别硬猜。把“源码已验证,但费率没读出来”记下来,比凭变量名猜一个数字强。

Solana:读 mint 账户的 TransferFeeConfig 扩展

Solana 的 Token-2022 则有专门的配置。Solana 文档 Transfer Fees说明,mint(代币铸造账户)的 TransferFeeConfig 扩展可以让每笔转账按配置扣费,扣下的部分记录在收款代币账户上,由获授权的一方提取。

先在支持 Token-2022 扩展显示的区块浏览器打开完整 mint 地址,找到 TransferFeeConfig。页面没显示扩展,不能直接认定它不存在;无法读出就记未确认。配置里的 olderTransferFee 和 newerTransferFee 各有 epoch、transferFeeBasisPoints、maximumFee,分别表示生效期、基点费率和费用上限;100 个基点等于 1%。两组都要看,不能只抄百分比、漏掉上限。

已经买了:用自己那笔交易倒算被扣了多少

下面只算一种容易核清的情况:同一代币在你的钱包和一个已确认的池子之间直接转账,日志完整,没有路由中转、分拆成交、退款或余额重算。遇到那些情况,不能照抄这个公式把所有差额都叫税。

EIP-20 要求转账触发 Transfer 事件。打开交易详情的 Logs,先按代币合约地址筛出事件,再按该代币的 decimals 把原始整数换算成同一单位。事件由合约自己发出;若记录不完整、与余额变动对不上,就不能只靠它倒算。

买入时,把该笔买入中从池子发出的同一代币数量相加,得到转出总量;把钱包收到的数量减去钱包在同一笔中转出的数量,得到实收。还要在源码或明确的费用记录中确认差额确实对应代币扣费。池子地址的核对方法见 流动性池锁仓怎么查。

假设这笔直接转账里,池子转出 100,000 枚,钱包实收 95,000 枚,差额全部是已核明的代币扣费:

  • 差额:100,000 − 95,000 = 5,000 枚
  • 买入实际扣除比例:5,000 ÷ 100,000 = 5%

卖出同样限于上述直接转账。钱包减少的代币总量是分母;池子从你钱包实际收到的同一代币数量是实收。池子从其他地址收到的币不能混进来,有退款或路由中转就先停止套公式。

继续假设:你把这 95,000 枚全部卖出,池子实收 87,400 枚。

  • 差额:95,000 − 87,400 = 7,600 枚
  • 卖出实际扣除比例:7,600 ÷ 95,000 = 8%

在买卖价格相同、且暂不计 DEX 兑换费、gas 和价格影响的假设下,两次扣费后剩下的比例是 0.95 × 0.92 = 0.874,数量损耗为 12.6%,不是把 5% 与 8% 直接相加。只补回这两次代币税,需要卖出单价约为买入单价的 1 ÷ 0.874 ≈ 1.144 倍,即上涨约 14.4%;算上其他成本,要求还会变。

若日志只写了一条池子到钱包的净额,分母就不够可靠:差额为 0 可能是没扣,也可能是费用没单列。报价会变化,不能拿旧报价补成扣费证据。回源码仍核不出就记未确认;只买过没卖过时,也不要用买入税推算卖出税。

带税代币为什么要调高滑点,几种报错各是什么意思

先看报价是否已包含代币扣费。若没计入,假设滑点容忍度为 1%,实收却比报价少 10%,就可能触发最低接收数量限制。能否成交还取决于所用路由是否支持这个代币,以及是否有其他交易限制;把滑点调高不保证成功。

PancakeSwap 文档 Troubleshooting Errors 一页举的例子就是这个关系:

PancakeSwap 排障文档中 SAFEMOON 的历史举例:10% 转账费用对应 12% 或更高的滑点设置
排障文档的 SAFEMOON 举例:10% 转账费用与 12% 或更高的滑点设置。该例只用于解释两者关系,当前交易应查当前代币配置与报价。截图:2026 年 10 月。

这段举例说明,转账扣费会让购买后实收少于预期。不能把截图中的设置直接搬到另一个代币上。

同一页还列了几种报错,对着文本就能判断方向:

  • PancakeRouter: INSUFFICIENT_OUTPUT_AMOUNT:可能是滑点容忍度太低或流动性不足。先刷新报价、检查交易量和最低接收数量;调高容忍度会放宽你接受的最差成交结果。
  • Pancake: K:文档把自带费用的代币列为一种原因,并给出改填 To 数量、让 From 成为估算值的办法。这是该文档针对相应路由的排障提示,操作前仍要检查更新后的报价。
  • Pancake: TRANSFER_FAILED:可能与 Restorative Rebase 类代币的设计有关,也可能是发行方暂停交易或只允许选定地址卖出。后两种不能靠提高滑点解决。

Uniswap 这边另有一个限制。它的 v3 开发者文档 Token Integration Issues 写:“Fee-on-transfer tokens will not function with our router contracts.”——转账收费的代币无法在 v3 的路由合约上正常运作。

滑点容忍度限制的是总偏差,不能把其中某一截专门留给税。用一个简化算式看:假设报价未计入 10% 代币税、只扣一次税,设 12% 滑点后,价格下移可占的比例是 1 − 0.88 ÷ 0.90 ≈ 2.22%;若设成 25%,就变成 1 − 0.75 ÷ 0.90 ≈ 16.67%。实际报价若已计税,就不能再这样相减。我建议先看最低接收数量能不能接受;失败原因未查明时,别靠一次次加滑点来试。

卖出税 100% 是什么情况,费率以后还能不能改

前述警告表把 “100% Sell Fee Detected” 用于被标记为收取 100% 卖出费的代币。按它说明的情形卖出,全部价值会归代币创建者,卖方拿不到价值。

这个警告值得立即停下来核查,不必为了验证标签再花钱试卖。标签本身也受前面提到的数据准确性限制。

比 100% 标签更难防的是“现在不高,以后能改”。你今天倒算出买 5% 卖 8%,只说明那两笔交易发生时是这个数。

EVM 链上要看费率修改函数、调用权限和可升级性。当前实现把费率写成常量,只能说明这份实现没有直接改该常量的入口;若代理能升级,实现仍可能换掉。费率存成变量时,要查谁能改、上限怎样约束,也要查看角色或外部配置,不只搜 owner。方法见 代币合约权限怎么看。LP 凭证由谁持有,则另查池子能不能被撤走。

Solana 配置中的 transferFeeConfigAuthority 管理费率修改,withdrawWithheldAuthority 管理已扣费用的提取。官方文档说明,SetTransferFee 更新 newerTransferFee,从两个 epoch 之后开始生效。判断当前用哪组,比较当前 epoch 与 newerTransferFee.epoch:达到生效期用 newer,否则看 older。两组不同不等于新费率已生效;两组相同也不能证明从未更新过配置。

查不出来的几种情况,记成“未确认”

下面这些情况,你得不到一个可靠的费率数字,记录里就写“未确认”,不要填一个猜的数:

  • 找不到与当前链上代码对应的源码,费用读取项又不明确,无法确认扣费规则。
  • 代币很新,界面没有任何警告。警告页自己说了新币可能没有数据,空白不能当作“无税”。
  • 代币不在以太坊或受支持的 Layer 2 上,那套警告本来就不覆盖。
  • 当前费率能读出,但谁能改、允许改到多少还没查明;当前值照记,未来条件另记未确认。
  • 只买过没卖过,卖出税没有实测数字,源码也没读出来。
  • 交易日志里这个代币只有一条转账记录、差额算出来是 0,源码也没读出扣费逻辑。

“未确认”要写到具体项目上。能读出当前买入税,就保留这个值;卖出税和修改权限没查清,分别留空。看不到退出时会扣多少,就先别把买入页面上的报价当作能换回来的金额。

关于代币税,还有几个具体问题

换一个 DEX 或者聚合器买,能避开代币税吗?

只换界面不能保证避开。费用在代币转账逻辑里执行;换池子或交易路径是否改变收费,取决于合约有没有针对地址或路径的不同规则。

不经过 DEX,只是把带税代币从一个钱包转到另一个钱包,也会被扣吗?

可能会。前文提到的 token fee 定义包括买入、卖出和转账时代币收取的数额。Solana 的 TransferFeeConfig 扩展则是对该 mint 的每一笔转账收费。EVM 链上具体扣不扣、扣多少,要看那个合约自己的代码。

Solana 上的代币税改了以后,是马上生效吗?

不是。Solana 文档说明,SetTransferFee 更新 newerTransferFee,从两个 epoch 之后开始生效。当前 epoch 达到 newerTransferFee.epoch 时用 newer,否则看 older;两组相同也不能据此判断更新历史。