From 8cabdbd15195d2940bf7bafcfdd3f77560056935 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Thu, 10 Apr 2025 21:06:43 +0000 Subject: [PATCH] improve(SpokeUtils): Use viem for RelayData hash computation The Viem ABI encoder permits supplying the ABI as an object, which is faster than ethers, which apparently requires that the ABI be supplied to AbiCoder.encode() as a string, which implies re-parsing the same ABI on each call. Brief testing showed that the new implementation is 50% faster than the existing one. Producing 500 RelayData hashes with each approach took 0.5 seconds with viem and 1 second with ethers. This is relevant in the relayer because performs bulk fillStatus queries of up to 250 RelayData hashes per chain on update. --- src/utils/SpokeUtils.ts | 50 ++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/utils/SpokeUtils.ts b/src/utils/SpokeUtils.ts index 696bd7c69..95e7166b3 100644 --- a/src/utils/SpokeUtils.ts +++ b/src/utils/SpokeUtils.ts @@ -1,8 +1,7 @@ -import { utils as ethersUtils } from "ethers"; +import { encodeAbiParameters, keccak256 } from "viem"; import { MAX_SAFE_DEPOSIT_ID, ZERO_ADDRESS, ZERO_BYTES } from "../constants"; import { Deposit, RelayData } from "../interfaces"; import { toBytes32 } from "./AddressUtils"; -import { keccak256 } from "./common"; import { BigNumber } from "./BigNumberUtils"; import { isMessageEmpty } from "./DepositUtils"; @@ -35,6 +34,27 @@ export function getDepositRelayData(deposit: Omit): Rela * @returns The corresponding RelayData hash. */ export function getRelayDataHash(relayData: RelayData, destinationChainId: number): string { + const abi = [ + { + type: "tuple", + components: [ + { type: "bytes32", name: "depositor" }, + { type: "bytes32", name: "recipient" }, + { type: "bytes32", name: "exclusiveRelayer" }, + { type: "bytes32", name: "inputToken" }, + { type: "bytes32", name: "outputToken" }, + { type: "uint256", name: "inputAmount" }, + { type: "uint256", name: "outputAmount" }, + { type: "uint256", name: "originChainId" }, + { type: "uint256", name: "depositId" }, + { type: "uint32", name: "fillDeadline" }, + { type: "uint32", name: "exclusivityDeadline" }, + { type: "bytes", name: "message" }, + ], + }, + { type: "uint256", name: "destinationChainId" }, + ]; + const _relayData = { ...relayData, depositor: toBytes32(relayData.depositor), @@ -43,28 +63,8 @@ export function getRelayDataHash(relayData: RelayData, destinationChainId: numbe outputToken: toBytes32(relayData.outputToken), exclusiveRelayer: toBytes32(relayData.exclusiveRelayer), }; - return keccak256( - ethersUtils.defaultAbiCoder.encode( - [ - "tuple(" + - "bytes32 depositor," + - "bytes32 recipient," + - "bytes32 exclusiveRelayer," + - "bytes32 inputToken," + - "bytes32 outputToken," + - "uint256 inputAmount," + - "uint256 outputAmount," + - "uint256 originChainId," + - "uint256 depositId," + - "uint32 fillDeadline," + - "uint32 exclusivityDeadline," + - "bytes message" + - ")", - "uint256 destinationChainId", - ], - [_relayData, destinationChainId] - ) - ); + + return keccak256(encodeAbiParameters(abi, [_relayData, destinationChainId])); } export function getRelayHashFromEvent(e: RelayData & { destinationChainId: number }): string { @@ -87,5 +87,5 @@ export function isZeroAddress(address: string): boolean { } export function getMessageHash(message: string): string { - return isMessageEmpty(message) ? ZERO_BYTES : keccak256(message); + return isMessageEmpty(message) ? ZERO_BYTES : keccak256(message as "0x{string}"); }