Verifying TypedData signature in Solidity with uint256[]

I have a method that receives an uint256[ ] parameter. I am able to sign the message using etherjs and and create a signature. But inside my Contract when I try to verify the Signature I get an incorrect recovered signer address.
I tried the above with just a uint256 (not array) and the Verification worked. When I try it with an array it does not work.
I would like to know how to encode the method parameters correctly. (if it is an uint256 array)

The message property of my ERC712 is like this:

message: {
      tokenIds: [1,2,3],
      uri: "abcd.com"
    },

Inside my SmartContract, I am verifying the data like this:

function pauseTokens(uint256[] tokenIds, string memory uri, bytes signature) public onlyRole(ABC) {

 bytes32 digest = _hashTypedDataV4(
      keccak256(
        abi.encode(
          keccak256("MyType(uint256[] tokenIds, string uri"),
          tokenIds,                  // IS THIS the CORRECT way to encode uint256[] ?
          keccak256(uri),
        ),
     )
 );
 
address recoveredSigner = ECDSA.recover(digest, signature);   // Incorrect signer :-( 
}

I was able to get the code to work with some Trial and Error.
The correct way to encode any array is:
keccak256(abi.encodePacked(tokenIds))

So my updated code is as follows:

function pauseTokens(uint256[] memory tokenIds, string memory uri, bytes signature) public onlyRole(ABC) {

 bytes32 digest = _hashTypedDataV4(
      keccak256(
        abi.encode(
          keccak256("MyType(uint256[] tokenIds, string uri"),
          keccak256(abi.encodePacked(tokenIds)),                  // THIS is the CORRECT way
          keccak256(bytes(uri)),
        ),
     )
 );
 
address recoveredSigner = ECDSA.recover(digest, signature);   // Correct signer :-) 
}
1 Like