如何实现合约内接收ERC20并自动转发的onReceivedERC20函数?
实现ERC20代币自动转发的合约方案
核心说明
ERC20标准没有内置的onReceived钩子函数(这是ERC721/ERC1155的特性),要实现用户转代币到合约后自动转发,通常有两种可行方式:
- 用户先给合约授权ERC20代币额度,再调用合约专用函数触发转账+转发流程(合约内自动完成)
- 依赖链下监控合约代币余额变化,主动调用合约转发函数(不属于合约内自动执行)
以下是第一种合约内自动完成转发的实现方案,匹配你需求的用户操作流程:用户授权后调用合约函数,合约直接将代币从用户地址转到指定钱包。
Solidity合约代码示例
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // 导入ERC20标准接口 interface IERC20 { function transferFrom(address from, address to, uint256 amount) external returns (bool); function transfer(address to, uint256 amount) external returns (bool); } contract ERC20Forwarder { // 固定的目标转发钱包地址 address public immutable forwardTarget; constructor(address _forwardTarget) { require(_forwardTarget != address(0), "无效的目标地址"); forwardTarget = _forwardTarget; } /** * 用户调用此函数转发指定ERC20代币到目标钱包 * 注意:调用前需先调用对应ERC20代币的approve函数,给合约授权足够额度 */ function forwardERC20(address tokenAddress, uint256 amount) external { require(tokenAddress != address(0), "无效的代币地址"); require(amount > 0, "转账金额需大于0"); // 从用户地址转代币到合约 bool success = IERC20(tokenAddress).transferFrom(msg.sender, address(this), amount); require(success, "从用户地址转账失败"); // 将代币转发到目标钱包 success = IERC20(tokenAddress).transfer(forwardTarget, amount); require(success, "转发到目标钱包失败"); } /** * 处理用户直接转ERC20到合约的情况(可选) * 由于ERC20转账不会主动触发合约函数,需用户或第三方主动调用此函数完成转发 */ function forwardReceivedTokens(address tokenAddress) external { uint256 balance = IERC20(tokenAddress).balanceOf(address(this)); require(balance > 0, "无待转发代币"); bool success = IERC20(tokenAddress).transfer(forwardTarget, balance); require(success, "转发失败"); } }
关键细节说明
- 授权前置操作:用户调用
forwardERC20前,必须先调用目标ERC20代币合约的approve函数,授权合约可转移指定数量的代币 - 错误校验:每一步转账都添加
require校验,确保操作失败时回滚交易,避免资金滞留 - 地址安全性:目标地址用
immutable修饰,部署后无法修改,降低权限风险 - 直接转账处理:若用户直接将代币转到合约,可调用
forwardReceivedTokens手动触发转发;若需完全自动,需配合链下监控服务(比如监听合约的Transfer事件,触发后调用此函数)
内容的提问来源于stack exchange,提问作者Sandip Bhujel
相关产品推荐
相关产品推荐

