Keccak256(abi.encode()) and ethers.solidityPackedKeccak256 give different hashes

Hey guys, I encountered a strange bug when using from OpenZeppelin. I'm currently using Hardhat and the latest version of OpenZeppelin. Here's a brief overview of the problem:

I have defined a MintRequest struct in Solidity like this:

struct MintRequest {
address buyer;
uint256 price;
uint256 deadline;
bytes32 requestId;
string did;
}

function getABIEncoded(MintRequest calldata request) public pure returns (bytes32) {
    return keccak256(abi.encode(request));
}

On the JavaScript side, I'm using ethers.js to create a corresponding hash:

const mintRequest = {
buyer: "0x41D69fdA39725F587058ca0B7a76AFb5c3E999d8",
did: "did:example:123",
price: 100000n,
deadline: 100000000,
requestId: requestId,
};

const hash = ethers.solidityPackedKeccak256(
["address", "uint256", "uint256", "bytes32", "string"],
[mintRequest.buyer, mintRequest.price, mintRequest.deadline, mintRequest.requestId, mintRequest.did]
);

The resulting hashes are different.
I am looking for insights into what might be going wrong here.

Edit:
Tried this way too, still not works

const hash = ethers.keccak256(
    abiCoder.encode(
        ["address", "uint256", "uint256", "bytes32", "bytes32"],
        [mintRequest.buyer, mintRequest.price, mintRequest.deadline, mintRequest.requestId, mintRequest.did]
    )
);
  1. When I call abi.encode(request) onchain, I found that

0x0000000000000000000000000000000000000000000000000000000000000020

was added to the beginning.

  1. I call keccak256(abi.encode(request)) onchain, and sign the hash using ethers.signMessage(). The contract still could not verify the signature.
1 Like