如何检测发送至合约的代币?通过receive/fallback识别非ETH类代币地址
检测发送至合约的币/代币类型
原生币(ETH/BNB等)的处理
当用户直接向合约转账原生币时,会触发合约的receive()或fallback()函数。这类原生资产没有合约地址,可通过msg.value确认转账金额,直接判定为链原生币。
示例代码:
receive() external payable { emit NativeReceived(msg.sender, msg.value); } event NativeReceived(address indexed sender, uint256 amount);
ERC20类代币的核心检测方法
重要提示:直接向合约转账ERC20代币不会触发receive()或fallback()——因为ERC20转账本质是调用代币自身合约的transfer/transferFrom方法,而非直接向你的合约发送资产。要获取代币地址,需通过ERC20标准的回调机制实现:
实现步骤
- 实现
IERC20Receiver接口的onERC20Received函数,当代币合约完成转账后,会自动调用该函数并传入代币地址参数。 - 函数需返回指定的selector值,否则代币合约会回滚转账。
示例代码:
pragma solidity ^0.8.0; interface IERC20Receiver { function onERC20Received(address operator, address from, address token, uint256 amount, bytes calldata data) external returns (bytes4); } contract TokenDetector is IERC20Receiver { event ERC20Received(address indexed from, address indexed token, uint256 amount); function onERC20Received(address operator, address from, address token, uint256 amount, bytes calldata data) external override returns (bytes4) { // `token` 参数即为转入的代币合约地址(如WBNB、BUSD的地址) emit ERC20Received(from, token, amount); // 必须返回该selector以确认接收 return IERC20Receiver.onERC20Received.selector; } // 处理原生币的receive函数 receive() external payable { emit NativeReceived(msg.sender, msg.value); } event NativeReceived(address indexed sender, uint256 amount); }
常见误区
- 不要尝试在
fallback()中获取ERC20代币地址:fallback()仅在调用合约不存在的函数且附带原生币时触发,与ERC20转账无关。 - 必须返回正确的selector:合规的ERC20代币会验证接收合约的回调返回值,返回错误会导致转账失败。
- 若仅需处理特定代币,可监听该代币的
Transfer事件,但通用场景下回调函数更直接可靠。
内容的提问来源于stack exchange,提问作者hertac
相关产品推荐
相关产品推荐

