Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
kinrezC committed Apr 26, 2024
1 parent 55418b8 commit c427eab
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 59 deletions.
11 changes: 9 additions & 2 deletions src/SYCoveredCall/SYCoveredCall.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { IPPrincipalToken } from "pendle/interfaces/IPPrincipalToken.sol";
import { IStandardizedYield } from "pendle/interfaces/IStandardizedYield.sol";
import { IPYieldToken } from "pendle/interfaces/IPYieldToken.sol";
import { Gaussian } from "solstat/Gaussian.sol";
import "forge-std/console2.sol";

enum UpdateCode {
Invalid,
Expand All @@ -39,6 +40,7 @@ struct InternalParams {
uint256 swapFee;
address controller;
uint256 lastTimestamp;
uint256 lastImpliedPrice;
IStandardizedYield SY;
IPPrincipalToken PT;
IPYieldToken YT;
Expand All @@ -52,6 +54,7 @@ struct SYCoveredCallParams {
uint256 swapFee;
address controller;
uint256 lastTimestamp;
uint256 lastImpliedPrice;
IStandardizedYield SY;
IPPrincipalToken PT;
IPYieldToken YT;
Expand Down Expand Up @@ -149,9 +152,11 @@ contract SYCoveredCall is PairStrategy {
internalParams[poolId].swapFee = params.swapFee;
internalParams[poolId].controller = params.controller;
internalParams[poolId].lastTimestamp = block.timestamp;
internalParams[poolId].lastImpliedPrice = computePriceGivenX(reserves[0], totalLiquidity, params);

invariant =
tradingFunction(reserves, totalLiquidity, abi.encode(params));
console2.log("initial invariant after init", invariant);
valid = invariant >= 0 && invariant <= EPSILON;
}

Expand Down Expand Up @@ -187,6 +192,7 @@ contract SYCoveredCall is PairStrategy {
params.swapFee = internalParams[poolId].swapFee;
params.maturity = internalParams[poolId].maturity;
params.lastTimestamp = internalParams[poolId].lastTimestamp;
params.lastImpliedPrice = internalParams[poolId].lastImpliedPrice;

return abi.encode(params);
}
Expand Down Expand Up @@ -242,7 +248,7 @@ contract SYCoveredCall is PairStrategy {
ccParams.lastTimestamp = swapTimestamp;

ccParams.mean =
computeKGivenLastPrice(pool.reserves[0], computedL, ccParams);
computeKGivenLastPrice(pool.reserves[0], pool.totalLiquidity, ccParams);

int256 computedInvariant =
tradingFunction(pool.reserves, computedL, abi.encode(ccParams));
Expand Down Expand Up @@ -275,14 +281,15 @@ contract SYCoveredCall is PairStrategy {
function postSwapHook(
address,
uint256 poolId,
Pool memory,
Pool memory pool,
bytes memory params
) external override onlyDFMM {
SYCoveredCallParams memory ccParams =
abi.decode(params, (SYCoveredCallParams));

internalParams[poolId].lastTimestamp = ccParams.lastTimestamp;
internalParams[poolId].mean = ccParams.mean;
internalParams[poolId].lastImpliedPrice = computePriceGivenX(pool.reserves[0], pool.totalLiquidity, ccParams);
}

/// @inheritdoc IStrategy
Expand Down
4 changes: 1 addition & 3 deletions src/SYCoveredCall/SYCoveredCallMath.sol
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,6 @@ function computeKGivenLastPrice(
uint256 L,
SYCoveredCallParams memory params
) pure returns (uint256 K) {
uint256 price = computePriceGivenX(rX, L, params);

uint256 tau = computeTau(params);
uint256 a = computeHalfSigmaSquaredTau(params.width, tau);
// $$\Phi^{-1} (1 - \frac{x}{L})$$
Expand All @@ -230,7 +228,7 @@ function computeKGivenLastPrice(
b.wadMul(int256(computeSigmaSqrtTau(params.width, tau))) - int256(a)
).expWad();

K = price.divWadDown(uint256(exp));
K = params.lastImpliedPrice.divWadDown(uint256(exp));
}

function computePriceGivenY(
Expand Down
92 changes: 44 additions & 48 deletions src/SYCoveredCall/SYCoveredCallSolver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
YEAR,
ONE
} from "src/SYCoveredCall/SYCoveredCallMath.sol";
import "forge-std/console2.sol";

contract SYCoveredCallSolver {
using FixedPointMathLib for uint256;
Expand Down Expand Up @@ -170,44 +171,37 @@ contract SYCoveredCallSolver {
}

function getNextLiquidity(
uint256 poolId,
uint256 rx,
uint256 ry,
uint256 L
) public view returns (uint256) {
SYCoveredCallParams memory poolParams =
getPoolParamsCustomTimestamp(poolId, block.timestamp);

int256 invariant = computeTradingFunction(rx, ry, L, poolParams);
return computeNextLiquidity(rx, ry, invariant, L, poolParams);
uint256 L,
SYCoveredCallParams memory params
) public pure returns (uint256) {
int256 invariant = computeTradingFunction(rx, ry, L, params);
return computeNextLiquidity(rx, ry, invariant, L, params);
}

function getNextReserveX(
uint256 poolId,
uint256 ry,
uint256 L,
uint256 S
) public view returns (uint256) {
SYCoveredCallParams memory poolParams =
getPoolParamsCustomTimestamp(poolId, block.timestamp);
uint256 approximatedRx = computeXGivenL(L, S, poolParams);
uint256 S,
SYCoveredCallParams memory params
) public pure returns (uint256) {
uint256 approximatedRx = computeXGivenL(L, S, params);
int256 invariant =
computeTradingFunction(approximatedRx, ry, L, poolParams);
return computeNextRx(ry, L, invariant, approximatedRx, poolParams);
computeTradingFunction(approximatedRx, ry, L, params);
return computeNextRx(ry, L, invariant, approximatedRx, params);
}

function getNextReserveY(
uint256 poolId,
uint256 rx,
uint256 L,
uint256 S
) public view returns (uint256) {
SYCoveredCallParams memory poolParams =
getPoolParamsCustomTimestamp(poolId, block.timestamp);
uint256 approximatedRy = computeYGivenL(L, S, poolParams);
uint256 S,
SYCoveredCallParams memory params
) public pure returns (uint256) {
uint256 approximatedRy = computeYGivenL(L, S, params);
int256 invariant =
computeTradingFunction(rx, approximatedRy, L, poolParams);
return computeNextRy(rx, L, invariant, approximatedRy, poolParams);
computeTradingFunction(rx, approximatedRy, L, params);
return computeNextRy(rx, L, invariant, approximatedRy, params);
}

struct SimulateSwapState {
Expand All @@ -226,18 +220,24 @@ contract SYCoveredCallSolver {
Reserves memory endReserves;
(uint256[] memory preReserves, uint256 preTotalLiquidity) =
getReservesAndLiquidity(poolId);
SYCoveredCallParams memory poolParams =
SYCoveredCallParams memory params =
getPoolParamsCustomTimestamp(poolId, timestamp);

SimulateSwapState memory state;
state.timestamp = timestamp;
params.lastTimestamp = timestamp;
console2.log("initial K", params.mean);

uint256 startComputedL = getNextLiquidity(
poolId, preReserves[0], preReserves[1], preTotalLiquidity
params.mean = computeKGivenLastPrice(
preReserves[0], preTotalLiquidity, params
);
poolParams.mean = computeKGivenLastPrice(
preReserves[0], preTotalLiquidity, poolParams
console2.log("updated K", params.mean);

console2.log("preL", preTotalLiquidity);
uint256 startComputedL = getNextLiquidity(
preReserves[0], preReserves[1], preTotalLiquidity, params
);
console2.log("computedL", startComputedL);

uint256 poolId = poolId;
uint256 swapAmountIn = amountIn;
Expand All @@ -248,17 +248,17 @@ contract SYCoveredCallSolver {
swapAmountIn,
preReserves[0],
preReserves[1],
preTotalLiquidity,
poolParams
startComputedL,
params
);

endReserves.rx = preReserves[0] + swapAmountIn;
endReserves.L = startComputedL + state.deltaLiquidity;
uint256 approxPrice =
getPriceGivenXL(poolId, endReserves.rx, endReserves.L);
getPriceGivenXL(endReserves.rx, endReserves.L, params);

endReserves.ry = getNextReserveY(
poolId, endReserves.rx, endReserves.L, approxPrice
endReserves.rx, endReserves.L, approxPrice, params
);

require(
Expand All @@ -271,17 +271,17 @@ contract SYCoveredCallSolver {
swapAmountIn,
preReserves[0],
preReserves[1],
preTotalLiquidity,
poolParams
startComputedL,
params
);

endReserves.ry = preReserves[1] + swapAmountIn;
endReserves.L = startComputedL + state.deltaLiquidity;
uint256 approxPrice =
getPriceGivenYL(poolId, endReserves.ry, endReserves.L);
getPriceGivenYL(endReserves.ry, endReserves.L, params);

endReserves.rx = getNextReserveX(
poolId, endReserves.ry, endReserves.L, approxPrice
endReserves.ry, endReserves.L, approxPrice, params
);

require(
Expand Down Expand Up @@ -325,28 +325,24 @@ contract SYCoveredCallSolver {
return (
valid,
state.amountOut,
computePriceGivenX(endReserves.rx, endReserves.L, poolParams),
computePriceGivenX(endReserves.rx, endReserves.L, params),
swapData
);
}

function getPriceGivenYL(
uint256 poolId,
uint256 ry,
uint256 L
) public view returns (uint256 price) {
SYCoveredCallParams memory params =
getPoolParamsCustomTimestamp(poolId, block.timestamp);
uint256 L,
SYCoveredCallParams memory params
) public pure returns (uint256 price) {
price = computePriceGivenY(ry, L, params);
}

function getPriceGivenXL(
uint256 poolId,
uint256 rx,
uint256 L
) public view returns (uint256 price) {
SYCoveredCallParams memory params =
getPoolParamsCustomTimestamp(poolId, block.timestamp);
uint256 L,
SYCoveredCallParams memory params
) public pure returns (uint256 price) {
price = computePriceGivenX(rx, L, params);
}

Expand Down
12 changes: 10 additions & 2 deletions test/SYCoveredCall/unit/SetUp.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import "forge-std/console2.sol";
import { IPMarket } from "pendle/interfaces/IPMarket.sol";
import "pendle/core/Market/MarketMathCore.sol";
import "pendle/interfaces/IPAllActionV3.sol";
import { FixedPointMathLib } from "solmate/utils/FixedPointMathLib.sol";

contract SYCoveredCallSetUp is SetUp {
using FixedPointMathLib for uint256;
using MarketMathCore for MarketState;
using MarketMathCore for int256;
using MarketMathCore for uint256;
Expand Down Expand Up @@ -42,6 +44,8 @@ contract SYCoveredCallSetUp is SetUp {
MarketState public pendleMarketState;
int256 pendleRateAnchor;
int256 pendleRateScalar;
int256 pendleExchangeRate;
uint256 ptRate;
uint256 timeToExpiry;

function mintSY(uint256 amount) public {
Expand All @@ -58,6 +62,7 @@ contract SYCoveredCallSetUp is SetUp {
vm.createSelectFork({ urlOrAlias: "mainnet", blockNumber: 19_662_269 });
SetUp.setUp();
(SY, PT, YT) = IPMarket(market).readTokens();
ptRate = SY.exchangeRate();
pendleMarketState = market.readState(address(router));
coveredCall = new SYCoveredCall(address(dfmm));
solver = new SYCoveredCallSolver(address(coveredCall));
Expand Down Expand Up @@ -93,19 +98,22 @@ contract SYCoveredCallSetUp is SetUp {
tokens[0] = address(tokenX);
tokens[1] = address(tokenY);

pendleExchangeRate = pendleMarketState.totalPt._getExchangeRate(pendleMarketState.totalSy, pendleRateScalar, pendleRateAnchor, 0);
defaultPrice = ptRate.mulWadDown(uint256(pendleExchangeRate));

SYCoveredCallParams memory defaultParams = SYCoveredCallParams({
mean: uint256(pendleRateAnchor),
mean: defaultPrice,
width: 0.1 ether,
maturity: PT.expiry(),
swapFee: 0.0005 ether,
lastTimestamp: block.timestamp,
lastImpliedPrice: 0,
controller: address(this),
SY: SY,
PT: PT,
YT: YT
});

defaultPrice = uint256(pendleRateAnchor);

bytes memory initialPoolData = solver.getInitialPoolDataGivenX(
defaultReserveX, defaultPrice, defaultParams
Expand Down
8 changes: 4 additions & 4 deletions test/SYCoveredCall/unit/Swap.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ contract SYCoveredCallSwapTest is SYCoveredCallSetUp {
(bool valid, uint256 amountOut,, bytes memory payload) =
solver.simulateSwap(POOL_ID, swapXForY, amountIn, block.timestamp);
assertEq(valid, true);

console2.log("swapIsValid", valid);
console2.log("out", amountOut);

(,, uint256 inputAmount, uint256 outputAmount) =
Expand Down Expand Up @@ -131,16 +131,16 @@ contract SYCoveredCallSwapTest is SYCoveredCallSetUp {

SYCoveredCallParams memory poolParams = solver.getPoolParams(POOL_ID);
uint256 startL = solver.getNextLiquidity(
POOL_ID, preReserves[0], preReserves[1], preTotalLiquidity
preReserves[0], preReserves[1], preTotalLiquidity, poolParams
);
uint256 deltaLiquidity =
amountIn.mulWadUp(poolParams.swapFee).divWadUp(poolParams.mean);

uint256 ry = preReserves[1] + amountIn;
uint256 L = startL + deltaLiquidity;
uint256 approxPrice = solver.getPriceGivenYL(POOL_ID, ry, L);
uint256 approxPrice = solver.getPriceGivenYL(ry, L, poolParams);

uint256 rx = solver.getNextReserveX(POOL_ID, ry, L, approxPrice);
uint256 rx = solver.getNextReserveX(ry, L, approxPrice, poolParams);

int256 invariant = computeTradingFunction(rx, ry, L, poolParams);
while (invariant >= 0) {
Expand Down

0 comments on commit c427eab

Please sign in to comment.