doc improvements
This commit is contained in:
@@ -4,9 +4,18 @@ pragma solidity ^0.8.30;
|
||||
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
|
||||
|
||||
/// @title PartyPool - LMSR-backed multi-asset pool with LP ERC20 token
|
||||
/// @notice Uses LMSRStabilized library; stores per-token uint bases to convert to/from 64.64 fixed point.
|
||||
/// - Caches qInternal[] (int128 64.64) and cachedUintBalances[] to minimize balanceOf() calls.
|
||||
/// - swap and swapToLimit mimic core lib; mint/burn call updateForProportionalChange() and manage LP tokens.
|
||||
/// @notice A multi-asset liquidity pool backed by the LMSRStabilized pricing model.
|
||||
/// The pool issues an ERC20 LP token representing proportional ownership.
|
||||
/// It supports:
|
||||
/// - Proportional minting and burning of LP tokens,
|
||||
/// - Single-token mint (swapMint) and single-asset withdrawal (burnSwap),
|
||||
/// - Exact-input swaps and swaps-to-price-limits,
|
||||
/// - Flash loans via a callback interface.
|
||||
///
|
||||
/// @dev The contract stores per-token uint "bases" used to scale token units into the internal Q64.64
|
||||
/// representation used by the LMSR library. Cached on-chain uint balances are kept to reduce balanceOf calls.
|
||||
/// The contract uses ceiling/floor rules described in function comments to bias rounding in favor of the pool
|
||||
/// (i.e., floor outputs to users, ceil inputs/fees where appropriate).
|
||||
interface IPartyPool is IERC20Metadata {
|
||||
// All int128's are ABDKMath64x64 format
|
||||
|
||||
@@ -47,25 +56,51 @@ interface IPartyPool is IERC20Metadata {
|
||||
|
||||
|
||||
// Immutable pool configuration (public getters)
|
||||
/// @notice Token addresses comprising the pool. Effectively immutable after construction.
|
||||
/// @dev tokens[i] corresponds to the i-th asset and maps to index i in the internal LMSR arrays.
|
||||
function tokens(uint256) external view returns (address); // get single token
|
||||
|
||||
/// @notice Returns the number of tokens (n) in the pool.
|
||||
function numTokens() external view returns (uint256);
|
||||
|
||||
/// @notice Returns the list of all token addresses in the pool (copy).
|
||||
function allTokens() external view returns (address[] memory);
|
||||
|
||||
/// @notice Per-token uint base denominators used to convert uint token amounts <-> internal Q64.64 representation.
|
||||
/// @dev denominators()[i] is the base for tokens[i]. These bases are chosen by deployer and must match token decimals.
|
||||
function denominators() external view returns (uint256[] memory);
|
||||
|
||||
/// @notice Trade fraction (Q64.64) representing a reference trade size as fraction of one asset's inventory.
|
||||
/// @dev Used by the LMSR stabilization logic to compute target slippage.
|
||||
function tradeFrac() external view returns (int128); // ABDK 64x64
|
||||
|
||||
/// @notice Target slippage (Q64.64) applied for the reference trade size specified by tradeFrac.
|
||||
function targetSlippage() external view returns (int128); // ABDK 64x64
|
||||
|
||||
/// @notice Per-swap fee in parts-per-million (ppm). Fee is taken from input amounts before LMSR computations.
|
||||
function swapFeePpm() external view returns (uint256);
|
||||
|
||||
/// @notice Flash-loan fee in parts-per-million (ppm) applied to flash borrow amounts.
|
||||
function flashFeePpm() external view returns (uint256);
|
||||
|
||||
/// @notice Mapping from token address => (index+1). A zero value indicates the token is not in the pool.
|
||||
/// @dev Use index = tokenAddressToIndexPlusOne[token] - 1 when non-zero.
|
||||
function tokenAddressToIndexPlusOne(address) external view returns (uint);
|
||||
|
||||
// Initialization / Mint / Burn (LP token managed)
|
||||
|
||||
/// @notice Calculate the proportional deposit amounts required for a given LP token amount
|
||||
/// @dev Returns the minimum token amounts (rounded up) that must be supplied to receive lpTokenAmount
|
||||
/// LP tokens at current pool proportions. If the pool is empty (initial deposit) returns zeros
|
||||
/// because the initial deposit is handled by transferring tokens then calling mint().
|
||||
/// @param lpTokenAmount The amount of LP tokens desired
|
||||
/// @return depositAmounts Array of token amounts to deposit (rounded up)
|
||||
function mintDepositAmounts(uint256 lpTokenAmount) external view returns (uint256[] memory depositAmounts);
|
||||
|
||||
/// @notice Proportional mint (or initial supply if first call).
|
||||
/// For initial supply: assumes tokens have already been transferred to the pool
|
||||
/// For subsequent mints: payer must approve tokens beforehand, receiver gets the LP tokens
|
||||
/// @dev - For initial supply: assumes tokens have already been transferred to the pool prior to calling.
|
||||
/// - For subsequent mints: payer must approve the required token amounts before calling.
|
||||
/// Rounds follow the pool-favorable conventions documented in helpers (ceil inputs, floor outputs).
|
||||
/// @param payer address that provides the input tokens (ignored for initial deposit)
|
||||
/// @param receiver address that receives the LP tokens
|
||||
/// @param lpTokenAmount desired amount of LP tokens to mint (ignored for initial deposit)
|
||||
@@ -73,12 +108,15 @@ interface IPartyPool is IERC20Metadata {
|
||||
function mint(address payer, address receiver, uint256 lpTokenAmount, uint256 deadline) external;
|
||||
|
||||
/// @notice Calculate the proportional withdrawal amounts for a given LP token amount
|
||||
/// @dev Returns the maximum token amounts (rounded down) that will be withdrawn when burning lpTokenAmount.
|
||||
/// If the pool is uninitialized or supply is zero, returns zeros.
|
||||
/// @param lpTokenAmount The amount of LP tokens to burn
|
||||
/// @return withdrawAmounts Array of token amounts to withdraw (rounded down)
|
||||
function burnReceiveAmounts(uint256 lpTokenAmount) external view returns (uint256[] memory withdrawAmounts);
|
||||
|
||||
/// @notice Burn LP tokens and withdraw the proportional basket to receiver.
|
||||
/// Payer must own the LP tokens; withdraw amounts are computed from current proportions.
|
||||
/// @dev Payer must own or approve the LP tokens being burned. The function updates LMSR state
|
||||
/// proportionally to reflect the reduced pool size after the withdrawal.
|
||||
/// @param payer address that provides the LP tokens to burn
|
||||
/// @param receiver address that receives the withdrawn tokens
|
||||
/// @param lpAmount amount of LP tokens to burn (proportional withdrawal)
|
||||
@@ -89,73 +127,114 @@ interface IPartyPool is IERC20Metadata {
|
||||
// Swaps
|
||||
|
||||
/// @notice External view to quote exact-in swap amounts (gross input incl. fee and output), matching swap() computations
|
||||
/// @param inputTokenIndex index of input token
|
||||
/// @param outputTokenIndex index of output token
|
||||
/// @param maxAmountIn maximum gross input allowed (inclusive of fee)
|
||||
/// @param limitPrice maximum acceptable marginal price (pass 0 to ignore)
|
||||
/// @return amountIn gross input amount to transfer (includes fee), amountOut output amount user would receive, fee fee amount taken
|
||||
function swapAmounts(
|
||||
uint256 i,
|
||||
uint256 j,
|
||||
uint256 inputTokenIndex,
|
||||
uint256 outputTokenIndex,
|
||||
uint256 maxAmountIn,
|
||||
int128 limitPrice
|
||||
) external view returns (uint256 amountIn, uint256 amountOut, uint256 fee);
|
||||
|
||||
/// @notice Swap input token inputTokenIndex -> token outputTokenIndex. Payer must approve token inputTokenIndex.
|
||||
/// @dev This function transfers the exact gross input (including fee) from payer and sends the computed output to receiver.
|
||||
/// Non-standard tokens (fee-on-transfer, rebasers) are rejected via balance checks.
|
||||
/// @param payer address of the account that pays for the swap
|
||||
/// @param receiver address that will receive the output tokens
|
||||
/// @param inputTokenIndex index of input asset
|
||||
/// @param outputTokenIndex index of output asset
|
||||
/// @param maxAmountIn maximum amount of token inputTokenIndex (uint256) to transfer in (inclusive of fees)
|
||||
/// @param limitPrice maximum acceptable marginal price (64.64 fixed point). Pass 0 to ignore.
|
||||
/// @param deadline timestamp after which the transaction will revert. Pass 0 to ignore.
|
||||
/// @return amountIn actual input used (uint256), amountOut actual output sent (uint256), fee fee taken from the input (uint256)
|
||||
function swap(
|
||||
address payer,
|
||||
address receiver,
|
||||
uint256 i,
|
||||
uint256 j,
|
||||
uint256 inputTokenIndex,
|
||||
uint256 outputTokenIndex,
|
||||
uint256 maxAmountIn,
|
||||
int128 limitPrice,
|
||||
uint256 deadline
|
||||
) external returns (uint256 amountIn, uint256 amountOut, uint256 fee);
|
||||
|
||||
/// @notice External view to quote swap-to-limit amounts (gross input incl. fee and output), matching swapToLimit() computations
|
||||
/// @param inputTokenIndex index of input token
|
||||
/// @param outputTokenIndex index of output token
|
||||
/// @param limitPrice target marginal price to reach (must be > 0)
|
||||
/// @return amountIn gross input amount to transfer (includes fee), amountOut output amount user would receive, fee fee amount taken
|
||||
function swapToLimitAmounts(
|
||||
uint256 i,
|
||||
uint256 j,
|
||||
uint256 inputTokenIndex,
|
||||
uint256 outputTokenIndex,
|
||||
int128 limitPrice
|
||||
) external view returns (uint256 amountIn, uint256 amountOut, uint256 fee);
|
||||
|
||||
/// @notice Swap up to the price limit; computes max input to reach limit then performs swap.
|
||||
/// @dev If balances prevent fully reaching the limit, the function caps and returns actuals.
|
||||
/// The payer must transfer the exact gross input computed by the view.
|
||||
/// @param payer address of the account that pays for the swap
|
||||
/// @param receiver address that will receive the output tokens
|
||||
/// @param inputTokenIndex index of input asset
|
||||
/// @param outputTokenIndex index of output asset
|
||||
/// @param limitPrice target marginal price to reach (must be > 0)
|
||||
/// @param deadline timestamp after which the transaction will revert. Pass 0 to ignore.
|
||||
/// @return amountInUsed actual input used excluding fee (uint256), amountOut actual output sent (uint256), fee fee taken from the input (uint256)
|
||||
function swapToLimit(
|
||||
address payer,
|
||||
address receiver,
|
||||
uint256 i,
|
||||
uint256 j,
|
||||
uint256 inputTokenIndex,
|
||||
uint256 outputTokenIndex,
|
||||
int128 limitPrice,
|
||||
uint256 deadline
|
||||
) external returns (uint256 amountInUsed, uint256 amountOut, uint256 fee);
|
||||
|
||||
/// @notice Single-token mint: deposit a single token, charge swap-LMSR cost, and mint LP.
|
||||
/// @dev swapMint executes as an exact-in planned swap followed by proportional scaling of qInternal.
|
||||
/// The function emits SwapMint (gross, net, fee) and also emits Mint for LP issuance.
|
||||
/// @param payer who transfers the input token
|
||||
/// @param receiver who receives the minted LP tokens
|
||||
/// @param i index of the input token
|
||||
/// @param inputTokenIndex index of the input token
|
||||
/// @param maxAmountIn maximum uint token input (inclusive of fee)
|
||||
/// @param deadline optional deadline
|
||||
/// @return lpMinted actual LP minted (uint)
|
||||
function swapMint(
|
||||
address payer,
|
||||
address receiver,
|
||||
uint256 i,
|
||||
uint256 inputTokenIndex,
|
||||
uint256 maxAmountIn,
|
||||
uint256 deadline
|
||||
) external returns (uint256 lpMinted);
|
||||
|
||||
/// @notice Burn LP tokens then swap the redeemed proportional basket into a single asset `i` and send to receiver.
|
||||
/// @notice Burn LP tokens then swap the redeemed proportional basket into a single asset `inputTokenIndex` and send to receiver.
|
||||
/// @dev The function burns LP tokens (authorization via allowance if needed), sends the single-asset payout and updates LMSR state.
|
||||
/// @param payer who burns LP tokens
|
||||
/// @param receiver who receives the single asset
|
||||
/// @param lpAmount amount of LP tokens to burn
|
||||
/// @param i index of target asset to receive
|
||||
/// @param inputTokenIndex index of target asset to receive
|
||||
/// @param deadline optional deadline
|
||||
/// @return amountOutUint uint amount of asset i sent to receiver
|
||||
/// @return amountOutUint uint amount of asset inputTokenIndex sent to receiver
|
||||
function burnSwap(
|
||||
address payer,
|
||||
address receiver,
|
||||
uint256 lpAmount,
|
||||
uint256 i,
|
||||
uint256 inputTokenIndex,
|
||||
uint256 deadline
|
||||
) external returns (uint256 amountOutUint);
|
||||
|
||||
/// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback
|
||||
/// @dev The caller of this method receives a callback in the form of IPartyFlashCallback#partyFlashCallback
|
||||
/// @notice Compute repayment amounts (principal + flash fee) for a proposed flash loan.
|
||||
/// @param loanAmounts array of per-token loan amounts; must match the pool's token ordering.
|
||||
/// @return repaymentAmounts array where repaymentAmounts[i] = loanAmounts[i] + ceil(loanAmounts[i] * flashFeePpm)
|
||||
function flashRepaymentAmounts(uint256[] memory loanAmounts) external view
|
||||
returns (uint256[] memory repaymentAmounts);
|
||||
|
||||
/// @notice Receive token amounts and require them to be repaid plus a fee inside a callback.
|
||||
/// @dev The caller must implement IPartyFlashCallback#partyFlashCallback which receives (amounts, repaymentAmounts, data).
|
||||
/// This function verifies that, after the callback returns, the pool's balances have increased by at least the fees
|
||||
/// for each borrowed token. Reverts if repayment (including fee) did not occur.
|
||||
/// @param recipient The address which will receive the token amounts
|
||||
/// @param amounts The amount of each token to send
|
||||
/// @param amounts The amount of each token to send (array length must equal pool size)
|
||||
/// @param data Any data to be passed through to the callback
|
||||
function flash(
|
||||
address recipient,
|
||||
|
||||
@@ -13,9 +13,18 @@ import "./IPartyPool.sol";
|
||||
import "./IPartyFlashCallback.sol";
|
||||
|
||||
/// @title PartyPool - LMSR-backed multi-asset pool with LP ERC20 token
|
||||
/// @notice Uses LMSRStabilized library; stores per-token uint bases to convert to/from 64.64 fixed point.
|
||||
/// - Caches qInternal[] (int128 64.64) and cachedUintBalances[] to minimize balanceOf() calls.
|
||||
/// - swap and swapToLimit mimic core lib; mint/burn call updateForProportionalChange() and manage LP tokens.
|
||||
/// @notice A multi-asset liquidity pool backed by the LMSRStabilized pricing model.
|
||||
/// The pool issues an ERC20 LP token representing proportional ownership.
|
||||
/// It supports:
|
||||
/// - Proportional minting and burning of LP tokens,
|
||||
/// - Single-token mint (swapMint) and single-asset withdrawal (burnSwap),
|
||||
/// - Exact-input swaps and swaps-to-price-limits,
|
||||
/// - Flash loans via a callback interface.
|
||||
///
|
||||
/// @dev The contract stores per-token uint "bases" used to scale token units into the internal Q64.64
|
||||
/// representation used by the LMSR library. Cached on-chain uint balances are kept to reduce balanceOf calls.
|
||||
/// The contract uses ceiling/floor rules described in function comments to bias rounding in favor of the pool
|
||||
/// (i.e., floor outputs to users, ceil inputs/fees where appropriate).
|
||||
contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
using ABDKMath64x64 for int128;
|
||||
using LMSRStabilized for LMSRStabilized.State;
|
||||
@@ -26,20 +35,31 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
// Immutable pool configuration
|
||||
//
|
||||
|
||||
/// @notice Token addresses comprising the pool. Effectively immutable after construction.
|
||||
/// @dev tokens[i] corresponds to the i-th asset and maps to index i in the internal LMSR arrays.
|
||||
address[] public tokens; // effectively immutable since there is no interface to change the tokens
|
||||
|
||||
/// @inheritdoc IPartyPool
|
||||
function numTokens() external view returns (uint256) { return tokens.length; }
|
||||
function allTokens() external view returns (address[] memory) { return tokens; }
|
||||
|
||||
/// @inheritdoc IPartyPool
|
||||
function allTokens() external view returns (address[] memory) { return tokens; }
|
||||
|
||||
// NOTE that the slippage target is only exactly achieved in completely balanced pools where all assets are
|
||||
// priced the same. This target is actually a minimum slippage that the pool imposes on traders, and the actual
|
||||
// slippage cost can be multiples bigger in practice due to pool inventory imbalances.
|
||||
|
||||
/// @notice Trade fraction (Q64.64) representing a reference trade size as fraction of one asset's inventory.
|
||||
/// @dev Used by the LMSR stabilization logic to compute target slippage.
|
||||
int128 public immutable tradeFrac; // slippage target trade size as a fraction of one asset's inventory
|
||||
|
||||
/// @notice Target slippage (Q64.64) applied for the reference trade size specified by tradeFrac.
|
||||
int128 public immutable targetSlippage; // target slippage applied to that trade size
|
||||
|
||||
// fee in parts-per-million (ppm), taken from inputs before swaps
|
||||
/// @notice Per-swap fee in parts-per-million (ppm). Fee is taken from input amounts before LMSR computations.
|
||||
uint256 public immutable swapFeePpm;
|
||||
|
||||
// flash loan fee in parts-per-million (ppm)
|
||||
/// @notice Flash-loan fee in parts-per-million (ppm) applied to flash borrow amounts.
|
||||
uint256 public immutable flashFeePpm;
|
||||
|
||||
//
|
||||
@@ -47,16 +67,27 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
//
|
||||
|
||||
LMSRStabilized.State internal lmsr;
|
||||
|
||||
/// @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
|
||||
|
||||
// Cached on-chain balances (uint) and internal 64.64 representation
|
||||
// balance / base = internal
|
||||
uint256[] internal cachedUintBalances;
|
||||
|
||||
/// @notice Per-token uint base denominators used to convert uint token amounts <-> internal Q64.64 representation.
|
||||
/// @dev denominators()[i] is the base for tokens[i]. These bases are chosen by deployer and must match token decimals.
|
||||
uint256[] internal bases; // per-token uint base used to scale token amounts <-> internal
|
||||
|
||||
/// @inheritdoc IPartyPool
|
||||
function denominators() external view returns (uint256[] memory) { return bases; }
|
||||
|
||||
/// @notice Mapping from token address => (index+1). A zero value indicates the token is not in the pool.
|
||||
/// @dev Use index = tokenAddressToIndexPlusOne[token] - 1 when non-zero.
|
||||
mapping(address=>uint) public tokenAddressToIndexPlusOne; // Uses index+1 so a result of 0 indicates a failed lookup
|
||||
|
||||
/// @notice Scale factor used when converting LMSR Q64.64 totals to LP token units (uint).
|
||||
/// @dev LP tokens are minted in units equal to ABDK.mulu(lastTotalQ64x64, LP_SCALE).
|
||||
uint256 public constant LP_SCALE = 1e18; // Scale used to convert LMSR lastTotal (Q64.64) into LP token units (uint)
|
||||
|
||||
/// @param name_ LP token name
|
||||
@@ -111,9 +142,7 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
Initialization / Mint / Burn (LP token managed)
|
||||
---------------------- */
|
||||
|
||||
/// @notice Calculate the proportional deposit amounts required for a given LP token amount
|
||||
/// @param lpTokenAmount The amount of LP tokens desired
|
||||
/// @return depositAmounts Array of token amounts to deposit (rounded up)
|
||||
/// @inheritdoc IPartyPool
|
||||
function mintDepositAmounts(uint256 lpTokenAmount) public view returns (uint256[] memory depositAmounts) {
|
||||
uint256 n = tokens.length;
|
||||
depositAmounts = new uint256[](n);
|
||||
@@ -139,9 +168,7 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
return depositAmounts;
|
||||
}
|
||||
|
||||
/// @notice Calculate the proportional withdrawal amounts for a given LP token amount
|
||||
/// @param lpTokenAmount The amount of LP tokens to burn
|
||||
/// @return withdrawAmounts Array of token amounts to withdraw (rounded down)
|
||||
/// @inheritdoc IPartyPool
|
||||
function burnReceiveAmounts(uint256 lpTokenAmount) external view returns (uint256[] memory withdrawAmounts) {
|
||||
return _burnReceiveAmounts(lpTokenAmount);
|
||||
}
|
||||
@@ -168,8 +195,9 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
}
|
||||
|
||||
/// @notice Proportional mint (or initial supply if first call).
|
||||
/// For initial supply: assumes tokens have already been transferred to the pool
|
||||
/// For subsequent mints: payer must approve tokens beforehand, receiver gets the LP tokens
|
||||
/// @dev - For initial supply: assumes tokens have already been transferred to the pool prior to calling.
|
||||
/// - For subsequent mints: payer must approve the required token amounts before calling.
|
||||
/// Rounds follow the pool-favorable conventions documented in helpers (ceil inputs, floor outputs).
|
||||
/// @param payer address that provides the input tokens (ignored for initial deposit)
|
||||
/// @param receiver address that receives the LP tokens
|
||||
/// @param lpTokenAmount desired amount of LP tokens to mint (ignored for initial deposit)
|
||||
@@ -267,7 +295,8 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
}
|
||||
|
||||
/// @notice Burn LP tokens and withdraw the proportional basket to receiver.
|
||||
/// Payer must own the LP tokens; withdraw amounts are computed from current proportions.
|
||||
/// @dev Payer must own or approve the LP tokens being burned. The function updates LMSR state
|
||||
/// proportionally to reflect the reduced pool size after the withdrawal.
|
||||
/// @param payer address that provides the LP tokens to burn
|
||||
/// @param receiver address that receives the withdrawn tokens
|
||||
/// @param lpAmount amount of LP tokens to burn (proportional withdrawal)
|
||||
@@ -341,12 +370,13 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
---------------------- */
|
||||
|
||||
/// @notice Internal quote for exact-input swap that mirrors swap() rounding and fee application
|
||||
/// @dev Returns amounts consistent with swap() semantics: grossIn includes fees (ceil), amountOut is floored.
|
||||
/// @return grossIn amount to transfer in (inclusive of fee), amountOutUint output amount (uint),
|
||||
/// amountInInternalUsed and amountOutInternal (64.64), amountInUintNoFee input amount excluding fee (uint),
|
||||
/// feeUint fee taken from the gross input (uint)
|
||||
function _quoteSwapExactIn(
|
||||
uint256 i,
|
||||
uint256 j,
|
||||
uint256 inputTokenIndex,
|
||||
uint256 outputTokenIndex,
|
||||
uint256 maxAmountIn,
|
||||
int128 limitPrice
|
||||
)
|
||||
@@ -362,7 +392,7 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
)
|
||||
{
|
||||
uint256 n = tokens.length;
|
||||
require(i < n && j < n, "swap: idx");
|
||||
require(inputTokenIndex < n && outputTokenIndex < n, "swap: idx");
|
||||
require(maxAmountIn > 0, "swap: input zero");
|
||||
require(lmsr.nAssets > 0, "swap: empty pool");
|
||||
|
||||
@@ -370,18 +400,18 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
(, uint256 netUintForSwap) = _computeFee(maxAmountIn);
|
||||
|
||||
// Convert to internal (floor)
|
||||
int128 deltaInternalI = _uintToInternalFloor(netUintForSwap, bases[i]);
|
||||
int128 deltaInternalI = _uintToInternalFloor(netUintForSwap, bases[inputTokenIndex]);
|
||||
require(deltaInternalI > int128(0), "swap: input too small after fee");
|
||||
|
||||
// Compute internal amounts using LMSR (exact-input with price limit)
|
||||
// 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);
|
||||
_stablePair ? LMSRStabilizedBalancedPair.swapAmountsForExactInput(lmsr, inputTokenIndex, outputTokenIndex, deltaInternalI, limitPrice)
|
||||
: lmsr.swapAmountsForExactInput(inputTokenIndex, outputTokenIndex, deltaInternalI, limitPrice);
|
||||
|
||||
// Convert actual used input internal -> uint (ceil)
|
||||
amountInUintNoFee = _internalToUintCeil(amountInInternalUsed, bases[i]);
|
||||
amountInUintNoFee = _internalToUintCeil(amountInInternalUsed, bases[inputTokenIndex]);
|
||||
require(amountInUintNoFee > 0, "swap: input zero");
|
||||
|
||||
// Compute gross transfer including fee on the used input (ceil)
|
||||
@@ -396,17 +426,18 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
require(grossIn <= maxAmountIn, "swap: transfer exceeds max");
|
||||
|
||||
// Compute output (floor)
|
||||
amountOutUint = _internalToUintFloor(amountOutInternal, bases[j]);
|
||||
amountOutUint = _internalToUintFloor(amountOutInternal, bases[outputTokenIndex]);
|
||||
require(amountOutUint > 0, "swap: output zero");
|
||||
}
|
||||
|
||||
/// @notice Internal quote for swap-to-limit that mirrors swapToLimit() rounding and fee application
|
||||
/// @dev Computes the input required to reach limitPrice and the resulting output; all rounding matches swapToLimit.
|
||||
/// @return grossIn amount to transfer in (inclusive of fee), amountOutUint output amount (uint),
|
||||
/// amountInInternal and amountOutInternal (64.64), amountInUintNoFee input amount excluding fee (uint),
|
||||
/// feeUint fee taken from the gross input (uint)
|
||||
function _quoteSwapToLimit(
|
||||
uint256 i,
|
||||
uint256 j,
|
||||
uint256 inputTokenIndex,
|
||||
uint256 outputTokenIndex,
|
||||
int128 limitPrice
|
||||
)
|
||||
internal
|
||||
@@ -421,15 +452,15 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
)
|
||||
{
|
||||
uint256 n = tokens.length;
|
||||
require(i < n && j < n, "swapToLimit: idx");
|
||||
require(inputTokenIndex < n && outputTokenIndex < n, "swapToLimit: idx");
|
||||
require(limitPrice > int128(0), "swapToLimit: limit <= 0");
|
||||
require(lmsr.nAssets > 0, "swapToLimit: pool uninitialized");
|
||||
|
||||
// Compute internal maxima at the price limit
|
||||
(amountInInternal, amountOutInternal) = lmsr.swapAmountsForPriceLimit(i, j, limitPrice);
|
||||
(amountInInternal, amountOutInternal) = lmsr.swapAmountsForPriceLimit(inputTokenIndex, outputTokenIndex, limitPrice);
|
||||
|
||||
// Convert input to uint (ceil) and output to uint (floor)
|
||||
amountInUintNoFee = _internalToUintCeil(amountInInternal, bases[i]);
|
||||
amountInUintNoFee = _internalToUintCeil(amountInInternal, bases[inputTokenIndex]);
|
||||
require(amountInUintNoFee > 0, "swapToLimit: input zero");
|
||||
|
||||
feeUint = 0;
|
||||
@@ -439,37 +470,39 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
grossIn += feeUint;
|
||||
}
|
||||
|
||||
amountOutUint = _internalToUintFloor(amountOutInternal, bases[j]);
|
||||
amountOutUint = _internalToUintFloor(amountOutInternal, bases[outputTokenIndex]);
|
||||
require(amountOutUint > 0, "swapToLimit: output zero");
|
||||
}
|
||||
|
||||
/// @notice External view to quote exact-in swap amounts (gross input incl. fee and output), matching swap() computations
|
||||
/// @inheritdoc IPartyPool
|
||||
function swapAmounts(
|
||||
uint256 i,
|
||||
uint256 j,
|
||||
uint256 inputTokenIndex,
|
||||
uint256 outputTokenIndex,
|
||||
uint256 maxAmountIn,
|
||||
int128 limitPrice
|
||||
) external view returns (uint256 amountIn, uint256 amountOut, uint256 fee) {
|
||||
(uint256 grossIn, uint256 outUint,,,, uint256 feeUint) = _quoteSwapExactIn(i, j, maxAmountIn, limitPrice);
|
||||
(uint256 grossIn, uint256 outUint,,,, uint256 feeUint) = _quoteSwapExactIn(inputTokenIndex, outputTokenIndex, maxAmountIn, limitPrice);
|
||||
return (grossIn, outUint, feeUint);
|
||||
}
|
||||
|
||||
/// @notice External view to quote swap-to-limit amounts (gross input incl. fee and output), matching swapToLimit() computations
|
||||
/// @inheritdoc IPartyPool
|
||||
function swapToLimitAmounts(
|
||||
uint256 i,
|
||||
uint256 j,
|
||||
uint256 inputTokenIndex,
|
||||
uint256 outputTokenIndex,
|
||||
int128 limitPrice
|
||||
) external view returns (uint256 amountIn, uint256 amountOut, uint256 fee) {
|
||||
(uint256 grossIn, uint256 outUint,,,, uint256 feeUint) = _quoteSwapToLimit(i, j, limitPrice);
|
||||
(uint256 grossIn, uint256 outUint,,,, uint256 feeUint) = _quoteSwapToLimit(inputTokenIndex, outputTokenIndex, limitPrice);
|
||||
return (grossIn, outUint, feeUint);
|
||||
}
|
||||
|
||||
|
||||
/// @notice Swap input token i -> token j. Payer must approve token i.
|
||||
/// @dev This function transfers the exact gross input (including fee) from payer and sends the computed output to receiver.
|
||||
/// Non-standard tokens (fee-on-transfer, rebasers) are rejected via balance checks.
|
||||
/// @param payer address of the account that pays for the swap
|
||||
/// @param receiver address that will receive the output tokens
|
||||
/// @param i index of input asset
|
||||
/// @param j index of output asset
|
||||
/// @param inputTokenIndex index of input asset
|
||||
/// @param outputTokenIndex index of output asset
|
||||
/// @param maxAmountIn maximum amount of token i (uint256) to transfer in (inclusive of fees)
|
||||
/// @param limitPrice maximum acceptable marginal price (64.64 fixed point). Pass 0 to ignore.
|
||||
/// @param deadline timestamp after which the transaction will revert. Pass 0 to ignore.
|
||||
@@ -477,96 +510,97 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
function swap(
|
||||
address payer,
|
||||
address receiver,
|
||||
uint256 i,
|
||||
uint256 j,
|
||||
uint256 inputTokenIndex,
|
||||
uint256 outputTokenIndex,
|
||||
uint256 maxAmountIn,
|
||||
int128 limitPrice,
|
||||
uint256 deadline
|
||||
) external nonReentrant returns (uint256 amountIn, uint256 amountOut, uint256 fee) {
|
||||
uint256 n = tokens.length;
|
||||
require(i < n && j < n, "swap: idx");
|
||||
require(inputTokenIndex < n && outputTokenIndex < n, "swap: idx");
|
||||
require(maxAmountIn > 0, "swap: input zero");
|
||||
require(deadline == 0 || block.timestamp <= deadline, "swap: deadline exceeded");
|
||||
|
||||
// Read previous balances for affected assets
|
||||
uint256 prevBalI = IERC20(tokens[i]).balanceOf(address(this));
|
||||
uint256 prevBalJ = IERC20(tokens[j]).balanceOf(address(this));
|
||||
uint256 prevBalI = IERC20(tokens[inputTokenIndex]).balanceOf(address(this));
|
||||
uint256 prevBalJ = IERC20(tokens[outputTokenIndex]).balanceOf(address(this));
|
||||
|
||||
// Compute amounts using the same path as views
|
||||
(uint256 totalTransferAmount, uint256 amountOutUint, int128 amountInInternalUsed, int128 amountOutInternal, , uint256 feeUint) =
|
||||
_quoteSwapExactIn(i, j, maxAmountIn, limitPrice);
|
||||
_quoteSwapExactIn(inputTokenIndex, outputTokenIndex, maxAmountIn, limitPrice);
|
||||
|
||||
// Transfer the exact amount from payer and require exact receipt (revert on fee-on-transfer)
|
||||
_safeTransferFrom(tokens[i], payer, address(this), totalTransferAmount);
|
||||
uint256 balIAfter = IERC20(tokens[i]).balanceOf(address(this));
|
||||
_safeTransferFrom(tokens[inputTokenIndex], payer, address(this), totalTransferAmount);
|
||||
uint256 balIAfter = IERC20(tokens[inputTokenIndex]).balanceOf(address(this));
|
||||
require(balIAfter == prevBalI + totalTransferAmount, "swap: non-standard tokenIn");
|
||||
|
||||
// Transfer output to receiver and verify exact decrease
|
||||
_safeTransfer(tokens[j], receiver, amountOutUint);
|
||||
uint256 balJAfter = IERC20(tokens[j]).balanceOf(address(this));
|
||||
_safeTransfer(tokens[outputTokenIndex], receiver, amountOutUint);
|
||||
uint256 balJAfter = IERC20(tokens[outputTokenIndex]).balanceOf(address(this));
|
||||
require(balJAfter == prevBalJ - amountOutUint, "swap: non-standard tokenOut");
|
||||
|
||||
// Update cached uint balances for i and j using actual balances
|
||||
cachedUintBalances[i] = balIAfter;
|
||||
cachedUintBalances[j] = balJAfter;
|
||||
cachedUintBalances[inputTokenIndex] = balIAfter;
|
||||
cachedUintBalances[outputTokenIndex] = balJAfter;
|
||||
|
||||
// Apply swap to LMSR state with the internal amounts actually used
|
||||
lmsr.applySwap(i, j, amountInInternalUsed, amountOutInternal);
|
||||
lmsr.applySwap(inputTokenIndex, outputTokenIndex, amountInInternalUsed, amountOutInternal);
|
||||
|
||||
emit Swap(payer, receiver, tokens[i], tokens[j], totalTransferAmount, amountOutUint);
|
||||
emit Swap(payer, receiver, tokens[inputTokenIndex], tokens[outputTokenIndex], totalTransferAmount, amountOutUint);
|
||||
|
||||
return (totalTransferAmount, amountOutUint, feeUint);
|
||||
}
|
||||
|
||||
/// @notice Swap up to the price limit; computes max input to reach limit then performs swap.
|
||||
/// If the pool can't fill entirely because of balances, it caps appropriately and returns actuals.
|
||||
/// Payer must approve token i for the exact computed input amount.
|
||||
/// @dev If balances prevent fully reaching the limit, the function caps and returns actuals.
|
||||
/// The payer must transfer the exact gross input computed by the view.
|
||||
/// @param deadline timestamp after which the transaction will revert. Pass 0 to ignore.
|
||||
function swapToLimit(
|
||||
address payer,
|
||||
address receiver,
|
||||
uint256 i,
|
||||
uint256 j,
|
||||
uint256 inputTokenIndex,
|
||||
uint256 outputTokenIndex,
|
||||
int128 limitPrice,
|
||||
uint256 deadline
|
||||
) external returns (uint256 amountInUsed, uint256 amountOut, uint256 fee) {
|
||||
uint256 n = tokens.length;
|
||||
require(i < n && j < n, "swapToLimit: idx");
|
||||
require(inputTokenIndex < n && outputTokenIndex < n, "swapToLimit: idx");
|
||||
require(limitPrice > int128(0), "swapToLimit: limit <= 0");
|
||||
require(deadline == 0 || block.timestamp <= deadline, "swapToLimit: deadline exceeded");
|
||||
|
||||
// Read previous balances for affected assets
|
||||
uint256 prevBalI = IERC20(tokens[i]).balanceOf(address(this));
|
||||
uint256 prevBalJ = IERC20(tokens[j]).balanceOf(address(this));
|
||||
uint256 prevBalI = IERC20(tokens[inputTokenIndex]).balanceOf(address(this));
|
||||
uint256 prevBalJ = IERC20(tokens[outputTokenIndex]).balanceOf(address(this));
|
||||
|
||||
// Compute amounts using the same path as views
|
||||
(uint256 totalTransferAmount, uint256 amountOutUint, int128 amountInInternalMax, int128 amountOutInternal, uint256 amountInUsedUint, uint256 feeUint) =
|
||||
_quoteSwapToLimit(i, j, limitPrice);
|
||||
_quoteSwapToLimit(inputTokenIndex, outputTokenIndex, limitPrice);
|
||||
|
||||
// Transfer the exact amount needed from payer and require exact receipt (revert on fee-on-transfer)
|
||||
_safeTransferFrom(tokens[i], payer, address(this), totalTransferAmount);
|
||||
uint256 balIAfter = IERC20(tokens[i]).balanceOf(address(this));
|
||||
_safeTransferFrom(tokens[inputTokenIndex], payer, address(this), totalTransferAmount);
|
||||
uint256 balIAfter = IERC20(tokens[inputTokenIndex]).balanceOf(address(this));
|
||||
require(balIAfter == prevBalI + totalTransferAmount, "swapToLimit: non-standard tokenIn");
|
||||
|
||||
// Transfer output to receiver and verify exact decrease
|
||||
_safeTransfer(tokens[j], receiver, amountOutUint);
|
||||
uint256 balJAfter = IERC20(tokens[j]).balanceOf(address(this));
|
||||
_safeTransfer(tokens[outputTokenIndex], receiver, amountOutUint);
|
||||
uint256 balJAfter = IERC20(tokens[outputTokenIndex]).balanceOf(address(this));
|
||||
require(balJAfter == prevBalJ - amountOutUint, "swapToLimit: non-standard tokenOut");
|
||||
|
||||
// Update caches to actual balances
|
||||
cachedUintBalances[i] = balIAfter;
|
||||
cachedUintBalances[j] = balJAfter;
|
||||
cachedUintBalances[inputTokenIndex] = balIAfter;
|
||||
cachedUintBalances[outputTokenIndex] = balJAfter;
|
||||
|
||||
// Apply swap to LMSR state with the internal amounts
|
||||
lmsr.applySwap(i, j, amountInInternalMax, amountOutInternal);
|
||||
lmsr.applySwap(inputTokenIndex, outputTokenIndex, amountInInternalMax, amountOutInternal);
|
||||
|
||||
// Maintain original event semantics (logs input without fee)
|
||||
emit Swap(payer, receiver, tokens[i], tokens[j], amountInUsedUint, amountOutUint);
|
||||
emit Swap(payer, receiver, tokens[inputTokenIndex], tokens[outputTokenIndex], amountInUsedUint, amountOutUint);
|
||||
|
||||
return (amountInUsedUint, amountOutUint, feeUint);
|
||||
}
|
||||
|
||||
/// @notice Ceiling fee helper: computes ceil(x * feePpm / 1_000_000)
|
||||
/// @dev Internal helper; public-facing functions use this to ensure fees round up in favor of pool.
|
||||
function _ceilFee(uint256 x, uint256 feePpm) internal pure returns (uint256) {
|
||||
if (feePpm == 0) return 0;
|
||||
// ceil division: (num + denom - 1) / denom
|
||||
@@ -595,21 +629,23 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
// which is already present in the standard Mint/Burn events.
|
||||
|
||||
/// @notice Single-token mint: deposit a single token, charge swap-LMSR cost, and mint LP.
|
||||
/// @dev swapMint executes as an exact-in planned swap followed by proportional scaling of qInternal.
|
||||
/// The function emits SwapMint (gross, net, fee) and also emits Mint for LP issuance.
|
||||
/// @param payer who transfers the input token
|
||||
/// @param receiver who receives the minted LP tokens
|
||||
/// @param i index of the input token
|
||||
/// @param inputTokenIndex index of the input token
|
||||
/// @param maxAmountIn maximum uint token input (inclusive of fee)
|
||||
/// @param deadline optional deadline
|
||||
/// @return lpMinted actual LP minted (uint)
|
||||
function swapMint(
|
||||
address payer,
|
||||
address receiver,
|
||||
uint256 i,
|
||||
uint256 inputTokenIndex,
|
||||
uint256 maxAmountIn,
|
||||
uint256 deadline
|
||||
) external nonReentrant returns (uint256 lpMinted) {
|
||||
uint256 n = tokens.length;
|
||||
require(i < n, "swapMint: idx");
|
||||
require(inputTokenIndex < n, "swapMint: idx");
|
||||
require(maxAmountIn > 0, "swapMint: input zero");
|
||||
require(deadline == 0 || block.timestamp <= deadline, "swapMint: deadline");
|
||||
|
||||
@@ -620,14 +656,14 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
(, uint256 netUintGuess) = _computeFee(maxAmountIn);
|
||||
|
||||
// Convert the net guess to internal (floor)
|
||||
int128 netInternalGuess = _uintToInternalFloor(netUintGuess, bases[i]);
|
||||
int128 netInternalGuess = _uintToInternalFloor(netUintGuess, bases[inputTokenIndex]);
|
||||
require(netInternalGuess > int128(0), "swapMint: input too small after fee");
|
||||
|
||||
// Use LMSR view to determine actual internal consumed and size-increase (ΔS) for mint
|
||||
(int128 amountInInternalUsed, int128 sizeIncreaseInternal) = lmsr.swapAmountsForMint(i, netInternalGuess);
|
||||
(int128 amountInInternalUsed, int128 sizeIncreaseInternal) = lmsr.swapAmountsForMint(inputTokenIndex, netInternalGuess);
|
||||
|
||||
// amountInInternalUsed may be <= netInternalGuess. Convert to uint (ceil) to determine actual transfer
|
||||
uint256 amountInUint = _internalToUintCeil(amountInInternalUsed, bases[i]);
|
||||
uint256 amountInUint = _internalToUintCeil(amountInInternalUsed, bases[inputTokenIndex]);
|
||||
require(amountInUint > 0, "swapMint: input zero after internal conversion");
|
||||
|
||||
// Compute fee on the actual used input and total transfer amount (ceiling)
|
||||
@@ -636,13 +672,13 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
require(totalTransfer > 0 && totalTransfer <= maxAmountIn, "swapMint: transfer exceeds max");
|
||||
|
||||
// Record pre-balance and transfer tokens from payer, require exact receipt (revert on fee-on-transfer)
|
||||
uint256 prevBalI = IERC20(tokens[i]).balanceOf(address(this));
|
||||
_safeTransferFrom(tokens[i], payer, address(this), totalTransfer);
|
||||
uint256 balIAfter = IERC20(tokens[i]).balanceOf(address(this));
|
||||
uint256 prevBalI = IERC20(tokens[inputTokenIndex]).balanceOf(address(this));
|
||||
_safeTransferFrom(tokens[inputTokenIndex], payer, address(this), totalTransfer);
|
||||
uint256 balIAfter = IERC20(tokens[inputTokenIndex]).balanceOf(address(this));
|
||||
require(balIAfter == prevBalI + totalTransfer, "swapMint: non-standard tokenIn");
|
||||
|
||||
// Update cached uint balances for token i (only i changed externally)
|
||||
cachedUintBalances[i] = balIAfter;
|
||||
// Update cached uint balances for token inputTokenIndex (only inputTokenIndex changed externally)
|
||||
cachedUintBalances[inputTokenIndex] = balIAfter;
|
||||
|
||||
// Compute old and new scaled size metrics to determine LP minted
|
||||
int128 oldTotal = _computeSizeMetric(lmsr.qInternal);
|
||||
@@ -679,13 +715,13 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
// Update cached internal and kappa via updateForProportionalChange
|
||||
lmsr.updateForProportionalChange(newQInternal);
|
||||
|
||||
// Note: we updated cachedUintBalances[i] above via reading balance; other token uint balances did not
|
||||
// Note: we updated cachedUintBalances[inputTokenIndex] above via reading balance; other token uint balances did not
|
||||
// change externally (they were not transferred in). We keep cachedUintBalances for others unchanged.
|
||||
// Mint LP tokens to receiver
|
||||
_mint(receiver, actualLpToMint);
|
||||
|
||||
// Emit SwapMint event with gross transfer, net input and fee (planned exact-in)
|
||||
emit SwapMint(payer, receiver, i, totalTransfer, amountInUint, feeUintActual);
|
||||
emit SwapMint(payer, receiver, inputTokenIndex, totalTransfer, amountInUint, feeUintActual);
|
||||
|
||||
// Emit standard Mint event which records deposit amounts and LP minted
|
||||
emit Mint(payer, receiver, new uint256[](n), actualLpToMint);
|
||||
@@ -694,22 +730,23 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
return actualLpToMint;
|
||||
}
|
||||
|
||||
/// @notice Burn LP tokens then swap the redeemed proportional basket into a single asset `i` and send to receiver.
|
||||
/// @notice Burn LP tokens then swap the redeemed proportional basket into a single asset `inputTokenIndex` and send to receiver.
|
||||
/// @dev The function burns LP tokens (authorization via allowance if needed), sends the single-asset payout and updates LMSR state.
|
||||
/// @param payer who burns LP tokens
|
||||
/// @param receiver who receives the single asset
|
||||
/// @param lpAmount amount of LP tokens to burn
|
||||
/// @param i index of target asset to receive
|
||||
/// @param inputTokenIndex index of target asset to receive
|
||||
/// @param deadline optional deadline
|
||||
/// @return amountOutUint uint amount of asset i sent to receiver
|
||||
function burnSwap(
|
||||
address payer,
|
||||
address receiver,
|
||||
uint256 lpAmount,
|
||||
uint256 i,
|
||||
uint256 inputTokenIndex,
|
||||
uint256 deadline
|
||||
) external nonReentrant returns (uint256 amountOutUint) {
|
||||
uint256 n = tokens.length;
|
||||
require(i < n, "burnSwap: idx");
|
||||
require(inputTokenIndex < n, "burnSwap: idx");
|
||||
require(lpAmount > 0, "burnSwap: zero lp");
|
||||
require(deadline == 0 || block.timestamp <= deadline, "burnSwap: deadline");
|
||||
|
||||
@@ -721,14 +758,14 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
int128 alpha = ABDKMath64x64.divu(lpAmount, supply);
|
||||
|
||||
// Use LMSR view to compute single-asset payout and burned size-metric
|
||||
(int128 payoutInternal, ) = lmsr.swapAmountsForBurn(i, alpha);
|
||||
(int128 payoutInternal, ) = lmsr.swapAmountsForBurn(inputTokenIndex, alpha);
|
||||
|
||||
// Convert payoutInternal -> uint (floor) to favor pool
|
||||
amountOutUint = _internalToUintFloor(payoutInternal, bases[i]);
|
||||
amountOutUint = _internalToUintFloor(payoutInternal, bases[inputTokenIndex]);
|
||||
require(amountOutUint > 0, "burnSwap: output zero");
|
||||
|
||||
// Transfer the payout to receiver
|
||||
_safeTransfer(tokens[i], receiver, amountOutUint);
|
||||
_safeTransfer(tokens[inputTokenIndex], receiver, amountOutUint);
|
||||
|
||||
// Burn LP tokens from payer (authorization via allowance)
|
||||
if (msg.sender != payer) {
|
||||
@@ -747,7 +784,7 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
}
|
||||
|
||||
// Emit BurnSwap with public-facing info only (do not expose ΔS or LP burned)
|
||||
emit BurnSwap(payer, receiver, i, amountOutUint);
|
||||
emit BurnSwap(payer, receiver, inputTokenIndex, amountOutUint);
|
||||
|
||||
// If entire pool drained, deinit; else update proportionally
|
||||
bool allZero = true;
|
||||
@@ -765,6 +802,7 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
}
|
||||
|
||||
|
||||
/// @inheritdoc IPartyPool
|
||||
function flashRepaymentAmounts(uint256[] memory loanAmounts) external view
|
||||
returns (uint256[] memory repaymentAmounts) {
|
||||
repaymentAmounts = new uint256[](tokens.length);
|
||||
@@ -777,10 +815,12 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
}
|
||||
|
||||
|
||||
/// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback
|
||||
/// @dev The caller of this method receives a callback in the form of IPartyFlashCallback#partyFlashCallback
|
||||
/// @notice Receive token amounts and require them to be repaid plus a fee inside a callback.
|
||||
/// @dev The caller must implement IPartyFlashCallback#partyFlashCallback which receives (amounts, repaymentAmounts, data).
|
||||
/// This function verifies that, after the callback returns, the pool's balances have increased by at least the fees
|
||||
/// for each borrowed token. Reverts if repayment (including fee) did not occur.
|
||||
/// @param recipient The address which will receive the token amounts
|
||||
/// @param amounts The amount of each token to send
|
||||
/// @param amounts The amount of each token to send (array length must equal pool size)
|
||||
/// @param data Any data to be passed through to the callback
|
||||
function flash(
|
||||
address recipient,
|
||||
@@ -886,6 +926,7 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard {
|
||||
}
|
||||
|
||||
/// @notice Helper to compute size metric (sum of all asset quantities) from internal balances
|
||||
/// @dev Returns the sum of all provided qInternal_ entries as a Q64.64 value.
|
||||
function _computeSizeMetric(int128[] memory qInternal_) private pure returns (int128) {
|
||||
int128 total = int128(0);
|
||||
for (uint i = 0; i < qInternal_.length; ) {
|
||||
|
||||
Reference in New Issue
Block a user