computed bases

This commit is contained in:
tim
2025-10-25 18:18:18 -04:00
parent 2972152e58
commit ba08da2fca
14 changed files with 93 additions and 98 deletions

View File

@@ -7,7 +7,6 @@ import numpy as np
log = logging.getLogger(__name__)
LMSR_FEE = 0.0025
# UNISWAP_GAS=0
# LMSR_GAS=0
UNISWAP_GAS=115_000
@@ -180,31 +179,66 @@ def lmsr_marginal_price(balances, base_index, quote_index, kappa):
def compare(file, tvl, kappa):
def compare(file, tvl, fee, kappa):
d = pd.read_csv(file)
d.columns = ['block', 'price0', 'price1', 'in0', 'out0', 'rate']
# Calibrate LMSR balances so that exp((q1 - q0)/b) equals the initial price
# New approach: derive bases from initial external balances (assuming equal-valued deposits)
# This matches the Solidity implementation and eliminates the κ·ln(price) constraint
p0 = float(d.iloc[0].price0)
S = float(tvl) # choose the LMSR size metric
b = kappa * S
delta = b * math.log(p0) # q1 - q0
q0 = 0.5 * (S - delta)
q1 = 0.5 * (S + delta)
if q0 <= 0.0 or q1 <= 0.0:
raise ValueError("Invalid LMSR calibration: choose kappa such that kappa * ln(price0) < 1.")
# Set external balances assuming equal values: if token0 = B0 and token1 = B1,
# and they have equal value, then B0 * price0 = B1 * price1 = V (value per asset)
# For simplicity, choose B0 such that the total value is tvl, then B1 = B0 * price0
total_value = float(tvl)
# Since B0 * price0 + B1 = total_value and B1 = B0 * price0, we get:
# B0 * price0 + B0 * price0 = total_value, so B0 = total_value / (2 * price0)
B0 = total_value / (2.0 * p0) # external balance of token 0
B1 = B0 * p0 # external balance of token 1 (equal value)
external_balances = [B0, B1]
# Derive bases: set base_i = B_i so that q_i = B_i / base_i = 1.0 internally
bases = [B0, B1]
# Internal balances: q_i = external_balance_i / base_i ≈ 1.0
q0 = B0 / bases[0] # ≈ 1.0
q1 = B1 / bases[1] # ≈ 1.0
balances = [q0, q1]
print(balances)
print(f"External balances: {external_balances}")
print(f"Bases: {bases}")
print(f"Internal balances: {balances}")
# Convert external input amounts to internal for LMSR calculations, then convert results back
X = np.geomspace(1, 1_000_000, 100)
orig_price = lmsr_marginal_price(balances, 0, 1, kappa)
in_out = [(float(amount_in), lmsr_swap_amount_out(balances, float(amount_in), 0, 1, LMSR_FEE, kappa)) for amount_in in X]
print(in_out)
# Convert X to internal amounts, compute swap, then convert back to external
in_out = []
for amount_in_external in X:
# Convert external input to internal units
amount_in_internal = amount_in_external / bases[0] # input token 0
# Compute swap in internal units
amount_out_internal = lmsr_swap_amount_out(balances, amount_in_internal, 0, 1, fee, kappa)
# Convert output back to external units
amount_out_external = amount_out_internal * bases[1] # output token 1
in_out.append((float(amount_in_external), float(amount_out_external)))
print(f"Sample internal/external conversions: {in_out[:3]}")
# Compute initial marginal price in external units
# Internal price is exp((q1 - q0)/b), external price needs conversion by bases[1]/bases[0]
orig_price_external = orig_price * (bases[1] / bases[0])
# Relative execution price deviation from the initial marginal price:
# slippage = |(amount_out/amount_in)/orig_price - 1|
# slippage = |(amount_out/amount_in)/orig_price_external - 1|
eps = 1e-12
Y = [max(eps, abs((amount_out / amount_in) / orig_price - 1.0))
Y = [max(eps, abs((amount_out / amount_in) / orig_price_external - 1.0))
for amount_in, amount_out in in_out]
plt.plot(X, Y, label=f'LMSR {LMSR_FEE:.2%} κ={kappa:.2f}', color='cornflowerblue')
plt.plot(X, Y, label=f'LMSR {fee:.2%} κ={kappa:.2g}', color='cornflowerblue')
# Uniswap execution price deviation from its initial quoted price:
# slippage = |(out/in)/initial_price - 1|
@@ -257,6 +291,6 @@ def plot_kappa():
if __name__ == '__main__':
# compare('uni4_quotes/swap_results_block_23640998.csv')
# compare('uni4_quotes/ETH-USDC-30.csv', 53_000_000, 0.1)
compare('uni4_quotes/ETH-USDC-30.csv', 1_00_000, .1)
compare('uni4_quotes/ETH-USDC-30.csv', 53_000_000, 0.0025, 0.00025)
# compare('uni4_quotes/ETH-USDC-30.csv', 100_000, 0.0025, 0.00025)
# plot_kappa()

View File

@@ -67,7 +67,6 @@ contract DeployMock is Script {
'Token Pool',
'TP',
tokens,
_bases,
ABDKMath64x64.divu(1, 10),
ABDKMath64x64.divu(1,10000),
_feePpm,
@@ -112,7 +111,6 @@ contract DeployMock is Script {
'Stablecoin Pool',
'STAP',
IERC20[](tokens),
_bases,
ABDKMath64x64.divu(1, 10),
ABDKMath64x64.divu(1,10000),
_feePpm,
@@ -154,7 +152,6 @@ contract DeployMock is Script {
'Stable Pair',
'SPAIR',
IERC20[](tokens),
_bases,
ABDKMath64x64.divu(8,10), // kappa = 0.8
_feePpm,
_feePpm,

View File

@@ -76,7 +76,6 @@ contract DeploySepolia is Script {
'Token Pool',
'TP',
tokens,
_bases,
ABDKMath64x64.divu(1, 10),
ABDKMath64x64.divu(1,10000),
_feePpm,
@@ -121,7 +120,6 @@ contract DeploySepolia is Script {
'Stablecoin Pool',
'STAP',
tokens,
_bases,
ABDKMath64x64.divu(1, 10),
ABDKMath64x64.divu(1,10000),
_feePpm,
@@ -163,7 +161,6 @@ contract DeploySepolia is Script {
'Stable Pair',
'SPAIR',
tokens,
_bases,
ABDKMath64x64.divu(8,10), // kappa = 0.8
_feePpm,
_feePpm,

View File

@@ -18,7 +18,6 @@ interface IPartyPlanner is IOwnable {
/// @param name LP token name
/// @param symbol LP token symbol
/// @param tokens token addresses (n)
/// @param bases scaling bases for each token (n) - used when converting to/from internal 64.64 amounts
/// @param tradeFrac trade fraction in 64.64 fixed-point (as used by LMSR)
/// @param targetSlippage target slippage in 64.64 fixed-point (as used by LMSR)
/// @param swapFeePpm fee in parts-per-million, taken from swap input amounts before LMSR calculations
@@ -35,7 +34,6 @@ interface IPartyPlanner is IOwnable {
string memory name,
string memory symbol,
IERC20[] memory tokens,
uint256[] memory bases,
int128 tradeFrac,
int128 targetSlippage,
uint256 swapFeePpm,
@@ -53,7 +51,6 @@ interface IPartyPlanner is IOwnable {
/// @param name LP token name
/// @param symbol LP token symbol
/// @param tokens token addresses (n)
/// @param bases scaling bases for each token (n) - used when converting to/from internal 64.64 amounts
/// @param kappa liquidity parameter κ in 64.64 fixed-point used to derive b = κ * S(q)
/// @param swapFeePpm fee in parts-per-million, taken from swap input amounts before LMSR calculations
/// @param flashFeePpm fee in parts-per-million, taken for flash loans
@@ -69,7 +66,6 @@ interface IPartyPlanner is IOwnable {
string memory name,
string memory symbol,
IERC20[] memory tokens,
uint256[] memory bases,
int128 kappa,
uint256 swapFeePpm,
uint256 flashFeePpm,

View File

@@ -87,7 +87,6 @@ contract PartyPlanner is OwnableExternal, IPartyPlanner {
string memory name_,
string memory symbol_,
IERC20[] memory tokens_,
uint256[] memory bases_,
int128 kappa_,
uint256 swapFeePpm_,
uint256 flashFeePpm_,
@@ -115,7 +114,6 @@ contract PartyPlanner is OwnableExternal, IPartyPlanner {
name_,
symbol_,
tokens_,
bases_,
kappa_,
swapFeePpm_,
flashFeePpm_,
@@ -165,7 +163,6 @@ contract PartyPlanner is OwnableExternal, IPartyPlanner {
string memory name_,
string memory symbol_,
IERC20[] memory tokens_,
uint256[] memory bases_,
int128 tradeFrac_,
int128 targetSlippage_,
uint256 swapFeePpm_,
@@ -190,7 +187,6 @@ contract PartyPlanner is OwnableExternal, IPartyPlanner {
name_,
symbol_,
tokens_,
bases_,
computedKappa,
swapFeePpm_,
flashFeePpm_,

View File

@@ -99,7 +99,6 @@ contract PartyPool is PartyPoolBase, OwnableExternal, ERC20External, IPartyPool
/// @param name_ LP token name
/// @param symbol_ LP token symbol
/// @param tokens_ token addresses (n)
/// @param bases_ scaling _bases for each token (n) - used when converting to/from internal 64.64 amounts
/// @param kappa_ liquidity parameter κ (Q64.64) used to derive b = κ * S(q)
/// @param swapFeePpm_ fee in parts-per-million, taken from swap input amounts before LMSR calculations
/// @param flashFeePpm_ fee in parts-per-million, taken for flash loans
@@ -110,7 +109,6 @@ contract PartyPool is PartyPoolBase, OwnableExternal, ERC20External, IPartyPool
string memory name_,
string memory symbol_,
IERC20[] memory tokens_,
uint256[] memory bases_,
int128 kappa_,
uint256 swapFeePpm_,
uint256 flashFeePpm_,
@@ -126,9 +124,7 @@ contract PartyPool is PartyPoolBase, OwnableExternal, ERC20External, IPartyPool
{
require(owner_ != address(0));
require(tokens_.length > 1, "Pool: need >1 asset");
require(tokens_.length == bases_.length, "Pool: lengths mismatch");
_tokens = tokens_;
_bases = bases_;
KAPPA = kappa_;
require(swapFeePpm_ < 1_000_000, "Pool: fee >= ppm");
SWAP_FEE_PPM = swapFeePpm_;
@@ -153,6 +149,9 @@ contract PartyPool is PartyPoolBase, OwnableExternal, ERC20External, IPartyPool
unchecked {i++;}
}
// Allocate denominators (bases) to be computed during initialMint from initial deposits
_bases = new uint256[](n);
// Initialize caches to zero and protocol ledger
_cachedUintBalances = new uint256[](n);
_protocolFeesOwed = new uint256[](n);

View File

@@ -15,7 +15,6 @@ contract PartyPoolBalancedPair is PartyPool {
string memory name_,
string memory symbol_,
IERC20[] memory tokens_,
uint256[] memory bases_,
int128 kappa_,
uint256 swapFeePpm_,
uint256 flashFeePpm_,
@@ -25,7 +24,7 @@ contract PartyPoolBalancedPair is PartyPool {
PartyPoolSwapImpl swapMintImpl_,
PartyPoolMintImpl mintImpl_
)
PartyPool(owner_, name_, symbol_, tokens_, bases_, kappa_, swapFeePpm_, flashFeePpm_, protocolFeePpm_, protocolFeeAddress_, wrapperToken_, swapMintImpl_, mintImpl_)
PartyPool(owner_, name_, symbol_, tokens_, kappa_, swapFeePpm_, flashFeePpm_, protocolFeePpm_, protocolFeeAddress_, wrapperToken_, swapMintImpl_, mintImpl_)
{}
function _swapAmountsForExactInput(uint256 i, uint256 j, int128 a, int128 limitPrice) internal virtual override view

View File

@@ -15,7 +15,6 @@ interface IPartyPoolDeployer {
string memory name_,
string memory symbol_,
IERC20[] memory tokens_,
uint256[] memory bases_,
int128 kappa_,
uint256 swapFeePpm_,
uint256 flashFeePpm_,
@@ -33,7 +32,6 @@ contract PartyPoolDeployer is IPartyPoolDeployer {
string memory name_,
string memory symbol_,
IERC20[] memory tokens_,
uint256[] memory bases_,
int128 kappa_,
uint256 swapFeePpm_,
uint256 flashFeePpm_,
@@ -48,7 +46,6 @@ contract PartyPoolDeployer is IPartyPoolDeployer {
name_,
symbol_,
tokens_,
bases_,
kappa_,
swapFeePpm_,
flashFeePpm_,
@@ -67,7 +64,6 @@ contract PartyPoolBalancedPairDeployer is IPartyPoolDeployer {
string memory name_,
string memory symbol_,
IERC20[] memory tokens_,
uint256[] memory bases_,
int128 kappa_,
uint256 swapFeePpm_,
uint256 flashFeePpm_,
@@ -82,7 +78,6 @@ contract PartyPoolBalancedPairDeployer is IPartyPoolDeployer {
name_,
symbol_,
tokens_,
bases_,
kappa_,
swapFeePpm_,
flashFeePpm_,

View File

@@ -33,30 +33,38 @@ contract PartyPoolMintImpl is PartyPoolBase {
bool isInitialDeposit = _totalSupply == 0 || _lmsr.nAssets == 0;
require(isInitialDeposit, "initialMint: pool already initialized");
// Update cached balances for all assets
// Read initial on-chain balances, require all > 0, and compute denominators (bases) from deposits.
// We assume equal-valued deposits; set base[i] = depositAmount so internal q_i starts at 1.0.
int128[] memory newQInternal = new int128[](n);
uint256[] memory depositAmounts = new uint256[](n);
for (uint i = 0; i < n; ) {
uint256 bal = IERC20(_tokens[i]).balanceOf(address(this));
_cachedUintBalances[i] = bal;
newQInternal[i] = _uintToInternalFloor(bal, _bases[i]);
require(bal > 0, "initialMint: zero initial balance");
depositAmounts[i] = bal;
// Cache external balances
_cachedUintBalances[i] = bal;
// Set per-asset denominator to the observed deposit amount (at least 1)
_bases[i] = bal;
// Compute internal q_i = bal / base_i => ~1.0 in 64.64
newQInternal[i] = _uintToInternalFloor(bal, _bases[i]);
require(newQInternal[i] > int128(0), "initialMint: zero internal q");
unchecked { i++; }
}
// Initialize the stabilized LMSR state with provided kappa
_lmsr.init(newQInternal, KAPPA);
// Compute actual LP _tokens to mint based on size metric (scaled)
if( lpTokens != 0 )
lpMinted = lpTokens;
else {
int128 newTotal = _computeSizeMetric(newQInternal);
lpMinted = ABDKMath64x64.mulu(newTotal, LP_SCALE);
}
// Obey the passed-in initial LP amount. If 0, default to 1e18
lpMinted = lpTokens == 0 ? 1e18 : lpTokens;
require(lpMinted > 0, "initialMint: zero LP amount");
_mint(receiver, lpMinted);
if (lpMinted > 0) {
_mint(receiver, lpMinted);
}
emit IPartyPool.Mint(address(0), receiver, depositAmounts, lpMinted);
}

View File

@@ -44,14 +44,13 @@ library Deploy {
string memory name_,
string memory symbol_,
IERC20[] memory tokens_,
uint256[] memory bases_,
int128 _kappa,
uint256 _swapFeePpm,
uint256 _flashFeePpm,
bool _stable
) internal returns (PartyPool) {
NativeWrapper wrapper = new WETH9();
return newPartyPool(owner_, name_, symbol_, tokens_, bases_, _kappa, _swapFeePpm, _flashFeePpm, wrapper, _stable);
return newPartyPool(owner_, name_, symbol_, tokens_, _kappa, _swapFeePpm, _flashFeePpm, wrapper, _stable);
}
function newPartyPool(
@@ -59,7 +58,6 @@ library Deploy {
string memory name_,
string memory symbol_,
IERC20[] memory tokens_,
uint256[] memory bases_,
int128 _kappa,
uint256 _swapFeePpm,
uint256 _flashFeePpm,
@@ -72,7 +70,6 @@ library Deploy {
name_,
symbol_,
tokens_,
bases_,
_kappa,
_swapFeePpm,
_flashFeePpm,
@@ -87,7 +84,6 @@ library Deploy {
name_,
symbol_,
tokens_,
bases_,
_kappa,
_swapFeePpm,
_flashFeePpm,

View File

@@ -141,7 +141,7 @@ contract GasTest is Test {
}
// Compute kappa from slippage params and number of _tokens, then construct pool with kappa
int128 computedKappa = LMSRStabilized.computeKappaFromSlippage(ierc20Tokens.length, tradeFrac, targetSlippage);
PartyPool newPool = Deploy.newPartyPool(address(this), poolName, poolName, ierc20Tokens, bases, computedKappa, feePpm, feePpm, false);
PartyPool newPool = Deploy.newPartyPool(address(this), poolName, poolName, ierc20Tokens, computedKappa, feePpm, feePpm, false);
// Transfer initial deposit amounts into pool before initial mint
for (uint256 i = 0; i < numTokens; i++) {
@@ -181,7 +181,7 @@ contract GasTest is Test {
ierc20Tokens[i] = IERC20(tokens[i]);
}
int128 computedKappa = LMSRStabilized.computeKappaFromSlippage(ierc20Tokens.length, tradeFrac, targetSlippage);
PartyPool newPool = Deploy.newPartyPool(address(this), poolName, poolName, ierc20Tokens, bases, computedKappa, feePpm, feePpm, true);
PartyPool newPool = Deploy.newPartyPool(address(this), poolName, poolName, ierc20Tokens, computedKappa, feePpm, feePpm, true);
// Transfer initial deposit amounts into pool before initial mint
for (uint256 i = 0; i < numTokens; i++) {

View File

@@ -94,7 +94,7 @@ contract NativeTest is Test {
uint256 feePpm = 1000;
int128 kappa = LMSRStabilized.computeKappaFromSlippage(tokens.length, tradeFrac, targetSlippage);
pool = Deploy.newPartyPool(address(this), "LP", "LP", tokens, bases, kappa, feePpm, feePpm, weth, false);
pool = Deploy.newPartyPool(address(this), "LP", "LP", tokens, kappa, feePpm, feePpm, weth, false);
// Transfer initial deposit amounts into pool
token0.transfer(address(pool), INIT_BAL);

View File

@@ -100,7 +100,6 @@ contract PartyPlannerTest is Test {
name,
symbol,
tokens,
bases,
computedKappa,
swapFeePpm,
flashFeePpm,
@@ -176,7 +175,7 @@ contract PartyPlannerTest is Test {
int128 kappa1 = LMSRStabilized.computeKappaFromSlippage(tokens1.length, int128((1 << 64) - 1), int128(1 << 62));
(IPartyPool pool1,) = planner.newPool(
"Pool 1", "LP1", tokens1, bases1,
"Pool 1", "LP1", tokens1,
kappa1, 3000, 5000, false,
payer, receiver, deposits1, 1000e18, 0
);
@@ -196,7 +195,7 @@ contract PartyPlannerTest is Test {
int128 kappa2 = LMSRStabilized.computeKappaFromSlippage(tokens2.length, int128((1 << 64) - 1), int128(1 << 62));
(IPartyPool pool2,) = planner.newPool(
"Pool 2", "LP2", tokens2, bases2,
"Pool 2", "LP2", tokens2,
kappa2, 3000, 5000, false,
payer, receiver, deposits2, 1000e18, 0
);
@@ -240,7 +239,7 @@ contract PartyPlannerTest is Test {
vm.expectRevert("Planner: tokens and deposits length mismatch");
// call old-signature convenience (it will still exist) for the mismatched-length revert check
planner.newPool(
"Test Pool", "TESTLP", tokens, bases,
"Test Pool", "TESTLP", tokens,
int128((1 << 64) - 1), int128(1 << 62), 3000, 5000, false,
payer, receiver, deposits, 1000e18, 0
);
@@ -254,7 +253,7 @@ contract PartyPlannerTest is Test {
vm.expectRevert("Planner: payer cannot be zero address");
planner.newPool(
"Test Pool", "TESTLP", tokens, bases,
"Test Pool", "TESTLP", tokens,
kappaErr, 3000, 5000, false,
address(0), receiver, validDeposits, 1000e18, 0
);
@@ -262,7 +261,7 @@ contract PartyPlannerTest is Test {
// Test zero receiver address
vm.expectRevert("Planner: receiver cannot be zero address");
planner.newPool(
"Test Pool", "TESTLP", tokens, bases,
"Test Pool", "TESTLP", tokens,
kappaErr, 3000, 5000, false,
payer, address(0), validDeposits, 1000e18, 0
);
@@ -273,7 +272,7 @@ contract PartyPlannerTest is Test {
vm.warp(1000);
vm.expectRevert("Planner: deadline exceeded");
planner.newPool(
"Test Pool", "TESTLP", tokens, bases,
"Test Pool", "TESTLP", tokens,
kappaDeadline, 3000, 5000, false,
payer, receiver, validDeposits, 1000e18, block.timestamp - 1
);
@@ -301,7 +300,7 @@ contract PartyPlannerTest is Test {
(IPartyPool pool,) = planner.newPool(
string(abi.encodePacked("Pool ", vm.toString(i))),
string(abi.encodePacked("LP", vm.toString(i))),
tokens, bases,
tokens,
kappaLoop, 3000, 5000, false,
payer, receiver, deposits, 1000e18, 0
);

View File

@@ -123,7 +123,6 @@ contract PartyPoolTest is Test {
int128 targetSlippage;
uint256 constant INIT_BAL = 1_000_000; // initial token units for each token (internal==amount when base==1)
uint256 constant BASE = 1; // use base=1 so internal amounts correspond to raw integers (Q64.64 units)
function setUp() public {
planner = Deploy.newPartyPlanner();
@@ -164,16 +163,11 @@ contract PartyPoolTest is Test {
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;
// Deploy pool with a small fee to test fee-handling paths (use 1000 ppm = 0.1%)
uint256 feePpm = 1000;
int128 kappa3 = LMSRStabilized.computeKappaFromSlippage(tokens.length, tradeFrac, targetSlippage);
pool = Deploy.newPartyPool(address(this), "LP", "LP", tokens, bases, kappa3, feePpm, feePpm, false);
pool = Deploy.newPartyPool(address(this), "LP", "LP", tokens, kappa3, feePpm, feePpm, false);
// Transfer initial deposit amounts into pool before initial mint (pool expects _tokens already in contract)
// We deposit equal amounts INIT_BAL for each token
@@ -197,13 +191,8 @@ contract PartyPoolTest is Test {
tokens10[8] = IERC20(address(token8));
tokens10[9] = IERC20(address(token9));
uint256[] memory bases10 = new uint256[](10);
for (uint i = 0; i < 10; i++) {
bases10[i] = BASE;
}
int128 kappa10 = LMSRStabilized.computeKappaFromSlippage(tokens10.length, tradeFrac, targetSlippage);
pool10 = Deploy.newPartyPool(address(this), "LP10", "LP10", tokens10, bases10, kappa10, feePpm, feePpm, false);
pool10 = Deploy.newPartyPool(address(this), "LP10", "LP10", tokens10, kappa10, feePpm, feePpm, false);
// Mint additional _tokens for pool10 initial deposit
token0.mint(address(this), INIT_BAL);
@@ -983,20 +972,15 @@ contract PartyPoolTest is Test {
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)
int128 kappaDefault = LMSRStabilized.computeKappaFromSlippage(tokens.length, tradeFrac, targetSlippage);
PartyPool poolDefault = Deploy.newPartyPool(address(this), "LP_DEFAULT", "LP_DEFAULT", tokens, bases, kappaDefault, feePpm, feePpm, false);
PartyPool poolDefault = Deploy.newPartyPool(address(this), "LP_DEFAULT", "LP_DEFAULT", tokens, kappaDefault, feePpm, feePpm, false);
// Pool with custom initialization (lpTokens = custom amount)
int128 kappaCustom = LMSRStabilized.computeKappaFromSlippage(tokens.length, tradeFrac, targetSlippage);
PartyPool poolCustom = Deploy.newPartyPool(address(this), "LP_CUSTOM", "LP_CUSTOM", tokens, bases, kappaCustom, feePpm, feePpm, false);
PartyPool poolCustom = Deploy.newPartyPool(address(this), "LP_CUSTOM", "LP_CUSTOM", tokens, kappaCustom, feePpm, feePpm, false);
// Mint additional _tokens for both pools
token0.mint(address(this), INIT_BAL * 2);
@@ -1060,17 +1044,12 @@ contract PartyPoolTest is Test {
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;
int128 kappaDefault2 = LMSRStabilized.computeKappaFromSlippage(tokens.length, tradeFrac, targetSlippage);
PartyPool poolDefault = Deploy.newPartyPool(address(this), "LP_DEFAULT", "LP_DEFAULT", tokens, bases, kappaDefault2, feePpm, feePpm, false);
PartyPool poolDefault = Deploy.newPartyPool(address(this), "LP_DEFAULT", "LP_DEFAULT", tokens, kappaDefault2, feePpm, feePpm, false);
int128 kappaCustom2 = LMSRStabilized.computeKappaFromSlippage(tokens.length, tradeFrac, targetSlippage);
PartyPool poolCustom = Deploy.newPartyPool(address(this), "LP_CUSTOM", "LP_CUSTOM", tokens, bases, kappaCustom2, feePpm, feePpm, false);
PartyPool poolCustom = Deploy.newPartyPool(address(this), "LP_CUSTOM", "LP_CUSTOM", tokens, kappaCustom2, feePpm, feePpm, false);
// Mint additional _tokens
token0.mint(address(this), INIT_BAL * 4);