Remix IDE与Ethers.js调用合约firstStage返回值不一致问题
问题分析与解决方案:Ethers.js调用firstStage返回challenge为0的原因
问题根源
你在JavaScript代码里用callStatic调用registerDevice方法,但callStatic是模拟调用——它只会计算函数返回值,不会向区块链发送交易,也不会修改合约的状态(比如你的devChals映射)。所以哪怕registerDevice返回了正确值,链上根本没存储设备的challenge和response数据,后续调用firstStage自然读不到,只能返回0。
而在Remix里调用时,你是直接发送了写入交易,合约状态被正常更新,所以firstStage能拿到正确的challenge值。
修复方案
把registerDevice的调用从callStatic改成正常的交易调用,等交易上链后再调用firstStage。另外注意signer.getAddress()是异步方法,必须用await获取实际地址。
修改后的JavaScript代码:
const {ethers} = require('ethers'); const provider = new ethers.providers.JsonRpcProvider(`HTTP://127.0.0.1:7545`); const signer = new ethers.Wallet("<wallet private key>", provider); const address = '<hex address>'; // smart contract address const ERC20_ABI = [ "function registerDevice(address, uint256, uint256) public returns(uint256, uint256)", "function firstStage(address) public returns(uint256, uint256, string)" ] const contract = new ethers.Contract(address, ERC20_ABI, provider); const contractWithSigner = contract.connect(signer); const main = async() => { var challenge = 103697318762117; var response = 83968343435925; // 改为正常交易调用,等待交易上链确认状态更新 const tx = await contractWithSigner.registerDevice(await signer.getAddress(), challenge, response); await tx.wait(); // 可选:用callStatic验证注册结果 const regDev = await contractWithSigner.callStatic.registerDevice(await signer.getAddress(), challenge, response); const {0: challengeReg, 1: responseReg} = regDev; console.log(`${challengeReg} ${responseReg}\n\n`); const firstStage = await contractWithSigner.callStatic.firstStage(await signer.getAddress()); const {0: challengeFirstStage, 1: MnodeFirstStage, 2: HnodeFirstStage} = firstStage; console.log(firstStage, challengeFirstStage, MnodeFirstStage.toNumber(), HnodeFirstStage); } main();
额外提醒
callStatic只适合只读函数或者需要提前算返回值但不修改状态的场景,对会改合约状态的写入函数,必须用正常交易调用(不带callStatic)。- 调用
signer.getAddress()一定要加await,不然会传入Promise对象而非实际地址,可能导致后续操作异常。
内容的提问来源于stack exchange,提问作者Arka Seth
相关产品推荐
相关产品推荐

