Skip to content

Commit

Permalink
Fix balanceAllocator call in _executePoolRebalanceLeaves
Browse files Browse the repository at this point in the history
  • Loading branch information
nicholaspai committed Nov 30, 2024
1 parent f7a7e1b commit b9f4e19
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 16 deletions.
54 changes: 44 additions & 10 deletions src/dataworker/Dataworker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1488,6 +1488,7 @@ export class Dataworker {
({ availableLiquidReserves: updatedLiquidReserves, syncedL1Tokens: updatedL1Tokens } =
await this._updateExchangeRatesBeforeExecutingHubChainLeaves(mainnetLeaves[0], submitExecution));
await this._executePoolRebalanceLeaves(
spokePoolClients,
mainnetLeaves,
balanceAllocator,
expectedTrees.poolRebalanceTree.tree,
Expand Down Expand Up @@ -1553,6 +1554,7 @@ export class Dataworker {

// Perform similar funding checks for remaining non-mainnet pool rebalance leaves.
await this._executePoolRebalanceLeaves(
spokePoolClients,
nonHubChainPoolRebalanceLeaves,
balanceAllocator,
expectedTrees.poolRebalanceTree.tree,
Expand All @@ -1563,6 +1565,9 @@ export class Dataworker {
}

async _executePoolRebalanceLeaves(
spokePoolClients: {
[chainId: number]: SpokePoolClient;
},
leaves: PoolRebalanceLeaf[],
balanceAllocator: BalanceAllocator,
tree: MerkleTree<PoolRebalanceLeaf>,
Expand All @@ -1574,12 +1579,16 @@ export class Dataworker {
(leaf) => sdkUtils.chainIsArbitrum(leaf.chainId) || sdkUtils.chainIsOrbit(leaf.chainId)
);
await forEachAsync(orbitLeaves, async (leaf) => {
const { amount: requiredAmount, token: feeToken } = await this._getRequiredEthForOrbitPoolRebalanceLeaf(leaf);
const {
amount: requiredAmount,
token: feeToken,
holder,
} = await this._getRequiredEthForOrbitPoolRebalanceLeaf(leaf);
const success = await balanceAllocator.requestBalanceAllocations([
{
tokens: [feeToken],
amount: requiredAmount,
holder: this.clients.hubPoolClient.hubPool.address,
holder: holder,
chainId: hubPoolChainId,
},
]);
Expand Down Expand Up @@ -1609,17 +1618,35 @@ export class Dataworker {
contract: new Contract(feeToken, ERC20.abi, signer),
chainId: hubPoolChainId,
method: "transfer",
args: [this.clients.hubPoolClient.hubPool.address, requiredAmount],
args: [holder, requiredAmount],
message: `Loaded orbit gas token for message to ${getNetworkName(leaf.chainId)} 📨!`,
mrkdwn: `Root hash: ${tree.getHexRoot()}\nLeaf: ${leaf.leafId}\nChain: ${leaf.chainId}`,
});
}
}
}
});
if (submitExecution) {
leaves.forEach((leaf) => {
const mrkdwn = `Root hash: ${tree.getHexRoot()}\nLeaf: ${leaf.leafId}\nChain: ${leaf.chainId}`;
await forEachAsync(leaves, async (leaf) => {
// Add balances to spoke pool on mainnet since we know it will be sent atomically.
if (leaf.chainId === hubPoolChainId) {
await Promise.all(
leaf.netSendAmounts.map(async (amount, i) => {
if (amount.gt(bnZero)) {
await balanceAllocator.addUsed(
leaf.chainId,
leaf.l1Tokens[i],
spokePoolClients[leaf.chainId].spokePool.address,
amount.mul(-1)
);
}
})
);
}
});

leaves.forEach((leaf) => {
const mrkdwn = `Root hash: ${tree.getHexRoot()}\nLeaf: ${leaf.leafId}\nChain: ${leaf.chainId}`;
if (submitExecution) {
this.clients.multiCallerClient.enqueueTransaction({
contract: this.clients.hubPoolClient.hubPool,
chainId: hubPoolChainId,
Expand All @@ -1641,8 +1668,10 @@ export class Dataworker {
// from relayer refund leaves.
canFailInSimulation: leaf.chainId !== hubPoolChainId,
});
});
}
} else {
this.logger.debug({ at: "Dataworker#_executePoolRebalanceLeaves", message: mrkdwn });
}
});
}

async _updateExchangeRatesBeforeExecutingHubChainLeaves(
Expand Down Expand Up @@ -2123,7 +2152,7 @@ export class Dataworker {
const success = await balanceAllocator.requestBalanceAllocations(balanceRequestsToQuery);
if (!success) {
this.logger.warn({
at: "Dataworker#executeRelayerRefundLeaves",
at: "Dataworker#_executeRelayerRefundLeaves",
message: "Not executing relayer refund leaf on SpokePool due to lack of funds.",
root: relayerRefundTree.getHexRoot(),
bundle: rootBundleId,
Expand Down Expand Up @@ -2174,7 +2203,7 @@ export class Dataworker {
canFailInSimulation: leaf.chainId === this.clients.hubPoolClient.chainId,
});
} else {
this.logger.debug({ at: "Dataworker#executeRelayerRefundLeaves", message: mrkdwn });
this.logger.debug({ at: "Dataworker#_executeRelayerRefundLeaves", message: mrkdwn });
}
});
}
Expand Down Expand Up @@ -2286,16 +2315,20 @@ export class Dataworker {
async _getRequiredEthForOrbitPoolRebalanceLeaf(leaf: PoolRebalanceLeaf): Promise<{
amount: BigNumber;
token: string;
holder: string;
}> {
// TODO: Make this code more dynamic in the future. For now, hard code custom gas token fees.
let relayMessageFee: BigNumber;
let token: string;
let holder: string;
if (leaf.chainId === CHAIN_IDs.ALEPH_ZERO) {
relayMessageFee = toBNWei("0.49");
token = TOKEN_SYMBOLS_MAP.AZERO.addresses[CHAIN_IDs.MAINNET];
holder = "0x0d57392895Db5aF3280e9223323e20F3951E81B1";
} else {
relayMessageFee = toBNWei("0.02");
token = ZERO_ADDRESS;
holder = this.clients.hubPoolClient.hubPool.address;
}

// For orbit chains, the bot needs enough ETH to pay for each L1 -> L2 message.
Expand All @@ -2314,6 +2347,7 @@ export class Dataworker {
return {
amount: requiredAmount,
token,
holder,
};
}

Expand Down
46 changes: 40 additions & 6 deletions test/Dataworker.executePoolRebalances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@ describe("Dataworker: Execute pool rebalances", async function () {
},
];
await dataworkerInstance._executePoolRebalanceLeaves(
spokePoolClients,
leaves,
balanceAllocator,
buildPoolRebalanceLeafTree(leaves),
Expand All @@ -522,6 +523,37 @@ describe("Dataworker: Execute pool rebalances", async function () {
expect(queuedTransactions[1].method).to.equal("executeRootBundle");
expect(queuedTransactions[1].message).to.match(/chain 137/);
});
it("subtracts used balance for ethereum leaves", async function () {
const leaves: PoolRebalanceLeaf[] = [
{
chainId: hubPoolClient.chainId,
groupIndex: 0,
bundleLpFees: [toBNWei("1")],
netSendAmounts: [toBNWei("1")],
runningBalances: [toBNWei("1")],
leafId: 0,
l1Tokens: [l1Token_1.address],
},
];
await dataworkerInstance._executePoolRebalanceLeaves(
spokePoolClients,
leaves,
balanceAllocator,
buildPoolRebalanceLeafTree(leaves),
true
);

expect(multiCallerClient.transactionCount()).to.equal(1);
const queuedTransactions = multiCallerClient.getQueuedTransactions(hubPoolClient.chainId);
expect(queuedTransactions[0].method).to.equal("executeRootBundle");
expect(
await balanceAllocator.getUsed(
hubPoolClient.chainId,
l1Token_1.address,
spokePoolClients[hubPoolClient.chainId].spokePool.address
)
).to.equal(toBNWei("-1"));
});
it("contains arbitrum leaf", async function () {
// Adds one fee per net send amount + one extra if groupIndex = 0
const leaves: PoolRebalanceLeaf[] = [
Expand Down Expand Up @@ -549,6 +581,7 @@ describe("Dataworker: Execute pool rebalances", async function () {
const expectedFeeLeaf1 = expectedFee.mul(2).add(expectedFee);
const expectedFeeLeaf2 = expectedFee.mul(2);
await dataworkerInstance._executePoolRebalanceLeaves(
spokePoolClients,
leaves,
balanceAllocator,
buildPoolRebalanceLeafTree(leaves),
Expand All @@ -571,10 +604,10 @@ describe("Dataworker: Execute pool rebalances", async function () {
address: TOKEN_SYMBOLS_MAP.AZERO.addresses[CHAIN_IDs.MAINNET],
provider: hubPoolClient.hubPool.signer.provider,
});
azero.balanceOf.whenCalledWith(hubPoolClient.hubPool.address).returns(0);
expect(
await balanceAllocator.getBalance(hubPoolClient.chainId, azero.address, hubPoolClient.hubPool.address)
).to.equal(0);
// Custom gas token funder for AZERO
const customGasTokenFunder = "0x0d57392895Db5aF3280e9223323e20F3951E81B1";
azero.balanceOf.whenCalledWith(customGasTokenFunder).returns(0);
expect(await balanceAllocator.getBalance(hubPoolClient.chainId, azero.address, customGasTokenFunder)).to.equal(0);

// Adds one fee per net send amount + one extra if groupIndex = 0
const leaves: PoolRebalanceLeaf[] = [
Expand Down Expand Up @@ -602,6 +635,7 @@ describe("Dataworker: Execute pool rebalances", async function () {
const expectedFeeLeaf1 = expectedFee.mul(2).add(expectedFee);
const expectedFeeLeaf2 = expectedFee.mul(2);
await dataworkerInstance._executePoolRebalanceLeaves(
spokePoolClients,
leaves,
balanceAllocator,
buildPoolRebalanceLeafTree(leaves),
Expand All @@ -612,9 +646,9 @@ describe("Dataworker: Execute pool rebalances", async function () {
expect(multiCallerClient.transactionCount()).to.equal(4);
const queuedTransactions = multiCallerClient.getQueuedTransactions(hubPoolClient.chainId);
expect(queuedTransactions[0].method).to.equal("transfer");
expect(queuedTransactions[0].args).to.deep.equal([hubPoolClient.hubPool.address, expectedFeeLeaf1]);
expect(queuedTransactions[0].args).to.deep.equal([customGasTokenFunder, expectedFeeLeaf1]);
expect(queuedTransactions[1].method).to.equal("transfer");
expect(queuedTransactions[1].args).to.deep.equal([hubPoolClient.hubPool.address, expectedFeeLeaf2]);
expect(queuedTransactions[1].args).to.deep.equal([customGasTokenFunder, expectedFeeLeaf2]);
expect(queuedTransactions[2].method).to.equal("executeRootBundle");
expect(queuedTransactions[3].method).to.equal("executeRootBundle");
});
Expand Down

0 comments on commit b9f4e19

Please sign in to comment.