Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test for 2CLP rounding fixes #1195

Merged
merged 3 commits into from
Dec 19, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions pkg/pool-gyro/test/foundry/Gyro2CLPMathRounding.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity ^0.8.24;

import "forge-std/Test.sol";

import { Rounding } from "@balancer-labs/v3-interfaces/contracts/vault/VaultTypes.sol";

import { ArrayHelpers } from "@balancer-labs/v3-solidity-utils/contracts/test/ArrayHelpers.sol";

import "../../contracts/lib/Gyro2CLPMath.sol";

struct QuadraticTerms {
uint256 a;
uint256 mb;
uint256 bSquare;
uint256 mc;
}

contract Gyro2CLPMathRoundingTest is Test {
using ArrayHelpers for *;

uint256 internal constant MIN_DIFF_ALPHA_BETA = 100;

uint256 internal constant MIN_SQRT_ALPHA = 0.01e18;
uint256 internal constant MAX_SQRT_ALPHA = 10e18 - MIN_DIFF_ALPHA_BETA;
// Make sqrtBeta 0.5% higher than sqrtAlpha
uint256 internal constant MIN_SQRT_BETA = MIN_SQRT_ALPHA;
uint256 internal constant MAX_SQRT_BETA = MAX_SQRT_ALPHA + MIN_DIFF_ALPHA_BETA;

function testCalculateQuadraticTermsRounding__Fuzz(
uint256[2] memory balances,
uint256 sqrtAlpha,
uint256 sqrtBeta
) public pure {
balances[0] = bound(balances[0], 1e16, 1e8 * 1e18);
balances[1] = bound(balances[1], 1e16, 1e8 * 1e18);
sqrtAlpha = bound(sqrtAlpha, MIN_SQRT_ALPHA, MAX_SQRT_ALPHA);
sqrtBeta = bound(sqrtBeta, sqrtAlpha + MIN_DIFF_ALPHA_BETA, MAX_SQRT_BETA);

QuadraticTerms memory qTermsDown;
QuadraticTerms memory qTermsUp;

(qTermsDown.a, qTermsDown.mb, qTermsDown.bSquare, qTermsDown.mc) = Gyro2CLPMath.calculateQuadraticTerms(
balances.toMemoryArray(),
sqrtAlpha,
sqrtBeta,
Rounding.ROUND_DOWN
);
(qTermsUp.a, qTermsUp.mb, qTermsUp.bSquare, qTermsUp.mc) = Gyro2CLPMath.calculateQuadraticTerms(
balances.toMemoryArray(),
sqrtAlpha,
sqrtBeta,
Rounding.ROUND_UP
);

assertLe(qTermsUp.a, qTermsDown.a, "Wrong rounding result (a)");
assertGe(qTermsUp.mb, qTermsDown.mb, "Wrong rounding result (mb)");
assertGe(qTermsUp.bSquare, qTermsDown.bSquare, "Wrong rounding result (bSquare)");
assertGe(qTermsUp.mc, qTermsDown.mc, "Wrong rounding result (mc)");
}

function testCalculateQuadraticRounding__Fuzz(uint256 a, uint256 mb, uint256 mc) public pure {
a = bound(a, 1, 1e18); // 0 < a < FP(1)
mb = bound(mb, 1, 1e8 * 1e18);
uint256 bSquare = mb * mb; // This is an approximation just to unit fuzz calculate quadratic.
mc = bound(mc, 1, 1e8 * 1e18);

uint256 quadraticRoundDown = Gyro2CLPMath.calculateQuadratic(a, mb, bSquare, mc, Rounding.ROUND_DOWN);
uint256 quadraticRoundUp = Gyro2CLPMath.calculateQuadratic(a, mb, bSquare, mc, Rounding.ROUND_UP);

assertGe(quadraticRoundUp, quadraticRoundDown, "Wrong rounding result");
}

function testComputeInvariantRounding__Fuzz(
uint256[2] memory balances,
uint256 sqrtAlpha,
uint256 sqrtBeta
) public pure {
balances[0] = bound(balances[0], 1e16, 1e8 * 1e18);
balances[1] = bound(balances[1], 1e16, 1e8 * 1e18);
sqrtAlpha = bound(sqrtAlpha, MIN_SQRT_ALPHA, MAX_SQRT_ALPHA);
sqrtBeta = bound(sqrtBeta, sqrtAlpha + MIN_DIFF_ALPHA_BETA, MAX_SQRT_BETA);

uint256 invariantDown = Gyro2CLPMath.calculateInvariant(
balances.toMemoryArray(),
sqrtAlpha,
sqrtBeta,
Rounding.ROUND_DOWN
);
uint256 invariantUp = Gyro2CLPMath.calculateInvariant(
balances.toMemoryArray(),
sqrtAlpha,
sqrtBeta,
Rounding.ROUND_UP
);

assertGe(invariantUp, invariantDown, "Wrong rounding result");
}
}
Loading