Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"dependencies": {
"@across-protocol/constants": "^3.1.72",
"@across-protocol/contracts": "^4.1.5",
"@across-protocol/sdk": "4.3.58",
"@across-protocol/sdk": "4.3.59",
"@arbitrum/sdk": "^4.0.2",
"@consensys/linea-sdk": "^0.3.0",
"@coral-xyz/anchor": "^0.31.1",
Expand Down Expand Up @@ -79,7 +79,8 @@
"deposit": "yarn ts-node ./scripts/spokepool.ts deposit",
"dispute": "yarn ts-node ./scripts/hubpool.ts dispute",
"update": "git pull && yarn reinstall && yarn version --non-interactive && git show --quiet",
"update-addresses": "yarn ts-node ./scripts/fetch-addresses.ts"
"update-addresses": "yarn ts-node ./scripts/fetch-addresses.ts",
"validate-root-bundle": "yarn ts-node src/scripts/validateRootBundle.ts"
},
"devDependencies": {
"@nomiclabs/hardhat-ethers": "^2.2.3",
Expand Down
7 changes: 3 additions & 4 deletions src/dataworker/PoolRebalanceUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
winston,
assert,
getNetworkName,
isChainDisabled,
EvmAddress,
Address,
isDefined,
Expand Down Expand Up @@ -68,9 +67,9 @@ export function generateMarkdownForRootBundle(
let bundleBlockRangePretty = "";
bundleBlockRange.forEach((_blockRange, index) => {
const chainId = chainIdListForBundleEvaluationBlockNumbers[index];
bundleBlockRangePretty += `\n\t\t${chainId}: ${JSON.stringify(bundleBlockRange[index])}${
isChainDisabled(bundleBlockRange[index]) ? " 🥶" : ""
}`;
const [startBlock, endBlock] = bundleBlockRange[index];
const paused = startBlock === endBlock ? " 🥶" : "";
bundleBlockRangePretty += `\n\t\t${chainId}: ${JSON.stringify(bundleBlockRange[index])}${paused}`;
});

const convertTokenListFromWei = (chainId: number, tokenAddresses: Address[], weiVals: string[]) => {
Expand Down
2 changes: 1 addition & 1 deletion src/utils/SDKUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export const {

export const {
getRefundsFromBundle,
isChainDisabled,
isChainDisabledAtBlock,
getWidestPossibleExpectedBlockRange,
getEndBlockBuffers,
buildPoolRebalanceLeafTree,
Expand Down
179 changes: 2 additions & 177 deletions test/Dataworker.executeRelayerRefunds.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
import { BundleDataClient, HubPoolClient, MultiCallerClient, SpokePoolClient } from "../src/clients";
import {
EvmAddress,
buildRelayerRefundTree,
MAX_UINT_VAL,
RelayerRefundLeaf,
toBN,
toBNWei,
toAddressType,
} from "../src/utils";
import { HubPoolClient, MultiCallerClient, SpokePoolClient } from "../src/clients";
import { EvmAddress, buildRelayerRefundTree, MAX_UINT_VAL, RelayerRefundLeaf, toBNWei } from "../src/utils";
import {
MAX_L1_TOKENS_PER_POOL_REBALANCE_LEAF,
MAX_REFUNDS_PER_RELAYER_REFUND_LEAF,
amountToDeposit,
destinationChainId,
repaymentChainId,
} from "./constants";
import { setupDataworker } from "./fixtures/Dataworker.Fixture";
import { Contract, SignerWithAddress, depositV3, ethers, expect, fillV3Relay } from "./utils";
Expand Down Expand Up @@ -148,11 +139,9 @@ describe("Dataworker: Execute relayer refunds", async function () {
});
describe("Computing refunds for bundles", function () {
let relayer: SignerWithAddress;
let bundleDataClient: BundleDataClient;

beforeEach(async function () {
relayer = depositor;
bundleDataClient = dataworkerInstance.clients.bundleDataClient;
await updateAllClients();

const deposit1 = await depositV3(
Expand All @@ -172,169 +161,5 @@ describe("Dataworker: Execute relayer refunds", async function () {

await updateAllClients();
});
it("No validated bundle refunds", async function () {
// Propose a bundle:
await dataworkerInstance.proposeRootBundle(spokePoolClients);
await multiCallerClient.executeTxnQueues();
await updateAllClients();

// No bundle is validated so no refunds.
const refunds = await bundleDataClient.getPendingRefundsFromValidBundles();
expect(
bundleDataClient.getTotalRefund(
refunds,
EvmAddress.from(relayer.address),
destinationChainId,
toAddressType(erc20_2.address, destinationChainId)
)
).to.equal(toBN(0));
});
it("Get refunds from validated bundles", async function () {
await updateAllClients();
// Propose a bundle:
await dataworkerInstance.proposeRootBundle(spokePoolClients);
await multiCallerClient.executeTxnQueues();

// Advance time and execute leaves:
await hubPool.setCurrentTime(Number(await hubPool.getCurrentTime()) + Number(await hubPool.liveness()) + 1);
await updateAllClients();
await dataworkerInstance.executePoolRebalanceLeaves(spokePoolClients, await getNewBalanceAllocator());
await multiCallerClient.executeTxnQueues();

// Before relayer refund leaves are not executed, should have pending refunds:
await updateAllClients();
const validatedRootBundles = hubPoolClient.getValidatedRootBundles();
expect(validatedRootBundles.length).to.equal(1);
const refunds = await bundleDataClient.getPendingRefundsFromValidBundles();
const totalRefund1 = bundleDataClient.getTotalRefund(
refunds,
toAddressType(relayer.address, destinationChainId),
destinationChainId,
toAddressType(erc20_2.address, destinationChainId)
);
expect(totalRefund1).to.gt(0);

// Test edge cases of `getTotalRefund` that should return BN(0)
expect(
bundleDataClient.getTotalRefund(
refunds,
toAddressType(relayer.address, repaymentChainId),
repaymentChainId,
toAddressType(erc20_2.address, repaymentChainId)
)
).to.equal(toBN(0));
expect(
bundleDataClient.getTotalRefund(
refunds,
toAddressType(relayer.address, destinationChainId),
destinationChainId,
toAddressType(erc20_1.address, destinationChainId)
)
).to.equal(toBN(0));

// Manually relay the roots to spoke pools since adapter is a dummy and won't actually relay messages.
const rootBundle = validatedRootBundles[0];
await spokePool_1.relayRootBundle(rootBundle.relayerRefundRoot, rootBundle.slowRelayRoot);
await spokePool_2.relayRootBundle(rootBundle.relayerRefundRoot, rootBundle.slowRelayRoot);
await updateAllClients();

// Execute relayer refund leaves. Send funds to spoke pools to execute the leaves.
await erc20_2.mint(spokePool_2.address, amountToDeposit);
await dataworkerInstance.executeRelayerRefundLeaves(spokePoolClients, await getNewBalanceAllocator());
await multiCallerClient.executeTxnQueues();

// Should now have zero pending refunds
await updateAllClients();
// If we call `getPendingRefundsFromLatestBundle` multiple times, there should be no error. If there is an error,
// then it means that `getPendingRefundsFromLatestBundle` is mutating the return value of `.loadData` which is
// stored in the bundle data client's cache. `getPendingRefundsFromLatestBundle` should instead be using a
// deep cloned copy of `.loadData`'s output.
await bundleDataClient.getPendingRefundsFromValidBundles();
const postExecutionRefunds = await bundleDataClient.getPendingRefundsFromValidBundles();
expect(
bundleDataClient.getTotalRefund(
postExecutionRefunds,
toAddressType(relayer.address, destinationChainId),
destinationChainId,
toAddressType(erc20_2.address, destinationChainId)
)
).to.equal(toBN(0));

// Submit fill2 and propose another bundle:
const newDepositAmount = amountToDeposit.mul(2);
const deposit2 = await depositV3(
spokePool_1,
destinationChainId,
depositor,
erc20_1.address,
newDepositAmount,
erc20_2.address,
amountToDeposit
);
await updateAllClients();

// Submit a valid fill.
await fillV3Relay(spokePool_2, deposit2, relayer, destinationChainId);
await updateAllClients();

// Validate another bundle:
await dataworkerInstance.proposeRootBundle(spokePoolClients);
await multiCallerClient.executeTxnQueues();
await hubPool.setCurrentTime(Number(await hubPool.getCurrentTime()) + Number(await hubPool.liveness()) + 1);
await updateAllClients();
await dataworkerInstance.executePoolRebalanceLeaves(spokePoolClients, await getNewBalanceAllocator());
await multiCallerClient.executeTxnQueues();
await updateAllClients();

expect(hubPoolClient.getValidatedRootBundles().length).to.equal(2);

// Should include refunds for most recently validated bundle but not count first one
// since they were already refunded.
const refunds2 = await bundleDataClient.getPendingRefundsFromValidBundles();
expect(
bundleDataClient.getTotalRefund(
refunds2,
toAddressType(relayer.address, destinationChainId),
destinationChainId,
toAddressType(erc20_2.address, destinationChainId)
)
).to.gt(0);
});
it("Refunds in next bundle", async function () {
// Before proposal should show refunds:
expect(
bundleDataClient.getRefundsFor(
(await bundleDataClient.getNextBundleRefunds())[0],
toAddressType(relayer.address, destinationChainId),
destinationChainId,
toAddressType(erc20_2.address, destinationChainId)
)
).to.gt(0);

// Propose a bundle:
await dataworkerInstance.proposeRootBundle(spokePoolClients);
await multiCallerClient.executeTxnQueues();
await updateAllClients();

// After proposal but before execution should show upcoming refund:
expect(
bundleDataClient.getRefundsFor(
(await bundleDataClient.getNextBundleRefunds())[0],
toAddressType(relayer.address, destinationChainId),
destinationChainId,
toAddressType(erc20_2.address, destinationChainId)
)
).to.gt(0);

// Advance time and execute root bundle:
await hubPool.setCurrentTime(Number(await hubPool.getCurrentTime()) + Number(await hubPool.liveness()) + 1);
await updateAllClients();
await dataworkerInstance.executePoolRebalanceLeaves(spokePoolClients, await getNewBalanceAllocator());
await multiCallerClient.executeTxnQueues();

// Should reset to no refunds in "next bundle", though these will show up in pending bundle.
await updateAllClients();
expect(await bundleDataClient.getNextBundleRefunds()).to.deep.equal([{}]);
});
});
});
80 changes: 4 additions & 76 deletions test/Dataworker.loadData.deposit.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { BundleDataClient, ConfigStoreClient, HubPoolClient, SpokePoolClient } from "../src/clients";
import { amountToDeposit, destinationChainId, originChainId, repaymentChainId } from "./constants";
import { destinationChainId, originChainId, repaymentChainId } from "./constants";
import { DataworkerConfig, setupDataworker } from "./fixtures/Dataworker.Fixture";
import {
Contract,
FakeContract,
SignerWithAddress,
V3FillFromDeposit,
depositV3,
ethers,
expect,
getDefaultBlockRange,
Expand All @@ -21,11 +20,11 @@ import { getCurrentTime, toBNWei, ZERO_ADDRESS, BigNumber, bnZero, toAddressType
import { MockHubPoolClient, MockSpokePoolClient } from "./mocks";
import { interfaces, utils as sdkUtils } from "@across-protocol/sdk";

let spokePool_1: Contract, erc20_1: Contract, spokePool_2: Contract, erc20_2: Contract;
let erc20_1: Contract, erc20_2: Contract;
let l1Token_1: Contract;
let depositor: SignerWithAddress, relayer: SignerWithAddress;
let relayer: SignerWithAddress;

let spokePoolClient_1: SpokePoolClient, spokePoolClient_2: SpokePoolClient, bundleDataClient: BundleDataClient;
let spokePoolClient_1: SpokePoolClient, spokePoolClient_2: SpokePoolClient;
let hubPoolClient: HubPoolClient, configStoreClient: ConfigStoreClient;
let dataworkerInstance: Dataworker;
let spokePoolClients: { [chainId: number]: SpokePoolClient };
Expand All @@ -38,14 +37,11 @@ let updateAllClients: () => Promise<void>;
describe("Dataworker: Load bundle data", async function () {
beforeEach(async function () {
({
spokePool_1,
erc20_1,
spokePool_2,
erc20_2,
configStoreClient,
hubPoolClient,
l1Token_1,
depositor,
relayer,
dataworkerInstance,
spokePoolClient_1,
Expand All @@ -54,7 +50,6 @@ describe("Dataworker: Load bundle data", async function () {
updateAllClients,
spy,
} = await setupDataworker(ethers, 25, 25, 0));
bundleDataClient = dataworkerInstance.clients.bundleDataClient;
});

describe("Computing bundle deposits and expired deposits to refund", function () {
Expand Down Expand Up @@ -558,71 +553,4 @@ describe("Dataworker: Load bundle data", async function () {
expect(data1.bundleFillsV3[repaymentChainId][toBytes32(l1Token_1.address)].fills.length).to.equal(1);
});
});

describe("Miscellaneous functions", function () {
it("getUpcomingDepositAmount", async function () {
// Send two deposits on different chains
await depositV3(
spokePool_1,
destinationChainId,
depositor,
erc20_1.address,
amountToDeposit,
ZERO_ADDRESS,
amountToDeposit
);
await depositV3(
spokePool_2,
originChainId,
depositor,
erc20_2.address,
amountToDeposit,
ZERO_ADDRESS,
amountToDeposit
);
await updateAllClients();
expect(
await bundleDataClient.getUpcomingDepositAmount(originChainId, toAddressType(erc20_1.address, originChainId), 0)
).to.equal(amountToDeposit);
expect(
await bundleDataClient.getUpcomingDepositAmount(
destinationChainId,
toAddressType(erc20_2.address, destinationChainId),
0
)
).to.equal(amountToDeposit);

// Removes deposits using block, token, and chain filters.
expect(
await bundleDataClient.getUpcomingDepositAmount(
originChainId,
toAddressType(erc20_1.address, originChainId),
spokePoolClient_1.latestHeightSearched // block higher than the deposit
)
).to.equal(0);
expect(
await bundleDataClient.getUpcomingDepositAmount(
originChainId,
toAddressType(erc20_2.address, originChainId), // diff token
0
)
).to.equal(0);
expect(
await bundleDataClient.getUpcomingDepositAmount(
destinationChainId, // diff chain
toAddressType(erc20_1.address, destinationChainId),
0
)
).to.equal(0);

// spoke pool client for chain not defined
expect(
await bundleDataClient.getUpcomingDepositAmount(
originChainId + destinationChainId + repaymentChainId + 1, // spoke pool client for chain is not defined in BundleDataClient
toAddressType(erc20_1.address, originChainId),
0
)
).to.equal(0);
});
});
});
Loading