balanced pair optimization

This commit is contained in:
tim
2025-09-18 22:16:01 -04:00
parent a96b494cef
commit 3eba6412a6
7 changed files with 549 additions and 27 deletions

View File

@@ -8,6 +8,7 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "./LMSRStabilized.sol";
import "./LMSRStabilizedBalancedPair.sol";
import "./IPartyPool.sol";
import "./IPartyFlashCallback.sol";
@@ -46,6 +47,7 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
//
LMSRStabilized.State internal lmsr;
bool immutable private _stablePair; // if true, the optimized LMSRStabilizedBalancedPair optimization path is enabled
// Cached on-chain balances (uint) and internal 64.64 representation
// balance / base = internal
@@ -65,6 +67,7 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
/// @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 _flashFeePpm fee in parts-per-million, taken for flash loans
/// @param _stable if true and assets.length==2, then the optimization for 2-asset stablecoin pools is activated.
constructor(
string memory name_,
string memory symbol_,
@@ -73,7 +76,8 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
int128 _tradeFrac,
int128 _targetSlippage,
uint256 _swapFeePpm,
uint256 _flashFeePpm
uint256 _flashFeePpm,
bool _stable
) ERC20(name_, symbol_) {
require(_tokens.length > 1, "Pool: need >1 asset");
require(_tokens.length == _bases.length, "Pool: lengths mismatch");
@@ -85,6 +89,7 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
swapFeePpm = _swapFeePpm;
require(_flashFeePpm < 1_000_000, "Pool: flash fee >= ppm");
flashFeePpm = _flashFeePpm;
_stablePair = _stable && _tokens.length == 2;
uint256 n = _tokens.length;
@@ -369,7 +374,11 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
require(deltaInternalI > int128(0), "swap: input too small after fee");
// Compute internal amounts using LMSR (exact-input with price limit)
(amountInInternalUsed, amountOutInternal) = lmsr.swapAmountsForExactInput(i, j, deltaInternalI, limitPrice);
// if _stablePair is true, use the optimized path
console2.log('stablepair optimization?', _stablePair);
(amountInInternalUsed, amountOutInternal) =
_stablePair ? LMSRStabilizedBalancedPair.swapAmountsForExactInput(lmsr, i, j, deltaInternalI, limitPrice)
: lmsr.swapAmountsForExactInput(i, j, deltaInternalI, limitPrice);
// Convert actual used input internal -> uint (ceil)
amountInUintNoFee = _internalToUintCeil(amountInInternalUsed, bases[i]);