From 4cc3782dee8192438aa09e728cf5f31bc15275ed Mon Sep 17 00:00:00 2001 From: Juan Ignacio Ubeira Date: Thu, 19 Dec 2024 16:10:58 -0300 Subject: [PATCH 1/3] Test. --- .../test/foundry/Gyro2CLPMathRounding.sol | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 pkg/pool-gyro/test/foundry/Gyro2CLPMathRounding.sol diff --git a/pkg/pool-gyro/test/foundry/Gyro2CLPMathRounding.sol b/pkg/pool-gyro/test/foundry/Gyro2CLPMathRounding.sol new file mode 100644 index 000000000..bc0f92873 --- /dev/null +++ b/pkg/pool-gyro/test/foundry/Gyro2CLPMathRounding.sol @@ -0,0 +1,98 @@ +// 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_SQRT_ALPHA = 0.8e18; + uint256 internal constant MAX_SQRT_ALPHA = 1.2e18; + // 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; + + 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, MIN_SQRT_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, 1e6 * 1e18); + balances[1] = bound(balances[1], 1e16, 1e6 * 1e18); + sqrtAlpha = bound(sqrtAlpha, MIN_SQRT_ALPHA, MAX_SQRT_ALPHA); + sqrtBeta = bound(sqrtBeta, MIN_SQRT_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"); + } +} From 65b21db8e86285c1e55de6bafa8085888b21b52d Mon Sep 17 00:00:00 2001 From: Juan Ignacio Ubeira Date: Thu, 19 Dec 2024 16:30:44 -0300 Subject: [PATCH 2/3] Fix tests. --- .../test/foundry/Gyro2CLPMathRounding.sol | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/pkg/pool-gyro/test/foundry/Gyro2CLPMathRounding.sol b/pkg/pool-gyro/test/foundry/Gyro2CLPMathRounding.sol index bc0f92873..33a3413b2 100644 --- a/pkg/pool-gyro/test/foundry/Gyro2CLPMathRounding.sol +++ b/pkg/pool-gyro/test/foundry/Gyro2CLPMathRounding.sol @@ -20,11 +20,13 @@ struct QuadraticTerms { contract Gyro2CLPMathRoundingTest is Test { using ArrayHelpers for *; + uint256 internal constant MIN_DIFF_ALPHA_BETA = 1e14; + uint256 internal constant MIN_SQRT_ALPHA = 0.8e18; - uint256 internal constant MAX_SQRT_ALPHA = 1.2e18; + uint256 internal constant MAX_SQRT_ALPHA = 1.2e18 - 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; + uint256 internal constant MAX_SQRT_BETA = MAX_SQRT_ALPHA + MIN_DIFF_ALPHA_BETA; function testCalculateQuadraticTermsRounding__Fuzz( uint256[2] memory balances, @@ -34,7 +36,7 @@ contract Gyro2CLPMathRoundingTest is Test { 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, MIN_SQRT_BETA, MAX_SQRT_BETA); + sqrtBeta = bound(sqrtBeta, sqrtAlpha + MIN_DIFF_ALPHA_BETA, MAX_SQRT_BETA); QuadraticTerms memory qTermsDown; QuadraticTerms memory qTermsUp; @@ -75,10 +77,10 @@ contract Gyro2CLPMathRoundingTest is Test { uint256 sqrtAlpha, uint256 sqrtBeta ) public pure { - balances[0] = bound(balances[0], 1e16, 1e6 * 1e18); - balances[1] = bound(balances[1], 1e16, 1e6 * 1e18); + 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, MIN_SQRT_BETA, MAX_SQRT_BETA); + sqrtBeta = bound(sqrtBeta, sqrtAlpha + MIN_DIFF_ALPHA_BETA, MAX_SQRT_BETA); uint256 invariantDown = Gyro2CLPMath.calculateInvariant( balances.toMemoryArray(), From af515016276b9406dba95e70cf2059d6e360ecc9 Mon Sep 17 00:00:00 2001 From: Juan Ignacio Ubeira Date: Thu, 19 Dec 2024 16:32:45 -0300 Subject: [PATCH 3/3] Expand ranges. --- pkg/pool-gyro/test/foundry/Gyro2CLPMathRounding.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/pool-gyro/test/foundry/Gyro2CLPMathRounding.sol b/pkg/pool-gyro/test/foundry/Gyro2CLPMathRounding.sol index 33a3413b2..c65456550 100644 --- a/pkg/pool-gyro/test/foundry/Gyro2CLPMathRounding.sol +++ b/pkg/pool-gyro/test/foundry/Gyro2CLPMathRounding.sol @@ -20,10 +20,10 @@ struct QuadraticTerms { contract Gyro2CLPMathRoundingTest is Test { using ArrayHelpers for *; - uint256 internal constant MIN_DIFF_ALPHA_BETA = 1e14; + uint256 internal constant MIN_DIFF_ALPHA_BETA = 100; - uint256 internal constant MIN_SQRT_ALPHA = 0.8e18; - uint256 internal constant MAX_SQRT_ALPHA = 1.2e18 - MIN_DIFF_ALPHA_BETA; + 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;