ERC20代币授权异常问题:如何将授权支出方从本地测试网站切换为1inch DEX
问题分析与解决方案
首先,我们来拆解你遇到的两个核心问题:
1. 授权对象错误的根本原因:链ID不匹配
你的代码中存在链ID不一致的关键问题:
- 你调用1inch健康检查接口时用的是BSC链ID(
56),但获取授权spender地址、代币列表和calldata时,却用了以太坊主网的链ID(1)。 - 你的目标代币PPAY(
0x0a50c93c762fdd6e56d86215c24aaad43ab629aa)是部署在BSC上的,必须使用BSC对应的1inch API端点,否则生成的calldata会指向以太坊主网的1inch地址,甚至导致授权逻辑完全错误。
2. 对Metamask提示的误解
Metamask显示“Allow Http://localhost:1234 to spend your PPAY”是正常的提示逻辑:它只是告诉你发起授权请求的网站是本地测试站,但实际被授权的支出方是包含在交易data字段里的合约地址(也就是1inch的地址)。只要calldata正确,授权对象就是1inch,而非你的本地网站。
修改步骤
步骤1:统一所有1inch API的链ID为BSC(56)
将代码中所有1inch API路径里的1替换为56,确保和你的代币所在链一致:
// 原错误代码(链ID=1,以太坊主网) // let url1 = "https://api.1inch.exchange/v3.0/1/approve/spender"; // let url2 = "https://api.1inch.exchange/v3.0/1/tokens"; // let url3 = "https://api.1inch.exchange/v3.0/1/approve/calldata?amount="+amount+"&tokenAddress="+selected_coin; // 修改后(链ID=56,对应BSC) let url1 = "https://api.1inch.exchange/v3.0/56/approve/spender"; let url2 = "https://api.1inch.exchange/v3.0/56/tokens"; let url3 = "https://api.1inch.exchange/v3.0/56/approve/calldata?amount="+amount+"&tokenAddress="+selected_coin;
步骤2:添加链ID检查(可选但推荐)
在发起交易前,检查用户钱包当前连接的链是否为BSC,避免因链不匹配导致交易失败:
// 在approveTokenSpent函数开头添加 const currentChainId = await ethereum.request({ method: 'eth_chainId' }); // BSC的链ID十六进制为0x38 if (currentChainId !== '0x38') { alert('请切换到BSC网络后再操作'); return; }
步骤3:验证生成的calldata(调试用)
在获取transactionParameters后,打印data字段,确认其中包含BSC的1inch授权地址(0x1111111254EEB25477B68fb85Ed929f73A960582):
const transactionParameters = await fetch(url3) .then(res => res.json()) .then(data1 => { console.log("生成的calldata: ", data1.data); const transactionParameters = { to: data1['to'], from: user_address[0], value: "0", data: data1['data'] }; return transactionParameters });
修改后的完整代码片段(关键部分)
approveTokenSpent = async () => { console.log("Approve v1"); const user_address = await checkEthereumAddress(); console.log(user_address); // 新增:检查当前链是否为BSC const currentChainId = await ethereum.request({ method: 'eth_chainId' }); if (currentChainId !== '0x38') { alert('请切换到BSC网络后再操作'); return; } const selected_coin = document.getElementById("select_coin1").value; var amount = document.getElementById("amount1").value; amount = amount * 1000000000000000000; console.log("SELECTED COIN " + selected_coin + " AMOUNT " + amount); let url = "https://api.1inch.exchange/v3.0/56/healthcheck"; answer = await urlSend(url); console.log("1inch status: "); if(answer.status === "OK") { console.log(answer.status); // 修改:使用BSC链ID的API let url1 = "https://api.1inch.exchange/v3.0/56/approve/spender"; let url2 = "https://api.1inch.exchange/v3.0/56/tokens"; console.log(url1); const address_spender = await fetch(url1) .then( res => res.json() ) .then( data => { console.log(data); return data }); console.log(url2); const tokens = await fetch(url2) .then( res => res.json() ) .then( data => { console.log(data); return data }); console.log(tokens.tokens["0x0a50c93c762fdd6e56d86215c24aaad43ab629aa"]); address_spender_new = address_spender["address"] console.log(address_spender["address"]); console.log(typeof(address_spender_new)); // 修改:使用BSC链ID的calldata API let url3 = `https://api.1inch.exchange/v3.0/56/approve/calldata?amount=${amount}&tokenAddress=${selected_coin}`; console.log("URL3 before tp"); console.log(url3); const transactionParameters = await fetch(url3) .then( res => res.json() ) .then( data1 => { console.log("url3 data: ", data1); // 调试:打印calldata确认spender地址 console.log("calldata: ", data1.data); const transactionParameters = { to: data1['to'], from: user_address[0], value: "0", data: data1['data'] }; return transactionParameters }); try { const txHash = await ethereum.request({ method: 'eth_sendTransaction', params: [transactionParameters], }); console.log("交易哈希: ", txHash); } catch (error) { if (error.code === 4001) { alert("用户拒绝了交易签名。") } else { alert(`交易错误: ${error.message}`) } } return address_spender } else { console.log(answer.status); } }
验证修改效果
修改完成后:
- 确保钱包切换到BSC网络;
- 发起授权请求,Metamask仍会显示“localhost:1234发起请求”,但实际授权的支出方是1inch的BSC合约地址;
- 你可以在BSC浏览器上查询该代币的
allowance方法,验证授权对象是否为1inch的地址。
内容的提问来源于stack exchange,提问作者Mariusz Sidorowicz
相关产品推荐
相关产品推荐

