PartyPlanner; chain.json
This commit is contained in:
@@ -182,10 +182,10 @@ contract PartyPoolTest is Test {
|
||||
targetSlippage = ABDKMath64x64.divu(10, 10_000); // 0.001
|
||||
|
||||
// Build arrays for pool constructor
|
||||
address[] memory tokens = new address[](3);
|
||||
tokens[0] = address(token0);
|
||||
tokens[1] = address(token1);
|
||||
tokens[2] = address(token2);
|
||||
IERC20[] memory tokens = new IERC20[](3);
|
||||
tokens[0] = IERC20(address(token0));
|
||||
tokens[1] = IERC20(address(token1));
|
||||
tokens[2] = IERC20(address(token2));
|
||||
|
||||
uint256[] memory bases = new uint256[](3);
|
||||
bases[0] = BASE;
|
||||
@@ -204,20 +204,20 @@ contract PartyPoolTest is Test {
|
||||
token2.transfer(address(pool), INIT_BAL);
|
||||
|
||||
// Perform initial mint (initial deposit); receiver is this contract
|
||||
pool.mint(address(0), address(this), 0, 0);
|
||||
pool.initialMint(address(this), 0);
|
||||
|
||||
// Set up pool10 with 10 tokens
|
||||
address[] memory tokens10 = new address[](10);
|
||||
tokens10[0] = address(token0);
|
||||
tokens10[1] = address(token1);
|
||||
tokens10[2] = address(token2);
|
||||
tokens10[3] = address(token3);
|
||||
tokens10[4] = address(token4);
|
||||
tokens10[5] = address(token5);
|
||||
tokens10[6] = address(token6);
|
||||
tokens10[7] = address(token7);
|
||||
tokens10[8] = address(token8);
|
||||
tokens10[9] = address(token9);
|
||||
IERC20[] memory tokens10 = new IERC20[](10);
|
||||
tokens10[0] = IERC20(address(token0));
|
||||
tokens10[1] = IERC20(address(token1));
|
||||
tokens10[2] = IERC20(address(token2));
|
||||
tokens10[3] = IERC20(address(token3));
|
||||
tokens10[4] = IERC20(address(token4));
|
||||
tokens10[5] = IERC20(address(token5));
|
||||
tokens10[6] = IERC20(address(token6));
|
||||
tokens10[7] = IERC20(address(token7));
|
||||
tokens10[8] = IERC20(address(token8));
|
||||
tokens10[9] = IERC20(address(token9));
|
||||
|
||||
uint256[] memory bases10 = new uint256[](10);
|
||||
for (uint i = 0; i < 10; i++) {
|
||||
@@ -251,7 +251,7 @@ contract PartyPoolTest is Test {
|
||||
token9.transfer(address(pool10), INIT_BAL);
|
||||
|
||||
// Perform initial mint for pool10
|
||||
pool10.mint(address(0), address(this), 0, 0);
|
||||
pool10.initialMint(address(this), 0);
|
||||
|
||||
// For later tests we will mint tokens to alice/bob as needed
|
||||
token0.mint(alice, INIT_BAL);
|
||||
@@ -349,7 +349,7 @@ contract PartyPoolTest is Test {
|
||||
token2.approve(address(pool), type(uint256).max);
|
||||
|
||||
// Snapshot pool totals (simple value metric = sum of token uint balances since base==1 in tests)
|
||||
address[] memory toks = pool.allTokens();
|
||||
IERC20[] memory toks = pool.allTokens();
|
||||
uint256 n = toks.length;
|
||||
uint256 poolValueBefore = 0;
|
||||
for (uint i = 0; i < n; i++) {
|
||||
@@ -1210,4 +1210,171 @@ contract PartyPoolTest is Test {
|
||||
pool.flash(alice, wrongLengthAmounts, "");
|
||||
}
|
||||
|
||||
/// @notice Test that passing nonzero lpTokens to initialMint doesn't affect swap results
|
||||
/// compared to pools initialized with default lpTokens (0)
|
||||
function testInitialMintCustomLpTokensDoesNotAffectSwaps() public {
|
||||
// Create two identical pools with different initial LP amounts
|
||||
IERC20[] memory tokens = new IERC20[](3);
|
||||
tokens[0] = IERC20(address(token0));
|
||||
tokens[1] = IERC20(address(token1));
|
||||
tokens[2] = IERC20(address(token2));
|
||||
|
||||
uint256[] memory bases = new uint256[](3);
|
||||
bases[0] = BASE;
|
||||
bases[1] = BASE;
|
||||
bases[2] = BASE;
|
||||
|
||||
uint256 feePpm = 1000;
|
||||
|
||||
// Pool with default initialization (lpTokens = 0)
|
||||
PartyPool poolDefault = new PartyPool("LP_DEFAULT", "LP_DEFAULT", tokens, bases, tradeFrac, targetSlippage, feePpm, feePpm, false);
|
||||
|
||||
// Pool with custom initialization (lpTokens = custom amount)
|
||||
PartyPool poolCustom = new PartyPool("LP_CUSTOM", "LP_CUSTOM", tokens, bases, tradeFrac, targetSlippage, feePpm, feePpm, false);
|
||||
|
||||
// Mint additional tokens for both pools
|
||||
token0.mint(address(this), INIT_BAL * 2);
|
||||
token1.mint(address(this), INIT_BAL * 2);
|
||||
token2.mint(address(this), INIT_BAL * 2);
|
||||
|
||||
// Transfer identical amounts to both pools
|
||||
token0.transfer(address(poolDefault), INIT_BAL);
|
||||
token1.transfer(address(poolDefault), INIT_BAL);
|
||||
token2.transfer(address(poolDefault), INIT_BAL);
|
||||
|
||||
token0.transfer(address(poolCustom), INIT_BAL);
|
||||
token1.transfer(address(poolCustom), INIT_BAL);
|
||||
token2.transfer(address(poolCustom), INIT_BAL);
|
||||
|
||||
// Initialize poolDefault with lpTokens = 0 (default behavior)
|
||||
uint256 lpDefault = poolDefault.initialMint(address(this), 0);
|
||||
|
||||
// Initialize poolCustom with custom lpTokens amount (5x the default)
|
||||
uint256 customLpAmount = lpDefault * 5;
|
||||
uint256 lpCustom = poolCustom.initialMint(address(this), customLpAmount);
|
||||
|
||||
// Verify the custom pool has the expected LP supply
|
||||
assertEq(lpCustom, customLpAmount, "Custom pool should have expected LP amount");
|
||||
assertEq(poolCustom.totalSupply(), customLpAmount, "Custom pool total supply should match");
|
||||
|
||||
// Both pools should have identical token balances
|
||||
assertEq(token0.balanceOf(address(poolDefault)), token0.balanceOf(address(poolCustom)), "Token0 balances should match");
|
||||
assertEq(token1.balanceOf(address(poolDefault)), token1.balanceOf(address(poolCustom)), "Token1 balances should match");
|
||||
assertEq(token2.balanceOf(address(poolDefault)), token2.balanceOf(address(poolCustom)), "Token2 balances should match");
|
||||
|
||||
// Prepare Alice for swapping
|
||||
token0.mint(alice, INIT_BAL);
|
||||
token1.mint(alice, INIT_BAL);
|
||||
|
||||
// Test identical swaps produce identical results
|
||||
uint256 swapAmount = 10_000;
|
||||
|
||||
vm.startPrank(alice);
|
||||
token0.approve(address(poolDefault), type(uint256).max);
|
||||
token0.approve(address(poolCustom), type(uint256).max);
|
||||
|
||||
// Perform identical swaps: token0 -> token1
|
||||
(uint256 amountInDefault, uint256 amountOutDefault, uint256 feeDefault) = poolDefault.swap(alice, alice, 0, 1, swapAmount, 0, 0);
|
||||
(uint256 amountInCustom, uint256 amountOutCustom, uint256 feeCustom) = poolCustom.swap(alice, alice, 0, 1, swapAmount, 0, 0);
|
||||
|
||||
// Swap results should be identical
|
||||
assertEq(amountInDefault, amountInCustom, "Swap input amounts should be identical");
|
||||
assertEq(amountOutDefault, amountOutCustom, "Swap output amounts should be identical");
|
||||
assertEq(feeDefault, feeCustom, "Swap fees should be identical");
|
||||
|
||||
vm.stopPrank();
|
||||
}
|
||||
|
||||
/// @notice Test that minting the same proportion in pools with different initial LP amounts
|
||||
/// returns correctly scaled LP tokens
|
||||
function testProportionalMintingScaledByInitialAmount() public {
|
||||
// Create two identical pools with different initial LP amounts
|
||||
IERC20[] memory tokens = new IERC20[](3);
|
||||
tokens[0] = IERC20(address(token0));
|
||||
tokens[1] = IERC20(address(token1));
|
||||
tokens[2] = IERC20(address(token2));
|
||||
|
||||
uint256[] memory bases = new uint256[](3);
|
||||
bases[0] = BASE;
|
||||
bases[1] = BASE;
|
||||
bases[2] = BASE;
|
||||
|
||||
uint256 feePpm = 1000;
|
||||
|
||||
PartyPool poolDefault = new PartyPool("LP_DEFAULT", "LP_DEFAULT", tokens, bases, tradeFrac, targetSlippage, feePpm, feePpm, false);
|
||||
PartyPool poolCustom = new PartyPool("LP_CUSTOM", "LP_CUSTOM", tokens, bases, tradeFrac, targetSlippage, feePpm, feePpm, false);
|
||||
|
||||
// Mint additional tokens
|
||||
token0.mint(address(this), INIT_BAL * 4);
|
||||
token1.mint(address(this), INIT_BAL * 4);
|
||||
token2.mint(address(this), INIT_BAL * 4);
|
||||
|
||||
// Transfer identical amounts to both pools
|
||||
token0.transfer(address(poolDefault), INIT_BAL);
|
||||
token1.transfer(address(poolDefault), INIT_BAL);
|
||||
token2.transfer(address(poolDefault), INIT_BAL);
|
||||
|
||||
token0.transfer(address(poolCustom), INIT_BAL);
|
||||
token1.transfer(address(poolCustom), INIT_BAL);
|
||||
token2.transfer(address(poolCustom), INIT_BAL);
|
||||
|
||||
// Initialize pools with different LP amounts
|
||||
uint256 lpDefault = poolDefault.initialMint(address(this), 0);
|
||||
uint256 scaleFactor = 3;
|
||||
uint256 customLpAmount = lpDefault * scaleFactor;
|
||||
uint256 lpCustom = poolCustom.initialMint(address(this), customLpAmount);
|
||||
|
||||
// Verify initial LP supplies
|
||||
assertEq(poolDefault.totalSupply(), lpDefault, "Default pool should have default LP supply");
|
||||
assertEq(poolCustom.totalSupply(), customLpAmount, "Custom pool should have custom LP supply");
|
||||
|
||||
// Prepare Alice for minting
|
||||
token0.mint(alice, INIT_BAL * 2);
|
||||
token1.mint(alice, INIT_BAL * 2);
|
||||
token2.mint(alice, INIT_BAL * 2);
|
||||
|
||||
// Test proportional minting: mint 10% of each pool's supply
|
||||
uint256 mintPercentage = 10; // 10%
|
||||
uint256 lpRequestDefault = poolDefault.totalSupply() * mintPercentage / 100;
|
||||
uint256 lpRequestCustom = poolCustom.totalSupply() * mintPercentage / 100;
|
||||
|
||||
vm.startPrank(alice);
|
||||
|
||||
// Approve tokens for both pools
|
||||
token0.approve(address(poolDefault), type(uint256).max);
|
||||
token1.approve(address(poolDefault), type(uint256).max);
|
||||
token2.approve(address(poolDefault), type(uint256).max);
|
||||
token0.approve(address(poolCustom), type(uint256).max);
|
||||
token1.approve(address(poolCustom), type(uint256).max);
|
||||
token2.approve(address(poolCustom), type(uint256).max);
|
||||
|
||||
// Get required deposit amounts for both pools
|
||||
uint256[] memory depositsDefault = poolDefault.mintDepositAmounts(lpRequestDefault);
|
||||
uint256[] memory depositsCustom = poolCustom.mintDepositAmounts(lpRequestCustom);
|
||||
|
||||
// Deposits should be identical (same proportion of identical balances)
|
||||
assertEq(depositsDefault[0], depositsCustom[0], "Token0 deposits should be identical");
|
||||
assertEq(depositsDefault[1], depositsCustom[1], "Token1 deposits should be identical");
|
||||
assertEq(depositsDefault[2], depositsCustom[2], "Token2 deposits should be identical");
|
||||
|
||||
// Perform the mints
|
||||
uint256 mintedDefault = poolDefault.mint(alice, alice, lpRequestDefault, 0);
|
||||
uint256 mintedCustom = poolCustom.mint(alice, alice, lpRequestCustom, 0);
|
||||
|
||||
// Minted LP amounts should be scaled by the same factor as initial supplies
|
||||
uint256 expectedRatio = (mintedCustom * 1000) / mintedDefault; // Use fixed point for precision
|
||||
uint256 actualRatio = (scaleFactor * 1000);
|
||||
|
||||
// Allow small rounding differences (within 0.1%)
|
||||
uint256 tolerance = actualRatio / 1000; // 0.1% tolerance
|
||||
assertTrue(expectedRatio >= actualRatio - tolerance && expectedRatio <= actualRatio + tolerance,
|
||||
"Minted LP ratio should match scale factor within tolerance");
|
||||
|
||||
// Verify Alice received the expected LP amounts
|
||||
assertTrue(poolDefault.balanceOf(alice) >= mintedDefault, "Alice should receive default LP");
|
||||
assertTrue(poolCustom.balanceOf(alice) >= mintedCustom, "Alice should receive custom LP");
|
||||
|
||||
vm.stopPrank();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user