Skip to content

Commit

Permalink
Merge pull request #145 from BeanstalkFarms/s2-upgr-well-remediations-2
Browse files Browse the repository at this point in the history
S2 upgr well remediations 2
  • Loading branch information
Brean0 authored Sep 6, 2024
2 parents c6ce202 + ff021fe commit ff0936e
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 9 deletions.
37 changes: 34 additions & 3 deletions src/functions/Stable2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ contract Stable2 is ProportionalLPToken2, IBeanstalkWellFunction {

// price threshold. more accurate pricing requires a lower threshold,
// at the cost of higher execution costs.
uint256 constant PRICE_THRESHOLD = 100; // 0.01%
uint256 constant PRICE_THRESHOLD = 10; // 0.001%

address immutable lookupTable;
uint256 immutable a;
Expand Down Expand Up @@ -86,17 +86,33 @@ contract Stable2 is ProportionalLPToken2, IBeanstalkWellFunction {
uint256 sumReserves = scaledReserves[0] + scaledReserves[1];
lpTokenSupply = sumReserves;
for (uint256 i = 0; i < 255; i++) {
bool stableOscillation;
uint256 dP = lpTokenSupply;
// If division by 0, this will be borked: only withdrawal will work. And that is good
dP = dP * lpTokenSupply / (scaledReserves[0] * N);
dP = dP * lpTokenSupply / (scaledReserves[1] * N);
uint256 prevReserves = lpTokenSupply;
lpTokenSupply = (Ann * sumReserves / A_PRECISION + (dP * N)) * lpTokenSupply
/ (((Ann - A_PRECISION) * lpTokenSupply / A_PRECISION) + ((N + 1) * dP));

// Equality with the precision of 1
// If the difference between the current lpTokenSupply and the previous lpTokenSupply is 2,
// Check that the oscillation is stable, and if so, return the average between the two.
if (lpTokenSupply > prevReserves) {
if (lpTokenSupply - prevReserves == 2) {
if (stableOscillation) {
return lpTokenSupply - 1;
}
stableOscillation = true;
}
if (lpTokenSupply - prevReserves <= 1) return lpTokenSupply;
} else {
if (prevReserves - lpTokenSupply == 2) {
if (stableOscillation) {
return lpTokenSupply + 1;
}
stableOscillation = true;
}
if (prevReserves - lpTokenSupply <= 1) return lpTokenSupply;
}
}
Expand Down Expand Up @@ -197,7 +213,7 @@ contract Stable2 is ProportionalLPToken2, IBeanstalkWellFunction {
uint256 parityReserve = lpTokenSupply / 2;

// update `scaledReserves` based on whether targetPrice is closer to low or high price:
if (pd.lutData.highPrice - pd.targetPrice > pd.targetPrice - pd.lutData.lowPrice) {
if (percentDiff(pd.lutData.highPrice, pd.targetPrice) > percentDiff(pd.lutData.lowPrice, pd.targetPrice)) {
// targetPrice is closer to lowPrice.
scaledReserves[i] = parityReserve * pd.lutData.lowPriceI / pd.lutData.precision;
scaledReserves[j] = parityReserve * pd.lutData.lowPriceJ / pd.lutData.precision;
Expand Down Expand Up @@ -281,7 +297,7 @@ contract Stable2 is ProportionalLPToken2, IBeanstalkWellFunction {

// update scaledReserve[j] such that calcRate(scaledReserves, i, j) = low/high Price,
// depending on which is closer to targetPrice.
if (pd.lutData.highPrice - pd.targetPrice > pd.targetPrice - pd.lutData.lowPrice) {
if (percentDiff(pd.lutData.highPrice, pd.targetPrice) > percentDiff(pd.lutData.lowPrice, pd.targetPrice)) {
// targetPrice is closer to lowPrice.
scaledReserves[j] = scaledReserves[i] * pd.lutData.lowPriceJ / pd.lutData.precision;

Expand Down Expand Up @@ -428,4 +444,19 @@ contract Stable2 is ProportionalLPToken2, IBeanstalkWellFunction {
+ pd.maxStepSize * (pd.currentPrice - pd.targetPrice) / (pd.lutData.highPrice - pd.lutData.lowPrice);
}
}

/**
* @notice Calculate the percentage difference between two numbers.
* @return The percentage difference as a fixed-point number with 18 decimals.
* @dev This function calculates the absolute percentage difference:
* |(a - b)| / ((a + b) / 2) * 100
* The result is scaled by 1e18 for precision.
*/
function percentDiff(uint256 _a, uint256 _b) internal pure returns (uint256) {
if (_a == _b) return 0;
uint256 difference = _a > _b ? _a - _b : _b - _a;
uint256 average = (_a + _b) / 2;
// Multiply by 100 * 1e18 to get percentage with 18 decimal places
return (difference * 100 * 1e18) / average;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ contract BeanstalkStable2LiquidityTest is TestHelper {
uint256 reserve0 = _f.calcReserveAtRatioLiquidity(reserves, 0, ratios, data);
uint256 reserve1 = _f.calcReserveAtRatioLiquidity(reserves, 1, ratios, data);

assertApproxEqRel(reserve0, 4.575771214546676444e18, 0.0001e18);
assertApproxEqRel(reserve0, 4.576236561359714812e18, 0.0001e18);
assertApproxEqRel(reserve1, 0.21852354514449462e18, 0.0001e18);
}

Expand Down
10 changes: 5 additions & 5 deletions test/beanstalk/BeanstalkStable2.calcReserveAtRatioSwap.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ contract BeanstalkStable2SwapTest is TestHelper {
uint256 reserve0 = _f.calcReserveAtRatioSwap(reserves, 0, ratios, data);
uint256 reserve1 = _f.calcReserveAtRatioSwap(reserves, 1, ratios, data);

assertEq(reserve0, 100.005058322101089709e18);
assertEq(reserve1, 100.005058322101089709e18);
assertEq(reserve0, 99.999921040536083478e18);
assertEq(reserve1, 99.999921040536083478e18);
}

function test_calcReserveAtRatioSwap_equal_diff() public view {
Expand All @@ -45,8 +45,8 @@ contract BeanstalkStable2SwapTest is TestHelper {
uint256 reserve0 = _f.calcReserveAtRatioSwap(reserves, 0, ratios, data);
uint256 reserve1 = _f.calcReserveAtRatioSwap(reserves, 1, ratios, data);

assertEq(reserve0, 73.517644476151580971e18);
assertEq(reserve1, 73.517644476151580971e18);
assertEq(reserve0, 73.513867858788351572e18);
assertEq(reserve1, 73.513867858788351572e18);
}

function test_calcReserveAtRatioSwap_diff_equal() public view {
Expand All @@ -61,7 +61,7 @@ contract BeanstalkStable2SwapTest is TestHelper {
uint256 reserve1 = _f.calcReserveAtRatioSwap(reserves, 1, ratios, data);

assertEq(reserve0, 180.644064978044534737e18); // 180.644064978044534737e18, 100e18
assertEq(reserve1, 39.475055811844664131e18); // 100e18, 39.475055811844664131e18
assertEq(reserve1, 39.474244037189430513e18); // 100e18, 39.475055811844664131e18
}

function test_calcReserveAtRatioSwap_diff_diff() public view {
Expand Down

0 comments on commit ff0936e

Please sign in to comment.