@across-protocol/sdk 3.1.27 → 3.1.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/clients/BundleDataClient/BundleDataClient.d.ts +60 -0
- package/dist/cjs/clients/BundleDataClient/BundleDataClient.js +929 -0
- package/dist/cjs/clients/BundleDataClient/BundleDataClient.js.map +1 -0
- package/dist/cjs/clients/BundleDataClient/index.d.ts +2 -0
- package/dist/cjs/clients/BundleDataClient/index.js +6 -0
- package/dist/cjs/clients/BundleDataClient/index.js.map +1 -0
- package/dist/cjs/clients/BundleDataClient/utils/DataworkerUtils.d.ts +15 -0
- package/dist/cjs/clients/BundleDataClient/utils/DataworkerUtils.js +131 -0
- package/dist/cjs/clients/BundleDataClient/utils/DataworkerUtils.js.map +1 -0
- package/dist/cjs/clients/BundleDataClient/utils/FillUtils.d.ts +6 -0
- package/dist/cjs/clients/BundleDataClient/utils/FillUtils.js +19 -0
- package/dist/cjs/clients/BundleDataClient/utils/FillUtils.js.map +1 -0
- package/dist/cjs/clients/BundleDataClient/utils/MerkleTreeUtils.d.ts +3 -0
- package/dist/cjs/clients/BundleDataClient/utils/MerkleTreeUtils.js +23 -0
- package/dist/cjs/clients/BundleDataClient/utils/MerkleTreeUtils.js.map +1 -0
- package/dist/cjs/clients/BundleDataClient/utils/PoolRebalanceUtils.d.ts +24 -0
- package/dist/cjs/clients/BundleDataClient/utils/PoolRebalanceUtils.js +129 -0
- package/dist/cjs/clients/BundleDataClient/utils/PoolRebalanceUtils.js.map +1 -0
- package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.d.ts +302 -0
- package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.js +77 -0
- package/dist/cjs/clients/BundleDataClient/utils/SuperstructUtils.js.map +1 -0
- package/dist/cjs/clients/BundleDataClient/utils/index.d.ts +6 -0
- package/dist/cjs/clients/BundleDataClient/utils/index.js +10 -0
- package/dist/cjs/clients/BundleDataClient/utils/index.js.map +1 -0
- package/dist/cjs/clients/BundleDataClient/utils/shims.d.ts +8 -0
- package/dist/cjs/clients/BundleDataClient/utils/shims.js +3 -0
- package/dist/cjs/clients/BundleDataClient/utils/shims.js.map +1 -0
- package/dist/cjs/clients/index.d.ts +1 -0
- package/dist/cjs/clients/index.js +2 -1
- package/dist/cjs/clients/index.js.map +1 -1
- package/dist/cjs/interfaces/BundleData.d.ts +63 -0
- package/dist/cjs/interfaces/BundleData.js +3 -0
- package/dist/cjs/interfaces/BundleData.js.map +1 -0
- package/dist/cjs/interfaces/index.d.ts +1 -0
- package/dist/cjs/interfaces/index.js +1 -0
- package/dist/cjs/interfaces/index.js.map +1 -1
- package/dist/cjs/providers/alchemy.js +5 -5
- package/dist/cjs/providers/alchemy.js.map +1 -1
- package/dist/cjs/providers/drpc.d.ts +2 -0
- package/dist/cjs/providers/drpc.js +21 -0
- package/dist/cjs/providers/drpc.js.map +1 -0
- package/dist/cjs/providers/infura.js +5 -5
- package/dist/cjs/providers/infura.js.map +1 -1
- package/dist/cjs/providers/types.d.ts +1 -1
- package/dist/cjs/providers/utils.js +3 -1
- package/dist/cjs/providers/utils.js.map +1 -1
- package/dist/cjs/utils/AddressUtils.d.ts +1 -0
- package/dist/cjs/utils/AddressUtils.js +15 -1
- package/dist/cjs/utils/AddressUtils.js.map +1 -1
- package/dist/cjs/utils/ContractUtils.d.ts +1 -0
- package/dist/cjs/utils/ContractUtils.js +12 -0
- package/dist/cjs/utils/ContractUtils.js.map +1 -0
- package/dist/cjs/utils/Multicall.d.ts +3 -2
- package/dist/cjs/utils/Multicall.js +40 -41
- package/dist/cjs/utils/Multicall.js.map +1 -1
- package/dist/cjs/utils/ObjectUtils.d.ts +18 -0
- package/dist/cjs/utils/ObjectUtils.js +27 -1
- package/dist/cjs/utils/ObjectUtils.js.map +1 -1
- package/dist/cjs/utils/abi/contracts/index.d.ts +1 -0
- package/dist/cjs/utils/abi/contracts/index.js +9 -0
- package/dist/cjs/utils/abi/contracts/index.js.map +1 -0
- package/dist/cjs/utils/abi/typechain/Multicall3.d.ts +289 -0
- package/dist/cjs/utils/abi/typechain/Multicall3.js +3 -0
- package/dist/cjs/utils/abi/typechain/Multicall3.js.map +1 -0
- package/dist/cjs/utils/abi/typechain/common.d.ts +21 -0
- package/dist/cjs/utils/abi/typechain/common.js +3 -0
- package/dist/cjs/utils/abi/typechain/common.js.map +1 -0
- package/dist/cjs/utils/abi/typechain/factories/Multicall3__factory.d.ts +339 -0
- package/dist/cjs/utils/abi/typechain/factories/Multicall3__factory.js +458 -0
- package/dist/cjs/utils/abi/typechain/factories/Multicall3__factory.js.map +1 -0
- package/dist/cjs/utils/abi/typechain/factories/index.d.ts +1 -0
- package/dist/cjs/utils/abi/typechain/factories/index.js +6 -0
- package/dist/cjs/utils/abi/typechain/factories/index.js.map +1 -0
- package/dist/cjs/utils/abi/typechain/index.d.ts +3 -0
- package/dist/cjs/utils/abi/typechain/index.js +8 -0
- package/dist/cjs/utils/abi/typechain/index.js.map +1 -0
- package/dist/esm/clients/BundleDataClient/BundleDataClient.d.ts +60 -0
- package/dist/esm/clients/BundleDataClient/BundleDataClient.js +1097 -0
- package/dist/esm/clients/BundleDataClient/BundleDataClient.js.map +1 -0
- package/dist/esm/clients/BundleDataClient/index.d.ts +2 -0
- package/dist/esm/clients/BundleDataClient/index.js +3 -0
- package/dist/esm/clients/BundleDataClient/index.js.map +1 -0
- package/dist/esm/clients/BundleDataClient/utils/DataworkerUtils.d.ts +15 -0
- package/dist/esm/clients/BundleDataClient/utils/DataworkerUtils.js +182 -0
- package/dist/esm/clients/BundleDataClient/utils/DataworkerUtils.js.map +1 -0
- package/dist/esm/clients/BundleDataClient/utils/FillUtils.d.ts +6 -0
- package/dist/esm/clients/BundleDataClient/utils/FillUtils.js +20 -0
- package/dist/esm/clients/BundleDataClient/utils/FillUtils.js.map +1 -0
- package/dist/esm/clients/BundleDataClient/utils/MerkleTreeUtils.d.ts +3 -0
- package/dist/esm/clients/BundleDataClient/utils/MerkleTreeUtils.js +20 -0
- package/dist/esm/clients/BundleDataClient/utils/MerkleTreeUtils.js.map +1 -0
- package/dist/esm/clients/BundleDataClient/utils/PoolRebalanceUtils.d.ts +24 -0
- package/dist/esm/clients/BundleDataClient/utils/PoolRebalanceUtils.js +157 -0
- package/dist/esm/clients/BundleDataClient/utils/PoolRebalanceUtils.js.map +1 -0
- package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.d.ts +302 -0
- package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.js +79 -0
- package/dist/esm/clients/BundleDataClient/utils/SuperstructUtils.js.map +1 -0
- package/dist/esm/clients/BundleDataClient/utils/index.d.ts +6 -0
- package/dist/esm/clients/BundleDataClient/utils/index.js +7 -0
- package/dist/esm/clients/BundleDataClient/utils/index.js.map +1 -0
- package/dist/esm/clients/BundleDataClient/utils/shims.d.ts +8 -0
- package/dist/esm/clients/BundleDataClient/utils/shims.js +2 -0
- package/dist/esm/clients/BundleDataClient/utils/shims.js.map +1 -0
- package/dist/esm/clients/index.d.ts +1 -0
- package/dist/esm/clients/index.js +2 -0
- package/dist/esm/clients/index.js.map +1 -1
- package/dist/esm/interfaces/BundleData.d.ts +63 -0
- package/dist/esm/interfaces/BundleData.js +2 -0
- package/dist/esm/interfaces/BundleData.js.map +1 -0
- package/dist/esm/interfaces/index.d.ts +1 -0
- package/dist/esm/interfaces/index.js +1 -0
- package/dist/esm/interfaces/index.js.map +1 -1
- package/dist/esm/providers/alchemy.js +6 -6
- package/dist/esm/providers/alchemy.js.map +1 -1
- package/dist/esm/providers/drpc.d.ts +2 -0
- package/dist/esm/providers/drpc.js +18 -0
- package/dist/esm/providers/drpc.js.map +1 -0
- package/dist/esm/providers/infura.js +6 -6
- package/dist/esm/providers/infura.js.map +1 -1
- package/dist/esm/providers/types.d.ts +1 -1
- package/dist/esm/providers/utils.js +3 -1
- package/dist/esm/providers/utils.js.map +1 -1
- package/dist/esm/utils/AddressUtils.d.ts +1 -0
- package/dist/esm/utils/AddressUtils.js +16 -1
- package/dist/esm/utils/AddressUtils.js.map +1 -1
- package/dist/esm/utils/ContractUtils.d.ts +1 -0
- package/dist/esm/utils/ContractUtils.js +8 -0
- package/dist/esm/utils/ContractUtils.js.map +1 -0
- package/dist/esm/utils/Multicall.d.ts +3 -2
- package/dist/esm/utils/Multicall.js +39 -42
- package/dist/esm/utils/Multicall.js.map +1 -1
- package/dist/esm/utils/ObjectUtils.d.ts +18 -0
- package/dist/esm/utils/ObjectUtils.js +24 -0
- package/dist/esm/utils/ObjectUtils.js.map +1 -1
- package/dist/esm/utils/abi/contracts/index.d.ts +1 -0
- package/dist/esm/utils/abi/contracts/index.js +2 -0
- package/dist/esm/utils/abi/contracts/index.js.map +1 -0
- package/dist/esm/utils/abi/typechain/Multicall3.d.ts +292 -0
- package/dist/esm/utils/abi/typechain/Multicall3.js +2 -0
- package/dist/esm/utils/abi/typechain/Multicall3.js.map +1 -0
- package/dist/esm/utils/abi/typechain/common.d.ts +21 -0
- package/dist/esm/utils/abi/typechain/common.js +2 -0
- package/dist/esm/utils/abi/typechain/common.js.map +1 -0
- package/dist/esm/utils/abi/typechain/factories/Multicall3__factory.d.ts +339 -0
- package/dist/esm/utils/abi/typechain/factories/Multicall3__factory.js +458 -0
- package/dist/esm/utils/abi/typechain/factories/Multicall3__factory.js.map +1 -0
- package/dist/esm/utils/abi/typechain/factories/index.d.ts +1 -0
- package/dist/esm/utils/abi/typechain/factories/index.js +5 -0
- package/dist/esm/utils/abi/typechain/factories/index.js.map +1 -0
- package/dist/esm/utils/abi/typechain/index.d.ts +3 -0
- package/dist/esm/utils/abi/typechain/index.js +4 -0
- package/dist/esm/utils/abi/typechain/index.js.map +1 -0
- package/dist/types/clients/BundleDataClient/BundleDataClient.d.ts +61 -0
- package/dist/types/clients/BundleDataClient/BundleDataClient.d.ts.map +1 -0
- package/dist/types/clients/BundleDataClient/index.d.ts +3 -0
- package/dist/types/clients/BundleDataClient/index.d.ts.map +1 -0
- package/dist/types/clients/BundleDataClient/utils/DataworkerUtils.d.ts +16 -0
- package/dist/types/clients/BundleDataClient/utils/DataworkerUtils.d.ts.map +1 -0
- package/dist/types/clients/BundleDataClient/utils/FillUtils.d.ts +7 -0
- package/dist/types/clients/BundleDataClient/utils/FillUtils.d.ts.map +1 -0
- package/dist/types/clients/BundleDataClient/utils/MerkleTreeUtils.d.ts +4 -0
- package/dist/types/clients/BundleDataClient/utils/MerkleTreeUtils.d.ts.map +1 -0
- package/dist/types/clients/BundleDataClient/utils/PoolRebalanceUtils.d.ts +25 -0
- package/dist/types/clients/BundleDataClient/utils/PoolRebalanceUtils.d.ts.map +1 -0
- package/dist/types/clients/BundleDataClient/utils/SuperstructUtils.d.ts +303 -0
- package/dist/types/clients/BundleDataClient/utils/SuperstructUtils.d.ts.map +1 -0
- package/dist/types/clients/BundleDataClient/utils/index.d.ts +7 -0
- package/dist/types/clients/BundleDataClient/utils/index.d.ts.map +1 -0
- package/dist/types/clients/BundleDataClient/utils/shims.d.ts +9 -0
- package/dist/types/clients/BundleDataClient/utils/shims.d.ts.map +1 -0
- package/dist/types/clients/index.d.ts +1 -0
- package/dist/types/clients/index.d.ts.map +1 -1
- package/dist/types/interfaces/BundleData.d.ts +64 -0
- package/dist/types/interfaces/BundleData.d.ts.map +1 -0
- package/dist/types/interfaces/index.d.ts +1 -0
- package/dist/types/interfaces/index.d.ts.map +1 -1
- package/dist/types/providers/drpc.d.ts +3 -0
- package/dist/types/providers/drpc.d.ts.map +1 -0
- package/dist/types/providers/types.d.ts +1 -1
- package/dist/types/providers/types.d.ts.map +1 -1
- package/dist/types/providers/utils.d.ts.map +1 -1
- package/dist/types/utils/AddressUtils.d.ts +1 -0
- package/dist/types/utils/AddressUtils.d.ts.map +1 -1
- package/dist/types/utils/ContractUtils.d.ts +2 -0
- package/dist/types/utils/ContractUtils.d.ts.map +1 -0
- package/dist/types/utils/Multicall.d.ts +3 -2
- package/dist/types/utils/Multicall.d.ts.map +1 -1
- package/dist/types/utils/ObjectUtils.d.ts +18 -0
- package/dist/types/utils/ObjectUtils.d.ts.map +1 -1
- package/dist/types/utils/abi/contracts/index.d.ts +2 -0
- package/dist/types/utils/abi/contracts/index.d.ts.map +1 -0
- package/dist/types/utils/abi/typechain/Multicall3.d.ts +293 -0
- package/dist/types/utils/abi/typechain/Multicall3.d.ts.map +1 -0
- package/dist/types/utils/abi/typechain/common.d.ts +22 -0
- package/dist/types/utils/abi/typechain/common.d.ts.map +1 -0
- package/dist/types/utils/abi/typechain/factories/Multicall3__factory.d.ts +340 -0
- package/dist/types/utils/abi/typechain/factories/Multicall3__factory.d.ts.map +1 -0
- package/dist/types/utils/abi/typechain/factories/index.d.ts +2 -0
- package/dist/types/utils/abi/typechain/factories/index.d.ts.map +1 -0
- package/dist/types/utils/abi/typechain/index.d.ts +4 -0
- package/dist/types/utils/abi/typechain/index.d.ts.map +1 -0
- package/package.json +6 -8
- package/src/clients/BundleDataClient/BundleDataClient.ts +1311 -0
- package/src/clients/BundleDataClient/index.ts +2 -0
- package/src/clients/BundleDataClient/utils/DataworkerUtils.ts +268 -0
- package/src/clients/BundleDataClient/utils/FillUtils.ts +46 -0
- package/src/clients/BundleDataClient/utils/MerkleTreeUtils.ts +26 -0
- package/src/clients/BundleDataClient/utils/PoolRebalanceUtils.ts +238 -0
- package/src/clients/BundleDataClient/utils/SuperstructUtils.ts +132 -0
- package/src/clients/BundleDataClient/utils/index.ts +6 -0
- package/src/clients/BundleDataClient/utils/shims.ts +10 -0
- package/src/clients/index.ts +1 -0
- package/src/interfaces/BundleData.ts +68 -0
- package/src/interfaces/index.ts +1 -0
- package/src/providers/alchemy.ts +6 -6
- package/src/providers/drpc.ts +19 -0
- package/src/providers/infura.ts +6 -6
- package/src/providers/types.ts +1 -1
- package/src/providers/utils.ts +3 -1
- package/src/utils/AddressUtils.ts +15 -1
- package/src/utils/ContractUtils.ts +8 -0
- package/src/utils/Multicall.ts +38 -30
- package/src/utils/ObjectUtils.ts +23 -0
- package/src/utils/abi/contracts/index.ts +1 -0
- package/src/utils/abi/typechain/Multicall3.ts +433 -0
- package/src/utils/abi/typechain/common.ts +30 -0
- package/src/utils/abi/typechain/factories/Multicall3__factory.ts +458 -0
- package/src/utils/abi/typechain/factories/index.ts +4 -0
- package/src/utils/abi/typechain/index.ts +6 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
// Create a combined `refunds` object containing refunds for V2 + V3 fills
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
BundleDepositsV3,
|
|
5
|
+
BundleExcessSlowFills,
|
|
6
|
+
BundleFillsV3,
|
|
7
|
+
BundleSlowFills,
|
|
8
|
+
CombinedRefunds,
|
|
9
|
+
ExpiredDepositsToRefundV3,
|
|
10
|
+
PoolRebalanceLeaf,
|
|
11
|
+
Refund,
|
|
12
|
+
RunningBalances,
|
|
13
|
+
} from "../../../interfaces";
|
|
14
|
+
import {
|
|
15
|
+
bnZero,
|
|
16
|
+
AnyObject,
|
|
17
|
+
groupObjectCountsByTwoProps,
|
|
18
|
+
fixedPointAdjustment,
|
|
19
|
+
count2DDictionaryValues,
|
|
20
|
+
count3DDictionaryValues,
|
|
21
|
+
} from "../../../utils";
|
|
22
|
+
import {
|
|
23
|
+
addLastRunningBalance,
|
|
24
|
+
constructPoolRebalanceLeaves,
|
|
25
|
+
PoolRebalanceRoot,
|
|
26
|
+
updateRunningBalance,
|
|
27
|
+
updateRunningBalanceForDeposit,
|
|
28
|
+
} from "./PoolRebalanceUtils";
|
|
29
|
+
import { V3FillWithBlock } from "./shims";
|
|
30
|
+
import { AcrossConfigStoreClient } from "../../AcrossConfigStoreClient";
|
|
31
|
+
import { HubPoolClient } from "../../HubPoolClient";
|
|
32
|
+
import { buildPoolRebalanceLeafTree } from "./MerkleTreeUtils";
|
|
33
|
+
|
|
34
|
+
// and expired deposits.
|
|
35
|
+
export function getRefundsFromBundle(
|
|
36
|
+
bundleFillsV3: BundleFillsV3,
|
|
37
|
+
expiredDepositsToRefundV3: ExpiredDepositsToRefundV3
|
|
38
|
+
): CombinedRefunds {
|
|
39
|
+
const combinedRefunds: {
|
|
40
|
+
[repaymentChainId: string]: {
|
|
41
|
+
[repaymentToken: string]: Refund;
|
|
42
|
+
};
|
|
43
|
+
} = {};
|
|
44
|
+
Object.entries(bundleFillsV3).forEach(([repaymentChainId, fillsForChain]) => {
|
|
45
|
+
combinedRefunds[repaymentChainId] ??= {};
|
|
46
|
+
Object.entries(fillsForChain).forEach(([l2TokenAddress, { refunds }]) => {
|
|
47
|
+
// refunds can be undefined if these fills were all slow fill executions.
|
|
48
|
+
if (refunds === undefined) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
// @dev use shallow copy so that modifying combinedRefunds doesn't modify the original refunds object.
|
|
52
|
+
const refundsShallowCopy = { ...refunds };
|
|
53
|
+
if (combinedRefunds[repaymentChainId][l2TokenAddress] === undefined) {
|
|
54
|
+
combinedRefunds[repaymentChainId][l2TokenAddress] = refundsShallowCopy;
|
|
55
|
+
} else {
|
|
56
|
+
// Each refunds object should have a unique refund address so we can add new ones to the
|
|
57
|
+
// existing dictionary.
|
|
58
|
+
combinedRefunds[repaymentChainId][l2TokenAddress] = {
|
|
59
|
+
...combinedRefunds[repaymentChainId][l2TokenAddress],
|
|
60
|
+
...refundsShallowCopy,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
Object.entries(expiredDepositsToRefundV3).forEach(([originChainId, depositsForChain]) => {
|
|
66
|
+
combinedRefunds[originChainId] ??= {};
|
|
67
|
+
Object.entries(depositsForChain).forEach(([l2TokenAddress, deposits]) => {
|
|
68
|
+
deposits.forEach((deposit) => {
|
|
69
|
+
if (combinedRefunds[originChainId][l2TokenAddress] === undefined) {
|
|
70
|
+
combinedRefunds[originChainId][l2TokenAddress] = { [deposit.depositor]: deposit.inputAmount };
|
|
71
|
+
} else {
|
|
72
|
+
const existingRefundAmount = combinedRefunds[originChainId][l2TokenAddress][deposit.depositor];
|
|
73
|
+
combinedRefunds[originChainId][l2TokenAddress][deposit.depositor] = deposit.inputAmount.add(
|
|
74
|
+
existingRefundAmount ?? bnZero
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
return combinedRefunds;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function prettyPrintV3SpokePoolEvents(
|
|
84
|
+
bundleDepositsV3: BundleDepositsV3,
|
|
85
|
+
bundleFillsV3: BundleFillsV3,
|
|
86
|
+
bundleInvalidFillsV3: V3FillWithBlock[],
|
|
87
|
+
bundleSlowFillsV3: BundleSlowFills,
|
|
88
|
+
expiredDepositsToRefundV3: ExpiredDepositsToRefundV3,
|
|
89
|
+
unexecutableSlowFills: BundleExcessSlowFills
|
|
90
|
+
): AnyObject {
|
|
91
|
+
return {
|
|
92
|
+
bundleDepositsV3: count2DDictionaryValues(bundleDepositsV3),
|
|
93
|
+
bundleFillsV3: count3DDictionaryValues(bundleFillsV3, "fills"),
|
|
94
|
+
bundleSlowFillsV3: count2DDictionaryValues(bundleSlowFillsV3),
|
|
95
|
+
expiredDepositsToRefundV3: count2DDictionaryValues(expiredDepositsToRefundV3),
|
|
96
|
+
unexecutableSlowFills: count2DDictionaryValues(unexecutableSlowFills),
|
|
97
|
+
allInvalidFillsInRangeByDestinationChainAndRelayer: groupObjectCountsByTwoProps(
|
|
98
|
+
bundleInvalidFillsV3,
|
|
99
|
+
"destinationChainId",
|
|
100
|
+
(fill) => `${fill.relayer}`
|
|
101
|
+
),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function getEndBlockBuffers(
|
|
106
|
+
chainIdListForBundleEvaluationBlockNumbers: number[],
|
|
107
|
+
blockRangeEndBlockBuffer: { [chainId: number]: number }
|
|
108
|
+
): number[] {
|
|
109
|
+
// These buffers can be configured by the bot runner. They have two use cases:
|
|
110
|
+
// 1) Validate the end blocks specified in the pending root bundle. If the end block is greater than the latest
|
|
111
|
+
// block for its chain, then we should dispute the bundle because we can't look up events in the future for that
|
|
112
|
+
// chain. However, there are some cases where the proposer's node for that chain is returning a higher HEAD block
|
|
113
|
+
// than the bot-runner is seeing, so we can use this buffer to allow the proposer some margin of error. If
|
|
114
|
+
// the bundle end block is less than HEAD but within this buffer, then we won't dispute and we'll just exit
|
|
115
|
+
// early from this function.
|
|
116
|
+
// 2) Subtract from the latest block in a new root bundle proposal. This can be used to reduce the chance that
|
|
117
|
+
// bot runs using different providers see different contract state close to the HEAD block for a chain.
|
|
118
|
+
// Reducing the latest block that we query also gives partially filled deposits slightly more buffer for relayers
|
|
119
|
+
// to fully fill the deposit and reduces the chance that the data worker includes a slow fill payment that gets
|
|
120
|
+
// filled during the challenge period.
|
|
121
|
+
return chainIdListForBundleEvaluationBlockNumbers.map((chainId: number) => blockRangeEndBlockBuffer[chainId] ?? 0);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function _buildPoolRebalanceRoot(
|
|
125
|
+
latestMainnetBlock: number,
|
|
126
|
+
mainnetBundleEndBlock: number,
|
|
127
|
+
bundleV3Deposits: BundleDepositsV3,
|
|
128
|
+
bundleFillsV3: BundleFillsV3,
|
|
129
|
+
bundleSlowFillsV3: BundleSlowFills,
|
|
130
|
+
unexecutableSlowFills: BundleExcessSlowFills,
|
|
131
|
+
expiredDepositsToRefundV3: ExpiredDepositsToRefundV3,
|
|
132
|
+
clients: { hubPoolClient: HubPoolClient; configStoreClient: AcrossConfigStoreClient },
|
|
133
|
+
maxL1TokenCountOverride?: number
|
|
134
|
+
): PoolRebalanceRoot {
|
|
135
|
+
// Running balances are the amount of tokens that we need to send to each SpokePool to pay for all instant and
|
|
136
|
+
// slow relay refunds. They are decreased by the amount of funds already held by the SpokePool. Balances are keyed
|
|
137
|
+
// by the SpokePool's network and L1 token equivalent of the L2 token to refund.
|
|
138
|
+
// Realized LP fees are keyed the same as running balances and represent the amount of LP fees that should be paid
|
|
139
|
+
// to LP's for each running balance.
|
|
140
|
+
|
|
141
|
+
// For each FilledRelay group, identified by { repaymentChainId, L1TokenAddress }, initialize a "running balance"
|
|
142
|
+
// to the total refund amount for that group.
|
|
143
|
+
const runningBalances: RunningBalances = {};
|
|
144
|
+
const realizedLpFees: RunningBalances = {};
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* REFUNDS FOR FAST FILLS
|
|
148
|
+
*/
|
|
149
|
+
|
|
150
|
+
// Add running balances and lp fees for v3 relayer refunds using BundleDataClient.bundleFillsV3. Refunds
|
|
151
|
+
// should be equal to inputAmount - lpFees so that relayers get to keep the relayer fee. Add the refund amount
|
|
152
|
+
// to the running balance for the repayment chain.
|
|
153
|
+
Object.entries(bundleFillsV3).forEach(([_repaymentChainId, fillsForChain]) => {
|
|
154
|
+
const repaymentChainId = Number(_repaymentChainId);
|
|
155
|
+
Object.entries(fillsForChain).forEach(
|
|
156
|
+
([l2TokenAddress, { realizedLpFees: totalRealizedLpFee, totalRefundAmount }]) => {
|
|
157
|
+
const l1TokenCounterpart = clients.hubPoolClient.getL1TokenForL2TokenAtBlock(
|
|
158
|
+
l2TokenAddress,
|
|
159
|
+
repaymentChainId,
|
|
160
|
+
mainnetBundleEndBlock
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
updateRunningBalance(runningBalances, repaymentChainId, l1TokenCounterpart, totalRefundAmount);
|
|
164
|
+
updateRunningBalance(realizedLpFees, repaymentChainId, l1TokenCounterpart, totalRealizedLpFee);
|
|
165
|
+
}
|
|
166
|
+
);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* PAYMENTS SLOW FILLS
|
|
171
|
+
*/
|
|
172
|
+
|
|
173
|
+
// Add running balances and lp fees for v3 slow fills using BundleDataClient.bundleSlowFillsV3.
|
|
174
|
+
// Slow fills should still increment bundleLpFees and updatedOutputAmount should be equal to inputAmount - lpFees.
|
|
175
|
+
// Increment the updatedOutputAmount to the destination chain.
|
|
176
|
+
Object.entries(bundleSlowFillsV3).forEach(([_destinationChainId, depositsForChain]) => {
|
|
177
|
+
const destinationChainId = Number(_destinationChainId);
|
|
178
|
+
Object.entries(depositsForChain).forEach(([outputToken, deposits]) => {
|
|
179
|
+
deposits.forEach((deposit) => {
|
|
180
|
+
const l1TokenCounterpart = clients.hubPoolClient.getL1TokenForL2TokenAtBlock(
|
|
181
|
+
outputToken,
|
|
182
|
+
destinationChainId,
|
|
183
|
+
mainnetBundleEndBlock
|
|
184
|
+
);
|
|
185
|
+
const lpFee = deposit.lpFeePct.mul(deposit.inputAmount).div(fixedPointAdjustment);
|
|
186
|
+
updateRunningBalance(runningBalances, destinationChainId, l1TokenCounterpart, deposit.inputAmount.sub(lpFee));
|
|
187
|
+
// Slow fill LP fees are accounted for when the slow fill executes and a V3FilledRelay is emitted. i.e. when
|
|
188
|
+
// the slow fill execution is included in bundleFillsV3.
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* EXCESSES FROM UNEXECUTABLE SLOW FILLS
|
|
195
|
+
*/
|
|
196
|
+
|
|
197
|
+
// Subtract destination chain running balances for BundleDataClient.unexecutableSlowFills.
|
|
198
|
+
// These are all slow fills that are impossible to execute and therefore the amount to return would be
|
|
199
|
+
// the updatedOutputAmount = inputAmount - lpFees.
|
|
200
|
+
Object.entries(unexecutableSlowFills).forEach(([_destinationChainId, slowFilledDepositsForChain]) => {
|
|
201
|
+
const destinationChainId = Number(_destinationChainId);
|
|
202
|
+
Object.entries(slowFilledDepositsForChain).forEach(([outputToken, slowFilledDeposits]) => {
|
|
203
|
+
slowFilledDeposits.forEach((deposit) => {
|
|
204
|
+
const l1TokenCounterpart = clients.hubPoolClient.getL1TokenForL2TokenAtBlock(
|
|
205
|
+
outputToken,
|
|
206
|
+
destinationChainId,
|
|
207
|
+
mainnetBundleEndBlock
|
|
208
|
+
);
|
|
209
|
+
const lpFee = deposit.lpFeePct.mul(deposit.inputAmount).div(fixedPointAdjustment);
|
|
210
|
+
updateRunningBalance(runningBalances, destinationChainId, l1TokenCounterpart, lpFee.sub(deposit.inputAmount));
|
|
211
|
+
// Slow fills don't add to lpFees, only when the slow fill is executed and a V3FilledRelay is emitted, so
|
|
212
|
+
// we don't need to subtract it here. Moreover, the HubPoole expects bundleLpFees to be > 0.
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* DEPOSITS
|
|
219
|
+
*/
|
|
220
|
+
|
|
221
|
+
// Handle v3Deposits. These decrement running balances from the origin chain equal to the inputAmount.
|
|
222
|
+
// There should not be early deposits in v3.
|
|
223
|
+
Object.entries(bundleV3Deposits).forEach(([, depositsForChain]) => {
|
|
224
|
+
Object.entries(depositsForChain).forEach(([, deposits]) => {
|
|
225
|
+
deposits.forEach((deposit) => {
|
|
226
|
+
updateRunningBalanceForDeposit(runningBalances, clients.hubPoolClient, deposit, deposit.inputAmount.mul(-1));
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* REFUNDS FOR EXPIRED DEPOSITS
|
|
233
|
+
*/
|
|
234
|
+
|
|
235
|
+
// Add origin chain running balance for expired v3 deposits. These should refund the inputAmount.
|
|
236
|
+
Object.entries(expiredDepositsToRefundV3).forEach(([_originChainId, depositsForChain]) => {
|
|
237
|
+
const originChainId = Number(_originChainId);
|
|
238
|
+
Object.entries(depositsForChain).forEach(([inputToken, deposits]) => {
|
|
239
|
+
deposits.forEach((deposit) => {
|
|
240
|
+
const l1TokenCounterpart = clients.hubPoolClient.getL1TokenForL2TokenAtBlock(
|
|
241
|
+
inputToken,
|
|
242
|
+
originChainId,
|
|
243
|
+
mainnetBundleEndBlock
|
|
244
|
+
);
|
|
245
|
+
updateRunningBalance(runningBalances, originChainId, l1TokenCounterpart, deposit.inputAmount);
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// Add to the running balance value from the last valid root bundle proposal for {chainId, l1Token}
|
|
251
|
+
// combination if found.
|
|
252
|
+
addLastRunningBalance(latestMainnetBlock, runningBalances, clients.hubPoolClient);
|
|
253
|
+
|
|
254
|
+
const leaves: PoolRebalanceLeaf[] = constructPoolRebalanceLeaves(
|
|
255
|
+
mainnetBundleEndBlock,
|
|
256
|
+
runningBalances,
|
|
257
|
+
realizedLpFees,
|
|
258
|
+
clients.configStoreClient,
|
|
259
|
+
maxL1TokenCountOverride
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
return {
|
|
263
|
+
runningBalances,
|
|
264
|
+
realizedLpFees,
|
|
265
|
+
leaves,
|
|
266
|
+
tree: buildPoolRebalanceLeafTree(leaves),
|
|
267
|
+
};
|
|
268
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Fill } from "../../../interfaces";
|
|
2
|
+
import { getBlockRangeForChain, isSlowFill } from "../../../utils";
|
|
3
|
+
import { HubPoolClient } from "../../HubPoolClient";
|
|
4
|
+
|
|
5
|
+
export function getRefundInformationFromFill(
|
|
6
|
+
fill: Fill,
|
|
7
|
+
hubPoolClient: HubPoolClient,
|
|
8
|
+
blockRangesForChains: number[][],
|
|
9
|
+
chainIdListForBundleEvaluationBlockNumbers: number[],
|
|
10
|
+
fromLiteChain: boolean
|
|
11
|
+
): {
|
|
12
|
+
chainToSendRefundTo: number;
|
|
13
|
+
repaymentToken: string;
|
|
14
|
+
} {
|
|
15
|
+
// Handle slow relay where repaymentChainId = 0. Slow relays always pay recipient on destination chain.
|
|
16
|
+
// So, save the slow fill under the destination chain, and save the fast fill under its repayment chain.
|
|
17
|
+
let chainToSendRefundTo = isSlowFill(fill) ? fill.destinationChainId : fill.repaymentChainId;
|
|
18
|
+
// If the fill is for a deposit originating from the lite chain, the repayment chain is the origin chain
|
|
19
|
+
// regardless of whether it is a slow or fast fill (we ignore slow fills but this is for posterity).
|
|
20
|
+
if (fromLiteChain) {
|
|
21
|
+
chainToSendRefundTo = fill.originChainId;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Save fill data and associate with repayment chain and L2 token refund should be denominated in.
|
|
25
|
+
const endBlockForMainnet = getBlockRangeForChain(
|
|
26
|
+
blockRangesForChains,
|
|
27
|
+
hubPoolClient.chainId,
|
|
28
|
+
chainIdListForBundleEvaluationBlockNumbers
|
|
29
|
+
)[1];
|
|
30
|
+
|
|
31
|
+
const l1TokenCounterpart = hubPoolClient.getL1TokenForL2TokenAtBlock(
|
|
32
|
+
fill.inputToken,
|
|
33
|
+
fill.originChainId,
|
|
34
|
+
endBlockForMainnet
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const repaymentToken = hubPoolClient.getL2TokenForL1TokenAtBlock(
|
|
38
|
+
l1TokenCounterpart,
|
|
39
|
+
chainToSendRefundTo,
|
|
40
|
+
endBlockForMainnet
|
|
41
|
+
);
|
|
42
|
+
return {
|
|
43
|
+
chainToSendRefundTo,
|
|
44
|
+
repaymentToken,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { MerkleTree } from "@across-protocol/contracts";
|
|
2
|
+
import { PoolRebalanceLeaf } from "../../../interfaces";
|
|
3
|
+
import { getParamType } from "../../../utils/ContractUtils";
|
|
4
|
+
import { utils } from "ethers";
|
|
5
|
+
|
|
6
|
+
export function buildPoolRebalanceLeafTree(poolRebalanceLeaves: PoolRebalanceLeaf[]): MerkleTree<PoolRebalanceLeaf> {
|
|
7
|
+
for (let i = 0; i < poolRebalanceLeaves.length; i++) {
|
|
8
|
+
// The 4 provided parallel arrays must be of equal length. Running Balances can optionally be 2x the length
|
|
9
|
+
if (
|
|
10
|
+
poolRebalanceLeaves[i].l1Tokens.length !== poolRebalanceLeaves[i].bundleLpFees.length ||
|
|
11
|
+
poolRebalanceLeaves[i].netSendAmounts.length !== poolRebalanceLeaves[i].bundleLpFees.length
|
|
12
|
+
) {
|
|
13
|
+
throw new Error("Provided lef arrays are not of equal length");
|
|
14
|
+
}
|
|
15
|
+
if (
|
|
16
|
+
poolRebalanceLeaves[i].runningBalances.length !== poolRebalanceLeaves[i].bundleLpFees.length * 2 &&
|
|
17
|
+
poolRebalanceLeaves[i].runningBalances.length !== poolRebalanceLeaves[i].bundleLpFees.length
|
|
18
|
+
) {
|
|
19
|
+
throw new Error("Running balances length unexpected");
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const paramType = getParamType("MerkleLibTest", "verifyPoolRebalance", "rebalance");
|
|
24
|
+
const hashFn = (input: PoolRebalanceLeaf) => utils.keccak256(utils.defaultAbiCoder.encode([paramType], [input]));
|
|
25
|
+
return new MerkleTree<PoolRebalanceLeaf>(poolRebalanceLeaves, hashFn);
|
|
26
|
+
}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { MerkleTree } from "@across-protocol/contracts/dist/utils/MerkleTree";
|
|
2
|
+
import { RunningBalances, PoolRebalanceLeaf, Clients, SpokePoolTargetBalance } from "../../../interfaces";
|
|
3
|
+
import { SpokePoolClient } from "../../SpokePoolClient";
|
|
4
|
+
import { BigNumber } from "ethers";
|
|
5
|
+
import { bnZero, compareAddresses } from "../../../utils";
|
|
6
|
+
import { HubPoolClient } from "../../HubPoolClient";
|
|
7
|
+
import { V3DepositWithBlock } from "./shims";
|
|
8
|
+
import { AcrossConfigStoreClient } from "../../AcrossConfigStoreClient";
|
|
9
|
+
|
|
10
|
+
export type PoolRebalanceRoot = {
|
|
11
|
+
runningBalances: RunningBalances;
|
|
12
|
+
realizedLpFees: RunningBalances;
|
|
13
|
+
leaves: PoolRebalanceLeaf[];
|
|
14
|
+
tree: MerkleTree<PoolRebalanceLeaf>;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// This returns a possible next block range that could be submitted as a new root bundle, or used as a reference
|
|
18
|
+
// when evaluating pending root bundle. The block end numbers must be less than the latest blocks for each chain ID
|
|
19
|
+
// (because we can't evaluate events in the future), and greater than the expected start blocks, which are the
|
|
20
|
+
// greater of 0 and the latest bundle end block for an executed root bundle proposal + 1.
|
|
21
|
+
export function getWidestPossibleExpectedBlockRange(
|
|
22
|
+
chainIdListForBundleEvaluationBlockNumbers: number[],
|
|
23
|
+
spokeClients: { [chainId: number]: SpokePoolClient },
|
|
24
|
+
endBlockBuffers: number[],
|
|
25
|
+
clients: Clients,
|
|
26
|
+
latestMainnetBlock: number,
|
|
27
|
+
enabledChains: number[]
|
|
28
|
+
): number[][] {
|
|
29
|
+
// We impose a buffer on the head of the chain to increase the probability that the received blocks are final.
|
|
30
|
+
// Reducing the latest block that we query also gives partially filled deposits slightly more buffer for relayers
|
|
31
|
+
// to fully fill the deposit and reduces the chance that the data worker includes a slow fill payment that gets
|
|
32
|
+
// filled during the challenge period.
|
|
33
|
+
const latestPossibleBundleEndBlockNumbers = chainIdListForBundleEvaluationBlockNumbers.map(
|
|
34
|
+
(chainId: number, index) =>
|
|
35
|
+
spokeClients[chainId] && Math.max(spokeClients[chainId].latestBlockSearched - endBlockBuffers[index], 0)
|
|
36
|
+
);
|
|
37
|
+
return chainIdListForBundleEvaluationBlockNumbers.map((chainId: number, index) => {
|
|
38
|
+
const lastEndBlockForChain = clients.hubPoolClient.getLatestBundleEndBlockForChain(
|
|
39
|
+
chainIdListForBundleEvaluationBlockNumbers,
|
|
40
|
+
latestMainnetBlock,
|
|
41
|
+
chainId
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
// If chain is disabled, re-use the latest bundle end block for the chain as both the start
|
|
45
|
+
// and end block.
|
|
46
|
+
if (!enabledChains.includes(chainId)) {
|
|
47
|
+
return [lastEndBlockForChain, lastEndBlockForChain];
|
|
48
|
+
} else {
|
|
49
|
+
// If the latest block hasn't advanced enough from the previous proposed end block, then re-use it. It will
|
|
50
|
+
// be regarded as disabled by the Dataworker clients. Otherwise, add 1 to the previous proposed end block.
|
|
51
|
+
if (lastEndBlockForChain >= latestPossibleBundleEndBlockNumbers[index]) {
|
|
52
|
+
// @dev: Without this check, then `getNextBundleStartBlockNumber` could return `latestBlock+1` even when the
|
|
53
|
+
// latest block for the chain hasn't advanced, resulting in an invalid range being produced.
|
|
54
|
+
return [lastEndBlockForChain, lastEndBlockForChain];
|
|
55
|
+
} else {
|
|
56
|
+
// Chain has advanced far enough including the buffer, return range from previous proposed end block + 1 to
|
|
57
|
+
// latest block for chain minus buffer.
|
|
58
|
+
return [
|
|
59
|
+
clients.hubPoolClient.getNextBundleStartBlockNumber(
|
|
60
|
+
chainIdListForBundleEvaluationBlockNumbers,
|
|
61
|
+
latestMainnetBlock,
|
|
62
|
+
chainId
|
|
63
|
+
),
|
|
64
|
+
latestPossibleBundleEndBlockNumbers[index],
|
|
65
|
+
];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function isChainDisabled(blockRangeForChain: number[]): boolean {
|
|
72
|
+
return blockRangeForChain[0] === blockRangeForChain[1];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Note: this function computes the intended transfer amount before considering the transfer threshold.
|
|
76
|
+
// A positive number indicates a transfer from hub to spoke.
|
|
77
|
+
export function computeDesiredTransferAmountToSpoke(
|
|
78
|
+
runningBalance: BigNumber,
|
|
79
|
+
spokePoolTargetBalance: SpokePoolTargetBalance
|
|
80
|
+
): BigNumber {
|
|
81
|
+
// Transfer is always desired if hub owes spoke.
|
|
82
|
+
if (runningBalance.gte(0)) {
|
|
83
|
+
return runningBalance;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Running balance is negative, but its absolute value is less than the spoke pool target balance threshold.
|
|
87
|
+
// In this case, we transfer nothing.
|
|
88
|
+
if (runningBalance.abs().lt(spokePoolTargetBalance.threshold)) {
|
|
89
|
+
return bnZero;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// We are left with the case where the spoke pool is beyond the threshold.
|
|
93
|
+
// A transfer needs to be initiated to bring it down to the target.
|
|
94
|
+
const transferSize = runningBalance.abs().sub(spokePoolTargetBalance.target);
|
|
95
|
+
|
|
96
|
+
// If the transferSize is < 0, this indicates that the target is still above the running balance.
|
|
97
|
+
// This can only happen if the threshold is less than the target. This is likely due to a misconfiguration.
|
|
98
|
+
// In this case, we transfer nothing until the target is exceeded.
|
|
99
|
+
if (transferSize.lt(0)) {
|
|
100
|
+
return bnZero;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Negate the transfer size because a transfer from spoke to hub is indicated by a negative number.
|
|
104
|
+
return transferSize.mul(-1);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// If the running balance is greater than the token transfer threshold, then set the net send amount
|
|
108
|
+
// equal to the running balance and reset the running balance to 0. Otherwise, the net send amount should be
|
|
109
|
+
// 0, indicating that we do not want the data worker to trigger a token transfer between hub pool and spoke
|
|
110
|
+
// pool when executing this leaf.
|
|
111
|
+
export function getNetSendAmountForL1Token(
|
|
112
|
+
spokePoolTargetBalance: SpokePoolTargetBalance,
|
|
113
|
+
runningBalance: BigNumber
|
|
114
|
+
): BigNumber {
|
|
115
|
+
return computeDesiredTransferAmountToSpoke(runningBalance, spokePoolTargetBalance);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function getRunningBalanceForL1Token(
|
|
119
|
+
spokePoolTargetBalance: SpokePoolTargetBalance,
|
|
120
|
+
runningBalance: BigNumber
|
|
121
|
+
): BigNumber {
|
|
122
|
+
const desiredTransferAmount = computeDesiredTransferAmountToSpoke(runningBalance, spokePoolTargetBalance);
|
|
123
|
+
return runningBalance.sub(desiredTransferAmount);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function updateRunningBalance(
|
|
127
|
+
runningBalances: RunningBalances,
|
|
128
|
+
l2ChainId: number,
|
|
129
|
+
l1Token: string,
|
|
130
|
+
updateAmount: BigNumber
|
|
131
|
+
): void {
|
|
132
|
+
// Initialize dictionary if empty.
|
|
133
|
+
if (!runningBalances[l2ChainId]) {
|
|
134
|
+
runningBalances[l2ChainId] = {};
|
|
135
|
+
}
|
|
136
|
+
const runningBalance = runningBalances[l2ChainId][l1Token];
|
|
137
|
+
if (runningBalance) {
|
|
138
|
+
runningBalances[l2ChainId][l1Token] = runningBalance.add(updateAmount);
|
|
139
|
+
} else {
|
|
140
|
+
runningBalances[l2ChainId][l1Token] = updateAmount;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function addLastRunningBalance(
|
|
145
|
+
latestMainnetBlock: number,
|
|
146
|
+
runningBalances: RunningBalances,
|
|
147
|
+
hubPoolClient: HubPoolClient
|
|
148
|
+
): void {
|
|
149
|
+
Object.keys(runningBalances).forEach((repaymentChainId) => {
|
|
150
|
+
Object.keys(runningBalances[Number(repaymentChainId)]).forEach((l1TokenAddress) => {
|
|
151
|
+
const { runningBalance } = hubPoolClient.getRunningBalanceBeforeBlockForChain(
|
|
152
|
+
latestMainnetBlock,
|
|
153
|
+
Number(repaymentChainId),
|
|
154
|
+
l1TokenAddress
|
|
155
|
+
);
|
|
156
|
+
if (!runningBalance.eq(bnZero)) {
|
|
157
|
+
updateRunningBalance(runningBalances, Number(repaymentChainId), l1TokenAddress, runningBalance);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function updateRunningBalanceForDeposit(
|
|
164
|
+
runningBalances: RunningBalances,
|
|
165
|
+
hubPoolClient: HubPoolClient,
|
|
166
|
+
deposit: V3DepositWithBlock,
|
|
167
|
+
updateAmount: BigNumber
|
|
168
|
+
): void {
|
|
169
|
+
const l1TokenCounterpart = hubPoolClient.getL1TokenForL2TokenAtBlock(
|
|
170
|
+
deposit.inputToken,
|
|
171
|
+
deposit.originChainId,
|
|
172
|
+
deposit.quoteBlockNumber
|
|
173
|
+
);
|
|
174
|
+
updateRunningBalance(runningBalances, deposit.originChainId, l1TokenCounterpart, updateAmount);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export function constructPoolRebalanceLeaves(
|
|
178
|
+
latestMainnetBlock: number,
|
|
179
|
+
runningBalances: RunningBalances,
|
|
180
|
+
realizedLpFees: RunningBalances,
|
|
181
|
+
configStoreClient: AcrossConfigStoreClient,
|
|
182
|
+
maxL1TokenCount?: number
|
|
183
|
+
): PoolRebalanceLeaf[] {
|
|
184
|
+
// Create one leaf per L2 chain ID. First we'll create a leaf with all L1 tokens for each chain ID, and then
|
|
185
|
+
// we'll split up any leaves with too many L1 tokens.
|
|
186
|
+
const leaves: PoolRebalanceLeaf[] = [];
|
|
187
|
+
Object.keys(runningBalances)
|
|
188
|
+
.map((chainId) => Number(chainId))
|
|
189
|
+
// Leaves should be sorted by ascending chain ID
|
|
190
|
+
.sort((chainIdA, chainIdB) => chainIdA - chainIdB)
|
|
191
|
+
.map((chainId) => {
|
|
192
|
+
// Sort addresses.
|
|
193
|
+
const sortedL1Tokens = Object.keys(runningBalances[chainId]).sort((addressA, addressB) => {
|
|
194
|
+
return compareAddresses(addressA, addressB);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// This begins at 0 and increments for each leaf for this { chainId, L1Token } combination.
|
|
198
|
+
let groupIndexForChainId = 0;
|
|
199
|
+
|
|
200
|
+
// Split addresses into multiple leaves if there are more L1 tokens than allowed per leaf.
|
|
201
|
+
const maxL1TokensPerLeaf =
|
|
202
|
+
maxL1TokenCount || configStoreClient.getMaxRefundCountForRelayerRefundLeafForBlock(latestMainnetBlock);
|
|
203
|
+
for (let i = 0; i < sortedL1Tokens.length; i += maxL1TokensPerLeaf) {
|
|
204
|
+
const l1TokensToIncludeInThisLeaf = sortedL1Tokens.slice(i, i + maxL1TokensPerLeaf);
|
|
205
|
+
|
|
206
|
+
const spokeTargetBalances = l1TokensToIncludeInThisLeaf.map((l1Token) =>
|
|
207
|
+
configStoreClient.getSpokeTargetBalancesForBlock(l1Token, chainId, latestMainnetBlock)
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
// Build leaves using running balances and realized lp fees data for l1Token + chain, or default to
|
|
211
|
+
// zero if undefined.
|
|
212
|
+
const leafBundleLpFees = l1TokensToIncludeInThisLeaf.map(
|
|
213
|
+
(l1Token) => realizedLpFees[chainId]?.[l1Token] ?? bnZero
|
|
214
|
+
);
|
|
215
|
+
const leafNetSendAmounts = l1TokensToIncludeInThisLeaf.map((l1Token, index) =>
|
|
216
|
+
runningBalances[chainId] && runningBalances[chainId][l1Token]
|
|
217
|
+
? getNetSendAmountForL1Token(spokeTargetBalances[index], runningBalances[chainId][l1Token])
|
|
218
|
+
: bnZero
|
|
219
|
+
);
|
|
220
|
+
const leafRunningBalances = l1TokensToIncludeInThisLeaf.map((l1Token, index) =>
|
|
221
|
+
runningBalances[chainId]?.[l1Token]
|
|
222
|
+
? getRunningBalanceForL1Token(spokeTargetBalances[index], runningBalances[chainId][l1Token])
|
|
223
|
+
: bnZero
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
leaves.push({
|
|
227
|
+
chainId: chainId,
|
|
228
|
+
bundleLpFees: leafBundleLpFees,
|
|
229
|
+
netSendAmounts: leafNetSendAmounts,
|
|
230
|
+
runningBalances: leafRunningBalances,
|
|
231
|
+
groupIndex: groupIndexForChainId++,
|
|
232
|
+
leafId: leaves.length,
|
|
233
|
+
l1Tokens: l1TokensToIncludeInThisLeaf,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
return leaves;
|
|
238
|
+
}
|