EIP-712 签名消息失败

EIP-712 Signing Messages fails

我有一个修改过的 truffle react box 合约,它应该符合 EIP712 标准:

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.21 <8.10.0;

contract SimpleStorage {
    string public constant name = "SimpleStorage";

    bytes32 public immutable DOMAIN_SEPARATOR;
    bytes32 public constant MESSAGE_HASH =
        keccak256("Data(address sender, uint value)");

    uint256 storedData;

    constructor() {
        uint256 chainId;
        assembly {
            chainId := chainid()
        }
        DOMAIN_SEPARATOR = keccak256(
            abi.encode(
                keccak256(
                    "EIP712Domain(string name,string version,uint256 chainId)"
                ),
                keccak256(bytes(name)),
                keccak256(bytes("1")),
                chainId
            )
        );
    }

    function setPermit(
        address sender,
        uint256 value,
        bytes memory sig
    ) external {
        bytes32 digest = keccak256(
            abi.encodePacked(
                "\x19\x01",
                DOMAIN_SEPARATOR,
                keccak256(abi.encode(MESSAGE_HASH, sender, value))
            )
        );

        bytes32 r;
        bytes32 s;
        uint8 v;

        assembly {
            r := mload(add(sig, 32))
            s := mload(add(sig, 64))
            v := byte(0, mload(add(sig, 96)))
        }

        address recoveredAddress = ecrecover(digest, v, r, s);
        require(recoveredAddress == sender, "INVALID_SIGNATURE");
        storedData = value;
    }

    function permit(
        address sender,
        uint256 value,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external {
        bytes32 digest = keccak256(
            abi.encodePacked(
                "\x19\x01",
                DOMAIN_SEPARATOR,
                keccak256(abi.encode(MESSAGE_HASH, sender, value))
            )
        );

        address recoveredAddress = ecrecover(digest, v, r, s);
        require(
            recoveredAddress != address(0) && recoveredAddress == sender,
            "INVALID_SIGNATURE"
        );
        storedData = value;
    }

    function set(uint256 x) public {
        storedData = x;
    }

    function get() public view returns (uint256) {
        return storedData;
    }
}

创建哈希结构和调用合约函数的代码:

 signMessage = async () => {
    const { web3, accounts, contract, address } = this.state;
    var signer = accounts[0];
    var value = 50; 
    const chainId = await web3.eth.getChainId();

    const domain = [
      { name: "name", type: "string" },
      { name: "version", type: "string" },
      { name: "chainId", type: "uint256" },
    ]; 
    const data = [
      { name: "sender", type: "address" },
      { name: "value", type: "uint" },
    ];

    const domainData = {
      name: "SimpleStorage",
      version: "1",
      chainId: chainId,
    }; 

    const messageData = {
      sender: signer,
      value: value,
    }; 

    const msgParams = JSON.stringify({
      types: {
        EIP712Domain: domain,
        Data: data,
      },
      domain: domainData,
      primaryType: "Data",
      message: messageData,
    });
    console.log(msgParams); 

    web3.currentProvider.sendAsync({
      method: "eth_signTypedData_v4", 
      params: [signer, msgParams], 
      from: signer
    }, async function(err, result) {
      if(err) { return console.error(err); }
      const signResult = result.result;
    
      await contract.methods.setPermit(signer, value, signResult)
      .send({ from: signer });
      const response = await contract.methods.get().call();
      this.setState({ storageValue: response });
    }); 
  };

我已经将合约部署到 Rinkeby (0x729352f7541F205226234e3B8C4ABB820c68B380),但每次我尝试使用 setPermit 函数时,我都会在 Metamask 中收到“此交易预计会失败”错误。进一步调查显示,交易fails。我该如何解决这个问题?

经常检查你的数据类型:)