Skip to content

Commit

Permalink
improve: reduce remove direct contract/rpc calls in bundle client (#723)
Browse files Browse the repository at this point in the history
Signed-off-by: james-a-morris <jaamorris@cs.stonybrook.edu>
  • Loading branch information
james-a-morris committed Sep 6, 2024
1 parent a56eb9d commit 68d656d
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 14 deletions.
8 changes: 3 additions & 5 deletions src/clients/BundleDataClient/BundleDataClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import {
getImpliedBundleBlockRanges,
isSlowFill,
mapAsync,
relayFillStatus,
bnUint32Max,
} from "../../utils";
import { BigNumber } from "ethers";
Expand Down Expand Up @@ -1125,8 +1124,7 @@ export class BundleDataClient {
) {
// If we haven't seen a fill matching this deposit, then we need to rule out that it was filled a long time ago
// by checkings its on-chain fill status.
const fillStatus = await relayFillStatus(
spokePoolClients[destinationChainId].spokePool,
const fillStatus = await spokePoolClients[destinationChainId].relayFillStatus(
deposit,
// We can assume that in production
// the block ranges passed into this function would never contain blocks where the spoke pool client
Expand Down Expand Up @@ -1313,8 +1311,8 @@ export class BundleDataClient {
const startBlockForChain = Math.min(_startBlockForChain, spokePoolClient.latestBlockSearched);
const endBlockForChain = Math.min(_endBlockForChain, spokePoolClient.latestBlockSearched);
const [startTime, endTime] = [
Number((await spokePoolClient.spokePool.provider.getBlock(startBlockForChain)).timestamp),
Number((await spokePoolClient.spokePool.provider.getBlock(endBlockForChain)).timestamp),
await spokePoolClient.getTimestampForBlock(startBlockForChain),
await spokePoolClient.getTimestampForBlock(endBlockForChain),
];
// Sanity checks:
assert(endTime >= startTime, "End time should be greater than start time.");
Expand Down
22 changes: 21 additions & 1 deletion src/clients/SpokePoolClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
Deposit,
DepositWithBlock,
Fill,
FillStatus,
FillWithBlock,
FilledV3RelayEvent,
RealizedLpFee,
Expand All @@ -38,7 +39,7 @@ import {
} from "../interfaces";
import { SpokePool } from "../typechain";
import { getNetworkName } from "../utils/NetworkUtils";
import { getBlockRangeForDepositId, getDepositIdAtBlock } from "../utils/SpokeUtils";
import { getBlockRangeForDepositId, getDepositIdAtBlock, relayFillStatus } from "../utils/SpokeUtils";
import { BaseAbstractClient, isUpdateFailureReason, UpdateFailureReason } from "./BaseAbstractClient";
import { HubPoolClient } from "./HubPoolClient";
import { AcrossConfigStoreClient } from "./AcrossConfigStoreClient";
Expand Down Expand Up @@ -883,4 +884,23 @@ export class SpokePoolClient extends BaseAbstractClient {
this.configStoreClient?.isChainLiteChainAtTimestamp(deposit.destinationChainId, deposit.quoteTimestamp) ?? false
);
}

public async getTimestampForBlock(blockTag: number): Promise<number> {
const block = await this.spokePool.provider.getBlock(blockTag);
return Number(block.timestamp);
}

/**
* Find the amount filled for a deposit at a particular block.
* @param relayData Deposit information that is used to complete a fill.
* @param blockTag Block tag (numeric or "latest") to query at.
* @returns The amount filled for the specified deposit at the requested block (or latest).
*/
public relayFillStatus(
relayData: RelayData,
blockTag?: number | "latest",
destinationChainId?: number
): Promise<FillStatus> {
return relayFillStatus(this.spokePool, relayData, blockTag, destinationChainId);
}
}
23 changes: 18 additions & 5 deletions test/SpokePoolClient.ValidateFill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
relayFillStatus,
validateFillForDeposit,
queryHistoricalDepositForFill,
DepositSearchResult,
} from "../src/utils";
import { CHAIN_ID_TEST_LIST, originChainId, destinationChainId, repaymentChainId } from "./constants";
import {
Expand Down Expand Up @@ -129,9 +130,17 @@ describe("SpokePoolClient: Fill Validation", function () {
let filled = await relayFillStatus(spokePool_2, deposit);
expect(filled).to.equal(FillStatus.Unfilled);

// Also test spoke client variant
filled = await spokePoolClient2.relayFillStatus(deposit);
expect(filled).to.equal(FillStatus.Unfilled);

await fillV3Relay(spokePool_2, deposit, relayer);
filled = await relayFillStatus(spokePool_2, deposit);
expect(filled).to.equal(FillStatus.Filled);

// Also test spoke client variant
filled = await spokePoolClient2.relayFillStatus(deposit);
expect(filled).to.equal(FillStatus.Filled);
});

it("Tracks bulk v3 fill status", async function () {
Expand Down Expand Up @@ -439,7 +448,9 @@ describe("SpokePoolClient: Fill Validation", function () {

const historicalDeposit = await queryHistoricalDepositForFill(spokePoolClient1, fill);
assert.equal(historicalDeposit.found, true, "Test is broken"); // Help tsc to narrow the discriminated union.
expect(historicalDeposit.deposit.depositId).to.deep.equal(deposit.depositId);
expect((historicalDeposit as Extract<DepositSearchResult, { found: true }>).deposit.depositId).to.deep.equal(
deposit.depositId
);
});

it("Can fetch younger deposit matching fill", async function () {
Expand Down Expand Up @@ -473,7 +484,9 @@ describe("SpokePoolClient: Fill Validation", function () {

const historicalDeposit = await queryHistoricalDepositForFill(spokePoolClient1, fill);
assert.equal(historicalDeposit.found, true, "Test is broken"); // Help tsc to narrow the discriminated union.
expect(historicalDeposit.deposit.depositId).to.deep.equal(deposit.depositId);
expect((historicalDeposit as Extract<DepositSearchResult, { found: true }>).deposit.depositId).to.deep.equal(
deposit.depositId
);
});

it("Loads fills from memory with deposit ID > spoke pool client's earliest deposit ID queried", async function () {
Expand Down Expand Up @@ -547,7 +560,7 @@ describe("SpokePoolClient: Fill Validation", function () {
const search = await queryHistoricalDepositForFill(spokePoolClient1, fill);

assert.equal(search.found, false, "Test is broken"); // Help tsc to narrow the discriminated union.
expect(search.code).to.equal(InvalidFill.DepositIdInvalid);
expect((search as Extract<DepositSearchResult, { found: false }>).code).to.equal(InvalidFill.DepositIdInvalid);
expect(lastSpyLogIncludes(spy, "Queried RPC for deposit")).is.not.true;
});

Expand All @@ -572,7 +585,7 @@ describe("SpokePoolClient: Fill Validation", function () {
const search = await queryHistoricalDepositForFill(spokePoolClient1, fill);

assert.equal(search.found, false, "Test is broken"); // Help tsc to narrow the discriminated union.
expect(search.code).to.equal(InvalidFill.DepositIdInvalid);
expect((search as Extract<DepositSearchResult, { found: false }>).code).to.equal(InvalidFill.DepositIdInvalid);
expect(lastSpyLogIncludes(spy, "Queried RPC for deposit")).is.not.true;
});

Expand All @@ -594,7 +607,7 @@ describe("SpokePoolClient: Fill Validation", function () {

const search = await queryHistoricalDepositForFill(spokePoolClient1, fill);
assert.equal(search.found, false, "Test is broken"); // Help tsc to narrow the discriminated union.
expect(search.code).to.equal(InvalidFill.FillMismatch);
expect((search as Extract<DepositSearchResult, { found: false }>).code).to.equal(InvalidFill.FillMismatch);
});

it("Returns sped up deposit matched with fill", async function () {
Expand Down
7 changes: 4 additions & 3 deletions test/SpokePoolClient.fills.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import hre from "hardhat";
import { SpokePoolClient } from "../src/clients";
import { V3Deposit } from "../src/interfaces";
import { Deposit } from "../src/interfaces";
import { bnOne, findFillBlock, getNetworkName } from "../src/utils";
import { EMPTY_MESSAGE, ZERO_ADDRESS } from "../src/constants";
import { originChainId, destinationChainId } from "./constants";
Expand All @@ -24,7 +24,7 @@ describe("SpokePoolClient: Fills", function () {
let depositor: SignerWithAddress, relayer1: SignerWithAddress, relayer2: SignerWithAddress;
let spokePoolClient: SpokePoolClient;
let deploymentBlock: number;
let deposit: V3Deposit;
let deposit: Deposit;

beforeEach(async function () {
[, depositor, relayer1, relayer2] = await ethers.getSigners();
Expand Down Expand Up @@ -57,12 +57,13 @@ describe("SpokePoolClient: Fills", function () {
inputAmount: outputAmount.add(bnOne),
outputToken: destErc20.address,
outputAmount: toBNWei("1"),
relayerFeePct: toBNWei("0.01"),
quoteTimestamp: spokePoolTime - 60,
message: EMPTY_MESSAGE,
fillDeadline: spokePoolTime + 600,
exclusivityDeadline: 0,
exclusiveRelayer: ZERO_ADDRESS,
fromLiteChain: false,
toLiteChain: false,
};
});

Expand Down

0 comments on commit 68d656d

Please sign in to comment.