如何在JavaScript中获取IERC20代币地址供合约调用
解答
固定ERC20代币地址的存储方式
你要求合约仅接收指定单种ERC20代币的场景下,代币地址不需要从MetaMask、链上或者用户端动态获取,直接作为常量硬编码在前端JS代码里即可——每个ERC20代币在对应链上的部署地址是固定不变的,你对接哪个代币,就把对应链上该代币的合约地址存为JS常量。
如果需要支持多网络部署,直接按链ID做地址映射表即可,参考:
// 不同链ID对应网络下,你允许接入的唯一ERC20代币地址 const ALLOWED_TOKEN = { 1: "0x以太坊主网目标代币合约地址", 5: "0xGoerli测试网目标代币合约地址", 56: "0xBSC主网目标代币合约地址" }
注意:绝对不要把用户输入、前端URL参数里的地址作为可信地址传入合约,前端限制可以被轻易绕过,你的智能合约层必须加对应校验:仅当传入的代币地址等于你预设的白名单地址时,才执行后续逻辑。
目标代币地址的获取逻辑
- 连接钱包后先获取用户当前所在的链ID,以ethers库为例:
const provider = new ethers.providers.Web3Provider(window.ethereum); const { chainId } = await provider.getNetwork();
- 直接从你提前写好的固定映射表中取对应链的代币地址即可,不需要额外发起请求:
const TOKENADDRESS = ALLOWED_TOKEN[chainId]; // 加层校验,当前链没配置对应代币时提示用户切链 if (!TOKENADDRESS) { alert("当前网络不支持,请切换到对应合规网络后重试"); return; }
现有代码的关键错误修正
你现在写的调用逻辑有核心误区:交易参数里的{value: xxx}是用来附带转账原生链币(比如ETH、BNB)的,和ERC20代币转账完全无关。
要让你的业务合约顺利收到用户的ERC20代币,必须走「先授权、后转账」的标准流程:
- 第一步:实例化目标ERC20代币合约,调用
approve方法给你的业务合约授权对应额度的代币使用权 - 第二步:等授权交易上链确认后,再调用业务合约的
getFunds方法,由业务合约通过之前的授权,从用户钱包划扣对应数量的ERC20代币
修正后的参考代码如下:
const placeFunds = async (side, e) => { e.preventDefault(); const provider = new ethers.providers.Web3Provider(window.ethereum); const signer = provider.getSigner(); const { chainId } = await provider.getNetwork(); const TOKENADDRESS = ALLOWED_TOKEN[chainId]; if (!TOKENADDRESS) { alert("当前网络未支持目标代币,请切换网络后重试"); return; } const inputAmount = e.target.elements[0].value; // 实例化ERC20合约,先做授权 const erc20 = new ethers.Contract( TOKENADDRESS, ["function approve(address spender, uint256 amount) external returns (bool)"], signer ); // 注意parseUnits的第二个参数要替换成对应代币的精度,比如USDC是6,常规ERC20是18 const parsedAmount = ethers.utils.parseUnits(inputAmount, 18); const approveTx = await erc20.approve(contract.address, parsedAmount); await approveTx.wait(); // 等待授权交易确认 // 授权完成后调用业务合约存币方法,不需要传value字段(除非你要同时转原生币) await contract.getFunds(side, TOKENADDRESS); }
内容的提问来源于stack exchange,提问作者adam
相关产品推荐
相关产品推荐

