BSCSCAN测试网ERC20代币交易正常但不显示持币地址求助
问题排查结论
BSCScan不展示持币地址(Holders)的核心原因是你的合约未严格遵循ERC20/BEP20标准实现,导致浏览器索引器无法正确识别代币、追踪持仓变动,同时代码还存在多个会导致余额记账错乱的逻辑bug,具体问题和修复方案如下:
核心问题点
- 标准接口命名完全不匹配,浏览器无法识别代币合规性
BSCScan识别BEP20代币的第一步是校验合约是否实现了标准接口,你的函数命名存在多处错误:- 标准余额查询接口为
balanceOf(address),你命名为Accountof(address),函数选择器完全不匹配,浏览器无法调用接口获取地址余额 - 标准授权额度查询接口为
allowance(address,address),你命名为allowances(address,address),多了一个s,不符合规范 - 标准总供应量查询接口为
totalSupply(),你额外实现了一个命名为totalsupply()的函数(s小写),会干扰接口校验
- 标准余额查询接口为
- 持仓变动未触发标准Transfer事件,浏览器无法索引余额变化
BSCScan完全依赖Transfer事件追踪所有地址的余额变动,你的代码存在多处事件缺失:- 转账扣除10%税费执行分红时,给所有持币地址增加余额的操作只触发了自定义的
reward事件,没有触发标准Transfer事件,浏览器无法感知这部分余额变动 burn函数销毁代币时,没有触发Transfer(msg.sender, address(0), amount)事件,浏览器无法统计销毁金额,总供应量校验不通过
- 转账扣除10%税费执行分红时,给所有持币地址增加余额的操作只触发了自定义的
- 存在严重逻辑bug,会导致余额记账完全错乱
transferFrom函数中扣减余额时错误扣减了调用者msg.sender的余额,而非授权方_from的余额,授权转账场景下记账完全错误removefromlist函数存在数组下标越界问题:你给用户分配的Number字段从1开始计数,但Solidity数组下标从0开始,删除元素时直接传入Number作为索引,且循环终止条件未做边界限制,会触发revert导致用户余额归零时转账失败- 分红逻辑存在余额缺口:
_charge/Usercount是整数除法,会产生余数,这部分余数没有做归集或销毁处理,会导致所有地址余额加总不等于totalSupply,浏览器校验通不过
修复步骤
- 修正所有不符合标准的接口命名
- 将
Accountof函数重命名为balanceOf - 将
allowances函数重命名为allowance - 删除自定义的
totalsupply函数,直接使用public状态变量totalSupply自动生成的标准getter接口
- 将
- 补全所有余额变动场景的
Transfer事件- 分红给每个持币地址发放奖励时,补充触发
Transfer(address(this), 持币地址, 单用户分红金额)事件 - 在
burn函数中补充emit Transfer(msg.sender, address(0), amount);
- 分红给每个持币地址发放奖励时,补充触发
- 修复逻辑bug
- 将
transferFrom函数中两处balances[msg.sender] -= _value;修改为balances[_from] -= _value;,同时确保Users映射中扣减的是_from地址的账户额度 - 修复
removefromlist下标逻辑:传入用户Number时先减1转为0基下标,循环终止条件改为i < Userlist.length - 1,避免数组越界 - 处理分红余数:整数除法产生的剩余税费可以打入创作者地址或黑洞地址,确保全地址余额总和等于
totalSupply
- 将
- 重新部署合约并在BSCScan完成开源验证,等待区块同步完成后即可正常展示持币地址列表。
内容的提问来源于stack exchange,提问作者Christian Head
相关产品推荐
相关产品推荐

