viem
Version:
83 lines (74 loc) • 2.9 kB
text/typescript
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 { getAction } from '../../utils/getAction.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<TChain extends Chain | undefined>(
client: Client<Transport, TChain>,
{ address, hash, signature, ...callRequest }: VerifyHashParameters,
): Promise<VerifyHashReturnType> {
const signatureHex = isHex(signature) ? signature : toHex(signature)
try {
const { data } = await getAction(
client,
call,
'call',
)({
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
}
}