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__) log = logging.getLogger(__name__)
LMSR_FEE = 0.0025
# UNISWAP_GAS=0 # UNISWAP_GAS=0
# LMSR_GAS=0 # LMSR_GAS=0
UNISWAP_GAS=115_000 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 = pd.read_csv(file)
d.columns = ['block', 'price0', 'price1', 'in0', 'out0', 'rate'] 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) p0 = float(d.iloc[0].price0)
S = float(tvl) # choose the LMSR size metric
b = kappa * S # Set external balances assuming equal values: if token0 = B0 and token1 = B1,
delta = b * math.log(p0) # q1 - q0 # and they have equal value, then B0 * price0 = B1 * price1 = V (value per asset)
q0 = 0.5 * (S - delta) # For simplicity, choose B0 such that the total value is tvl, then B1 = B0 * price0
q1 = 0.5 * (S + delta) total_value = float(tvl)
if q0 <= 0.0 or q1 <= 0.0: # Since B0 * price0 + B1 = total_value and B1 = B0 * price0, we get:
raise ValueError("Invalid LMSR calibration: choose kappa such that kappa * ln(price0) < 1.") # 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] 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) X = np.geomspace(1, 1_000_000, 100)
orig_price = lmsr_marginal_price(balances, 0, 1, kappa) 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: # 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 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] 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: # Uniswap execution price deviation from its initial quoted price:
# slippage = |(out/in)/initial_price - 1| # slippage = |(out/in)/initial_price - 1|
@@ -257,6 +291,6 @@ def plot_kappa():
if __name__ == '__main__': if __name__ == '__main__':
# compare('uni4_quotes/swap_results_block_23640998.csv') # 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', 53_000_000, 0.0025, 0.00025)
compare('uni4_quotes/ETH-USDC-30.csv', 1_00_000, .1) # compare('uni4_quotes/ETH-USDC-30.csv', 100_000, 0.0025, 0.00025)
# plot_kappa() # plot_kappa()

View File

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

View File

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

View File

@@ -18,7 +18,6 @@ interface IPartyPlanner is IOwnable {
/// @param name LP token name /// @param name LP token name
/// @param symbol LP token symbol /// @param symbol LP token symbol
/// @param tokens token addresses (n) /// @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 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 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 /// @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 name,
string memory symbol, string memory symbol,
IERC20[] memory tokens, IERC20[] memory tokens,
uint256[] memory bases,
int128 tradeFrac, int128 tradeFrac,
int128 targetSlippage, int128 targetSlippage,
uint256 swapFeePpm, uint256 swapFeePpm,
@@ -53,7 +51,6 @@ interface IPartyPlanner is IOwnable {
/// @param name LP token name /// @param name LP token name
/// @param symbol LP token symbol /// @param symbol LP token symbol
/// @param tokens token addresses (n) /// @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 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 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 /// @param flashFeePpm fee in parts-per-million, taken for flash loans
@@ -69,7 +66,6 @@ interface IPartyPlanner is IOwnable {
string memory name, string memory name,
string memory symbol, string memory symbol,
IERC20[] memory tokens, IERC20[] memory tokens,
uint256[] memory bases,
int128 kappa, int128 kappa,
uint256 swapFeePpm, uint256 swapFeePpm,
uint256 flashFeePpm, uint256 flashFeePpm,

View File

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

View File

@@ -99,7 +99,6 @@ contract PartyPool is PartyPoolBase, OwnableExternal, ERC20External, IPartyPool
/// @param name_ LP token name /// @param name_ LP token name
/// @param symbol_ LP token symbol /// @param symbol_ LP token symbol
/// @param tokens_ token addresses (n) /// @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 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 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 /// @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 name_,
string memory symbol_, string memory symbol_,
IERC20[] memory tokens_, IERC20[] memory tokens_,
uint256[] memory bases_,
int128 kappa_, int128 kappa_,
uint256 swapFeePpm_, uint256 swapFeePpm_,
uint256 flashFeePpm_, uint256 flashFeePpm_,
@@ -126,9 +124,7 @@ contract PartyPool is PartyPoolBase, OwnableExternal, ERC20External, IPartyPool
{ {
require(owner_ != address(0)); require(owner_ != address(0));
require(tokens_.length > 1, "Pool: need >1 asset"); require(tokens_.length > 1, "Pool: need >1 asset");
require(tokens_.length == bases_.length, "Pool: lengths mismatch");
_tokens = tokens_; _tokens = tokens_;
_bases = bases_;
KAPPA = kappa_; KAPPA = kappa_;
require(swapFeePpm_ < 1_000_000, "Pool: fee >= ppm"); require(swapFeePpm_ < 1_000_000, "Pool: fee >= ppm");
SWAP_FEE_PPM = swapFeePpm_; SWAP_FEE_PPM = swapFeePpm_;
@@ -153,6 +149,9 @@ contract PartyPool is PartyPoolBase, OwnableExternal, ERC20External, IPartyPool
unchecked {i++;} unchecked {i++;}
} }
// Allocate denominators (bases) to be computed during initialMint from initial deposits
_bases = new uint256[](n);
// Initialize caches to zero and protocol ledger // Initialize caches to zero and protocol ledger
_cachedUintBalances = new uint256[](n); _cachedUintBalances = new uint256[](n);
_protocolFeesOwed = new uint256[](n); _protocolFeesOwed = new uint256[](n);

View File

@@ -15,7 +15,6 @@ contract PartyPoolBalancedPair is PartyPool {
string memory name_, string memory name_,
string memory symbol_, string memory symbol_,
IERC20[] memory tokens_, IERC20[] memory tokens_,
uint256[] memory bases_,
int128 kappa_, int128 kappa_,
uint256 swapFeePpm_, uint256 swapFeePpm_,
uint256 flashFeePpm_, uint256 flashFeePpm_,
@@ -25,7 +24,7 @@ contract PartyPoolBalancedPair is PartyPool {
PartyPoolSwapImpl swapMintImpl_, PartyPoolSwapImpl swapMintImpl_,
PartyPoolMintImpl mintImpl_ 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 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 name_,
string memory symbol_, string memory symbol_,
IERC20[] memory tokens_, IERC20[] memory tokens_,
uint256[] memory bases_,
int128 kappa_, int128 kappa_,
uint256 swapFeePpm_, uint256 swapFeePpm_,
uint256 flashFeePpm_, uint256 flashFeePpm_,
@@ -33,7 +32,6 @@ contract PartyPoolDeployer is IPartyPoolDeployer {
string memory name_, string memory name_,
string memory symbol_, string memory symbol_,
IERC20[] memory tokens_, IERC20[] memory tokens_,
uint256[] memory bases_,
int128 kappa_, int128 kappa_,
uint256 swapFeePpm_, uint256 swapFeePpm_,
uint256 flashFeePpm_, uint256 flashFeePpm_,
@@ -48,7 +46,6 @@ contract PartyPoolDeployer is IPartyPoolDeployer {
name_, name_,
symbol_, symbol_,
tokens_, tokens_,
bases_,
kappa_, kappa_,
swapFeePpm_, swapFeePpm_,
flashFeePpm_, flashFeePpm_,
@@ -67,7 +64,6 @@ contract PartyPoolBalancedPairDeployer is IPartyPoolDeployer {
string memory name_, string memory name_,
string memory symbol_, string memory symbol_,
IERC20[] memory tokens_, IERC20[] memory tokens_,
uint256[] memory bases_,
int128 kappa_, int128 kappa_,
uint256 swapFeePpm_, uint256 swapFeePpm_,
uint256 flashFeePpm_, uint256 flashFeePpm_,
@@ -82,7 +78,6 @@ contract PartyPoolBalancedPairDeployer is IPartyPoolDeployer {
name_, name_,
symbol_, symbol_,
tokens_, tokens_,
bases_,
kappa_, kappa_,
swapFeePpm_, swapFeePpm_,
flashFeePpm_, flashFeePpm_,

View File

@@ -33,30 +33,38 @@ contract PartyPoolMintImpl is PartyPoolBase {
bool isInitialDeposit = _totalSupply == 0 || _lmsr.nAssets == 0; bool isInitialDeposit = _totalSupply == 0 || _lmsr.nAssets == 0;
require(isInitialDeposit, "initialMint: pool already initialized"); 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); int128[] memory newQInternal = new int128[](n);
uint256[] memory depositAmounts = new uint256[](n); uint256[] memory depositAmounts = new uint256[](n);
for (uint i = 0; i < n; ) { for (uint i = 0; i < n; ) {
uint256 bal = IERC20(_tokens[i]).balanceOf(address(this)); uint256 bal = IERC20(_tokens[i]).balanceOf(address(this));
_cachedUintBalances[i] = bal; require(bal > 0, "initialMint: zero initial balance");
newQInternal[i] = _uintToInternalFloor(bal, _bases[i]);
depositAmounts[i] = bal; 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++; } unchecked { i++; }
} }
// Initialize the stabilized LMSR state with provided kappa // Initialize the stabilized LMSR state with provided kappa
_lmsr.init(newQInternal, KAPPA); _lmsr.init(newQInternal, KAPPA);
// Compute actual LP _tokens to mint based on size metric (scaled) // Obey the passed-in initial LP amount. If 0, default to 1e18
if( lpTokens != 0 ) lpMinted = lpTokens == 0 ? 1e18 : lpTokens;
lpMinted = lpTokens;
else {
int128 newTotal = _computeSizeMetric(newQInternal);
lpMinted = ABDKMath64x64.mulu(newTotal, LP_SCALE);
}
require(lpMinted > 0, "initialMint: zero LP amount"); if (lpMinted > 0) {
_mint(receiver, lpMinted); _mint(receiver, lpMinted);
}
emit IPartyPool.Mint(address(0), receiver, depositAmounts, lpMinted); emit IPartyPool.Mint(address(0), receiver, depositAmounts, lpMinted);
} }

View File

@@ -44,14 +44,13 @@ library Deploy {
string memory name_, string memory name_,
string memory symbol_, string memory symbol_,
IERC20[] memory tokens_, IERC20[] memory tokens_,
uint256[] memory bases_,
int128 _kappa, int128 _kappa,
uint256 _swapFeePpm, uint256 _swapFeePpm,
uint256 _flashFeePpm, uint256 _flashFeePpm,
bool _stable bool _stable
) internal returns (PartyPool) { ) internal returns (PartyPool) {
NativeWrapper wrapper = new WETH9(); 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( function newPartyPool(
@@ -59,7 +58,6 @@ library Deploy {
string memory name_, string memory name_,
string memory symbol_, string memory symbol_,
IERC20[] memory tokens_, IERC20[] memory tokens_,
uint256[] memory bases_,
int128 _kappa, int128 _kappa,
uint256 _swapFeePpm, uint256 _swapFeePpm,
uint256 _flashFeePpm, uint256 _flashFeePpm,
@@ -72,7 +70,6 @@ library Deploy {
name_, name_,
symbol_, symbol_,
tokens_, tokens_,
bases_,
_kappa, _kappa,
_swapFeePpm, _swapFeePpm,
_flashFeePpm, _flashFeePpm,
@@ -87,7 +84,6 @@ library Deploy {
name_, name_,
symbol_, symbol_,
tokens_, tokens_,
bases_,
_kappa, _kappa,
_swapFeePpm, _swapFeePpm,
_flashFeePpm, _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 // Compute kappa from slippage params and number of _tokens, then construct pool with kappa
int128 computedKappa = LMSRStabilized.computeKappaFromSlippage(ierc20Tokens.length, tradeFrac, targetSlippage); 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 // Transfer initial deposit amounts into pool before initial mint
for (uint256 i = 0; i < numTokens; i++) { for (uint256 i = 0; i < numTokens; i++) {
@@ -181,7 +181,7 @@ contract GasTest is Test {
ierc20Tokens[i] = IERC20(tokens[i]); ierc20Tokens[i] = IERC20(tokens[i]);
} }
int128 computedKappa = LMSRStabilized.computeKappaFromSlippage(ierc20Tokens.length, tradeFrac, targetSlippage); 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 // Transfer initial deposit amounts into pool before initial mint
for (uint256 i = 0; i < numTokens; i++) { for (uint256 i = 0; i < numTokens; i++) {

View File

@@ -94,7 +94,7 @@ contract NativeTest is Test {
uint256 feePpm = 1000; uint256 feePpm = 1000;
int128 kappa = LMSRStabilized.computeKappaFromSlippage(tokens.length, tradeFrac, targetSlippage); 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 // Transfer initial deposit amounts into pool
token0.transfer(address(pool), INIT_BAL); token0.transfer(address(pool), INIT_BAL);

View File

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

View File

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