Skip to content

Commit

Permalink
fix: handle early deposits (#932)
Browse files Browse the repository at this point in the history
* fix: handle early deposits

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

* fix: resolve block error

* WIP

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

* fix: 🎨 Import from primary directory

This change imports from the correct directory rather than import from the dist directly.

---------

Signed-off-by: Matt Rice <[email protected]>
Co-authored-by: james-a-morris <[email protected]>
  • Loading branch information
mrice32 and james-a-morris authored Sep 10, 2023
1 parent 3061e41 commit 279fad9
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 17 deletions.
22 changes: 20 additions & 2 deletions src/clients/BundleDataClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
flattenAndFilterUnfilledDepositsByOriginChain,
updateUnfilledDepositsWithMatchedDeposit,
getUniqueDepositsInRange,
getUniqueEarlyDepositsInRange,
queryHistoricalDepositForFill,
} from "../utils";
import { Clients } from "../common";
Expand All @@ -30,14 +31,15 @@ import {
prettyPrintSpokePoolEvents,
} from "../dataworker/DataworkerUtils";
import { getWidestPossibleExpectedBlockRange, isChainDisabled } from "../dataworker/PoolRebalanceUtils";
import { clients } from "@across-protocol/sdk-v2";
import { clients, typechain } from "@across-protocol/sdk-v2";
const { refundRequestIsValid, isUBAActivatedAtBlock } = clients;

type DataCacheValue = {
unfilledDeposits: UnfilledDeposit[];
fillsToRefund: FillsToRefund;
allValidFills: FillWithBlock[];
deposits: DepositWithBlock[];
earlyDeposits: typechain.FundsDepositedEvent[];
};
type DataCache = Record<string, DataCacheValue>;

Expand Down Expand Up @@ -175,6 +177,7 @@ export class BundleDataClient {
fillsToRefund: FillsToRefund;
allValidFills: FillWithBlock[];
deposits: DepositWithBlock[];
earlyDeposits: typechain.FundsDepositedEvent[];
}> {
const mainnetStartBlock = getBlockRangeForChain(
blockRangesForChains,
Expand All @@ -197,6 +200,7 @@ export class BundleDataClient {
fillsToRefund: FillsToRefund;
allValidFills: FillWithBlock[];
deposits: DepositWithBlock[];
earlyDeposits: typechain.FundsDepositedEvent[];
}> {
const key = JSON.stringify(blockRangesForChains);

Expand All @@ -222,6 +226,7 @@ export class BundleDataClient {
const deposits: DepositWithBlock[] = [];
const allValidFills: FillWithBlock[] = [];
const allInvalidFills: FillWithBlock[] = [];
const earlyDeposits: typechain.FundsDepositedEvent[] = [];

// Save refund in-memory for validated fill.
const addRefundForValidFill = (
Expand Down Expand Up @@ -359,6 +364,19 @@ export class BundleDataClient {
)
);

// TODO: replace this logic with something more clear where all deposits can be queried at once,
// but separated into early and not after the initial filter/query.
earlyDeposits.push(
...getUniqueEarlyDepositsInRange(
blockRangesForChains,
Number(originChainId),
Number(destinationChainId),
this.chainIdListForBundleEvaluationBlockNumbers,
originClient,
earlyDeposits
)
);

const blockRangeForChain = getBlockRangeForChain(
blockRangesForChains,
Number(destinationChainId),
Expand Down Expand Up @@ -432,7 +450,7 @@ export class BundleDataClient {
});
}

this.loadDataCache[key] = { fillsToRefund, deposits, unfilledDeposits, allValidFills };
this.loadDataCache[key] = { fillsToRefund, deposits, unfilledDeposits, allValidFills, earlyDeposits };

return this.loadDataFromCache(key);
}
Expand Down
18 changes: 8 additions & 10 deletions src/dataworker/Dataworker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,8 @@ export class Dataworker {
spokePoolClients: SpokePoolClientsByChain,
latestMainnetBlock?: number
): Promise<PoolRebalanceRoot> {
const { fillsToRefund, deposits, allValidFills, unfilledDeposits } = await this.clients.bundleDataClient.loadData(
blockRangesForChains,
spokePoolClients
);
const { fillsToRefund, deposits, allValidFills, unfilledDeposits, earlyDeposits } =
await this.clients.bundleDataClient.loadData(blockRangesForChains, spokePoolClients);

const mainnetBundleEndBlock = getBlockRangeForChain(
blockRangesForChains,
Expand All @@ -193,6 +191,7 @@ export class Dataworker {
allValidFills,
allValidFillsInRange,
unfilledDeposits,
earlyDeposits,
true
);
}
Expand Down Expand Up @@ -492,12 +491,8 @@ export class Dataworker {
logData = false
): Promise<ProposeRootBundleReturnType> {
const timerStart = Date.now();
const { fillsToRefund, deposits, allValidFills, unfilledDeposits } = await this.clients.bundleDataClient._loadData(
blockRangesForProposal,
spokePoolClients,
false,
logData
);
const { fillsToRefund, deposits, allValidFills, unfilledDeposits, earlyDeposits } =
await this.clients.bundleDataClient._loadData(blockRangesForProposal, spokePoolClients, false, logData);
const allValidFillsInRange = getFillsInRange(
allValidFills,
blockRangesForProposal,
Expand All @@ -520,6 +515,7 @@ export class Dataworker {
allValidFills,
allValidFillsInRange,
unfilledDeposits,
earlyDeposits,
true
);
const relayerRefundRoot = _buildRelayerRefundRoot(
Expand Down Expand Up @@ -2226,6 +2222,7 @@ export class Dataworker {
allValidFills: FillWithBlock[],
allValidFillsInRange: FillWithBlock[],
unfilledDeposits: UnfilledDeposit[],
earlyDeposits: sdk.typechain.FundsDepositedEvent[],
logSlowFillExcessData = false
): Promise<PoolRebalanceRoot> {
const key = JSON.stringify(blockRangesForChains);
Expand All @@ -2241,6 +2238,7 @@ export class Dataworker {
allValidFills,
allValidFillsInRange,
unfilledDeposits,
earlyDeposits,
this.clients,
spokePoolClients,
this.chainIdListForBundleEvaluationBlockNumbers,
Expand Down
17 changes: 16 additions & 1 deletion src/dataworker/DataworkerUtils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { utils } from "@across-protocol/sdk-v2";
import { utils, typechain } from "@across-protocol/sdk-v2";
import { SpokePoolClient } from "../clients";
import { spokesThatHoldEthAndWeth } from "../common/Constants";
import { CONTRACT_ADDRESSES } from "../common/ContractAddresses";
Expand Down Expand Up @@ -38,6 +38,7 @@ import {
initializeRunningBalancesFromRelayerRepayments,
subtractExcessFromPreviousSlowFillsFromRunningBalances,
updateRunningBalanceForDeposit,
updateRunningBalanceForEarlyDeposit,
} from "./PoolRebalanceUtils";
import {
getAmountToReturnForRelayerRefundLeaf,
Expand Down Expand Up @@ -328,6 +329,7 @@ export async function _buildPoolRebalanceRoot(
allValidFills: FillWithBlock[],
allValidFillsInRange: FillWithBlock[],
unfilledDeposits: UnfilledDeposit[],
earlyDeposits: typechain.FundsDepositedEvent[],
clients: DataworkerClients,
spokePoolClients: SpokePoolClientsByChain,
chainIdListForBundleEvaluationBlockNumbers: number[],
Expand Down Expand Up @@ -383,6 +385,19 @@ export async function _buildPoolRebalanceRoot(
updateRunningBalanceForDeposit(runningBalances, clients.hubPoolClient, deposit, deposit.amount.mul(toBN(-1)));
});

earlyDeposits.forEach((earlyDeposit) => {
updateRunningBalanceForEarlyDeposit(
runningBalances,
clients.hubPoolClient,
earlyDeposit,
// TODO: fix this.
// Because cloneDeep drops the non-array elements of args, we have to use the index rather than the name.
// As a fix, earlyDeposits should be treated similarly to other events and transformed at ingestion time
// into a type that is more digestable rather than a raw event.
earlyDeposit.args[0].mul(toBN(-1))
);
});

// Add to the running balance value from the last valid root bundle proposal for {chainId, l1Token}
// combination if found.
addLastRunningBalance(latestMainnetBlock, runningBalances, clients.hubPoolClient);
Expand Down
23 changes: 23 additions & 0 deletions src/dataworker/PoolRebalanceUtils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { typechain } from "@across-protocol/sdk-v2";
import { ConfigStoreClient, HubPoolClient, SpokePoolClient } from "../clients";
import { Clients } from "../common";
import * as interfaces from "../interfaces";
Expand Down Expand Up @@ -77,6 +78,28 @@ export function updateRunningBalanceForDeposit(
updateRunningBalance(runningBalances, deposit.originChainId, l1TokenCounterpart, updateAmount);
}

export function updateRunningBalanceForEarlyDeposit(
runningBalances: interfaces.RunningBalances,
hubPoolClient: HubPoolClient,
deposit: typechain.FundsDepositedEvent,
updateAmount: BigNumber
): void {
const l1TokenCounterpart = hubPoolClient.getL1TokenCounterpartAtBlock(
Number(deposit.args.originChainId.toString()),
deposit.args.originToken,
// TODO: this must be handled s.t. it doesn't depend on when this is run.
// For now, tokens do not change their mappings often, so this will work, but
// to keep the system resilient, this must be updated.
hubPoolClient.latestBlockNumber
);
updateRunningBalance(
runningBalances,
Number(deposit.args.originChainId.toString()),
l1TokenCounterpart,
updateAmount
);
}

export function addLastRunningBalance(
latestMainnetBlock: number,
runningBalances: interfaces.RunningBalances,
Expand Down
28 changes: 27 additions & 1 deletion src/utils/DepositUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Deposit, DepositWithBlock, Fill, UnfilledDeposit, UnfilledDepositsForOr
import { SpokePoolClient } from "../clients";
import { assign, toBN, isFirstFillForDeposit } from "./";
import { getBlockRangeForChain } from "../dataworker/DataworkerUtils";
import { utils } from "@across-protocol/sdk-v2";
import { utils, typechain } from "@across-protocol/sdk-v2";
const { validateFillForDeposit } = utils;

export function getDepositPath(deposit: Deposit): string {
Expand Down Expand Up @@ -93,6 +93,32 @@ export function getUniqueDepositsInRange(
) as DepositWithBlock[];
}

export function getUniqueEarlyDepositsInRange(
blockRangesForChains: number[][],
originChain: number,
destinationChain: number,
chainIdListForBundleEvaluationBlockNumbers: number[],
originClient: SpokePoolClient,
existingUniqueDeposits: typechain.FundsDepositedEvent[]
): typechain.FundsDepositedEvent[] {
const originChainBlockRange = getBlockRangeForChain(
blockRangesForChains,
originChain,
chainIdListForBundleEvaluationBlockNumbers
);
return (originClient["earlyDeposits"] as unknown as typechain.FundsDepositedEvent[]).filter(
(deposit: typechain.FundsDepositedEvent) =>
deposit.blockNumber <= originChainBlockRange[1] &&
deposit.blockNumber >= originChainBlockRange[0] &&
deposit.args.destinationChainId.toString() === destinationChain.toString() &&
!existingUniqueDeposits.some(
(existingDeposit) =>
existingDeposit.args.originChainId.toString() === deposit.args.originChainId.toString() &&
existingDeposit.args.depositId.toString() === deposit.args.depositId.toString()
)
);
}

export function isDepositSpedUp(deposit: Deposit): boolean {
return deposit.speedUpSignature !== undefined && deposit.newRelayerFeePct !== undefined;
}
Expand Down
9 changes: 6 additions & 3 deletions test/Dataworker.loadData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import {

import { spokePoolClientsToProviders } from "../src/common";
import { Dataworker } from "../src/dataworker/Dataworker"; // Tested
import { DepositWithBlock, Fill } from "../src/interfaces";
import { Deposit, DepositWithBlock, Fill } from "../src/interfaces";
import { MAX_UINT_VAL, getRealizedLpFeeForFills, getRefundForFills, toBN } from "../src/utils";

let spokePool_1: Contract, erc20_1: Contract, spokePool_2: Contract, erc20_2: Contract;
Expand Down Expand Up @@ -103,10 +103,13 @@ describe("Dataworker: Load data used in all functions", async function () {
deposits: [],
fillsToRefund: {},
allValidFills: [],
earlyDeposits: [],
});
});
describe("Computing refunds for bundles", function () {
let fill1: Fill, deposit1;
let fill1: Fill;
let deposit1: Deposit;

beforeEach(async function () {
await updateAllClients();

Expand Down Expand Up @@ -579,7 +582,7 @@ describe("Dataworker: Load data used in all functions", async function () {
erc20_1,
depositor,
relayer,
{ ...deposit2, realizedLpFeePct: deposit2.realizedLpFeePct.div(toBN(2)) },
{ ...deposit2, realizedLpFeePct: deposit2.realizedLpFeePct?.div(toBN(2)) },
0.25
);
// Note: This fill has identical deposit data to fill2 except for the destination token being different
Expand Down

0 comments on commit 279fad9

Please sign in to comment.