Skip to content
This repository has been archived by the owner on Aug 30, 2024. It is now read-only.

Commit

Permalink
OP Horizon not respected on rought profitability estimation
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeychr committed Dec 8, 2023
1 parent 3f7fc66 commit 37d2a6f
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 29 deletions.
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
- [Testing the order execution flow in the wild](#testing-the-order-execution-flow-in-the-wild)
- [Restricting orders from fulfillment](#restricting-orders-from-fulfillment)
- [Placing new orders](#placing-new-orders)
- [Smart contract addresses](#smart-contract-addresses)
- [Miscellaneous](#miscellaneous)
- [Disable OP Horizon campaign](#disable-op-horizon-campaign)

## TL;DR

Expand Down Expand Up @@ -339,6 +342,12 @@ You can use the [order placement app](https://dln.debridge.finance/) to place ne

If you decided to use the `whitelistedReceiver` filter (mentioned in the previous section) then don't forget to set the `receiver` property of an order with your trusted address.

# Smart contract addresses
## Smart contract addresses

The DLN smart contracts deployed across supported chains which are used to run the DLN are listed in [this file](./src/environments.ts). `dln-taker` sets the unlimited approvals to the `contracts` upon first launch.

## Miscellaneous

### Disable OP Horizon campaign

Orders coming from/to Optimism participate in the OP Horizon campaign, which rebates expenses and taker's profits in the OP token. To get out of the campaign, use the `DISABLE_OP_HORIZON_CAMPAIGN` env variable set to `true`.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@debridge-finance/dln-taker",
"version": "3.0.0",
"version": "3.0.1",
"description": "DLN executor is the rule-based daemon service developed to automatically execute orders placed on the deSwap Liquidity Network (DLN) across supported blockchains",
"license": "GPL-3.0-only",
"author": "deBridge",
Expand Down
4 changes: 2 additions & 2 deletions src/chain-common/order-estimator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,14 @@ export class OrderEstimator extends OrderEvaluationContextual {
logger: createClientLogger(this.logger),
batchSize: this.order.giveChain.srcConstraints.batchUnlockSize,
swapEstimationPreference: this.getRouteHint(),
isFeatureEnableOpHorizon: process.env.FEATURE_OP_HORIZON_CAMPAIGN === 'true',
isFeatureEnableOpHorizon: process.env.DISABLE_OP_HORIZON_CAMPAIGN !== 'true',
};
}

protected async getRawOrderEstimation(): Promise<RawOrderEstimation> {
const rawEstimation = await calculateExpectedTakeAmount(
this.order.orderData,
this.order.giveChain.srcConstraints.profitability,
this.order.legacyRequiredMargin,
await this.getExpectedTakeAmountContext(),
);

Expand Down
32 changes: 30 additions & 2 deletions src/chain-common/order.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
buffersAreEqual,
getEngineByChainId,
ChainEngine,
ChainId,
} from '@debridge-finance/dln-client';
import { findExpectedBucket } from '@debridge-finance/legacy-dln-profitability';
import { helpers } from '@debridge-finance/solana-utils';
Expand Down Expand Up @@ -87,9 +88,8 @@ export class CreatedOrder {

async getMaxProfitableReserveAmountWithoutOperatingExpenses(): Promise<bigint> {
// getting the rough amount we are willing to spend after reserving our intended margin
const margin = BigInt(this.giveChain.srcConstraints.profitability);
const reserveDstAmount = await this.getGiveAmountInReserveToken();
const amount = (reserveDstAmount * (10_000n - margin)) / 10_000n;
const amount = (reserveDstAmount * (10_000n - BigInt(this.requiredMargin))) / 10_000n;
return amount;
}

Expand All @@ -98,6 +98,34 @@ export class CreatedOrder {
return this.finalization;
}

/**
* Returns margin requirement for this particular order. It may take give- and take-chain into consideration
*/
get requiredMargin(): number {
let margin = this.legacyRequiredMargin;

if (process.env.DISABLE_OP_HORIZON_CAMPAIGN !== 'true') {
if (this.takeChain.chain === ChainId.Optimism) {
margin -= 4;
} else if (this.giveChain.chain === ChainId.Optimism) {
margin -= 2;
}

if (margin < 0) margin = 0;
}

return margin;
}

/**
* Similar to `requiredMargin`, but used by the legacy-dln-profitability package. The difference between
* requiredMargin and legacyRequiredMargin is that the latter does not account for OP HORIZON Campaign rebates
* bc legacy-dln-profitability does this internally
*/
get legacyRequiredMargin(): number {
return this.giveChain.srcConstraints.profitability;
}

public srcConstraints(): SrcOrderConstraints {
return this.srcConstraintsRange() || this.giveChain.srcConstraints;
}
Expand Down
48 changes: 27 additions & 21 deletions src/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ export class Executor implements IExecutor {
);

const srcConstraints: ExecutorSupportedChain['srcConstraints'] = {
...Executor.getSrcConstraints(
...this.getSrcConstraints(
chain.chain,
chain.constraints || {},
config.srcConstraints || {},
Expand Down Expand Up @@ -631,38 +631,44 @@ export class Executor implements IExecutor {
);
}

private static getSrcConstraints(
private getSrcConstraints(
chainId: ChainId,
chainConstraint: RawSrcConstraints,
sharedConstraint: RawSrcConstraints,
): SrcConstraints {
const maxBatchSize = 10;
const maxBatchSizeToSolana = 7;
const getBatchSize = (): number => {
const maxBatchSize = 10;
const maxBatchSizeToSolana = 7;
const size =
chainConstraint.batchUnlockSize || sharedConstraint.batchUnlockSize || maxBatchSize;

if (size < 1 || size > maxBatchSize) {
throw new Error(
`Unlock batch size is out of bounds: expected [1,${maxBatchSize}]; actual: ${size} for ${ChainId[chainId]}`,
);
}

if (chainId === ChainId.Solana) {
if (size > maxBatchSizeToSolana) {
this.logger.warn(
`Size of batch unlock to Solana forcibly reduced to ${maxBatchSizeToSolana}`,
);
return maxBatchSizeToSolana;
}
}

return size;
};

const srcConstraints = {
const srcConstraints: SrcConstraints = {
TVLBudget: chainConstraint.TVLBudget || sharedConstraint.TVLBudget || 0,
profitability:
chainConstraint.minProfitabilityBps ||
sharedConstraint.minProfitabilityBps ||
DEFAULT_MIN_PROFITABILITY_BPS,
batchUnlockSize:
chainConstraint.batchUnlockSize || sharedConstraint.batchUnlockSize || maxBatchSize,
batchUnlockSize: getBatchSize(),
};

if (srcConstraints.batchUnlockSize < 1 || srcConstraints.batchUnlockSize > maxBatchSize) {
throw new Error(
`Unlock batch size is out of bounds: expected [1,${maxBatchSize}]; actual: ${srcConstraints.batchUnlockSize} for ${ChainId[chainId]}`,
);
}

if (chainId === ChainId.Solana) {
if (srcConstraints.batchUnlockSize > maxBatchSizeToSolana) {
srcConstraints.batchUnlockSize = maxBatchSizeToSolana;
// TODO write WARN to log
// throw new Error(`Unlock batch size for Solana is out of bounds: expected to be up to ${maxBatchSizeToSolana}, actual: ${srcConstraints.unlockBatchSize}`)
}
}

return srcConstraints;
}

Expand Down

0 comments on commit 37d2a6f

Please sign in to comment.