poolPrice() bugfix; burn() and mint() precision bugfixes

This commit is contained in:
tim
2025-12-01 15:42:12 -04:00
parent ea54059337
commit 4e56f54f27
6 changed files with 120 additions and 73 deletions

View File

@@ -2,7 +2,6 @@
pragma solidity ^0.8.20;
import "forge-std/Test.sol";
import "forge-std/console2.sol";
import "@openzeppelin/contracts/interfaces/IERC20Metadata.sol";
import "../src/LMSRStabilized.sol";
import "../src/LMSRStabilizedBalancedPair.sol";
@@ -90,7 +89,6 @@ contract LMSRStabilizedTest is Test {
int128 newE0 = eValues[0].mul(_exp(tradeAmount.div(b)));
int128 slippageRatio = newE0.div(eValues[0]).div(eValues[1].div(eValues[1]));
int128 slippage = slippageRatio.sub(ABDKMath64x64.fromInt(1));
console2.log('slippage', slippage);
// Slippage should be close to stdSlippage (within 1% relative error)
int128 relativeError = slippage.sub(stdSlippage).abs().div(stdSlippage);
@@ -133,7 +131,6 @@ contract LMSRStabilizedTest is Test {
int128 newE0 = eValues[0].mul(_exp(tradeAmount.div(b)));
int128 slippageRatio = newE0.div(eValues[0]).div(eValues[1].div(eValues[1]));
int128 slippage = slippageRatio.sub(ABDKMath64x64.fromInt(1));
console2.log('slippage', slippage);
int128 relativeError = slippage.sub(stdSlippage).abs().div(stdSlippage);
assertLt(relativeError, ABDKMath64x64.divu(1, 100), "Almost balanced pool slippage error too high");
}
@@ -175,14 +172,12 @@ contract LMSRStabilizedTest is Test {
int128 newE0 = eValues[0].mul(_exp(tradeAmount.div(b)));
int128 slippageRatio = newE0.div(eValues[0]).div(eValues[2].div(eValues[2]));
int128 slippage = slippageRatio.sub(ABDKMath64x64.fromInt(1));
console2.log('slippage', slippage);
// Since the imbalance is extreme, with one coin worth lots more than the others, the actual slippage for
// this swap is actually off by about 100%
// When we configure kappa, it is a best case slippage (worst case AMM loss) that only occurs with balanced
// assets
int128 relativeError = slippage.sub(stdSlippage).abs().div(stdSlippage);
console2.log('relative error', relativeError);
assertLt(relativeError, ABDKMath64x64.divu(100, 100), "Imbalanced pool slippage error too high");
}
@@ -249,7 +244,6 @@ contract LMSRStabilizedTest is Test {
int128 newE0 = eValues[0].mul(_exp(tradeAmount.div(newB)));
int128 slippageRatio = newE0.div(eValues[0]).div(eValues[1].div(eValues[1]));
int128 slippage = slippageRatio.sub(ABDKMath64x64.fromInt(1));
console2.log('post-deposit slippage', slippage);
int128 relativeError = slippage.sub(stdSlippage).abs().div(stdSlippage);
assertLt(relativeError, ABDKMath64x64.divu(1, 100), "Slippage target not met after deposit");
@@ -398,7 +392,6 @@ contract LMSRStabilizedTest is Test {
int128 newE0 = eValues[0].mul(_exp(tradeAmount.div(newB)));
int128 slippageRatio = newE0.div(eValues[0]).div(eValues[1].div(eValues[1]));
int128 slippage = slippageRatio.sub(ABDKMath64x64.fromInt(1));
console2.log('post-withdrawal slippage', slippage);
int128 relativeError = slippage.sub(stdSlippage).abs().div(stdSlippage);
assertLt(relativeError, ABDKMath64x64.divu(1, 100), "Slippage target not met after withdrawal");
@@ -712,10 +705,6 @@ contract LMSRStabilizedTest is Test {
// The path independence property isn't perfect due to discrete swap mechanics,
// but the difference should be within reasonable bounds
console2.log("Direct swap output:");
console2.logInt(directAmountOut);
console2.log("Indirect swap total output:");
console2.logInt(indirectAmountOut2);
// Basic verification that both paths produce positive outputs
assertTrue(directAmountOut > 0, "Direct swap should produce positive output");
@@ -736,8 +725,6 @@ contract LMSRStabilizedTest is Test {
// Update the state's cached qInternal
_updateCachedQInternal(initialQ);
console2.log("Testing round-trip trades for balanced pool");
// Use standard trade size
int128 tradeAmount = s.qInternal[0].mul(stdTradeSize);
@@ -754,9 +741,6 @@ contract LMSRStabilizedTest is Test {
// Calculate round-trip slippage: (initial amount - final amount) / initial amount
int128 roundTripSlippage = (amountIn1.sub(amountOut2)).div(amountIn1);
console2.log("Round-trip slippage (micro-units):");
console2.logInt(_toMicro(roundTripSlippage));
// Verify round-trip slippage is reasonable
int128 tolerance = ABDKMath64x64.divu(1, 100000); // 0.001% tolerance
assertLt(roundTripSlippage.abs(), tolerance, "Round-trip slippage should be near zero");
@@ -797,15 +781,6 @@ contract LMSRStabilizedTest is Test {
// Second direction: asset 1 -> asset 0
(int128 amountIn1to0, int128 amountOut1to0) = s.swapAmountsForExactInput(1, 0, tradeAmount1, 0);
console2.log("0->1 swap amountIn:");
console2.logInt(amountIn0to1);
console2.log("0->1 swap amountOut:");
console2.logInt(amountOut0to1);
console2.log("1->0 swap amountIn:");
console2.logInt(amountIn1to0);
console2.log("1->0 swap amountOut:");
console2.logInt(amountOut1to0);
// For balanced pools, the swap ratios should be approximately symmetric
int128 ratio0to1 = amountOut0to1.div(amountIn0to1);
int128 ratio1to0 = amountOut1to0.div(amountIn1to0);
@@ -814,9 +789,6 @@ contract LMSRStabilizedTest is Test {
int128 ratioDifference = (ratio0to1.sub(ratio1to0)).abs();
int128 relativeRatioDiff = ratioDifference.div(ratio0to1.add(ratio1to0).div(ABDKMath64x64.fromInt(2)));
console2.log("Relative ratio difference (micro-units):");
console2.logInt(_toMicro(relativeRatioDiff));
// Assert that the relative difference between ratios is small
int128 tolerance = ABDKMath64x64.divu(5, 100); // 5% tolerance
assertLt(relativeRatioDiff, tolerance,