linted
This commit is contained in:
@@ -12,6 +12,7 @@ import "./IPartyPool.sol";
|
||||
import "./IPartyFlashCallback.sol";
|
||||
import "./PartyPoolBase.sol";
|
||||
import {PartyPoolSwapMintImpl} from "./PartyPoolSwapMintImpl.sol";
|
||||
import {PartyPoolMintImpl} from "./PartyPoolMintImpl.sol";
|
||||
|
||||
/// @title PartyPool - LMSR-backed multi-asset pool with LP ERC20 token
|
||||
/// @notice A multi-asset liquidity pool backed by the LMSRStabilized pricing model.
|
||||
@@ -34,22 +35,28 @@ contract PartyPool is PartyPoolBase, IPartyPool {
|
||||
/// @notice Liquidity parameter κ (Q64.64) used by the LMSR kernel: b = κ * S(q)
|
||||
/// @dev Pool is constructed with a fixed κ. Clients that previously passed tradeFrac/targetSlippage
|
||||
/// should use LMSRStabilized.computeKappaFromSlippage(...) to derive κ and pass it here.
|
||||
int128 public immutable kappa; // kappa in Q64.64
|
||||
int128 private immutable KAPPA; // kappa in Q64.64
|
||||
function kappa() external view returns (int128) { return KAPPA; }
|
||||
|
||||
/// @notice Per-swap fee in parts-per-million (ppm). Fee is taken from input amounts before LMSR computations.
|
||||
uint256 public immutable swapFeePpm;
|
||||
uint256 private immutable SWAP_FEE_PPM;
|
||||
function swapFeePpm() external view returns (uint256) { return SWAP_FEE_PPM; }
|
||||
|
||||
/// @notice Flash-loan fee in parts-per-million (ppm) applied to flash borrow amounts.
|
||||
uint256 public immutable flashFeePpm;
|
||||
uint256 private immutable FLASH_FEE_PPM;
|
||||
function flashFeePpm() external view returns (uint256) { return FLASH_FEE_PPM; }
|
||||
|
||||
/// @notice If true and there are exactly two assets, an optimized 2-asset stable-pair path is used for some computations.
|
||||
bool immutable private _stablePair; // if true, the optimized LMSRStabilizedBalancedPair optimization path is enabled
|
||||
|
||||
/// @notice Address of the SwapMint implementation contract for delegatecall
|
||||
address public immutable swapMintImpl;
|
||||
bool immutable private IS_STABLE_PAIR; // if true, the optimized LMSRStabilizedBalancedPair optimization path is enabled
|
||||
|
||||
/// @notice Address of the Mint implementation contract for delegatecall
|
||||
address public immutable mintImpl;
|
||||
PartyPoolMintImpl private immutable MINT_IMPL;
|
||||
function mintImpl() external view returns (PartyPoolMintImpl) { return MINT_IMPL; }
|
||||
|
||||
/// @notice Address of the SwapMint implementation contract for delegatecall
|
||||
PartyPoolSwapMintImpl private immutable SWAP_MINT_IMPL;
|
||||
function swapMintImpl() external view returns (PartyPoolSwapMintImpl) { return SWAP_MINT_IMPL; }
|
||||
|
||||
|
||||
/// @inheritdoc IPartyPool
|
||||
function getToken(uint256 i) external view returns (IERC20) { return tokens[i]; }
|
||||
@@ -67,38 +74,36 @@ contract PartyPool is PartyPoolBase, IPartyPool {
|
||||
/// @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
|
||||
/// @param _stable if true and assets.length==2, then the optimization for 2-asset stablecoin pools is activated.
|
||||
/// @param _swapMintImpl address of the SwapMint implementation contract
|
||||
/// @param _mintImpl address of the Mint implementation contract
|
||||
/// @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
|
||||
/// @param stable_ if true and assets.length==2, then the optimization for 2-asset stablecoin pools is activated.
|
||||
/// @param swapMintImpl_ address of the SwapMint implementation contract
|
||||
/// @param mintImpl_ address of the Mint implementation contract
|
||||
constructor(
|
||||
string memory name_,
|
||||
string memory symbol_,
|
||||
IERC20[] memory tokens_,
|
||||
uint256[] memory bases_,
|
||||
int128 _kappa,
|
||||
uint256 _swapFeePpm,
|
||||
uint256 _flashFeePpm,
|
||||
bool _stable,
|
||||
PartyPoolSwapMintImpl _swapMintImpl,
|
||||
address _mintImpl
|
||||
int128 kappa_,
|
||||
uint256 swapFeePpm_,
|
||||
uint256 flashFeePpm_,
|
||||
bool stable_,
|
||||
PartyPoolSwapMintImpl swapMintImpl_,
|
||||
PartyPoolMintImpl mintImpl_
|
||||
) PartyPoolBase(name_, symbol_) {
|
||||
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");
|
||||
swapFeePpm = _swapFeePpm;
|
||||
require(_flashFeePpm < 1_000_000, "Pool: flash fee >= ppm");
|
||||
flashFeePpm = _flashFeePpm;
|
||||
_stablePair = _stable && tokens_.length == 2;
|
||||
require(address(_swapMintImpl) != address(0), "Pool: swapMintImpl address zero");
|
||||
swapMintImpl = address(_swapMintImpl);
|
||||
require(_mintImpl != address(0), "Pool: mintImpl address zero");
|
||||
mintImpl = _mintImpl;
|
||||
KAPPA = kappa_;
|
||||
require(swapFeePpm_ < 1_000_000, "Pool: fee >= ppm");
|
||||
SWAP_FEE_PPM = swapFeePpm_;
|
||||
require(flashFeePpm_ < 1_000_000, "Pool: flash fee >= ppm");
|
||||
FLASH_FEE_PPM = flashFeePpm_;
|
||||
IS_STABLE_PAIR = stable_ && tokens_.length == 2;
|
||||
SWAP_MINT_IMPL = swapMintImpl_;
|
||||
MINT_IMPL = mintImpl_;
|
||||
|
||||
uint256 n = tokens_.length;
|
||||
|
||||
@@ -175,7 +180,7 @@ contract PartyPool is PartyPoolBase, IPartyPool {
|
||||
}
|
||||
|
||||
// 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)
|
||||
if( lpTokens != 0 )
|
||||
@@ -206,7 +211,7 @@ contract PartyPool is PartyPoolBase, IPartyPool {
|
||||
deadline
|
||||
);
|
||||
|
||||
bytes memory result = Address.functionDelegateCall(mintImpl, data);
|
||||
bytes memory result = Address.functionDelegateCall(address(MINT_IMPL), data);
|
||||
return abi.decode(result, (uint256));
|
||||
}
|
||||
|
||||
@@ -251,7 +256,7 @@ contract PartyPool is PartyPoolBase, IPartyPool {
|
||||
deadline
|
||||
);
|
||||
|
||||
Address.functionDelegateCall(mintImpl, data);
|
||||
Address.functionDelegateCall(address(MINT_IMPL), data);
|
||||
}
|
||||
|
||||
/* ----------------------
|
||||
@@ -411,7 +416,7 @@ contract PartyPool is PartyPoolBase, IPartyPool {
|
||||
require(lmsr.nAssets > 0, "swap: empty pool");
|
||||
|
||||
// Estimate max net input (fee on gross rounded up, then subtract)
|
||||
(, uint256 netUintForSwap) = _computeFee(maxAmountIn, swapFeePpm);
|
||||
(, uint256 netUintForSwap) = _computeFee(maxAmountIn, SWAP_FEE_PPM);
|
||||
|
||||
// Convert to internal (floor)
|
||||
int128 deltaInternalI = _uintToInternalFloor(netUintForSwap, bases[inputTokenIndex]);
|
||||
@@ -419,9 +424,9 @@ contract PartyPool is PartyPoolBase, IPartyPool {
|
||||
|
||||
// Compute internal amounts using LMSR (exact-input with price limit)
|
||||
// if _stablePair is true, use the optimized path
|
||||
console2.log('stablepair optimization?', _stablePair);
|
||||
console2.log('stablepair optimization?', IS_STABLE_PAIR);
|
||||
(amountInInternalUsed, amountOutInternal) =
|
||||
_stablePair ? LMSRStabilizedBalancedPair.swapAmountsForExactInput(lmsr, inputTokenIndex, outputTokenIndex, deltaInternalI, limitPrice)
|
||||
IS_STABLE_PAIR ? LMSRStabilizedBalancedPair.swapAmountsForExactInput(lmsr, inputTokenIndex, outputTokenIndex, deltaInternalI, limitPrice)
|
||||
: lmsr.swapAmountsForExactInput(inputTokenIndex, outputTokenIndex, deltaInternalI, limitPrice);
|
||||
|
||||
// Convert actual used input internal -> uint (ceil)
|
||||
@@ -431,8 +436,8 @@ contract PartyPool is PartyPoolBase, IPartyPool {
|
||||
// Compute gross transfer including fee on the used input (ceil)
|
||||
feeUint = 0;
|
||||
grossIn = amountInUintNoFee;
|
||||
if (swapFeePpm > 0) {
|
||||
feeUint = _ceilFee(amountInUintNoFee, swapFeePpm);
|
||||
if (SWAP_FEE_PPM > 0) {
|
||||
feeUint = _ceilFee(amountInUintNoFee, SWAP_FEE_PPM);
|
||||
grossIn += feeUint;
|
||||
}
|
||||
|
||||
@@ -479,8 +484,8 @@ contract PartyPool is PartyPoolBase, IPartyPool {
|
||||
|
||||
feeUint = 0;
|
||||
grossIn = amountInUintNoFee;
|
||||
if (swapFeePpm > 0) {
|
||||
feeUint = _ceilFee(amountInUintNoFee, swapFeePpm);
|
||||
if (SWAP_FEE_PPM > 0) {
|
||||
feeUint = _ceilFee(amountInUintNoFee, SWAP_FEE_PPM);
|
||||
grossIn += feeUint;
|
||||
}
|
||||
|
||||
@@ -491,17 +496,17 @@ contract PartyPool is PartyPoolBase, IPartyPool {
|
||||
/// @notice Compute fee and net amounts for a gross input (fee rounded up to favor the pool).
|
||||
/// @return feeUint fee taken (uint) and netUint remaining for protocol use (uint)
|
||||
function _computeFee(uint256 gross) internal view returns (uint256 feeUint, uint256 netUint) {
|
||||
if (swapFeePpm == 0) {
|
||||
if (SWAP_FEE_PPM == 0) {
|
||||
return (0, gross);
|
||||
}
|
||||
feeUint = _ceilFee(gross, swapFeePpm);
|
||||
feeUint = _ceilFee(gross, SWAP_FEE_PPM);
|
||||
netUint = gross - feeUint;
|
||||
}
|
||||
|
||||
/// @notice Convenience: return gross = net + fee(net) using ceiling for fee.
|
||||
function _addFee(uint256 netUint) internal view returns (uint256 gross) {
|
||||
if (swapFeePpm == 0) return netUint;
|
||||
uint256 fee = _ceilFee(netUint, swapFeePpm);
|
||||
if (SWAP_FEE_PPM == 0) return netUint;
|
||||
uint256 fee = _ceilFee(netUint, SWAP_FEE_PPM);
|
||||
return netUint + fee;
|
||||
}
|
||||
|
||||
@@ -533,10 +538,10 @@ contract PartyPool is PartyPoolBase, IPartyPool {
|
||||
inputTokenIndex,
|
||||
maxAmountIn,
|
||||
deadline,
|
||||
swapFeePpm
|
||||
SWAP_FEE_PPM
|
||||
);
|
||||
|
||||
bytes memory result = Address.functionDelegateCall(swapMintImpl, data);
|
||||
bytes memory result = Address.functionDelegateCall(address(SWAP_MINT_IMPL), data);
|
||||
return abi.decode(result, (uint256));
|
||||
}
|
||||
|
||||
@@ -562,10 +567,10 @@ contract PartyPool is PartyPoolBase, IPartyPool {
|
||||
lpAmount,
|
||||
inputTokenIndex,
|
||||
deadline,
|
||||
swapFeePpm
|
||||
SWAP_FEE_PPM
|
||||
);
|
||||
|
||||
bytes memory result = Address.functionDelegateCall(swapMintImpl, data);
|
||||
bytes memory result = Address.functionDelegateCall(address(SWAP_MINT_IMPL), data);
|
||||
return abi.decode(result, (uint256));
|
||||
}
|
||||
|
||||
@@ -577,7 +582,7 @@ contract PartyPool is PartyPoolBase, IPartyPool {
|
||||
for (uint256 i = 0; i < tokens.length; i++) {
|
||||
uint256 amount = loanAmounts[i];
|
||||
if (amount > 0) {
|
||||
repaymentAmounts[i] = amount + _ceilFee(amount, flashFeePpm);
|
||||
repaymentAmounts[i] = amount + _ceilFee(amount, FLASH_FEE_PPM);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -617,7 +622,7 @@ contract PartyPool is PartyPoolBase, IPartyPool {
|
||||
hasNonZeroAmount = true;
|
||||
|
||||
// Calculate repayment amount with fee (ceiling)
|
||||
repaymentAmounts[i] = amount + _ceilFee(amount, flashFeePpm);
|
||||
repaymentAmounts[i] = amount + _ceilFee(amount, FLASH_FEE_PPM);
|
||||
|
||||
// Record initial balance
|
||||
initialBalances[i] = IERC20(tokens[i]).balanceOf(address(this));
|
||||
@@ -640,7 +645,7 @@ contract PartyPool is PartyPoolBase, IPartyPool {
|
||||
|
||||
// Verify repayment: current balance must be at least (initial balance + fee)
|
||||
require(
|
||||
currentBalance >= initialBalances[i] + _ceilFee(amounts[i], flashFeePpm),
|
||||
currentBalance >= initialBalances[i] + _ceilFee(amounts[i], FLASH_FEE_PPM),
|
||||
"flash: repayment failed"
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user