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

如何修复合约调用中的Invalid Signature错误及生成正确签名

解决方案:生成正确签名修复Invalid Signature错误

错误原因

你的签名生成逻辑和合约验证逻辑不匹配,核心差异有两点:

  1. 参数打包方式不一致:合约用abi.encodePacked紧凑打包参数后哈希,而你用solidityKeccak256结合类型数组的方式,本质是基于abi.encode(带内存对齐的打包)生成哈希,两者结果完全不同。
  2. 缺少以太坊签名前缀:合约通过ECDSA.toEthSignedMessageHash给原始哈希添加了以太坊标准签名前缀(\x19Ethereum Signed Message:\n32),但你的代码直接签名了原始哈希,未添加该前缀。

修正后的代码

替换原签名生成部分的逻辑即可,以下是完整修正后的lending函数:

const lending = async () => {
  const id = 992581;
  const tokenId = 16587857756452;
  const price = 500000000000;
  const expiredAt = Date.now() + 60;

  // 1. 对应合约的abi.encodePacked,紧凑打包参数
  const packedParams = ethers.utils.solidityPack(
    ["uint256", "uint256", "uint256", "uint256"],
    [id, tokenId, price, expiredAt]
  );
  // 2. 计算打包后的原始哈希
  const criteriaMessageHash = ethers.utils.keccak256(packedParams);
  
  // 3. 用signer直接签名,自动处理以太坊签名前缀,和合约逻辑匹配
  const signatureString = await signer.signMessage(ethers.utils.arrayify(criteriaMessageHash));

  const tx = await contract.lending(
    id,
    tokenId,
    price,
    expiredAt,
    signatureString,
    {
      gasLimit: 500000, // 建议提高gasLimit,避免因gas不足交易失败
    }
  );
  const receipt = await tx.wait();

  console.log(receipt);
};

额外注意事项

  • 确保privateKey对应的地址,和合约中signer变量指定的地址完全一致,否则签名验证必然失败。
  • 原代码中gasLimit设为50000过低,BSC链上合约调用通常需要更高的gas,调整为500000可有效避免gas不足问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 12:46:14