Skip to content

Commit

Permalink
chore: bump sdk version for new BundleDataClient (#2024)
Browse files Browse the repository at this point in the history
* chore: bump sdk version for new BundleDataClient

Signed-off-by: bennett <[email protected]>

---------

Signed-off-by: bennett <[email protected]>
  • Loading branch information
bmzig authored Jan 30, 2025
1 parent 3cd7a7e commit 591652b
Show file tree
Hide file tree
Showing 4 changed files with 240 additions and 10 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"dependencies": {
"@across-protocol/constants": "^3.1.30",
"@across-protocol/contracts": "^3.0.25",
"@across-protocol/sdk": "^3.4.14",
"@across-protocol/sdk": "^3.4.16",
"@arbitrum/sdk": "^4.0.2",
"@consensys/linea-sdk": "^0.2.1",
"@defi-wonderland/smock": "^2.3.5",
Expand Down
226 changes: 221 additions & 5 deletions test/Dataworker.loadData.fill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ import {
sinon,
smock,
spyLogIncludes,
bnZero,
} from "./utils";

import { Dataworker } from "../src/dataworker/Dataworker"; // Tested
import { getCurrentTime, toBN, Event, toBNWei, fixedPointAdjustment, ZERO_ADDRESS, BigNumber } from "../src/utils";
import { MockConfigStoreClient, MockHubPoolClient, MockSpokePoolClient } from "./mocks";
import { interfaces, utils as sdkUtils } from "@across-protocol/sdk";
import { interfaces, utils as sdkUtils, providers } from "@across-protocol/sdk";
import { cloneDeep } from "lodash";
import { CombinedRefunds } from "../src/dataworker/DataworkerUtils";
import { INFINITE_FILL_DEADLINE } from "../src/common";
Expand Down Expand Up @@ -124,6 +125,7 @@ describe("Dataworker: Load data used in all functions", async function () {
spokePoolClient_1.chainId,
spokePoolClient_1.deploymentBlock
);

mockDestinationSpokePool = await smock.fake(spokePoolClient_2.spokePool.interface);
mockDestinationSpokePoolClient = new MockSpokePoolClient(
spokePoolClient_2.logger,
Expand Down Expand Up @@ -634,11 +636,10 @@ describe("Dataworker: Load data used in all functions", async function () {
inputAmount: depositEvent.args.inputAmount.add(1),
outputAmount: depositEvent.args.outputAmount.add(1),
originChainId: destinationChainId,
depositId: depositEvent.args.depositId + 1,
depositId: toBN(depositEvent.args.depositId + 1),
fillDeadline: depositEvent.args.fillDeadline + 1,
exclusivityDeadline: depositEvent.args.exclusivityDeadline + 1,
message: randomAddress(),
destinationChainId: originChainId,
};
for (const [key, val] of Object.entries(invalidRelayData)) {
const _depositEvent = cloneDeep(depositEvent);
Expand Down Expand Up @@ -801,6 +802,221 @@ describe("Dataworker: Load data used in all functions", async function () {
dataworkerInstance.clients.bundleDataClient.setBundleTimestampsInCache(key3, cache3);
expect(dataworkerInstance.clients.bundleDataClient.getBundleTimestampsFromCache(key3)).to.deep.equal(cache3);
});
describe("Bytes32 address invalid cases", async function () {
it("Fallback to msg.sender when the relayer repayment address is invalid on an EVM chain", async function () {
const depositV3Events: Event[] = [];
const fillV3Events: Event[] = [];
const destinationChainId = mockDestinationSpokePoolClient.chainId;
// Create three valid deposits
depositV3Events.push(generateV3Deposit({ outputToken: randomAddress() }));
depositV3Events.push(generateV3Deposit({ outputToken: randomAddress() }));
depositV3Events.push(generateV3Deposit({ outputToken: randomAddress() }));
await mockOriginSpokePoolClient.update(["V3FundsDeposited"]);
const deposits = mockOriginSpokePoolClient.getDeposits();

// Fill deposits from different relayers
const relayer2 = randomAddress();
fillV3Events.push(generateV3FillFromDeposit(deposits[0]));
fillV3Events.push(generateV3FillFromDeposit(deposits[1]));
fillV3Events.push(generateV3FillFromDeposit(deposits[2], {}, ethers.utils.randomBytes(32)));
await mockDestinationSpokePoolClient.update(["FilledV3Relay"]);
// Replace the dataworker providers to use mock providers. We need to explicitly do this since we do not actually perform a contract call, so
// we must inject a transaction response into the provider to simulate the case when the relayer repayment address is invalid.
const provider = new providers.mocks.MockedProvider(bnZero, bnZero, destinationChainId);
const spokeWrapper = new Contract(
mockDestinationSpokePoolClient.spokePool.address,
mockDestinationSpokePoolClient.spokePool.interface,
provider
);
fillV3Events.forEach((event) => provider._setTransaction(event.transactionHash, { from: relayer2 }));
mockDestinationSpokePoolClient.spokePool = spokeWrapper;

const data1 = await dataworkerInstance.clients.bundleDataClient.loadData(
getDefaultBlockRange(5),
spokePoolClients
);
expect(data1.bundleFillsV3[repaymentChainId][l1Token_1.address].fills.length).to.equal(depositV3Events.length);
expect(data1.bundleFillsV3[repaymentChainId][l1Token_1.address].fills.map((e) => e.depositId)).to.deep.equal(
fillV3Events.map((event) => event.args.depositId)
);
expect(data1.bundleFillsV3[repaymentChainId][l1Token_1.address].fills.map((e) => e.lpFeePct)).to.deep.equal(
fillV3Events.map(() => lpFeePct)
);
const totalGrossRefundAmount = fillV3Events.reduce((agg, e) => agg.add(e.args.inputAmount), toBN(0));
const totalV3LpFees = totalGrossRefundAmount.mul(lpFeePct).div(fixedPointAdjustment);
expect(totalV3LpFees).to.equal(data1.bundleFillsV3[repaymentChainId][l1Token_1.address].realizedLpFees);
expect(data1.bundleFillsV3[repaymentChainId][l1Token_1.address].totalRefundAmount).to.equal(
totalGrossRefundAmount.sub(totalV3LpFees)
);
const refundAmountPct = fixedPointAdjustment.sub(lpFeePct);
expect(data1.bundleFillsV3[repaymentChainId][l1Token_1.address].refunds).to.deep.equal({
[relayer.address]: fillV3Events
.slice(0, fillV3Events.length - 1)
.reduce((agg, e) => agg.add(e.args.inputAmount), toBN(0))
.mul(refundAmountPct)
.div(fixedPointAdjustment),
[relayer2]: fillV3Events[fillV3Events.length - 1].args.inputAmount
.mul(refundAmountPct)
.div(fixedPointAdjustment),
});
});
it("Treats a relayer's fill with a bytes32 address taking repayment on an EVM network as invalid", async function () {
const depositV3Events: Event[] = [];
const fillV3Events: Event[] = [];
const destinationChainId = mockDestinationSpokePoolClient.chainId;
// Create three valid deposits
depositV3Events.push(generateV3Deposit({ outputToken: randomAddress() }));
depositV3Events.push(generateV3Deposit({ outputToken: randomAddress() }));
depositV3Events.push(generateV3Deposit({ outputToken: randomAddress() }));
await mockOriginSpokePoolClient.update(["V3FundsDeposited"]);
const deposits = mockOriginSpokePoolClient.getDeposits();

// Fill deposits from different relayers
const invalidRelayer = ethers.utils.randomBytes(32);
fillV3Events.push(generateV3FillFromDeposit(deposits[0]));
fillV3Events.push(generateV3FillFromDeposit(deposits[1]));
fillV3Events.push(generateV3FillFromDeposit(deposits[2], {}, invalidRelayer));
await mockDestinationSpokePoolClient.update(["FilledV3Relay"]);
// Replace the dataworker providers to use mock providers. We need to explicitly do this since we do not actually perform a contract call, so
// we must inject a transaction response into the provider to simulate the case when the relayer repayment address is invalid. In this case,
// set the msg.sender as an invalid address.
const provider = new providers.mocks.MockedProvider(bnZero, bnZero, destinationChainId);
const spokeWrapper = new Contract(
mockDestinationSpokePoolClient.spokePool.address,
mockDestinationSpokePoolClient.spokePool.interface,
provider
);
fillV3Events.forEach((event) => provider._setTransaction(event.transactionHash, { from: invalidRelayer }));
mockDestinationSpokePoolClient.spokePool = spokeWrapper;

const data1 = await dataworkerInstance.clients.bundleDataClient.loadData(
getDefaultBlockRange(5),
spokePoolClients
);

// We expect the last fillV3Event to be invalid.
const nValidFills = fillV3Events.length - 1;
expect(data1.bundleFillsV3[repaymentChainId][l1Token_1.address].fills.length).to.equal(nValidFills);
expect(data1.bundleFillsV3[repaymentChainId][l1Token_1.address].fills.map((e) => e.depositId)).to.deep.equal(
fillV3Events.slice(0, nValidFills).map((event) => event.args.depositId)
);
expect(data1.bundleFillsV3[repaymentChainId][l1Token_1.address].fills.map((e) => e.lpFeePct)).to.deep.equal(
fillV3Events.slice(0, nValidFills).map(() => lpFeePct)
);
expect(spyLogIncludes(spy, -2, "invalid V3 fills in range")).to.be.true;
});
// This is essentially a copy of the first test in this block, with the addition of the change to the config store.
it("Fill with bytes32 relayer with lite chain deposit is refunded on lite chain to msg.sender", async function () {
const depositV3Events: Event[] = [];
const fillV3Events: Event[] = [];
const destinationChainId = mockDestinationSpokePoolClient.chainId;
// Update and set the config store client.
hubPoolClient.configStoreClient._updateLiteChains([mockOriginSpokePoolClient.chainId]);
mockOriginSpokePoolClient.configStoreClient = hubPoolClient.configStoreClient;
// Create three valid deposits
depositV3Events.push(generateV3Deposit({ outputToken: randomAddress() }));
depositV3Events.push(generateV3Deposit({ outputToken: randomAddress() }));
depositV3Events.push(generateV3Deposit({ outputToken: randomAddress() }));
await mockOriginSpokePoolClient.update(["V3FundsDeposited"]);
const deposits = mockOriginSpokePoolClient.getDeposits();

// Fill deposits from different relayers
const relayer2 = randomAddress();
const invalidRelayer = ethers.utils.randomBytes(32);
fillV3Events.push(generateV3FillFromDeposit(deposits[0]));
fillV3Events.push(generateV3FillFromDeposit(deposits[1]));
fillV3Events.push(generateV3FillFromDeposit(deposits[2], {}, invalidRelayer));
await mockDestinationSpokePoolClient.update(["FilledV3Relay"]);
// Replace the dataworker providers to use mock providers. We need to explicitly do this since we do not actually perform a contract call, so
// we must inject a transaction response into the provider to simulate the case when the relayer repayment address is invalid.
const provider = new providers.mocks.MockedProvider(bnZero, bnZero, destinationChainId);
const spokeWrapper = new Contract(
mockDestinationSpokePoolClient.spokePool.address,
mockDestinationSpokePoolClient.spokePool.interface,
provider
);
fillV3Events.forEach((event) => provider._setTransaction(event.transactionHash, { from: relayer2 }));
mockDestinationSpokePoolClient.spokePool = spokeWrapper;

const data1 = await dataworkerInstance.clients.bundleDataClient.loadData(
getDefaultBlockRange(5),
spokePoolClients
);
expect(data1.bundleFillsV3[originChainId][erc20_1.address].fills.length).to.equal(depositV3Events.length);
expect(data1.bundleFillsV3[originChainId][erc20_1.address].fills.map((e) => e.depositId)).to.deep.equal(
fillV3Events.map((event) => event.args.depositId)
);
expect(data1.bundleFillsV3[originChainId][erc20_1.address].fills.map((e) => e.lpFeePct)).to.deep.equal(
fillV3Events.map(() => lpFeePct)
);
const totalGrossRefundAmount = fillV3Events.reduce((agg, e) => agg.add(e.args.inputAmount), toBN(0));
const totalV3LpFees = totalGrossRefundAmount.mul(lpFeePct).div(fixedPointAdjustment);
expect(totalV3LpFees).to.equal(data1.bundleFillsV3[originChainId][erc20_1.address].realizedLpFees);
expect(data1.bundleFillsV3[originChainId][erc20_1.address].totalRefundAmount).to.equal(
totalGrossRefundAmount.sub(totalV3LpFees)
);
const refundAmountPct = fixedPointAdjustment.sub(lpFeePct);
expect(data1.bundleFillsV3[originChainId][erc20_1.address].refunds).to.deep.equal({
[relayer.address]: fillV3Events
.slice(0, fillV3Events.length - 1)
.reduce((agg, e) => agg.add(e.args.inputAmount), toBN(0))
.mul(refundAmountPct)
.div(fixedPointAdjustment),
[relayer2]: fillV3Events[fillV3Events.length - 1].args.inputAmount
.mul(refundAmountPct)
.div(fixedPointAdjustment),
});
});
// This is almost the same as the second test in this block, with the exception of the change to the config store.
it("Fill with bytes32 relayer with lite chain deposit is invalid if msg.sender is not a bytes20 address", async function () {
const depositV3Events: Event[] = [];
const fillV3Events: Event[] = [];
const destinationChainId = mockDestinationSpokePoolClient.chainId;
// Update and set the config store client.
hubPoolClient.configStoreClient._updateLiteChains([mockOriginSpokePoolClient.chainId]);
mockOriginSpokePoolClient.configStoreClient = hubPoolClient.configStoreClient;
// Create three valid deposits
depositV3Events.push(generateV3Deposit({ outputToken: randomAddress() }));
depositV3Events.push(generateV3Deposit({ outputToken: randomAddress() }));
depositV3Events.push(generateV3Deposit({ outputToken: randomAddress() }));
await mockOriginSpokePoolClient.update(["V3FundsDeposited"]);
const deposits = mockOriginSpokePoolClient.getDeposits();

// Fill deposits from different relayers
const invalidRelayer = ethers.utils.randomBytes(32);
fillV3Events.push(generateV3FillFromDeposit(deposits[0]));
fillV3Events.push(generateV3FillFromDeposit(deposits[1]));
fillV3Events.push(generateV3FillFromDeposit(deposits[2], {}, invalidRelayer));
await mockDestinationSpokePoolClient.update(["FilledV3Relay"]);
// Replace the dataworker providers to use mock providers. We need to explicitly do this since we do not actually perform a contract call, so
// we must inject a transaction response into the provider to simulate the case when the relayer repayment address is invalid. In this case,
// set the msg.sender as an invalid address.
const provider = new providers.mocks.MockedProvider(bnZero, bnZero, destinationChainId);
const spokeWrapper = new Contract(
mockDestinationSpokePoolClient.spokePool.address,
mockDestinationSpokePoolClient.spokePool.interface,
provider
);
fillV3Events.forEach((event) => provider._setTransaction(event.transactionHash, { from: invalidRelayer }));
mockDestinationSpokePoolClient.spokePool = spokeWrapper;

const data1 = await dataworkerInstance.clients.bundleDataClient.loadData(
getDefaultBlockRange(5),
spokePoolClients
);

// We expect the last fillV3Event to be invalid.
const nValidFills = fillV3Events.length - 1;
expect(data1.bundleFillsV3[originChainId][erc20_1.address].fills.length).to.equal(nValidFills);
expect(data1.bundleFillsV3[originChainId][erc20_1.address].fills.map((e) => e.depositId)).to.deep.equal(
fillV3Events.slice(0, nValidFills).map((event) => event.args.depositId)
);
expect(data1.bundleFillsV3[originChainId][erc20_1.address].fills.map((e) => e.lpFeePct)).to.deep.equal(
fillV3Events.slice(0, nValidFills).map(() => lpFeePct)
);
expect(spyLogIncludes(spy, -2, "invalid V3 fills in range")).to.be.true;
});
});
});

describe("Miscellaneous functions", function () {
Expand Down Expand Up @@ -894,7 +1110,7 @@ describe("Dataworker: Load data used in all functions", async function () {

// Approximate refunds should count both fills
await updateAllClients();
const refunds = bundleDataClient.getApproximateRefundsForBlockRange(
const refunds = await bundleDataClient.getApproximateRefundsForBlockRange(
[originChainId, destinationChainId],
getDefaultBlockRange(5)
);
Expand Down Expand Up @@ -934,7 +1150,7 @@ describe("Dataworker: Load data used in all functions", async function () {
await updateAllClients();
expect(
convertToNumericStrings(
bundleDataClient.getApproximateRefundsForBlockRange(
await bundleDataClient.getApproximateRefundsForBlockRange(
[originChainId, destinationChainId],
getDefaultBlockRange(5)
)
Expand Down
14 changes: 14 additions & 0 deletions test/mocks/MockConfigStoreClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,18 @@ export class MockConfigStoreClient extends clients.mocks.MockConfigStoreClient {
enabledChainIds
);
}

_updateLiteChains(chainIds: number[], blockNumber = 0, blockTimestamp = 0) {
this.liteChainIndicesUpdates = [
{
...this.liteChainIndicesUpdates,
value: [...(this.liteChainIndicesUpdates.value ?? []), ...chainIds],
blockNumber,
timestamp: blockTimestamp,
transactionIndex: Math.floor(Math.random() * 10),
logIndex: Math.floor(Math.random() * 10),
transactionHash: "",
},
];
}
}
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@
yargs "^17.7.2"
zksync-web3 "^0.14.3"

"@across-protocol/sdk@^3.4.14":
version "3.4.14"
resolved "https://registry.yarnpkg.com/@across-protocol/sdk/-/sdk-3.4.14.tgz#3246e3b24a08fe0ca188d84c1b615ca0823ae5f8"
integrity sha512-rT+Q0Kh9t6bBdvxma407LSkUI1zN9+0f6X/20kOyuJz9zShCwqFusQ5k5vmLwHvwb7LRdpL5sKGlYTjU/fsT9g==
"@across-protocol/sdk@^3.4.16":
version "3.4.16"
resolved "https://registry.yarnpkg.com/@across-protocol/sdk/-/sdk-3.4.16.tgz#ede633ea59003da78c77af4b185611499f837b45"
integrity sha512-9RLJxdHv7rJWiKVZ/VtPf9rcS+3phpDou0wu2B56NQ9dcfZUKaXHk+M3vm1A9NlSIiHoDHLowSkFztdhsnnbvQ==
dependencies:
"@across-protocol/across-token" "^1.0.0"
"@across-protocol/constants" "^3.1.30"
Expand Down

0 comments on commit 591652b

Please sign in to comment.