This commit is contained in:
tim
2025-10-24 20:01:24 -04:00
parent 2972152e58
commit 96dc134769
11 changed files with 421 additions and 253 deletions

View File

@@ -15,6 +15,7 @@ import {LMSRStabilized} from "../src/LMSRStabilized.sol";
import {PartyPlanner} from "../src/PartyPlanner.sol";
import {PartyPool} from "../src/PartyPool.sol";
import {MockERC20} from "./PartyPlanner.t.sol";
import "@abdk/ABDKMath64x64.sol";
// Mock ERC20 token for testing
contract MockERC20 is ERC20 {
@@ -34,11 +35,37 @@ contract MockERC20 is ERC20 {
}
contract PartyPlannerTest is Test {
using ABDKMath64x64 for int128;
PartyPlanner public planner;
MockERC20 public tokenA;
MockERC20 public tokenB;
MockERC20 public tokenC;
function _computeFixedBFromDeposits(
uint256 nAssets,
uint256[] memory bases,
uint256[] memory initialDeposits,
int128 tradeFrac,
int128 targetSlippage
) internal pure returns (int128) {
require(bases.length == initialDeposits.length && bases.length == nAssets, "length mismatch");
// Compute S = sum(deposit_i / base_i) in Q64.64
int128 S = 0;
for (uint256 i = 0; i < nAssets; i++) {
S = S + ABDKMath64x64.divu(initialDeposits[i], bases[i]);
}
// E = (1 - s*(n-1)) / (1 + s)
int128 one = ABDKMath64x64.fromInt(1);
int128 nMinus1 = ABDKMath64x64.fromUInt(nAssets - 1);
int128 numerator = one.sub(targetSlippage.mul(nMinus1));
int128 denominator = one.add(targetSlippage);
int128 E = numerator.div(denominator);
// y = -ln(E) / f, b = S / y
int128 y = ABDKMath64x64.ln(E).neg().div(tradeFrac);
return S.div(y);
}
address public payer = makeAddr("payer");
address public receiver = makeAddr("receiver");
@@ -93,15 +120,15 @@ contract PartyPlannerTest is Test {
uint256 initialTokenACount = planner.poolsByTokenCount(IERC20(address(tokenA)));
uint256 initialTokenBCount = planner.poolsByTokenCount(IERC20(address(tokenB)));
// Compute kappa then create pool via kappa overload
int128 computedKappa = LMSRStabilized.computeKappaFromSlippage(tokens.length, tradeFrac, targetSlippage);
// Compute fixed b from slippage and initial deposits, then create pool
int128 bFixed = _computeFixedBFromDeposits(tokens.length, bases, initialDeposits, tradeFrac, targetSlippage);
(IPartyPool pool, uint256 lpAmount) = planner.newPool(
name,
symbol,
tokens,
bases,
computedKappa,
bFixed,
swapFeePpm,
flashFeePpm,
false, // not stable
@@ -174,10 +201,10 @@ contract PartyPlannerTest is Test {
deposits1[0] = INITIAL_DEPOSIT_AMOUNT;
deposits1[1] = INITIAL_DEPOSIT_AMOUNT;
int128 kappa1 = LMSRStabilized.computeKappaFromSlippage(tokens1.length, int128((1 << 64) - 1), int128(1 << 62));
int128 b1 = _computeFixedBFromDeposits(tokens1.length, bases1, deposits1, int128((1 << 64) - 1), int128(1 << 62));
(IPartyPool pool1,) = planner.newPool(
"Pool 1", "LP1", tokens1, bases1,
kappa1, 3000, 5000, false,
b1, 3000, 5000, false,
payer, receiver, deposits1, 1000e18, 0
);
@@ -194,10 +221,10 @@ contract PartyPlannerTest is Test {
deposits2[0] = INITIAL_DEPOSIT_AMOUNT;
deposits2[1] = INITIAL_DEPOSIT_AMOUNT / 1e12; // Adjust for 6 decimals
int128 kappa2 = LMSRStabilized.computeKappaFromSlippage(tokens2.length, int128((1 << 64) - 1), int128(1 << 62));
int128 b2 = _computeFixedBFromDeposits(tokens2.length, bases2, deposits2, int128((1 << 64) - 1), int128(1 << 62));
(IPartyPool pool2,) = planner.newPool(
"Pool 2", "LP2", tokens2, bases2,
kappa2, 3000, 5000, false,
b2, 3000, 5000, false,
payer, receiver, deposits2, 1000e18, 0
);
@@ -250,12 +277,12 @@ contract PartyPlannerTest is Test {
validDeposits[0] = INITIAL_DEPOSIT_AMOUNT;
validDeposits[1] = INITIAL_DEPOSIT_AMOUNT;
int128 kappaErr = LMSRStabilized.computeKappaFromSlippage(tokens.length, int128((1 << 64) - 1), int128(1 << 62));
int128 bErr = _computeFixedBFromDeposits(tokens.length, bases, validDeposits, int128((1 << 64) - 1), int128(1 << 62));
vm.expectRevert("Planner: payer cannot be zero address");
planner.newPool(
"Test Pool", "TESTLP", tokens, bases,
kappaErr, 3000, 5000, false,
bErr, 3000, 5000, false,
address(0), receiver, validDeposits, 1000e18, 0
);
@@ -263,18 +290,18 @@ contract PartyPlannerTest is Test {
vm.expectRevert("Planner: receiver cannot be zero address");
planner.newPool(
"Test Pool", "TESTLP", tokens, bases,
kappaErr, 3000, 5000, false,
bErr, 3000, 5000, false,
payer, address(0), validDeposits, 1000e18, 0
);
// Test deadline exceeded
// The default timestamp is 1 and 1-0 is 0 which means "ignore deadline," so we need to set a proper timestamp.
int128 kappaDeadline = LMSRStabilized.computeKappaFromSlippage(tokens.length, int128((1 << 64) - 1), int128(1 << 62));
int128 bDeadline = _computeFixedBFromDeposits(tokens.length, bases, validDeposits, int128((1 << 64) - 1), int128(1 << 62));
vm.warp(1000);
vm.expectRevert("Planner: deadline exceeded");
planner.newPool(
"Test Pool", "TESTLP", tokens, bases,
kappaDeadline, 3000, 5000, false,
bDeadline, 3000, 5000, false,
payer, receiver, validDeposits, 1000e18, block.timestamp - 1
);
}
@@ -297,12 +324,12 @@ contract PartyPlannerTest is Test {
deposits[0] = INITIAL_DEPOSIT_AMOUNT;
deposits[1] = INITIAL_DEPOSIT_AMOUNT;
int128 kappaLoop = LMSRStabilized.computeKappaFromSlippage(tokens.length, int128((1 << 64) - 1), int128(1 << 62));
int128 bLoop = _computeFixedBFromDeposits(tokens.length, bases, deposits, int128((1 << 64) - 1), int128(1 << 62));
(IPartyPool pool,) = planner.newPool(
string(abi.encodePacked("Pool ", vm.toString(i))),
string(abi.encodePacked("LP", vm.toString(i))),
tokens, bases,
kappaLoop, 3000, 5000, false,
bLoop, 3000, 5000, false,
payer, receiver, deposits, 1000e18, 0
);