Skip to content

Commit

Permalink
improve: Upgrade fill/deposit comparison utils (#549)
Browse files Browse the repository at this point in the history
This pivots fill comparison for v3 towards using relay data hashes. This
is simpler code and should also be safer, since this code inherits
existing assurances about the RelayData being complete.
  • Loading branch information
pxrl committed Feb 12, 2024
1 parent a201093 commit 56d371d
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 47 deletions.
77 changes: 32 additions & 45 deletions src/utils/FlowUtils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Deposit, Fill } from "../interfaces";
import { isV2Deposit, isV3Deposit, isV2Fill, isV3Fill } from "./V3Utils";
import { Deposit, Fill, RelayData, SlowFillRequest, V2RelayData, V3Fill } from "../interfaces";
import { getV2RelayHash, getV3RelayHash } from "./SpokeUtils";
import { isV2Deposit, isV2RelayData, isV3Deposit, isV2Fill, isV3Fill } from "./V3Utils";

export const FILL_DEPOSIT_COMPARISON_KEYS = [
"depositId",
Expand Down Expand Up @@ -31,61 +32,47 @@ export const V3_DEPOSIT_COMPARISON_KEYS = [

export function filledSameDeposit(fillA: Fill, fillB: Fill): boolean {
if (isV2Fill(fillA) && isV2Fill(fillB)) {
return (
fillA.depositId === fillB.depositId &&
fillA.originChainId === fillB.originChainId &&
fillA.amount.eq(fillB.amount) &&
fillA.destinationChainId === fillB.destinationChainId &&
fillA.relayerFeePct.eq(fillB.relayerFeePct) &&
fillA.recipient === fillB.recipient &&
fillA.depositor === fillB.depositor &&
fillA.message === fillB.message
);
return getV2RelayHash(fillA) === getV2RelayHash(fillB);
} else if (isV3Fill(fillA) && isV3Fill(fillB)) {
return (
fillA.depositId === fillB.depositId &&
fillA.originChainId === fillB.originChainId &&
fillA.destinationChainId === fillB.destinationChainId &&
fillA.recipient === fillB.recipient &&
fillA.depositor === fillB.depositor &&
fillA.inputToken === fillB.inputToken &&
fillA.outputToken === fillB.outputToken &&
fillA.message === fillB.message &&
fillA.inputAmount.eq(fillB.inputAmount) &&
fillA.outputAmount.eq(fillB.outputAmount) &&
fillA.fillDeadline === fillB.fillDeadline &&
fillA.exclusivityDeadline === fillB.exclusivityDeadline &&
fillA.exclusiveRelayer === fillB.exclusiveRelayer
);
const { destinationChainId: chainA } = fillA;
const { destinationChainId: chainB } = fillB;
return getV3RelayHash(fillA, chainA) === getV3RelayHash(fillB, chainB);
}

return false;
}

// Ensure that each deposit element is included with the same value in the fill. This includes all elements defined
// by the depositor as well as the realizedLpFeePct and the destinationToken, which are pulled from other clients.
export function validateFillForDeposit(fill: Fill, deposit?: Deposit, fillFieldsToIgnore: string[] = []): boolean {
export function validateFillForDeposit(
relayData: RelayData & { destinationChainId: number }, // V2Deposit, V3Fill, SlowFillRequest...
deposit?: Deposit,
fillFieldsToIgnore: string[] = []
): boolean {
if (deposit === undefined) {
return false;
}

if (isV2Deposit(deposit) && isV2Fill(fill)) {
return V2_DEPOSIT_COMPARISON_KEYS.every((key) => {
if (fillFieldsToIgnore.includes(key)) {
return true;
}
return fill[key] !== undefined && fill[key].toString() === deposit[key]?.toString();
});
return isV2RelayData(relayData)
? validateV2FillForDeposit(relayData, deposit, fillFieldsToIgnore)
: validateV3FillForDeposit(relayData, deposit);
}

function validateV2FillForDeposit(fill: V2RelayData, deposit: Deposit, fillFieldsToIgnore: string[] = []): boolean {
if (!isV2Deposit(deposit)) {
return false;
}

if (isV3Deposit(deposit) && isV3Fill(fill)) {
return V3_DEPOSIT_COMPARISON_KEYS.every((key) => {
if (fillFieldsToIgnore.includes(key)) {
return true;
}
return fill[key] !== undefined && fill[key].toString() === deposit[key]?.toString();
});
return V2_DEPOSIT_COMPARISON_KEYS.every((key) => {
if (fillFieldsToIgnore.includes(key)) {
return true;
}
return fill[key] !== undefined && fill[key].toString() === deposit[key]?.toString();
});
}

function validateV3FillForDeposit(fill: V3Fill | SlowFillRequest, deposit: Deposit): boolean {
if (!isV3Deposit(deposit)) {
return false;
}

return false;
return getV3RelayHash(fill, fill.destinationChainId) === getV3RelayHash(deposit, deposit.destinationChainId);
}
4 changes: 2 additions & 2 deletions src/utils/SpokeUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ export function getRelayDataHash(relayData: RelayData, destinationChainId?: numb
* @param relayData V2RelayData information that is used to complete a fill.
* @returns The corresponding RelayData hash.
*/
function getV2RelayHash(relayData: V2RelayData): string {
export function getV2RelayHash(relayData: V2RelayData): string {
return ethersUtils.keccak256(
ethersUtils.defaultAbiCoder.encode(
[
Expand Down Expand Up @@ -215,7 +215,7 @@ function getV2RelayHash(relayData: V2RelayData): string {
* @param destinationChainId Supplementary destination chain ID required by V3 hashes.
* @returns The corresponding RelayData hash.
*/
function getV3RelayHash(relayData: V3RelayData, destinationChainId: number): string {
export function getV3RelayHash(relayData: V3RelayData, destinationChainId: number): string {
return ethersUtils.keccak256(
ethersUtils.defaultAbiCoder.encode(
[
Expand Down

0 comments on commit 56d371d

Please sign in to comment.