Skip to content

Commit

Permalink
feat: Add protection against computing LP fees for future quote times…
Browse files Browse the repository at this point in the history
…tamps (#944)

* improve(dataworker): Remove `transferThreshold`

Fixes ACX-1537

Removes a lot of code needed to support deprecated config store variable that is always set to 0 in production

* Update Dataworker.ts

* bumpity

* Update Dataworker.ts

* Update package.json

* Update yarn.lock

* wip

* fix(Dataworker): Dereference originChainId by index, not key (#936)

* fix(Dataworker): Dereference originChainId by index, not key

Temporary fix to resolve an issue with future quoteTimestamps. We need a
more robust solution than this in the long run.

* Extract originToken from array

* lint

* WIP

Signed-off-by: Matt Rice <[email protected]>

---------

Signed-off-by: Matt Rice <[email protected]>
Co-authored-by: Matt Rice <[email protected]>

* improve: leverage default TTL & leverage caching (#938)

* improve: leverage default TTL

* improve: set fn signature to default

* feat: add dataworker force bundle range (#912)

* feat: add dataworker force bundle range

* docs: add documentation to example env

* improve: allow for boba

* improve: allow forced proposal range with sending

---------

Co-authored-by: Paul <[email protected]>

* feat: test chain routes (#897)

* feat: Script for automating SpokePool deposits

This is useful for making deposits to the zkSync SpokePool(s) because
zkSync's block explorer doesn't yet support making transactions via
proxy contracts.

* Add yarn script target + tweak usage

* Add basic support for dumping SpokePool config

* lint

* fix: Gracefully handle token searches where token missing

Not all tokens are defined on all chains, so don't try to drop case
unless the token actually exists on a chain.

* Add "fetch" for dumping deposit and fill information

Currently limitations:
 - Does not display updated values (i.e. after a speed-up).
 - Does not display message data.
 - Should normalise from the token decimals for better readability.
 - Does not gracefully handle when the txnHash is not found.

* lint

* fix conflict

* lint

* chore: allow base-units to easily be sent

* chore: allow token to be passed as origin token addr or symbol

* feat: test chain routes

* nit: improve docs

* docs: add docs

* improve: account for checksummed value

Co-authored-by: Paul <[email protected]>

* improve: remove unneeded flag

Co-authored-by: Paul <[email protected]>

* improve: docs

Co-authored-by: Paul <[email protected]>

* improve: do not hardcode amounts

* improve: modification

* improve: dynamically compute price

---------

Co-authored-by: Paul <[email protected]>
Co-authored-by: nicholaspai <[email protected]>

* WIP

* Update yarn.lock

* Revert "WIP"

This reverts commit 381e5bf.

* feat: Add protection against computing LP fees for future quote timestamps

This resolves the [reverted SDK PR](across-protocol/sdk#399) and re-introduces protection from deposit quote timestamps that are impossible to compute.

This PR essentially moves that protection to the production version of Hub and Spoke clients so that the unit tests can continue to work and not have to add additional logic to set quote times correctly. Ideally in the future we set the quote times how they would in production but for now this solution results in a much smaller code diff

* lint

* fix

* lint

* Update HubPoolClient.ts

* refactor: Import getNetworkName from sdk (#945)

* chore: bump sdk to latest (#943)

* chore: bump sdk to latest

* chore: bump version

* chore: bump sdk

---------

Signed-off-by: Matt Rice <[email protected]>
Co-authored-by: Paul <[email protected]>
Co-authored-by: Matt Rice <[email protected]>
Co-authored-by: James Morris, MS <[email protected]>
  • Loading branch information
4 people authored Sep 28, 2023
1 parent a5b8324 commit 3ea5360
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 69 deletions.
19 changes: 18 additions & 1 deletion src/clients/HubPoolClient.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { clients } from "@across-protocol/sdk-v2";
import { Contract } from "ethers";
import { BigNumber, Contract } from "ethers";
import winston from "winston";
import { MakeOptional, EventSearchConfig } from "../utils";
import { IGNORED_HUB_EXECUTED_BUNDLES, IGNORED_HUB_PROPOSED_BUNDLES } from "../common";
import { DepositWithBlock } from "../interfaces";

export class HubPoolClient extends clients.HubPoolClient {
constructor(
Expand All @@ -18,4 +19,20 @@ export class HubPoolClient extends clients.HubPoolClient {
ignoredHubProposedBundles: IGNORED_HUB_PROPOSED_BUNDLES,
});
}

async computeRealizedLpFeePct(
deposit: Pick<
DepositWithBlock,
"quoteTimestamp" | "amount" | "destinationChainId" | "originChainId" | "blockNumber"
>,
l1Token: string
): Promise<{ realizedLpFeePct: BigNumber | undefined; quoteBlock: number }> {
if (deposit.quoteTimestamp > this.currentTime) {
throw new Error(
`Cannot compute lp fee percent for quote timestamp ${deposit.quoteTimestamp} in the future. Current time: ${this.currentTime}.`
);
}

return await super.computeRealizedLpFeePct(deposit, l1Token);
}
}
12 changes: 11 additions & 1 deletion src/clients/SpokePoolClient.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
import { clients } from "@across-protocol/sdk-v2";
import { FundsDepositedEvent } from "../interfaces";
import { isDefined } from "../utils/TypeGuards";

export class SpokePoolClient extends clients.SpokePoolClient {}
export class SpokePoolClient extends clients.SpokePoolClient {
_isEarlyDeposit(depositEvent: FundsDepositedEvent, currentTime: number): boolean {
const hubCurrentTime = this.hubPoolClient?.currentTime;
if (!isDefined(hubCurrentTime)) {
throw new Error("HubPoolClient's currentTime is not defined");
}
return depositEvent.args.quoteTimestamp > currentTime || depositEvent.args.quoteTimestamp > hubCurrentTime;
}
}
10 changes: 7 additions & 3 deletions test/HubPoolClient.Utilization.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HubPoolClient } from "../src/clients";
import { clients } from "@across-protocol/sdk-v2";
import {
amountToLp,
destinationChainId,
Expand Down Expand Up @@ -29,7 +29,7 @@ import {

let configStore: Contract, hubPool: Contract;
let l1Token: Contract, l2Token: Contract, timer: Contract, weth: Contract;
let configStoreClient: MockConfigStoreClient, hubPoolClient: HubPoolClient;
let configStoreClient: MockConfigStoreClient, hubPoolClient: clients.HubPoolClient;
let owner: SignerWithAddress;

// Same rate model used for across-v1 tests:
Expand Down Expand Up @@ -96,7 +96,11 @@ describe("HubPool Utilization", async function () {

await configStoreClient.update();

hubPoolClient = new HubPoolClient(createSpyLogger().spyLogger, hubPool, configStoreClient);
hubPoolClient = new clients.HubPoolClient(
createSpyLogger().spyLogger,
hubPool,
configStoreClient as unknown as clients.AcrossConfigStoreClient
);
await configStoreClient.update();
await hubPoolClient.update();
});
Expand Down
28 changes: 13 additions & 15 deletions test/Relayer.BasicFill.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
import { random } from "lodash";
import {
AcrossApiClient,
ConfigStoreClient,
HubPoolClient,
MultiCallerClient,
SpokePoolClient,
TokenClient,
} from "../src/clients";
import { AcrossApiClient, ConfigStoreClient, MultiCallerClient, TokenClient } from "../src/clients";
import { CONFIG_STORE_VERSION, UBA_MIN_CONFIG_STORE_VERSION } from "../src/common";
import { Deposit } from "../src/interfaces";
import { Relayer } from "../src/relayer/Relayer";
Expand Down Expand Up @@ -45,15 +38,16 @@ import {
winston,
} from "./utils";
import { generateNoOpSpokePoolClientsForDefaultChainIndices } from "./utils/UBAUtils";
import { clients } from "@across-protocol/sdk-v2";

let spokePool_1: Contract, erc20_1: Contract, spokePool_2: Contract, erc20_2: Contract;
let hubPool: Contract, configStore: Contract, l1Token: Contract;
let owner: SignerWithAddress, depositor: SignerWithAddress, relayer: SignerWithAddress;
let spy: sinon.SinonSpy, spyLogger: winston.Logger;

let spokePoolClient_1: SpokePoolClient, spokePoolClient_2: SpokePoolClient;
let spokePoolClients: { [chainId: number]: SpokePoolClient };
let configStoreClient: ConfigStoreClient, hubPoolClient: HubPoolClient, tokenClient: TokenClient;
let spokePoolClient_1: clients.SpokePoolClient, spokePoolClient_2: clients.SpokePoolClient;
let spokePoolClients: { [chainId: number]: clients.SpokePoolClient };
let configStoreClient: ConfigStoreClient, hubPoolClient: clients.HubPoolClient, tokenClient: TokenClient;
let relayerInstance: Relayer;
let multiCallerClient: MultiCallerClient, profitClient: MockProfitClient;
let spokePool1DeploymentBlock: number, spokePool2DeploymentBlock: number;
Expand Down Expand Up @@ -99,19 +93,19 @@ describe("Relayer: Check for Unfilled Deposits and Fill", async function () {
) as unknown as ConfigStoreClient;
await configStoreClient.update();

hubPoolClient = new HubPoolClient(spyLogger, hubPool, configStoreClient);
hubPoolClient = new clients.HubPoolClient(spyLogger, hubPool, configStoreClient);
await hubPoolClient.update();

multiCallerClient = new MockedMultiCallerClient(spyLogger);

spokePoolClient_1 = new SpokePoolClient(
spokePoolClient_1 = new clients.SpokePoolClient(
spyLogger,
spokePool_1.connect(relayer),
hubPoolClient,
originChainId,
spokePool1DeploymentBlock
);
spokePoolClient_2 = new SpokePoolClient(
spokePoolClient_2 = new clients.SpokePoolClient(
spyLogger,
spokePool_2.connect(relayer),
hubPoolClient,
Expand Down Expand Up @@ -477,7 +471,11 @@ describe("Relayer: Check for Unfilled Deposits and Fill", async function () {
const version = UBA_MIN_CONFIG_STORE_VERSION;
configStoreClient = new ConfigStoreClient(spyLogger, configStore, { fromBlock: 0 }, version);
await configStoreClient.update();
hubPoolClient = new HubPoolClient(spyLogger, hubPool, configStoreClient);
hubPoolClient = new clients.HubPoolClient(
spyLogger,
hubPool,
configStoreClient as unknown as clients.AcrossConfigStoreClient
);
relayerInstance = new Relayer(
relayer.address,
spyLogger,
Expand Down
21 changes: 7 additions & 14 deletions test/Relayer.UnfilledDeposits.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,4 @@
import {
AcrossApiClient,
ConfigStoreClient,
HubPoolClient,
MultiCallerClient,
SpokePoolClient,
TokenClient,
UBAClient,
} from "../src/clients";
import { AcrossApiClient, ConfigStoreClient, MultiCallerClient, TokenClient, UBAClient } from "../src/clients";
import {
CHAIN_ID_TEST_LIST,
amountToLp,
Expand Down Expand Up @@ -35,6 +27,7 @@ import {
simpleDeposit,
toBNWei,
} from "./utils";
import { clients } from "@across-protocol/sdk-v2";

// Tested
import { Relayer } from "../src/relayer/Relayer";
Expand All @@ -46,8 +39,8 @@ let hubPool: Contract, l1Token: Contract, configStore: Contract;
let owner: SignerWithAddress, depositor: SignerWithAddress, relayer: SignerWithAddress;

const { spy, spyLogger } = createSpyLogger();
let spokePoolClient_1: SpokePoolClient, spokePoolClient_2: SpokePoolClient;
let configStoreClient: MockConfigStoreClient, hubPoolClient: HubPoolClient;
let spokePoolClient_1: clients.SpokePoolClient, spokePoolClient_2: clients.SpokePoolClient;
let configStoreClient: MockConfigStoreClient, hubPoolClient: clients.HubPoolClient;
let multiCallerClient: MultiCallerClient, tokenClient: TokenClient;
let profitClient: MockProfitClient;
let spokePool1DeploymentBlock: number, spokePool2DeploymentBlock: number;
Expand Down Expand Up @@ -93,17 +86,17 @@ describe("Relayer: Unfilled Deposits", async function () {
configStoreClient = new MockConfigStoreClient(spyLogger, configStore, undefined, undefined, CHAIN_ID_TEST_LIST);
await configStoreClient.update();

hubPoolClient = new HubPoolClient(spyLogger, hubPool, configStoreClient);
hubPoolClient = new clients.HubPoolClient(spyLogger, hubPool, configStoreClient);
await hubPoolClient.update();

spokePoolClient_1 = new SpokePoolClient(
spokePoolClient_1 = new clients.SpokePoolClient(
spyLogger,
spokePool_1,
hubPoolClient,
originChainId,
spokePool1DeploymentBlock
);
spokePoolClient_2 = new SpokePoolClient(
spokePoolClient_2 = new clients.SpokePoolClient(
spyLogger,
spokePool_2,
hubPoolClient,
Expand Down
12 changes: 9 additions & 3 deletions test/SpokePoolClient.SpeedUp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import {
toBNWei,
} from "./utils";

import { SpokePoolClient } from "../src/clients";
import { clients } from "@across-protocol/sdk-v2";
import { DepositWithBlock } from "../src/interfaces";

let spokePool: Contract, erc20: Contract, destErc20: Contract, weth: Contract;
let depositor: SignerWithAddress, deploymentBlock: number;
const destinationChainId2 = destinationChainId + 1;

let spokePoolClient: SpokePoolClient;
let spokePoolClient: clients.SpokePoolClient;

describe("SpokePoolClient: SpeedUp", async function () {
const ignoredFields = [
Expand All @@ -37,7 +37,13 @@ describe("SpokePoolClient: SpeedUp", async function () {
[, depositor] = await ethers.getSigners();
({ spokePool, erc20, destErc20, weth, deploymentBlock } = await deploySpokePoolWithToken(originChainId));
await enableRoutes(spokePool, [{ originToken: erc20.address, destinationChainId: destinationChainId2 }]);
spokePoolClient = new SpokePoolClient(createSpyLogger().spyLogger, spokePool, null, originChainId, deploymentBlock);
spokePoolClient = new clients.SpokePoolClient(
createSpyLogger().spyLogger,
spokePool,
null,
originChainId,
deploymentBlock
);

await setupTokensForWallet(spokePool, depositor, [erc20, destErc20], weth, 10);
});
Expand Down
22 changes: 13 additions & 9 deletions test/SpokePoolClient.ValidateFill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ import {
sinon,
} from "./utils";

import { ConfigStoreClient, HubPoolClient, SpokePoolClient } from "../src/clients";
import { ConfigStoreClient } from "../src/clients";
import { queryHistoricalDepositForFill } from "../src/utils";
import { MockConfigStoreClient, MockSpokePoolClient } from "./mocks";
import { utils } from "@across-protocol/sdk-v2";
import { utils, clients } from "@across-protocol/sdk-v2";
import { CHAIN_ID_TEST_LIST, repaymentChainId } from "./constants";
const { validateFillForDeposit } = utils;

Expand All @@ -40,8 +40,8 @@ let spokePool1DeploymentBlock: number, spokePool2DeploymentBlock: number;
let l1Token: Contract, configStore: Contract;
let spy: sinon.SinonSpy, spyLogger: winston.Logger;

let spokePoolClient2: SpokePoolClient, hubPoolClient: HubPoolClient;
let spokePoolClient1: SpokePoolClient, configStoreClient: ConfigStoreClient;
let spokePoolClient2: clients.SpokePoolClient, hubPoolClient: clients.HubPoolClient;
let spokePoolClient1: clients.SpokePoolClient, configStoreClient: ConfigStoreClient;

describe("SpokePoolClient: Fill Validation", async function () {
beforeEach(async function () {
Expand Down Expand Up @@ -81,17 +81,21 @@ describe("SpokePoolClient: Fill Validation", async function () {
) as unknown as ConfigStoreClient;
await configStoreClient.update();

hubPoolClient = new HubPoolClient(spyLogger, hubPool, configStoreClient);
hubPoolClient = new clients.HubPoolClient(
spyLogger,
hubPool,
configStoreClient as unknown as clients.AcrossConfigStoreClient
);

await hubPoolClient.update();
spokePoolClient1 = new SpokePoolClient(
spokePoolClient1 = new clients.SpokePoolClient(
spyLogger,
spokePool_1,
hubPoolClient,
originChainId,
spokePool1DeploymentBlock
);
spokePoolClient2 = new SpokePoolClient(
spokePoolClient2 = new clients.SpokePoolClient(
createSpyLogger().spyLogger,
spokePool_2,
null,
Expand Down Expand Up @@ -132,7 +136,7 @@ describe("SpokePoolClient: Fill Validation", async function () {
it("Returns deposit matched with fill", async function () {
const deposit_1 = await buildDeposit(hubPoolClient, spokePool_1, erc20_1, l1Token, depositor, destinationChainId);
const fill_1 = await buildFill(spokePool_2, erc20_2, depositor, relayer, deposit_1, 0.5);
const spokePoolClientForDestinationChain = new SpokePoolClient(
const spokePoolClientForDestinationChain = new clients.SpokePoolClient(
createSpyLogger().spyLogger,
spokePool_1,
null,
Expand Down Expand Up @@ -488,7 +492,7 @@ describe("SpokePoolClient: Fill Validation", async function () {
const fill_1 = await buildFill(spokePool_2, erc20_2, depositor, relayer, expectedDeposit, 0.2);
const fill_2 = await buildModifiedFill(spokePool_2, depositor, relayer, fill_1, 2, 0.2, relayer.address, "0x12"); // Fill same % of deposit with 2x larger relayer fee pct.

const spokePoolClientForDestinationChain = new SpokePoolClient(
const spokePoolClientForDestinationChain = new clients.SpokePoolClient(
createSpyLogger().spyLogger,
spokePool_1,
null,
Expand Down
12 changes: 9 additions & 3 deletions test/SpokePoolClient.deposits.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SpokePoolClient } from "../src/clients";
import { clients } from "@across-protocol/sdk-v2";
import {
Contract,
SignerWithAddress,
Expand All @@ -18,14 +18,20 @@ let depositor1: SignerWithAddress, depositor2: SignerWithAddress;
let deploymentBlock: number;
const destinationChainId2 = destinationChainId + 1;

let spokePoolClient: SpokePoolClient;
let spokePoolClient: clients.SpokePoolClient;

describe("SpokePoolClient: Deposits", async function () {
beforeEach(async function () {
[, depositor1, depositor2] = await ethers.getSigners();
({ spokePool, erc20, destErc20, weth, deploymentBlock } = await deploySpokePoolWithToken(originChainId));
await enableRoutes(spokePool, [{ originToken: erc20.address, destinationChainId: destinationChainId2 }]);
spokePoolClient = new SpokePoolClient(createSpyLogger().spyLogger, spokePool, null, originChainId, deploymentBlock);
spokePoolClient = new clients.SpokePoolClient(
createSpyLogger().spyLogger,
spokePool,
null,
originChainId,
deploymentBlock
);

await setupTokensForWallet(spokePool, depositor1, [erc20, destErc20], weth, 10);
await setupTokensForWallet(spokePool, depositor2, [erc20, destErc20], weth, 10);
Expand Down
Loading

0 comments on commit 3ea5360

Please sign in to comment.