Skip to content

Commit

Permalink
feat: use exclusivity configuration in suggested fees (#1327)
Browse files Browse the repository at this point in the history
Signed-off-by: james-a-morris <[email protected]>
  • Loading branch information
james-a-morris authored Dec 12, 2024
1 parent 5dbddd3 commit fda8381
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 40 deletions.
123 changes: 83 additions & 40 deletions api/_exclusivity/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,23 @@ import * as sdk from "@across-protocol/sdk";
import { getCachedTokenBalances } from "../_utils";
import { getExclusivityPeriod, getRelayerConfig, getStrategy } from "./config";
import { ExclusiveRelayer } from "./types";
import { getCachedRelayerFillLimit } from "./cache";

type BigNumber = ethers.BigNumber;
const { parseUnits } = ethers.utils;
const { ZERO_ADDRESS } = sdk.constants;
const { fixedPointAdjustment: fixedPoint } = sdk.utils;

// @todo: The minimum native token balance should probably be configurable.
const MIN_NATIVE_BALANCE = parseUnits("0.001");

/**
* Select a specific relayer exclusivity strategy to apply.
* This currently hardcodes the "none" strategy, but will be updated to support additional strategies
* and selection from on env-based configuration.
* @param originChainId Origin chain for deposit.
* @param destinationChainId Destination chain for fill.
* @param outputToken Input token to be referenced in fill.
* @param outputToken Output token to be used in fill.
* @param outputAmount Output amount to be used in fill.
* @param outputAmountUsd Output amount in USD.
Expand All @@ -24,6 +29,10 @@ const { fixedPointAdjustment: fixedPoint } = sdk.utils;
export async function selectExclusiveRelayer(
originChainId: number,
destinationChainId: number,
inputToken: {
address: string;
symbol: string;
},
outputToken: {
address: string;
symbol: string;
Expand All @@ -49,6 +58,7 @@ export async function selectExclusiveRelayer(
const relayers = await getEligibleRelayers(
originChainId,
destinationChainId,
inputToken.address,
outputToken.address,
outputAmount,
outputAmountUsd,
Expand All @@ -71,6 +81,7 @@ export async function selectExclusiveRelayer(
* and selection from on env-based configuration.
* @param originChainId Origin chain for deposit.
* @param destinationChainId Destination chain for fill.
* @param inputToken Input token to be referenced
* @param outputToken Output token to be used in fill.
* @param outputAmount Output amount to be used in fill.
* @param outputAmountUsd Output amount in USD.
Expand All @@ -80,6 +91,7 @@ export async function selectExclusiveRelayer(
async function getEligibleRelayers(
originChainId: number,
destinationChainId: number,
inputToken: string,
outputToken: string,
outputAmount: BigNumber,
outputAmountUsd: BigNumber,
Expand All @@ -94,48 +106,79 @@ async function getEligibleRelayers(
}

// @todo: Balances are returned as strings; consider mapping them automagically to BNs.
const { balances } = await getCachedTokenBalances(
destinationChainId,
relayers.map(({ address }) => address),
[ZERO_ADDRESS, outputToken]
);

// @todo: The minimum native token balance should probably be configurable.
const minNativeBalance = parseUnits("0.001");
const candidateRelayers = relayers
.filter(({ address: relayer, ...config }) => {
const balance = balances[relayer]; // Balances of outputToken + nativeToken.

// @todo: The balance multiplier must be scaled to n decimals to avoid underflow. Precompute it?
const effectiveBalance = ethers.BigNumber.from(balance[outputToken])
.mul(parseUnits(String(config.balanceMultiplier)))
.div(fixedPoint);

if (exclusivityPeriodSec < config.minExclusivityPeriod) {
return false;
}

if (effectiveBalance.lte(outputAmount)) {
return false;
}

const [{ balances }, fillConfigurations] = await Promise.all([
getCachedTokenBalances(
destinationChainId,
relayers.map(({ address }) => address),
[ZERO_ADDRESS, outputToken]
),
Promise.all(
relayers.map(({ address }) =>
getCachedRelayerFillLimit(
address,
originChainId,
destinationChainId,
inputToken,
outputToken
)
)
),
]);

const candidates = relayers.map(({ address: relayer, ...config }, idx) => {
const balance = balances[relayer]; // Balances of outputToken + nativeToken.
// Resolve the specific configuration for our given range
const relevantConfiguration = fillConfigurations[idx]?.find(
({ maxOutputAmount, minOutputAmount }) =>
outputAmount.gte(minOutputAmount) && outputAmount.lte(maxOutputAmount)
);
// @todo: The balance multiplier must be scaled to n decimals to avoid underflow. Precompute it?
const effectiveBalance = ethers.BigNumber.from(balance[outputToken])
.mul(
parseUnits(
String(
// Check the custom configuration then fall back to the github multiplier
relevantConfiguration?.balanceMultiplier ?? config.balanceMultiplier
)
)
)
.div(fixedPoint);
const effectiveExclusivityPeriod =
relevantConfiguration?.minExclusivityPeriod
? Number(relevantConfiguration.minExclusivityPeriod)
: config.minExclusivityPeriod;

if (exclusivityPeriodSec < effectiveExclusivityPeriod) {
return undefined;
}
if (effectiveBalance.lte(outputAmount)) {
return undefined;
}
if (
relayerFeePct.lt(
parseUnits(
String(
relevantConfiguration?.minProfitThreshold ??
config.minProfitThreshold
)
)
)
) {
return undefined;
}
if (ethers.BigNumber.from(balance[ZERO_ADDRESS]).lt(MIN_NATIVE_BALANCE)) {
return undefined;
}
// No custom configuration set within defined buckets, fall back to the hardcoded configs
if (relevantConfiguration === undefined) {
if (
outputAmountUsd.gt(ethers.utils.parseEther(String(config.maxFillSize)))
) {
return false;
}

if (relayerFeePct.lt(parseUnits(String(config.minProfitThreshold)))) {
return false;
return undefined;
}

if (ethers.BigNumber.from(balance[ZERO_ADDRESS]).lt(minNativeBalance)) {
return false;
}

return true;
})
.map(({ address }) => address);

return candidateRelayers;
}
// A valid custom configuration bucket is found and all above checks have been made
return relayer;
});
return candidates.filter((v) => v !== undefined);
}
1 change: 1 addition & 0 deletions api/suggested-fees.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ const handler = async (
await selectExclusiveRelayer(
computedOriginChainId,
destinationChainId,
inputToken,
outputToken,
amount.sub(totalRelayFee),
amountInUsd,
Expand Down

0 comments on commit fda8381

Please sign in to comment.