@humanode-hyperlane/rebalancer 27.2.2 → 1029.1.0
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/bridges/LiFiBridge.d.ts +3 -3
- package/dist/bridges/LiFiBridge.d.ts.map +1 -1
- package/dist/bridges/LiFiBridge.js +66 -55
- package/dist/bridges/LiFiBridge.js.map +1 -1
- package/dist/bridges/LiFiBridge.test.js +213 -0
- package/dist/bridges/LiFiBridge.test.js.map +1 -1
- package/dist/config/RebalancerConfig.d.ts +4 -3
- package/dist/config/RebalancerConfig.d.ts.map +1 -1
- package/dist/config/RebalancerConfig.js +7 -5
- package/dist/config/RebalancerConfig.js.map +1 -1
- package/dist/config/RebalancerConfig.test.js +278 -2
- package/dist/config/RebalancerConfig.test.js.map +1 -1
- package/dist/config/types.d.ts +707 -2664
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +62 -7
- package/dist/config/types.js.map +1 -1
- package/dist/core/InventoryRebalancer.d.ts +13 -19
- package/dist/core/InventoryRebalancer.d.ts.map +1 -1
- package/dist/core/InventoryRebalancer.js +404 -276
- package/dist/core/InventoryRebalancer.js.map +1 -1
- package/dist/core/InventoryRebalancer.test.js +814 -25
- package/dist/core/InventoryRebalancer.test.js.map +1 -1
- package/dist/core/Rebalancer.d.ts.map +1 -1
- package/dist/core/Rebalancer.js +12 -6
- package/dist/core/Rebalancer.js.map +1 -1
- package/dist/core/Rebalancer.test.js +51 -0
- package/dist/core/Rebalancer.test.js.map +1 -1
- package/dist/core/RebalancerOrchestrator.d.ts.map +1 -1
- package/dist/core/RebalancerOrchestrator.test.js +0 -1
- package/dist/core/RebalancerOrchestrator.test.js.map +1 -1
- package/dist/core/RebalancerService.d.ts.map +1 -1
- package/dist/core/RebalancerService.js +3 -2
- package/dist/core/RebalancerService.js.map +1 -1
- package/dist/core/RebalancerService.test.js +24 -0
- package/dist/core/RebalancerService.test.js.map +1 -1
- package/dist/e2e/fixtures/routes.d.ts +3 -3
- package/dist/e2e/fixtures/routes.d.ts.map +1 -1
- package/dist/e2e/harness/BaseLocalDeploymentManager.d.ts.map +1 -1
- package/dist/e2e/harness/BaseLocalDeploymentManager.js +3 -2
- package/dist/e2e/harness/BaseLocalDeploymentManager.js.map +1 -1
- package/dist/e2e/harness/Erc20InventoryLocalDeploymentManager.d.ts.map +1 -1
- package/dist/e2e/harness/Erc20InventoryLocalDeploymentManager.js.map +1 -1
- package/dist/e2e/harness/Erc20LocalDeploymentManager.d.ts.map +1 -1
- package/dist/e2e/harness/ForkIndexer.d.ts.map +1 -1
- package/dist/e2e/harness/ForkIndexer.js.map +1 -1
- package/dist/e2e/harness/LocalProvider.d.ts +3 -0
- package/dist/e2e/harness/LocalProvider.d.ts.map +1 -0
- package/dist/e2e/harness/LocalProvider.js +9 -0
- package/dist/e2e/harness/LocalProvider.js.map +1 -0
- package/dist/e2e/harness/LocalProvider.test.d.ts +2 -0
- package/dist/e2e/harness/LocalProvider.test.d.ts.map +1 -0
- package/dist/e2e/harness/LocalProvider.test.js +14 -0
- package/dist/e2e/harness/LocalProvider.test.js.map +1 -0
- package/dist/e2e/harness/MixedLocalDeploymentManager.d.ts.map +1 -1
- package/dist/e2e/harness/MixedLocalDeploymentManager.js.map +1 -1
- package/dist/e2e/harness/MockExplorerClient.d.ts.map +1 -1
- package/dist/e2e/harness/MockExplorerClient.js.map +1 -1
- package/dist/e2e/harness/MockExternalBridge.d.ts.map +1 -1
- package/dist/e2e/harness/MockExternalBridge.js.map +1 -1
- package/dist/e2e/harness/NativeLocalDeploymentManager.d.ts.map +1 -1
- package/dist/e2e/harness/NativeLocalDeploymentManager.js +2 -1
- package/dist/e2e/harness/NativeLocalDeploymentManager.js.map +1 -1
- package/dist/e2e/harness/SnapshotHelper.d.ts.map +1 -1
- package/dist/e2e/harness/SnapshotHelper.js +3 -5
- package/dist/e2e/harness/SnapshotHelper.js.map +1 -1
- package/dist/e2e/harness/TestHelpers.js +1 -2
- package/dist/e2e/harness/TestHelpers.js.map +1 -1
- package/dist/e2e/harness/TestRebalancer.d.ts +5 -1
- package/dist/e2e/harness/TestRebalancer.d.ts.map +1 -1
- package/dist/e2e/harness/TestRebalancer.js +14 -4
- package/dist/e2e/harness/TestRebalancer.js.map +1 -1
- package/dist/e2e/relayer-denylist.e2e-test.d.ts +2 -0
- package/dist/e2e/relayer-denylist.e2e-test.d.ts.map +1 -0
- package/dist/e2e/relayer-denylist.e2e-test.js +388 -0
- package/dist/e2e/relayer-denylist.e2e-test.js.map +1 -0
- package/dist/factories/RebalancerContextFactory.d.ts.map +1 -1
- package/dist/factories/RebalancerContextFactory.js +61 -31
- package/dist/factories/RebalancerContextFactory.js.map +1 -1
- package/dist/factories/RebalancerContextFactory.test.js +336 -5
- package/dist/factories/RebalancerContextFactory.test.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces/IRebalancer.d.ts +4 -2
- package/dist/interfaces/IRebalancer.d.ts.map +1 -1
- package/dist/metrics/Metrics.d.ts.map +1 -1
- package/dist/metrics/Metrics.js +1 -1
- package/dist/metrics/Metrics.js.map +1 -1
- package/dist/metrics/PriceGetter.d.ts +1 -0
- package/dist/metrics/PriceGetter.d.ts.map +1 -1
- package/dist/metrics/PriceGetter.js +14 -4
- package/dist/metrics/PriceGetter.js.map +1 -1
- package/dist/metrics/PriceGetter.test.d.ts +2 -0
- package/dist/metrics/PriceGetter.test.d.ts.map +1 -0
- package/dist/metrics/PriceGetter.test.js +84 -0
- package/dist/metrics/PriceGetter.test.js.map +1 -0
- package/dist/metrics/scripts/metrics.d.ts +4 -4
- package/dist/monitor/Monitor.d.ts +1 -0
- package/dist/monitor/Monitor.d.ts.map +1 -1
- package/dist/monitor/Monitor.js +55 -46
- package/dist/monitor/Monitor.js.map +1 -1
- package/dist/monitor/Monitor.test.d.ts +2 -0
- package/dist/monitor/Monitor.test.d.ts.map +1 -0
- package/dist/monitor/Monitor.test.js +346 -0
- package/dist/monitor/Monitor.test.js.map +1 -0
- package/dist/service.d.ts +1 -1
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +9 -5
- package/dist/service.js.map +1 -1
- package/dist/strategy/BaseStrategy.d.ts.map +1 -1
- package/dist/strategy/BaseStrategy.js +13 -11
- package/dist/strategy/BaseStrategy.js.map +1 -1
- package/dist/strategy/CollateralDeficitStrategy.d.ts.map +1 -1
- package/dist/strategy/CollateralDeficitStrategy.js +2 -2
- package/dist/strategy/CollateralDeficitStrategy.js.map +1 -1
- package/dist/strategy/CompositeStrategy.d.ts.map +1 -1
- package/dist/strategy/CompositeStrategy.js.map +1 -1
- package/dist/strategy/CompositeStrategy.test.js.map +1 -1
- package/dist/strategy/MinAmountStrategy.d.ts +1 -0
- package/dist/strategy/MinAmountStrategy.d.ts.map +1 -1
- package/dist/strategy/MinAmountStrategy.js +12 -8
- package/dist/strategy/MinAmountStrategy.js.map +1 -1
- package/dist/strategy/MinAmountStrategy.test.js +189 -2
- package/dist/strategy/MinAmountStrategy.test.js.map +1 -1
- package/dist/strategy/StrategyFactory.d.ts.map +1 -1
- package/dist/strategy/StrategyFactory.js.map +1 -1
- package/dist/strategy/WeightedStrategy.d.ts.map +1 -1
- package/dist/test/helpers.d.ts +11 -3
- package/dist/test/helpers.d.ts.map +1 -1
- package/dist/test/helpers.js +9 -11
- package/dist/test/helpers.js.map +1 -1
- package/dist/test/lifiMocks.d.ts +6 -6
- package/dist/test/lifiMocks.d.ts.map +1 -1
- package/dist/test/lifiMocks.js +5 -2
- package/dist/test/lifiMocks.js.map +1 -1
- package/dist/test/pendingTransferMiddlewareMocks.d.ts +17 -0
- package/dist/test/pendingTransferMiddlewareMocks.d.ts.map +1 -0
- package/dist/test/pendingTransferMiddlewareMocks.js +43 -0
- package/dist/test/pendingTransferMiddlewareMocks.js.map +1 -0
- package/dist/tracking/ActionTracker.d.ts +4 -0
- package/dist/tracking/ActionTracker.d.ts.map +1 -1
- package/dist/tracking/ActionTracker.js +76 -9
- package/dist/tracking/ActionTracker.js.map +1 -1
- package/dist/tracking/ActionTracker.test.js +418 -1
- package/dist/tracking/ActionTracker.test.js.map +1 -1
- package/dist/tracking/IActionTracker.d.ts +4 -2
- package/dist/tracking/IActionTracker.d.ts.map +1 -1
- package/dist/tracking/InflightContextAdapter.d.ts.map +1 -1
- package/dist/tracking/InflightContextAdapter.js.map +1 -1
- package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.d.ts +64 -0
- package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.js +474 -0
- package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.test.d.ts +2 -0
- package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.test.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.test.js +1168 -0
- package/dist/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.test.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.d.ts +61 -0
- package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.js +160 -0
- package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.test.d.ts +2 -0
- package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.test.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.test.js +369 -0
- package/dist/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.test.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.d.ts +60 -0
- package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.js +288 -0
- package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.test.d.ts +2 -0
- package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.test.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.test.js +606 -0
- package/dist/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.test.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.d.ts +25 -0
- package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.js +41 -0
- package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.test.d.ts +2 -0
- package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.test.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.test.js +141 -0
- package/dist/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.test.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/matchBody.d.ts +12 -0
- package/dist/tracking/pendingTransferMiddlewares/matchBody.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/matchBody.js +29 -0
- package/dist/tracking/pendingTransferMiddlewares/matchBody.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.d.ts +59 -0
- package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.js +661 -0
- package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.test.d.ts +2 -0
- package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.test.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.test.js +1093 -0
- package/dist/tracking/pendingTransferMiddlewares/relayerDenylistRules.test.js.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/types.d.ts +2 -0
- package/dist/tracking/pendingTransferMiddlewares/types.d.ts.map +1 -0
- package/dist/tracking/pendingTransferMiddlewares/types.js +4 -0
- package/dist/tracking/pendingTransferMiddlewares/types.js.map +1 -0
- package/dist/tracking/store/InMemoryStore.d.ts.map +1 -1
- package/dist/utils/ExplorerClient.d.ts +1 -0
- package/dist/utils/ExplorerClient.d.ts.map +1 -1
- package/dist/utils/ExplorerClient.js +8 -3
- package/dist/utils/ExplorerClient.js.map +1 -1
- package/dist/utils/ExplorerClient.test.js +25 -0
- package/dist/utils/ExplorerClient.test.js.map +1 -1
- package/dist/utils/balanceUtils.d.ts +7 -1
- package/dist/utils/balanceUtils.d.ts.map +1 -1
- package/dist/utils/balanceUtils.js +39 -1
- package/dist/utils/balanceUtils.js.map +1 -1
- package/dist/utils/balanceUtils.test.js +55 -1
- package/dist/utils/balanceUtils.test.js.map +1 -1
- package/dist/utils/blockTag.d.ts +5 -4
- package/dist/utils/blockTag.d.ts.map +1 -1
- package/dist/utils/blockTag.js +26 -10
- package/dist/utils/blockTag.js.map +1 -1
- package/dist/utils/blockTag.test.d.ts +2 -0
- package/dist/utils/blockTag.test.d.ts.map +1 -0
- package/dist/utils/blockTag.test.js +132 -0
- package/dist/utils/blockTag.test.js.map +1 -0
- package/dist/utils/bridgeUtils.js.map +1 -1
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/gasEstimation.d.ts +2 -1
- package/dist/utils/gasEstimation.d.ts.map +1 -1
- package/dist/utils/gasEstimation.js +16 -13
- package/dist/utils/gasEstimation.js.map +1 -1
- package/dist/utils/gasEstimation.test.d.ts +2 -0
- package/dist/utils/gasEstimation.test.d.ts.map +1 -0
- package/dist/utils/gasEstimation.test.js +104 -0
- package/dist/utils/gasEstimation.test.js.map +1 -0
- package/dist/utils/tokenUtils.d.ts.map +1 -1
- package/dist/utils/tokenUtils.js +5 -2
- package/dist/utils/tokenUtils.js.map +1 -1
- package/package.json +23 -22
- package/src/bridges/LiFiBridge.test.ts +270 -0
- package/src/bridges/LiFiBridge.ts +90 -71
- package/src/config/RebalancerConfig.test.ts +315 -1
- package/src/config/RebalancerConfig.ts +6 -3
- package/src/config/types.ts +98 -8
- package/src/core/InventoryRebalancer.test.ts +1092 -38
- package/src/core/InventoryRebalancer.ts +584 -351
- package/src/core/Rebalancer.test.ts +84 -0
- package/src/core/Rebalancer.ts +22 -6
- package/src/core/RebalancerOrchestrator.test.ts +0 -1
- package/src/core/RebalancerService.test.ts +35 -0
- package/src/core/RebalancerService.ts +3 -2
- package/src/e2e/harness/BaseLocalDeploymentManager.ts +3 -1
- package/src/e2e/harness/LocalProvider.test.ts +16 -0
- package/src/e2e/harness/LocalProvider.ts +10 -0
- package/src/e2e/harness/NativeLocalDeploymentManager.ts +2 -1
- package/src/e2e/harness/SnapshotHelper.ts +2 -5
- package/src/e2e/harness/TestHelpers.ts +3 -3
- package/src/e2e/harness/TestRebalancer.ts +21 -1
- package/src/e2e/relayer-denylist.e2e-test.ts +558 -0
- package/src/factories/RebalancerContextFactory.test.ts +489 -8
- package/src/factories/RebalancerContextFactory.ts +86 -36
- package/src/index.ts +2 -0
- package/src/interfaces/IRebalancer.ts +4 -1
- package/src/metrics/Metrics.ts +1 -0
- package/src/metrics/PriceGetter.test.ts +113 -0
- package/src/metrics/PriceGetter.ts +18 -3
- package/src/monitor/Monitor.test.ts +408 -0
- package/src/monitor/Monitor.ts +123 -97
- package/src/service.ts +14 -8
- package/src/strategy/BaseStrategy.ts +18 -15
- package/src/strategy/CollateralDeficitStrategy.ts +4 -3
- package/src/strategy/MinAmountStrategy.test.ts +238 -2
- package/src/strategy/MinAmountStrategy.ts +29 -17
- package/src/test/helpers.ts +13 -12
- package/src/test/lifiMocks.ts +5 -2
- package/src/test/pendingTransferMiddlewareMocks.ts +65 -0
- package/src/tracking/ActionTracker.test.ts +635 -3
- package/src/tracking/ActionTracker.ts +92 -12
- package/src/tracking/IActionTracker.ts +4 -2
- package/src/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.test.ts +1693 -0
- package/src/tracking/pendingTransferMiddlewares/BlacklistIsmMiddleware.ts +784 -0
- package/src/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.test.ts +554 -0
- package/src/tracking/pendingTransferMiddlewares/PendingTransferMiddleware.ts +233 -0
- package/src/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.test.ts +894 -0
- package/src/tracking/pendingTransferMiddlewares/RelayerDenylistMiddleware.ts +404 -0
- package/src/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.test.ts +205 -0
- package/src/tracking/pendingTransferMiddlewares/buildPendingTransferMiddlewares.ts +89 -0
- package/src/tracking/pendingTransferMiddlewares/fixtures/mainnet-denylist.json +3556 -0
- package/src/tracking/pendingTransferMiddlewares/matchBody.ts +43 -0
- package/src/tracking/pendingTransferMiddlewares/relayerDenylistRules.test.ts +1220 -0
- package/src/tracking/pendingTransferMiddlewares/relayerDenylistRules.ts +934 -0
- package/src/tracking/pendingTransferMiddlewares/types.ts +3 -0
- package/src/utils/ExplorerClient.test.ts +42 -0
- package/src/utils/ExplorerClient.ts +14 -3
- package/src/utils/balanceUtils.test.ts +87 -1
- package/src/utils/balanceUtils.ts +73 -2
- package/src/utils/blockTag.test.ts +173 -0
- package/src/utils/blockTag.ts +35 -15
- package/src/utils/gasEstimation.test.ts +192 -0
- package/src/utils/gasEstimation.ts +17 -11
- package/src/utils/tokenUtils.ts +5 -2
|
@@ -0,0 +1,558 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
import { BigNumber, ethers, providers } from 'ethers';
|
|
3
|
+
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { pathToFileURL } from 'node:url';
|
|
7
|
+
|
|
8
|
+
import { ERC20__factory } from '@humanode-hyperlane/core';
|
|
9
|
+
import {
|
|
10
|
+
HyperlaneCore,
|
|
11
|
+
MultiProvider,
|
|
12
|
+
snapshot,
|
|
13
|
+
} from '@humanode-hyperlane/sdk';
|
|
14
|
+
import { assert, sleep } from '@humanode-hyperlane/utils';
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
PendingTransferMiddlewareType,
|
|
18
|
+
RebalancerStrategyOptions,
|
|
19
|
+
type StrategyConfig,
|
|
20
|
+
} from '../config/types.js';
|
|
21
|
+
import type { RebalanceAction } from '../tracking/types.js';
|
|
22
|
+
import type { ExplorerMessage } from '../utils/ExplorerClient.js';
|
|
23
|
+
|
|
24
|
+
import {
|
|
25
|
+
ANVIL_TEST_PRIVATE_KEY,
|
|
26
|
+
DOMAIN_IDS,
|
|
27
|
+
type DeployedAddresses,
|
|
28
|
+
TEST_CHAINS,
|
|
29
|
+
type TestChain,
|
|
30
|
+
} from './fixtures/routes.js';
|
|
31
|
+
import { getAllCollateralBalances } from './harness/BridgeSetup.js';
|
|
32
|
+
import { type LocalDeploymentContext } from './harness/BaseLocalDeploymentManager.js';
|
|
33
|
+
import { Erc20LocalDeploymentManager } from './harness/Erc20LocalDeploymentManager.js';
|
|
34
|
+
import { resetSnapshotsAndRefreshProviders } from './harness/SnapshotHelper.js';
|
|
35
|
+
import { getFirstMonitorEvent } from './harness/TestHelpers.js';
|
|
36
|
+
import {
|
|
37
|
+
TestRebalancer,
|
|
38
|
+
type TestRebalancerContext,
|
|
39
|
+
} from './harness/TestRebalancer.js';
|
|
40
|
+
import { tryRelayMessage } from './harness/TransferHelper.js';
|
|
41
|
+
|
|
42
|
+
const USDC = 1_000_000n;
|
|
43
|
+
const REBALANCE_MESSAGE = 'rebalance_message';
|
|
44
|
+
|
|
45
|
+
// Re-reads the denylist on every Explorer query, so a rule written between
|
|
46
|
+
// cycles applies to the next one. Config files cannot set 0: the schema
|
|
47
|
+
// requires a positive interval.
|
|
48
|
+
const DENYLIST_REFRESH_INTERVAL_SECS = 0;
|
|
49
|
+
const POSITIVE_REFRESH_INTERVAL_SECS = 20;
|
|
50
|
+
const REFRESH_WAIT_MARGIN_MS = 1_000;
|
|
51
|
+
|
|
52
|
+
describe('RelayerDenylist middleware rebalance messages E2E', function () {
|
|
53
|
+
this.timeout(300_000);
|
|
54
|
+
|
|
55
|
+
let deploymentManager: Erc20LocalDeploymentManager;
|
|
56
|
+
let multiProvider: MultiProvider;
|
|
57
|
+
let localProviders: Map<string, providers.JsonRpcProvider>;
|
|
58
|
+
let snapshotIds: Map<string, string>;
|
|
59
|
+
let hyperlaneCore: HyperlaneCore;
|
|
60
|
+
let deployedAddresses: DeployedAddresses;
|
|
61
|
+
let weightedStrategyConfig: StrategyConfig[];
|
|
62
|
+
let denylistDir: string;
|
|
63
|
+
let denylistPath: string;
|
|
64
|
+
|
|
65
|
+
before(async function () {
|
|
66
|
+
deploymentManager = new Erc20LocalDeploymentManager();
|
|
67
|
+
const ctx: LocalDeploymentContext<DeployedAddresses> =
|
|
68
|
+
await deploymentManager.start();
|
|
69
|
+
multiProvider = ctx.multiProvider;
|
|
70
|
+
localProviders = ctx.providers;
|
|
71
|
+
deployedAddresses = ctx.deployedAddresses;
|
|
72
|
+
|
|
73
|
+
const coreAddresses: Record<string, Record<string, string>> = {};
|
|
74
|
+
for (const chain of TEST_CHAINS) {
|
|
75
|
+
coreAddresses[chain] = {
|
|
76
|
+
mailbox: deployedAddresses.chains[chain].mailbox,
|
|
77
|
+
interchainSecurityModule: deployedAddresses.chains[chain].ism,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
hyperlaneCore = HyperlaneCore.fromAddressesMap(
|
|
81
|
+
coreAddresses,
|
|
82
|
+
multiProvider,
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
weightedStrategyConfig = [
|
|
86
|
+
{
|
|
87
|
+
rebalanceStrategy: RebalancerStrategyOptions.Weighted,
|
|
88
|
+
chains: {
|
|
89
|
+
anvil1: {
|
|
90
|
+
weighted: { weight: 60n, tolerance: 5n },
|
|
91
|
+
bridge: deployedAddresses.bridgeRoute1.anvil1,
|
|
92
|
+
},
|
|
93
|
+
anvil2: {
|
|
94
|
+
weighted: { weight: 20n, tolerance: 5n },
|
|
95
|
+
bridge: deployedAddresses.bridgeRoute1.anvil2,
|
|
96
|
+
},
|
|
97
|
+
anvil3: {
|
|
98
|
+
weighted: { weight: 20n, tolerance: 5n },
|
|
99
|
+
bridge: deployedAddresses.bridgeRoute1.anvil3,
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
];
|
|
104
|
+
|
|
105
|
+
snapshotIds = new Map();
|
|
106
|
+
for (const [chain, provider] of localProviders) {
|
|
107
|
+
snapshotIds.set(chain, await snapshot(provider));
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
beforeEach(function () {
|
|
112
|
+
denylistDir = mkdtempSync(join(tmpdir(), 'rebalancer-denylist-e2e-'));
|
|
113
|
+
denylistPath = join(denylistDir, 'denylist.json');
|
|
114
|
+
writeDenylist([]);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
afterEach(async function () {
|
|
118
|
+
rmSync(denylistDir, { recursive: true, force: true });
|
|
119
|
+
await resetSnapshotsAndRefreshProviders({
|
|
120
|
+
localProviders,
|
|
121
|
+
multiProvider,
|
|
122
|
+
snapshotIds,
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
after(async function () {
|
|
127
|
+
if (deploymentManager) {
|
|
128
|
+
await deploymentManager.stop();
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
function writeDenylist(
|
|
133
|
+
messageIds: string[],
|
|
134
|
+
matches: Record<string, unknown>[] = [],
|
|
135
|
+
): void {
|
|
136
|
+
writeFileSync(
|
|
137
|
+
denylistPath,
|
|
138
|
+
JSON.stringify({
|
|
139
|
+
rules: [
|
|
140
|
+
...messageIds.map((messageId) => ({ messageId })),
|
|
141
|
+
...matches,
|
|
142
|
+
].map((match) => ({
|
|
143
|
+
reason: 'CCTP delivered the funds out of band',
|
|
144
|
+
addedBy: 'e2e',
|
|
145
|
+
match,
|
|
146
|
+
})),
|
|
147
|
+
}),
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function buildContext(
|
|
152
|
+
balances: string | Record<string, BigNumber>,
|
|
153
|
+
mockRebalanceActions: ExplorerMessage[] = [],
|
|
154
|
+
refreshIntervalSecs = DENYLIST_REFRESH_INTERVAL_SECS,
|
|
155
|
+
): Promise<TestRebalancerContext> {
|
|
156
|
+
const builder = TestRebalancer.builder(deploymentManager, multiProvider)
|
|
157
|
+
.withStrategy(weightedStrategyConfig)
|
|
158
|
+
.withBalances(balances)
|
|
159
|
+
.withPendingTransferMiddlewares([
|
|
160
|
+
{
|
|
161
|
+
type: PendingTransferMiddlewareType.RelayerDenylist,
|
|
162
|
+
url: pathToFileURL(denylistPath).href,
|
|
163
|
+
refreshIntervalSecs,
|
|
164
|
+
},
|
|
165
|
+
])
|
|
166
|
+
.withExecutionMode('execute');
|
|
167
|
+
for (const message of mockRebalanceActions) {
|
|
168
|
+
builder.withMockRebalanceAction(message);
|
|
169
|
+
}
|
|
170
|
+
return builder.build();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async function runCycle(context: TestRebalancerContext): Promise<void> {
|
|
174
|
+
const event = await getFirstMonitorEvent(context.createMonitor(0));
|
|
175
|
+
await context.orchestrator.executeCycle(event);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function getBalances(): Promise<Record<string, BigNumber>> {
|
|
179
|
+
return getAllCollateralBalances(
|
|
180
|
+
localProviders,
|
|
181
|
+
TEST_CHAINS,
|
|
182
|
+
deployedAddresses.monitoredRoute,
|
|
183
|
+
deployedAddresses.tokens,
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function expectBalances(
|
|
188
|
+
balances: Record<string, BigNumber>,
|
|
189
|
+
expected: Record<TestChain, bigint>,
|
|
190
|
+
): void {
|
|
191
|
+
for (const chain of TEST_CHAINS) {
|
|
192
|
+
expect(balances[chain].toBigInt(), `${chain} collateral`).to.equal(
|
|
193
|
+
expected[chain],
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Simulates CCTP minting the bridged funds to the destination router while
|
|
199
|
+
// the companion Hyperlane message stays undeliverable.
|
|
200
|
+
async function deliverOutOfBand(
|
|
201
|
+
chain: TestChain,
|
|
202
|
+
amount: bigint,
|
|
203
|
+
): Promise<void> {
|
|
204
|
+
const provider = localProviders.get(chain);
|
|
205
|
+
assert(provider, `Missing provider for chain ${chain}`);
|
|
206
|
+
const token = ERC20__factory.connect(
|
|
207
|
+
deployedAddresses.tokens[chain],
|
|
208
|
+
new ethers.Wallet(ANVIL_TEST_PRIVATE_KEY, provider),
|
|
209
|
+
);
|
|
210
|
+
const tx = await token.transfer(
|
|
211
|
+
deployedAddresses.monitoredRoute[chain],
|
|
212
|
+
amount,
|
|
213
|
+
);
|
|
214
|
+
await tx.wait();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function findAction(
|
|
218
|
+
actions: RebalanceAction[],
|
|
219
|
+
destination: TestChain,
|
|
220
|
+
): RebalanceAction {
|
|
221
|
+
const action = actions.find(
|
|
222
|
+
(a) => a.destination === DOMAIN_IDS[destination],
|
|
223
|
+
);
|
|
224
|
+
assert(action, `Missing rebalance action to ${destination}`);
|
|
225
|
+
return action;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function getMessageId(action: RebalanceAction): string {
|
|
229
|
+
assert(action.messageId, `Missing message id on action ${action.id}`);
|
|
230
|
+
return action.messageId;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Cycle 1 moves 1000 USDC anvil1 -> anvil3; CCTP then delivers it out of
|
|
234
|
+
// band, leaving the routers balanced at 6000/2000/2000.
|
|
235
|
+
async function rebalanceAndDeliverOutOfBand(
|
|
236
|
+
context: TestRebalancerContext,
|
|
237
|
+
): Promise<RebalanceAction> {
|
|
238
|
+
await runCycle(context);
|
|
239
|
+
|
|
240
|
+
const intents = await context.tracker.getActiveRebalanceIntents();
|
|
241
|
+
expect(intents.length).to.equal(1);
|
|
242
|
+
const actions = await context.tracker.getActionsByType(REBALANCE_MESSAGE);
|
|
243
|
+
expect(actions.length).to.equal(1);
|
|
244
|
+
const [action] = actions;
|
|
245
|
+
expect(action.intentId).to.equal(intents[0].id);
|
|
246
|
+
expect(action.origin).to.equal(DOMAIN_IDS.anvil1);
|
|
247
|
+
expect(action.destination).to.equal(DOMAIN_IDS.anvil3);
|
|
248
|
+
expect(action.amount).to.equal(1000n * USDC);
|
|
249
|
+
expect(action.status).to.equal('in_progress');
|
|
250
|
+
expectBalances(await getBalances(), {
|
|
251
|
+
anvil1: 6000n * USDC,
|
|
252
|
+
anvil2: 2000n * USDC,
|
|
253
|
+
anvil3: 1000n * USDC,
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
await deliverOutOfBand('anvil3', action.amount);
|
|
257
|
+
expectBalances(await getBalances(), {
|
|
258
|
+
anvil1: 6000n * USDC,
|
|
259
|
+
anvil2: 2000n * USDC,
|
|
260
|
+
anvil3: 2000n * USDC,
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
return action;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Seen as still in flight, the out-of-band 1000 USDC inflates the total to
|
|
267
|
+
// 11000, so anvil3 looks 800 over its 2200 target.
|
|
268
|
+
async function expectDoubleCounted(
|
|
269
|
+
context: TestRebalancerContext,
|
|
270
|
+
action: RebalanceAction,
|
|
271
|
+
): Promise<void> {
|
|
272
|
+
const actions = await context.tracker.getActionsByType(REBALANCE_MESSAGE);
|
|
273
|
+
expect(actions.length).to.equal(3);
|
|
274
|
+
const toAnvil1 = findAction(actions, 'anvil1');
|
|
275
|
+
expect(toAnvil1.origin).to.equal(DOMAIN_IDS.anvil3);
|
|
276
|
+
expect(toAnvil1.amount).to.equal(600n * USDC);
|
|
277
|
+
const toAnvil2 = findAction(actions, 'anvil2');
|
|
278
|
+
expect(toAnvil2.origin).to.equal(DOMAIN_IDS.anvil3);
|
|
279
|
+
expect(toAnvil2.amount).to.equal(200n * USDC);
|
|
280
|
+
|
|
281
|
+
const intents = await context.tracker.getActiveRebalanceIntents();
|
|
282
|
+
expect(intents.map((i) => i.id)).to.have.members([
|
|
283
|
+
action.intentId,
|
|
284
|
+
toAnvil1.intentId,
|
|
285
|
+
toAnvil2.intentId,
|
|
286
|
+
]);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
async function getIndexedMessage(
|
|
290
|
+
context: TestRebalancerContext,
|
|
291
|
+
messageId: string,
|
|
292
|
+
): Promise<ExplorerMessage> {
|
|
293
|
+
await context.forkIndexer.sync(await context.getConfirmedBlockTags());
|
|
294
|
+
const message = context.forkIndexer
|
|
295
|
+
.getRebalanceActions()
|
|
296
|
+
.find((m) => m.msg_id === messageId);
|
|
297
|
+
assert(message, `Fork indexer did not index message ${messageId}`);
|
|
298
|
+
return message;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
async function expectStillInProgress(
|
|
302
|
+
context: TestRebalancerContext,
|
|
303
|
+
action: RebalanceAction,
|
|
304
|
+
): Promise<void> {
|
|
305
|
+
const storedAction = await context.tracker.getRebalanceAction(action.id);
|
|
306
|
+
expect(storedAction?.status).to.equal('in_progress');
|
|
307
|
+
const storedIntent = await context.tracker.getRebalanceIntent(
|
|
308
|
+
action.intentId,
|
|
309
|
+
);
|
|
310
|
+
expect(storedIntent?.status).to.equal('in_progress');
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
it('double counts an out-of-band delivered rebalance that is not denylisted', async function () {
|
|
314
|
+
const context = await buildContext('WEIGHTED_IMBALANCED');
|
|
315
|
+
const action = await rebalanceAndDeliverOutOfBand(context);
|
|
316
|
+
|
|
317
|
+
await runCycle(context);
|
|
318
|
+
|
|
319
|
+
await expectDoubleCounted(context, action);
|
|
320
|
+
await expectStillInProgress(context, action);
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
it('stops counting a rebalance once its message is denylisted', async function () {
|
|
324
|
+
const context = await buildContext('WEIGHTED_IMBALANCED');
|
|
325
|
+
const action = await rebalanceAndDeliverOutOfBand(context);
|
|
326
|
+
|
|
327
|
+
writeDenylist([getMessageId(action)]);
|
|
328
|
+
await runCycle(context);
|
|
329
|
+
|
|
330
|
+
expect(await context.tracker.getActiveRebalanceIntents()).to.be.empty;
|
|
331
|
+
const actions = await context.tracker.getActionsByType(REBALANCE_MESSAGE);
|
|
332
|
+
expect(actions.length).to.equal(1);
|
|
333
|
+
expect(actions[0].id).to.equal(action.id);
|
|
334
|
+
await expectStillInProgress(context, action);
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
it('stops counting a denylisted rebalance once the refresh interval passes', async function () {
|
|
338
|
+
const context = await buildContext(
|
|
339
|
+
'WEIGHTED_IMBALANCED',
|
|
340
|
+
[],
|
|
341
|
+
POSITIVE_REFRESH_INTERVAL_SECS,
|
|
342
|
+
);
|
|
343
|
+
const action = await rebalanceAndDeliverOutOfBand(context);
|
|
344
|
+
|
|
345
|
+
writeDenylist([getMessageId(action)]);
|
|
346
|
+
const ruleWrittenAt = Date.now();
|
|
347
|
+
await context.tracker.syncRebalanceActions(
|
|
348
|
+
await context.getConfirmedBlockTags(),
|
|
349
|
+
);
|
|
350
|
+
expect(
|
|
351
|
+
(await context.tracker.getActiveRebalanceIntents()).map((i) => i.id),
|
|
352
|
+
).to.deep.equal([action.intentId]);
|
|
353
|
+
|
|
354
|
+
// The rule was not loaded above, so the last load predates it.
|
|
355
|
+
await sleep(
|
|
356
|
+
ruleWrittenAt +
|
|
357
|
+
POSITIVE_REFRESH_INTERVAL_SECS * 1_000 +
|
|
358
|
+
REFRESH_WAIT_MARGIN_MS -
|
|
359
|
+
Date.now(),
|
|
360
|
+
);
|
|
361
|
+
await runCycle(context);
|
|
362
|
+
|
|
363
|
+
expect(await context.tracker.getActiveRebalanceIntents()).to.be.empty;
|
|
364
|
+
const actions = await context.tracker.getActionsByType(REBALANCE_MESSAGE);
|
|
365
|
+
expect(actions.length).to.equal(1);
|
|
366
|
+
expect(actions[0].id).to.equal(action.id);
|
|
367
|
+
await expectStillInProgress(context, action);
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
it('counts the rebalance again once its deny rule is removed', async function () {
|
|
371
|
+
const context = await buildContext('WEIGHTED_IMBALANCED');
|
|
372
|
+
const action = await rebalanceAndDeliverOutOfBand(context);
|
|
373
|
+
|
|
374
|
+
writeDenylist([getMessageId(action)]);
|
|
375
|
+
await runCycle(context);
|
|
376
|
+
|
|
377
|
+
expect(await context.tracker.getActiveRebalanceIntents()).to.be.empty;
|
|
378
|
+
expect(
|
|
379
|
+
(await context.tracker.getActionsByType(REBALANCE_MESSAGE)).length,
|
|
380
|
+
).to.equal(1);
|
|
381
|
+
|
|
382
|
+
writeDenylist([]);
|
|
383
|
+
await runCycle(context);
|
|
384
|
+
|
|
385
|
+
await expectDoubleCounted(context, action);
|
|
386
|
+
await expectStillInProgress(context, action);
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it('recovers and counts a non-denylisted rebalance after a restart', async function () {
|
|
390
|
+
const context = await buildContext('WEIGHTED_IMBALANCED');
|
|
391
|
+
const action = await rebalanceAndDeliverOutOfBand(context);
|
|
392
|
+
const messageId = getMessageId(action);
|
|
393
|
+
const message = await getIndexedMessage(context, messageId);
|
|
394
|
+
|
|
395
|
+
const restarted = await buildContext(await getBalances(), [message]);
|
|
396
|
+
|
|
397
|
+
const recovered =
|
|
398
|
+
await restarted.tracker.getActionsByType(REBALANCE_MESSAGE);
|
|
399
|
+
expect(recovered.length).to.equal(1);
|
|
400
|
+
expect(recovered[0].id).to.equal(messageId);
|
|
401
|
+
expect(recovered[0].status).to.equal('in_progress');
|
|
402
|
+
expect(
|
|
403
|
+
(await restarted.tracker.getActiveRebalanceIntents()).map((i) => i.id),
|
|
404
|
+
).to.deep.equal([recovered[0].intentId]);
|
|
405
|
+
|
|
406
|
+
await runCycle(restarted);
|
|
407
|
+
|
|
408
|
+
await expectDoubleCounted(restarted, recovered[0]);
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
it('does not recover a denylisted rebalance after a restart', async function () {
|
|
412
|
+
const context = await buildContext('WEIGHTED_IMBALANCED');
|
|
413
|
+
const action = await rebalanceAndDeliverOutOfBand(context);
|
|
414
|
+
const messageId = getMessageId(action);
|
|
415
|
+
const message = await getIndexedMessage(context, messageId);
|
|
416
|
+
|
|
417
|
+
writeDenylist([messageId]);
|
|
418
|
+
const restarted = await buildContext(await getBalances(), [message]);
|
|
419
|
+
|
|
420
|
+
expect(await restarted.tracker.getActionsByType(REBALANCE_MESSAGE)).to.be
|
|
421
|
+
.empty;
|
|
422
|
+
expect(await restarted.tracker.getActiveRebalanceIntents()).to.be.empty;
|
|
423
|
+
|
|
424
|
+
await runCycle(restarted);
|
|
425
|
+
|
|
426
|
+
expect(await restarted.tracker.getActionsByType(REBALANCE_MESSAGE)).to.be
|
|
427
|
+
.empty;
|
|
428
|
+
expect(await restarted.tracker.getActiveRebalanceIntents()).to.be.empty;
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
it('completes a denylisted rebalance whose message is delivered', async function () {
|
|
432
|
+
const context = await buildContext('WEIGHTED_IMBALANCED');
|
|
433
|
+
await runCycle(context);
|
|
434
|
+
|
|
435
|
+
const actions = await context.tracker.getActionsByType(REBALANCE_MESSAGE);
|
|
436
|
+
expect(actions.length).to.equal(1);
|
|
437
|
+
const [action] = actions;
|
|
438
|
+
const messageId = getMessageId(action);
|
|
439
|
+
writeDenylist([messageId]);
|
|
440
|
+
await context.tracker.syncRebalanceActions(
|
|
441
|
+
await context.getConfirmedBlockTags(),
|
|
442
|
+
);
|
|
443
|
+
expect(await context.tracker.getActiveRebalanceIntents()).to.be.empty;
|
|
444
|
+
|
|
445
|
+
const originProvider = localProviders.get('anvil1');
|
|
446
|
+
assert(originProvider, 'Missing provider for chain anvil1');
|
|
447
|
+
assert(action.txHash, `Missing tx hash on action ${action.id}`);
|
|
448
|
+
const relayResult = await tryRelayMessage(multiProvider, hyperlaneCore, {
|
|
449
|
+
dispatchTx: await originProvider.getTransactionReceipt(action.txHash),
|
|
450
|
+
messageId,
|
|
451
|
+
origin: 'anvil1',
|
|
452
|
+
destination: 'anvil3',
|
|
453
|
+
});
|
|
454
|
+
expect(relayResult.success, `Relay failed: ${relayResult.error}`).to.be
|
|
455
|
+
.true;
|
|
456
|
+
|
|
457
|
+
await context.tracker.syncRebalanceActions(
|
|
458
|
+
await context.getConfirmedBlockTags(),
|
|
459
|
+
);
|
|
460
|
+
|
|
461
|
+
const storedAction = await context.tracker.getRebalanceAction(action.id);
|
|
462
|
+
expect(storedAction?.status).to.equal('complete');
|
|
463
|
+
const storedIntent = await context.tracker.getRebalanceIntent(
|
|
464
|
+
action.intentId,
|
|
465
|
+
);
|
|
466
|
+
expect(storedIntent?.status).to.equal('complete');
|
|
467
|
+
expect(await context.tracker.getInProgressActions()).to.be.empty;
|
|
468
|
+
expect(await context.tracker.getActiveRebalanceIntents()).to.be.empty;
|
|
469
|
+
expectBalances(await getBalances(), {
|
|
470
|
+
anvil1: 6000n * USDC,
|
|
471
|
+
anvil2: 2000n * USDC,
|
|
472
|
+
anvil3: 2000n * USDC,
|
|
473
|
+
});
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
interface BroadRuleCase {
|
|
477
|
+
name: string;
|
|
478
|
+
match: (message: ExplorerMessage) => Record<string, unknown>;
|
|
479
|
+
}
|
|
480
|
+
const broadRuleCases: BroadRuleCase[] = [
|
|
481
|
+
{
|
|
482
|
+
name: 'destination',
|
|
483
|
+
match: () => ({ destinationDomain: DOMAIN_IDS.anvil3 }),
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
name: 'route',
|
|
487
|
+
match: (message) => ({
|
|
488
|
+
originDomain: message.origin_domain_id,
|
|
489
|
+
senderAddress: message.sender,
|
|
490
|
+
destinationDomain: message.destination_domain_id,
|
|
491
|
+
recipientAddress: message.recipient,
|
|
492
|
+
}),
|
|
493
|
+
},
|
|
494
|
+
];
|
|
495
|
+
for (const c of broadRuleCases) {
|
|
496
|
+
it(`keeps counting an undelivered rebalance a ${c.name} rule denies`, async function () {
|
|
497
|
+
const context = await buildContext('WEIGHTED_IMBALANCED');
|
|
498
|
+
await runCycle(context);
|
|
499
|
+
const [action] =
|
|
500
|
+
await context.tracker.getActionsByType(REBALANCE_MESSAGE);
|
|
501
|
+
assert(action, 'Missing rebalance action from cycle 1');
|
|
502
|
+
const message = await getIndexedMessage(context, getMessageId(action));
|
|
503
|
+
|
|
504
|
+
writeDenylist([], [c.match(message)]);
|
|
505
|
+
await runCycle(context);
|
|
506
|
+
await runCycle(context);
|
|
507
|
+
|
|
508
|
+
const actions = await context.tracker.getActionsByType(REBALANCE_MESSAGE);
|
|
509
|
+
expect(actions.map((a) => a.id)).to.deep.equal([action.id]);
|
|
510
|
+
expect(
|
|
511
|
+
(await context.tracker.getActiveRebalanceIntents()).map((i) => i.id),
|
|
512
|
+
).to.deep.equal([action.intentId]);
|
|
513
|
+
await expectStillInProgress(context, action);
|
|
514
|
+
expectBalances(await getBalances(), {
|
|
515
|
+
anvil1: 6000n * USDC,
|
|
516
|
+
anvil2: 2000n * USDC,
|
|
517
|
+
anvil3: 1000n * USDC,
|
|
518
|
+
});
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
it('keeps counting the rebalance that is not denylisted', async function () {
|
|
523
|
+
const context = await buildContext({
|
|
524
|
+
anvil1: BigNumber.from(8000n * USDC),
|
|
525
|
+
anvil2: BigNumber.from(1000n * USDC),
|
|
526
|
+
anvil3: BigNumber.from(1000n * USDC),
|
|
527
|
+
});
|
|
528
|
+
await runCycle(context);
|
|
529
|
+
|
|
530
|
+
const actions = await context.tracker.getActionsByType(REBALANCE_MESSAGE);
|
|
531
|
+
expect(actions.length).to.equal(2);
|
|
532
|
+
const toAnvil2 = findAction(actions, 'anvil2');
|
|
533
|
+
const toAnvil3 = findAction(actions, 'anvil3');
|
|
534
|
+
expect(toAnvil2.amount).to.equal(1000n * USDC);
|
|
535
|
+
expect(toAnvil3.amount).to.equal(1000n * USDC);
|
|
536
|
+
expect((await context.tracker.getActiveRebalanceIntents()).length).to.equal(
|
|
537
|
+
2,
|
|
538
|
+
);
|
|
539
|
+
|
|
540
|
+
await deliverOutOfBand('anvil3', toAnvil3.amount);
|
|
541
|
+
writeDenylist([getMessageId(toAnvil3)]);
|
|
542
|
+
expectBalances(await getBalances(), {
|
|
543
|
+
anvil1: 6000n * USDC,
|
|
544
|
+
anvil2: 1000n * USDC,
|
|
545
|
+
anvil3: 2000n * USDC,
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
await runCycle(context);
|
|
549
|
+
|
|
550
|
+
const intents = await context.tracker.getActiveRebalanceIntents();
|
|
551
|
+
expect(intents.map((i) => i.id)).to.deep.equal([toAnvil2.intentId]);
|
|
552
|
+
expect(
|
|
553
|
+
(await context.tracker.getActionsByType(REBALANCE_MESSAGE)).length,
|
|
554
|
+
).to.equal(2);
|
|
555
|
+
await expectStillInProgress(context, toAnvil2);
|
|
556
|
+
await expectStillInProgress(context, toAnvil3);
|
|
557
|
+
});
|
|
558
|
+
});
|