You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过MetaMask RPC API发送代币 解决tokenContract未定义问题

通过MetaMask RPC API发送USDC等ERC20代币实现方案

常见误区纠正

  • MetaMask并未停止对web3.js、ethers.js等库的支持,只是不再默认向页面注入web3全局变量,相关库需要自行安装依赖后,用MetaMask注入的window.ethereum对象初始化即可使用。
  • 旧示例中未定义的tokenContract是ERC20代币合约的实例对象,需要通过对应链上SDK初始化后才能调用方法生成交易参数。
  • Ropsten测试网已正式停止运行,测试USDC建议使用Sepolia、Goerli测试网;你示例中填写的to地址0x07865c6E87B9F70255377e024ace6630C1Eaa37F为Goerli测试网USDC合约地址,与Ropsten网络不匹配,是交易失败的常见诱因。
  • ERC20代币转账的核心逻辑是调用合约的transfer方法,交易的to字段必须填代币合约地址,接收方地址和转账金额都编码在data字段中,不要把接收方地址填在to字段里。

方案一:无第三方依赖原生实现(无版本兼容问题,最稳定)

不需要初始化合约实例,直接按照ERC20标准手动构造交易data字段即可:

// 可根据实际需求修改配置
const PARAMS = {
  tokenContract: "0x07865c6E87B9F70255377e024ace6630C1Eaa37F", // Goerli测试网USDC合约地址
  receiver: "0x替换为实际接收方钱包地址",
  amount: 100, // 对应0.0001 USDC,USDC精度为6位,0.0001 * 10^6 = 100
}
// 先请求连接钱包
await ethereum.request({ method: 'eth_requestAccounts' });
// transfer(address,uint256)方法的函数选择器为keccak256哈希前4字节,固定值0xa9059cbb
const functionSelector = '0xa9059cbb';
// 接收方地址去掉0x前缀,左侧补0至64位
const paddedReceiver = PARAMS.receiver.toLowerCase().replace('0x', '').padStart(64, '0');
// 转账金额转十六进制,去掉0x前缀,左侧补0至64位
const paddedAmount = PARAMS.amount.toString(16).padStart(64, '0');
// 拼接为完整交易data
const txData = functionSelector + paddedReceiver + paddedAmount;
// 发起交易
const txHash = await ethereum.request({
  method: "eth_sendTransaction",
  params: [
    {
      from: ethereum.selectedAddress,
      to: PARAMS.tokenContract,
      data: txData,
      value: '0x0' // 转ERC20代币时value必须为0
    }
  ]
});
console.log('交易发起成功,交易哈希:', txHash);

方案二:使用ethers.js初始化合约实例(匹配旧示例的写法)

首先安装依赖:

npm install ethers@6

代码实现:

import { ethers } from 'ethers';
// 用MetaMask注入的provider初始化签名器
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
// ERC20标准最小ABI,仅保留transfer方法即可
const MIN_ERC20_ABI = [
  "function transfer(address to, uint256 amount) returns (bool)"
];
// 初始化代币合约实例,即旧示例中缺失的tokenContract变量
const tokenContract = new ethers.Contract(
  "0x07865c6E87B9F70255377e024ace6630C1Eaa37F", // 对应代币合约地址
  MIN_ERC20_ABI,
  signer
);
// 发起转账,金额自动按USDC 6位精度换算为最小单位
const tx = await tokenContract.transfer(
  "0x替换为实际接收方钱包地址",
  ethers.parseUnits("0.0001", 6)
);
console.log('交易发起成功,交易哈希:', tx.hash);

常见踩坑点

  • 转账金额必须按对应代币的精度换算为最小单位整数,USDC精度为6位,不要直接传入小数,也不要误用以太坊原生币的18位精度换算。
  • 发起交易前需确认MetaMask已切换到对应网络,网络与合约地址不匹配会直接报错。
  • 旧教程中直接使用的全局web3对象已被MetaMask移除,如需使用web3.js需自行安装依赖后,传入window.ethereum初始化,不存在MetaMask不支持web3.js的情况。
  • transfer方法的第一个参数必须是合法的0x开头42位十六进制钱包地址,不能传入自定义别名、"My Wallet"这类非地址字符串。

内容的提问来源于stack exchange,提问作者Zac Feng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 16:15:54