-
Hi, I'm using Ethers v6 with Openzeppelin contracts Here are the relevant parts for verification in the contract: // data structure that is used in verification
struct OrderRequest {
address buyer;
uint orderType;
uint amount;
uint paymentTokenAmount;
uint timestamp;
bytes32 nonce;
}
// typehash
bytes32 public constant ORDER_REQUEST_TYPEHASH =
keccak256(
"OrderRequest(address buyer,uint orderType,uint amount,uint paymentTokenAmount,uint timestamp,bytes32 nonce)"
);
// validation function itself
function _validateSigner(
OrderRequest calldata orderRequest,
bytes calldata signature
) internal virtual view returns (bool) {
bytes32 structHash = keccak256(
abi.encode(
ORDER_REQUEST_TYPEHASH,
orderRequest.buyer,
orderRequest.orderType,
orderRequest.amount,
orderRequest.paymentTokenAmount,
orderRequest.timestamp,
orderRequest.nonce
)
);
address signer = ECDSA.recover(
MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash),
signature
);
return signer == orderSigner; // order signer is a known address
}
And here's how the data is signed in the tests: const domain = {
name: 'OrderBook',
version: '1',
chainId: 31337,
verifyingContract: orderbookAddress
};
const types = {
OrderRequest: [
{ name: 'buyer', type: 'address' },
{ name: 'orderType', type: 'uint' },
{ name: 'amount', type: 'uint' },
{ name: 'paymentTokenAmount', type: 'uint' },
{ name: 'timestamp', type: 'uint' },
{ name: 'nonce', type: 'bytes32' }
]
};
let value = {
buyer: buyerAddress,
orderType: order,
amount: waterAmount,
paymentTokenAmount: paymentAmount,
timestamp: time,
nonce: nonceValue
};
let signature = await signer.signTypedData(domain, types, value); I double and triple-checked that signer indeed is the same address as used in tests and the order of submitted parameters is correct and as intended, both in tests and contract. Not sure what can be wrong, would appreciate any advice. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
The issue was resolved by changing uint type in the typehash to explicit uint256 type in Solidity, with the same change to type used in Ethers-using code: bytes32 public constant ORDER_REQUEST_TYPEHASH =
keccak256(
"OrderRequest(address buyer,uint orderType,uint amount,uint paymentTokenAmount,uint timestamp,bytes32 nonce)"
); to bytes32 public constant ORDER_REQUEST_TYPEHASH =
keccak256(
"OrderRequest(address buyer,uint256 orderType,uint256 amount,uint256 paymentTokenAmount,uint256 timestamp,bytes32 nonce)"
); and on Ethers side const types = {
OrderRequest: [
{ name: 'buyer', type: 'address' },
{ name: 'orderType', type: 'uint' },
{ name: 'amount', type: 'uint' },
{ name: 'paymentTokenAmount', type: 'uint' },
{ name: 'timestamp', type: 'uint' },
{ name: 'nonce', type: 'bytes32' }
]
}; to const types = {
OrderRequest: [
{ name: 'buyer', type: 'address' },
{ name: 'orderType', type: 'uint256' },
{ name: 'amount', type: 'uint256' },
{ name: 'paymentTokenAmount', type: 'uint256' },
{ name: 'timestamp', type: 'uint256' },
{ name: 'nonce', type: 'bytes32' }
]
}; I hope it helps someone who's got stuck on the same thing :) |
Beta Was this translation helpful? Give feedback.
The issue was resolved by changing uint type in the typehash to explicit uint256 type in Solidity, with the same change to type used in Ethers-using code:
to
and on Ethers side