0

I am trying to sign typed data via MetaMask "eth_signTypedData_v4". Recovering signer via recoverTypedSignature_v4 returns correct address that I signed my data with. But smart contract returns random address every time as ecrecover output. Can't understand what is wrong with the code.

JS:

 //constructing a thing
 
    const EIP712Domain = [
      { name: 'name', type: 'string' },
      { name: 'version', type: 'string' },
      { name: 'chainId', type: 'uint256' },
      { name: 'verifyingContract', type: 'address' }
    ]

    const domain = {
      name: 'SomeName', //(replaced from original value)
      version: '1',
      chainId: 500, //(replaced from original value)
      verifyingContract: '0xd093dD097772300939Ec1ED7482B415bd43D9246'
    }

    const SomeObject = [
      { name: 'someAddress', type: 'address' },
      { name: 'someAddressTwo', type: 'address' },
      { name: 'someAddressThree', type: 'address' },
      { name: 'value', type: 'uint256' },
      { name: 'valueTwo', type: 'uint256' },
      { name: 'someAddressFour', type: 'address' },
      { name: 'deadline', type: 'uint256' }
    ]

    const message = {
      someAddress: account,
      someAddressTwo: from,
      someAddressThree: to,
      value: '1000000000000000000',
      valueTwo: '17',
      someAddressFour: account,
      deadline: deadline.toString()
    }

    const data = JSON.stringify({
      types: {
        EIP712Domain,
        SomeObject
      },
      domain,
      primaryType: 'SomeObject',
      message
    })

 //signing

    library?.send('eth_signTypedData_v4', [account, data])
      .then(sig => {
        return splitSignature(sig)
      })
      .then(signature => {
        return signature
      })

//using signature in smart contract call

      const args = [
      account,
      from,
      to,
      '1000000000000000000',
      '17',
      account,
      deadline.toString(),
      signature?.v,
      signature?.r,
      signature?.s
      ]

      const response = await mainContract?.doSomething(args)
    

Smart contract side:

    function doSomething(SomeObject memory someobject) public {

        bytes32 hash = someobject.hash();
        address signer = EIP712.recover(DOMAIN_SEPARATOR, hash, someobject.v, someobject.r, someobject.s);

        //failing here

        require(signer != address(0) && signer == someobject.someAddress, "wrong signature");

    }

    struct SomeObject {
        address someAddress;
        address someAddressTwo;
        address someAddressThree;
        uint256 value;
        uint256 valueTwo;
        address someAddressFour;
        uint256 deadline;
        uint8 v;
        bytes32 r;
        bytes32 s;
    }

    function recover(
        bytes32 DOMAIN_SEPARATOR,
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        bytes32 digest = keccak256(abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR, hash));
        return ecrecover(digest, v, r, s);
    }

   function hash(SomeObject memory someobject) internal pure returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    SOMEOBJECT_TYPEHASH,
                    someobject.someAddress,
                    someobject.someAddressTwo,
                    someobject.someAddressThree,
                    someobject.value,
                    someobject.valueTwo,
                    someobject.someAddressFour,
                    someobject.deadline
                )
            );
    }

    constructor() public {
        uint256 chainId;
        assembly {
            chainId := chainid()
        }
        DOMAIN_SEPARATOR = keccak256(
            abi.encode(
                keccak256("EIP712Domain(string name,string version,uint256 chainId,address 
    verifyingContract)"),
                keccak256("SomeName"),
                keccak256("1"),
                chainId,
                address(this)
            )
        );
    }
0

Nvm, it is working now. Had wrong elements order (fixed prior to making this question) in array const SomeObject = [...] which messed the whole thing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.