Skip to content

Commit

Permalink
Merge pull request #9 from haiko-xyz/feat/test-reversion-solver
Browse files Browse the repository at this point in the history
feat: reversion solver impl + tests
  • Loading branch information
parketh authored Sep 29, 2024
2 parents b6bef80 + 276a2f1 commit 4c26b12
Show file tree
Hide file tree
Showing 50 changed files with 6,089 additions and 171 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ Solver implementations are standalone contracts that inherits from `SolverCompon
scarb build

# Run the tests
snforge test
snforge test --max-n-steps 4294967295
```

## Version control
Expand Down
10 changes: 10 additions & 0 deletions Scarb.lock
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ dependencies = [
"snforge_std",
]

[[package]]
name = "haiko_solver_reversion"
version = "1.0.0"
dependencies = [
"haiko_lib",
"haiko_solver_core",
"openzeppelin",
"snforge_std",
]

[[package]]
name = "openzeppelin"
version = "0.11.0"
Expand Down
1 change: 1 addition & 0 deletions Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
members = [
"packages/core",
"packages/replicating",
"packages/reversion",
]
File renamed without changes.
File renamed without changes.
79 changes: 79 additions & 0 deletions models/src/common/math/feeMath.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import Decimal from "decimal.js";
import { PRECISION, ROUNDING } from "../config";

export const calcFee = (grossAmount: Decimal.Value, feeRate: Decimal.Value) => {
Decimal.set({ precision: PRECISION, rounding: ROUNDING });
let grossAmountDec = new Decimal(grossAmount);
let fee = grossAmountDec.mul(feeRate);
return fee.toFixed();
};

export const netToFee = (netAmount: Decimal.Value, feeRate: Decimal.Value) => {
Decimal.set({ precision: PRECISION, rounding: ROUNDING });
let netAmountBN = new Decimal(netAmount);
let one = new Decimal(1);
let fee = netAmountBN.mul(feeRate).div(one.sub(feeRate));
return fee.toFixed();
};

export const netToGross = (
netAmount: Decimal.Value,
feeRate: Decimal.Value
) => {
Decimal.set({ precision: PRECISION, rounding: ROUNDING });
let netAmountBN = new Decimal(netAmount);
let one = new Decimal(1);
let fee = netAmountBN.div(one.sub(feeRate));
return fee.toFixed();
};

export const grossToNet = (
grossAmount: Decimal.Value,
feeRate: Decimal.Value
) => {
Decimal.set({ precision: PRECISION, rounding: ROUNDING });
let grossAmountDec = new Decimal(grossAmount);
let one = new Decimal(1);
let netAmount = grossAmountDec.mul(one.sub(feeRate));
return netAmount.toFixed();
};

export const getFeeInside = (
lowerBaseFeeFactor: Decimal.Value,
lowerQuoteFeeFactor: Decimal.Value,
upperBaseFeeFactor: Decimal.Value,
upperQuoteFeeFactor: Decimal.Value,
lowerLimit: Decimal.Value,
upperLimit: Decimal.Value,
currLimit: Decimal.Value,
marketBaseFeeFactor: Decimal.Value,
marketQuoteFeeFactor: Decimal.Value
) => {
const currLimitDec = new Decimal(currLimit);
const marketBaseFeeFactorDec = new Decimal(marketBaseFeeFactor);
const marketQuoteFeeFactorDec = new Decimal(marketQuoteFeeFactor);

const baseFeesBelow = currLimitDec.gte(lowerLimit)
? lowerBaseFeeFactor
: marketBaseFeeFactorDec.sub(lowerBaseFeeFactor);
const baseFeesAbove = currLimitDec.lt(upperLimit)
? upperBaseFeeFactor
: marketBaseFeeFactorDec.sub(upperBaseFeeFactor);
const quoteFeesBelow = currLimitDec.gte(lowerLimit)
? lowerQuoteFeeFactor
: marketQuoteFeeFactorDec.sub(lowerQuoteFeeFactor);
const quoteFeesAbove = currLimitDec.lt(upperLimit)
? upperQuoteFeeFactor
: marketQuoteFeeFactorDec.sub(upperQuoteFeeFactor);

const baseFeeFactor = marketBaseFeeFactorDec
.sub(baseFeesBelow)
.sub(baseFeesAbove)
.toFixed();
const quoteFeeFactor = marketQuoteFeeFactorDec
.sub(quoteFeesBelow)
.sub(quoteFeesAbove)
.toFixed();

return { baseFeeFactor, quoteFeeFactor };
};
File renamed without changes.
File renamed without changes.
File renamed without changes.
21 changes: 0 additions & 21 deletions models/src/math/feeMath.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import Decimal from "decimal.js";
import { PRECISION, ROUNDING } from "../config";
import { baseToLiquidity, quoteToLiquidity } from "../math/liquidityMath";
import { limitToSqrtPrice, priceToLimit } from "../math/priceMath";
import { PRECISION, ROUNDING } from "../../common/config";
import {
baseToLiquidity,
quoteToLiquidity,
} from "../../common/math/liquidityMath";
import { limitToSqrtPrice, priceToLimit } from "../../common/math/priceMath";

type PositionInfo = {
lowerSqrtPrice: Decimal.Value;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import Decimal from "decimal.js";
import { PRECISION, ROUNDING } from "../config";
import { liquidityToBase, liquidityToQuote } from "../math/liquidityMath";
import { grossToNet, netToFee } from "../math/feeMath";
import { PRECISION, ROUNDING } from "../../common/config";
import {
liquidityToBase,
liquidityToQuote,
} from "../../common/math/liquidityMath";
import { grossToNet, netToFee } from "../../common/math/feeMath";

export const getSwapAmounts = ({
isBuy,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import {
getDelta,
getVirtualPosition,
getVirtualPositionRange,
} from "../../src/libraries/SpreadMath";
import { getSwapAmounts } from "../../src/libraries/SwapLib";
} from "../libraries/SpreadMath";
import { getSwapAmounts } from "../libraries/SwapLib";

const isBuy = false;
const exactInput = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Decimal from "decimal.js";
import {
getVirtualPosition,
getVirtualPositionRange,
} from "../../src/libraries/SpreadMath";
} from "../../replicating/libraries/SpreadMath";

const testGetVirtualPositionCases = () => {
const cases = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import {
getDelta,
getVirtualPosition,
getVirtualPositionRange,
} from "../../src/libraries/SpreadMath";
import { getSwapAmounts } from "../../src/libraries/SwapLib";
} from "../libraries/SpreadMath";
import { getSwapAmounts } from "../libraries/SwapLib";

type Case = {
description: string;
Expand Down Expand Up @@ -328,19 +328,19 @@ const testSwapCases = () => {
upperLimit,
isBuy ? baseReserves : quoteReserves
);
const { amountIn, amountOut, fees } = getSwapAmounts(
const { amountIn, amountOut, fees } = getSwapAmounts({
isBuy,
exactInput,
amount,
Number(feeRate) / 10000,
swapFeeRate: Number(feeRate) / 10000,
thresholdSqrtPrice,
thresholdAmount,
lowerSqrtPrice,
upperSqrtPrice,
liquidity,
baseDecimals,
quoteDecimals
);
quoteDecimals,
});
console.log({
amountIn: new Decimal(amountIn).mul(1e18).toFixed(0),
amountOut: new Decimal(amountOut).mul(1e18).toFixed(0),
Expand Down
150 changes: 150 additions & 0 deletions models/src/reversion/libraries/SpreadMath.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import Decimal from "decimal.js";
import {
baseToLiquidity,
quoteToLiquidity,
} from "../../common/math/liquidityMath";
import { PRECISION, ROUNDING } from "../../common/config";
import { limitToSqrtPrice, priceToLimit } from "../../common/math/priceMath";
import { Trend } from "../types";

type PositionInfo = {
lowerSqrtPrice: Decimal.Value;
upperSqrtPrice: Decimal.Value;
liquidity: Decimal.Value;
};

type PositionRange = {
bidLower: Decimal.Value;
bidUpper: Decimal.Value;
askLower: Decimal.Value;
askUpper: Decimal.Value;
};

export const getVirtualPosition = (
isBid: boolean,
lowerLimit: Decimal.Value,
upperLimit: Decimal.Value,
amount: Decimal.Value
): PositionInfo => {
Decimal.set({ precision: PRECISION, rounding: ROUNDING });

const lowerSqrtPrice = limitToSqrtPrice(lowerLimit, 1);
const upperSqrtPrice = limitToSqrtPrice(upperLimit, 1);
if (isBid) {
const liquidity = quoteToLiquidity(
lowerSqrtPrice,
upperSqrtPrice,
amount
).toFixed();
return { lowerSqrtPrice, upperSqrtPrice, liquidity };
} else {
const liquidity = baseToLiquidity(
lowerSqrtPrice,
upperSqrtPrice,
amount
).toFixed();
return { lowerSqrtPrice, upperSqrtPrice, liquidity };
}
};

export const getVirtualPositionRange = (
trend: Trend,
range: Decimal.Value,
cachedPrice: Decimal.Value,
oraclePrice: Decimal.Value
): PositionRange => {
Decimal.set({ precision: PRECISION, rounding: ROUNDING });

if (new Decimal(oraclePrice).isZero()) {
throw new Error("Oracle price is zero");
}

const oracleLimit = priceToLimit(oraclePrice, 1);
const newBidLower = oracleLimit.sub(range);
const newBidUpper = oracleLimit;
const newAskLower = oracleLimit;
const newAskUpper = oracleLimit.add(range);

let cachedPriceSet = cachedPrice;
if (new Decimal(cachedPrice).isZero()) {
cachedPriceSet = oraclePrice;
}

const cachedLimit = priceToLimit(cachedPriceSet, 1);
const bidLower = cachedLimit.sub(range);
const bidUpper = cachedLimit;
const askLower = cachedLimit;
const askUpper = cachedLimit.add(range);

switch (trend) {
case Trend.Up:
if (newBidUpper.gt(bidUpper)) {
return {
bidLower: newBidLower,
bidUpper: newBidUpper,
askLower: 0,
askUpper: 0,
};
} else if (newAskLower.lte(bidLower)) {
return {
bidLower: 0,
bidUpper: 0,
askLower: bidLower,
askUpper: bidUpper,
};
} else {
if (newAskLower.gte(bidUpper)) {
return {
bidLower: bidLower,
bidUpper: newBidUpper,
askLower: 0,
askUpper: 0,
};
}
return {
bidLower: bidLower,
bidUpper: newBidUpper,
askLower: newAskLower,
askUpper: bidUpper,
};
}
case Trend.Down:
if (newAskLower.lt(askLower)) {
return {
bidLower: 0,
bidUpper: 0,
askLower: newAskLower,
askUpper: newAskUpper,
};
} else if (newBidUpper.gte(askUpper)) {
return {
bidLower: askLower,
bidUpper: askUpper,
askLower: 0,
askUpper: 0,
};
} else {
if (newBidUpper.lte(askLower)) {
return {
bidLower: 0,
bidUpper: 0,
askLower: newAskLower,
askUpper: askUpper,
};
}
return {
bidLower: askLower,
bidUpper: newBidUpper,
askLower: newAskLower,
askUpper: askUpper,
};
}
default:
return {
bidLower: newBidLower,
bidUpper: newBidUpper,
askLower: newAskLower,
askUpper: newAskUpper,
};
}
};
Loading

0 comments on commit 4c26b12

Please sign in to comment.