import type { Address } from 'abitype' import type { Client } from '../../clients/createClient.js' import type { Transport } from '../../clients/transports/createTransport.js' import { universalSignatureValidatorAbi } from '../../constants/abis.js' import { universalSignatureValidatorByteCode } from '../../constants/contracts.js' import { CallExecutionError } from '../../errors/contract.js' import type { ErrorType } from '../../errors/utils.js' import type { Chain } from '../../types/chain.js' import type { ByteArray, Hex } from '../../types/misc.js' import type { EncodeDeployDataErrorType } from '../../utils/abi/encodeDeployData.js' import { type IsBytesEqualErrorType, isBytesEqual, } from '../../utils/data/isBytesEqual.js' import type { IsHexErrorType } from '../../utils/data/isHex.js' import type { ToHexErrorType } from '../../utils/encoding/toHex.js' import { encodeDeployData, isHex, toHex } from '../../utils/index.js' import { type CallErrorType, type CallParameters, call } from './call.js' export type VerifyHashParameters = Pick< CallParameters, 'blockNumber' | 'blockTag' > & { /** The address that signed the original message. */ address: Address /** The hash to be verified. */ hash: Hex /** The signature that was generated by signing the message with the address's private key. */ signature: Hex | ByteArray } export type VerifyHashReturnType = boolean export type VerifyHashErrorType = | CallErrorType | IsHexErrorType | ToHexErrorType | IsBytesEqualErrorType | EncodeDeployDataErrorType | ErrorType /** * Verifies a message hash on chain using ERC-6492. * * @param client - Client to use. * @param parameters - {@link VerifyHashParameters} * @returns Whether or not the signature is valid. {@link VerifyHashReturnType} */ export async function verifyHash( client: Client, { address, hash, signature, ...callRequest }: VerifyHashParameters, ): Promise { const signatureHex = isHex(signature) ? signature : toHex(signature) try { const { data } = await call(client, { data: encodeDeployData({ abi: universalSignatureValidatorAbi, args: [address, hash, signatureHex], bytecode: universalSignatureValidatorByteCode, }), ...callRequest, } as unknown as CallParameters) return isBytesEqual(data ?? '0x0', '0x1') } catch (error) { if (error instanceof CallExecutionError) { // if the execution fails, the signature was not valid and an internal method inside of the validator reverted // this can happen for many reasons, for example if signer can not be recovered from the signature // or if the signature has no valid format return false } throw error } }