50 EIP-712验证错误

etherjs和web3.js签名相同,solidity自己实现和openzeppelin验签结果地址不对 js使用了vue

ether.js

async walletSignMessage() {
  const message = {
      from: "0xE3a463d743F762D538031BAD3f1E748BB41f96ec",
          to: "0x39Ef50bd29Ae125FE10C6a909E42e1C6a94Dde29",
          value: 12345789,
    };

    const domain= {
      name: "Demo",
      version: '1.0',
    };

    const types = {
      Mail: [
        {name: 'from', type: 'address'},
        {name: 'to', type: 'address'},
        {name: 'value', type: 'uint256'},
      ],
    };

    const signature = await window.ethProvider
      .getSigner()
      ._signTypedData(domain, types, message);
    console.log("signature====" + signature);

    const address = verifyTypedData(
      domain,
      types,
      message,
      signature
    ).toLowerCase();
    console.log("验证address===" + address);
  },

web3.js

async sign111() {
  const typedData = {
    types: {
      EIP712Domain: [
        {name: 'name', type: 'string'},
        {name: 'version', type: 'string'},
      ],
      Mail: [
        {name: 'from', type: 'address'},
        {name: 'to', type: 'address'},
        {name: 'value', type: 'uint256'},
      ],
    },
    domain: {
      name: 'Demo',
      version: '1.0',
    },
    primaryType: 'Mail',
    message: {
      from: "0xE3a463d743F762D538031BAD3f1E748BB41f96ec",
      to: "0x39Ef50bd29Ae125FE10C6a909E42e1C6a94Dde29",
      value: 12345789,
    },
  }
  var privateKeyHex = Buffer.from("privateKey", 'hex')

  var signature = sigUtil.signTypedData_v4(privateKeyHex, {data: typedData})
  console.log("signature:", signature)

},

上面函数得到的结果都是 0xf1105ec987e4e3a5e03917945baab82cdb9a58be6e5475145148ec813bdc321b2604d9017d878644f650dce7923860f9f6c69f2ae21310fd27302cf7e9e4118f1c

solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/draft-EIP712.sol";

contract MyContract is EIP712 {

    constructor(string memory name, string memory version) EIP712(name, version) {
    }

    function recoverV4(
        address from,
        address to,
        uint256 value,
        bytes memory signature
    ) public view returns (address) {
        bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
        keccak256("Mail(address from,address to,uint256 value)"),
            from,
            to,
            value
        )));
        return ECDSA.recover(digest, signature);
    }
 }

solidity验签的结果就不同,求教是solidity哪里写错了吗?困在这两天了,闹心 我是想做opensea那样的对订单签名,或者有什么别的更好的签名方式吗。

吐槽一下:ETH的签名真的是太太太太太恶心了,网上的教程还都基本是千篇一律的

请先 登录 后评论

最佳答案 2022-04-14 09:15

你的代码里 Solidity 的domain 和 web3.js 的domain不一样。

代码里web3.js 的domain 需按Solidity ERC712 的标准处理: EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)

这个是签名的特性决定的,哪怕签名内容多了一个空格, 结果就完全不一样。这个其实和 ETH 无关。

请先 登录 后评论

其它 0 个回答

  • 1 关注
  • 1 收藏,3559 浏览
  • 点点点的点 提出于 2022-04-13 21:04