使用etherjs调用Solidity payable函数报需signer错误如何解决
问题原因
报错的核心原因有两个:
- 你初始化合约实例时传入的是
provider对象,该对象仅具备链上读权限,没有交易签名能力。你在调用accumulated方法时把wallet作为函数参数传入的写法是错误的——ethers.js不会把传入合约方法的signer识别为交易签名者,只会把它当做合约函数的入参处理,而绑定了provider的合约实例发起写交易时,会直接抛出缺少signer的错误。 - 你的
accumulated合约函数本身没有定义入参,你传入的第一个参数'1'属于无效入参。如果要向payable函数转ETH,需要将转账金额放在overrides配置对象中作为最后一个参数传入,不能直接作为函数入参传递。
另外你的代码里还存在两个隐性问题:
- 读取
_blockTimestamp时使用的合约实例名是NFTLTokenContract,和你前面初始化的TestContract实例名不一致,运行时会触发变量未定义错误 - 你配置的节点是Rinkeby测试网节点,私钥却是Ropsten测试网的私钥,两个测试网链ID不匹配,就算签名逻辑正确也会广播交易失败。
修正方法
有两种标准写法可以解决问题:
写法1:初始化合约时直接绑定签名者
这是最常用的实现方式,初始化合约时直接传入wallet实例(wallet本身就是集成了provider的signer对象),后续读、写操作都可以用同一个合约实例完成:
const provider = new providers.JsonRpcProvider(getEnv('RINKEBY_NODE_URL')); const wallet = new Wallet(getEnv('ROPSTEN_PRIVATE_KEY'), provider); // 第二个参数传入wallet(signer),而非仅传provider const TestContract = TestContract__factory.connect(getEnv('TEST_CONTRACT'), wallet); // 读操作无需签名,可正常调用 const _blockTimestamp = await TestContract._blockTimestamp(); // 调用payable函数,不需要转ETH时直接调用即可 const tx = await TestContract.accumulated(); // 如果需要转1wei,就传入overrides配置:const tx = await TestContract.accumulated({value: 1}); // 等待交易确认上链 await tx.wait();
写法2:临时为合约实例绑定签名者
如果你已经有绑定了provider的合约实例用于高频读操作,不想重新初始化合约,可以在发起写交易前,用connect方法临时生成绑定签名者的合约实例再调用:
const provider = new providers.JsonRpcProvider(getEnv('RINKEBY_NODE_URL')); const wallet = new Wallet(getEnv('ROPSTEN_PRIVATE_KEY'), provider); // 绑定provider的合约实例仅用于读操作 const TestContract = TestContract__factory.connect(getEnv('TEST_CONTRACT'), provider); const _blockTimestamp = await TestContract._blockTimestamp(); // 发起交易前临时绑定signer const tx = await TestContract.connect(wallet).accumulated(); // 需要转1wei时写法:const tx = await TestContract.connect(wallet).accumulated({value: 1}); await tx.wait();
调用规则说明
- 所有合约读操作(纯函数、视图函数、public变量读取):用绑定provider的合约实例即可调用,不需要签名
- 所有合约写操作(修改链上状态的函数,不管是不是payable):必须用绑定了signer的合约实例调用,否则会抛出缺少signer的错误
- payable函数如果需要转入ETH,转账金额必须放在函数调用的最后一个参数,格式为
{value: 转账金额(单位wei)}的overrides对象,不能直接作为函数入参传递。
内容的提问来源于stack exchange,提问作者ste
相关产品推荐
相关产品推荐

