styling consistency
This commit is contained in:
@@ -19,7 +19,7 @@ contract DeployMock is Script {
|
||||
function run() public {
|
||||
vm.startBroadcast();
|
||||
|
||||
// create mock tokens
|
||||
// create mock _tokens
|
||||
usxd = new MockERC20('Joke Currency', 'USXD', 6);
|
||||
fusd = new MockERC20('Fake USD', 'FUSD', 6);
|
||||
dive = new MockERC20('DAI Virtually Equal', 'DIVE', 18);
|
||||
@@ -41,7 +41,7 @@ contract DeployMock is Script {
|
||||
// deploy a PartyPlanner factory and create the pool via factory
|
||||
PartyPlanner planner = Deploy.newPartyPlanner();
|
||||
|
||||
// prepare initial deposits (10_000 units of each token, scaled by bases)
|
||||
// prepare initial deposits (10_000 units of each token, scaled by _bases)
|
||||
uint256[] memory initialDeposits = new uint256[](3);
|
||||
initialDeposits[0] = _bases[0] * 10_000;
|
||||
initialDeposits[1] = _bases[1] * 10_000;
|
||||
@@ -49,7 +49,7 @@ contract DeployMock is Script {
|
||||
uint256 initialLpAmount = 0;
|
||||
uint256 deadline = 0;
|
||||
|
||||
// mint tokens to the deployer so it can fund the initial deposits and approve the factory
|
||||
// mint _tokens to the deployer so it can fund the initial deposits and approve the factory
|
||||
mintAll(msg.sender, 10_000);
|
||||
|
||||
// approve factory to move initial deposits
|
||||
@@ -75,7 +75,7 @@ contract DeployMock is Script {
|
||||
deadline
|
||||
);
|
||||
|
||||
// give tokens to dev7 for later use
|
||||
// give _tokens to dev7 for later use
|
||||
mintAll(DEV_ACCOUNT_7, 1_000_000);
|
||||
|
||||
vm.stopBroadcast();
|
||||
|
||||
@@ -38,7 +38,7 @@ contract ERC20External is ERC20Internal, IERC20Metadata {
|
||||
|
||||
/**
|
||||
* @dev Returns the number of decimals used to get its user representation.
|
||||
* For example, if `decimals` equals `2`, a balance of `505` tokens should
|
||||
* For example, if `decimals` equals `2`, a balance of `505` _tokens should
|
||||
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
|
||||
*
|
||||
* Tokens usually opt for a value of 18, imitating the relationship between
|
||||
@@ -111,7 +111,7 @@ contract ERC20External is ERC20Internal, IERC20Metadata {
|
||||
*
|
||||
* - `from` and `to` cannot be the zero address.
|
||||
* - `from` must have a balance of at least `value`.
|
||||
* - the caller must have allowance for ``from``'s tokens of at least
|
||||
* - the caller must have allowance for ``from``'s _tokens of at least
|
||||
* `value`.
|
||||
*/
|
||||
function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
|
||||
|
||||
@@ -16,7 +16,7 @@ abstract contract ERC20Internal is Context, IERC20Errors {
|
||||
|
||||
|
||||
/**
|
||||
* @dev Moves a `value` amount of tokens from `from` to `to`.
|
||||
* @dev Moves a `value` amount of _tokens from `from` to `to`.
|
||||
*
|
||||
* This internal function is equivalent to {transfer}, and can be used to
|
||||
* e.g. implement automatic token fees, slashing mechanisms, etc.
|
||||
@@ -36,7 +36,7 @@ abstract contract ERC20Internal is Context, IERC20Errors {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
|
||||
* @dev Transfers a `value` amount of _tokens from `from` to `to`, or alternatively mints (or burns) if `from`
|
||||
* (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
|
||||
* this function.
|
||||
*
|
||||
@@ -73,7 +73,7 @@ abstract contract ERC20Internal is Context, IERC20Errors {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
|
||||
* @dev Creates a `value` amount of _tokens and assigns them to `account`, by transferring it from address(0).
|
||||
* Relies on the `_update` mechanism
|
||||
*
|
||||
* Emits a {Transfer} event with `from` set to the zero address.
|
||||
@@ -88,7 +88,7 @@ abstract contract ERC20Internal is Context, IERC20Errors {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
|
||||
* @dev Destroys a `value` amount of _tokens from `account`, lowering the total supply.
|
||||
* Relies on the `_update` mechanism.
|
||||
*
|
||||
* Emits a {Transfer} event with `to` set to the zero address.
|
||||
@@ -103,7 +103,7 @@ abstract contract ERC20Internal is Context, IERC20Errors {
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens.
|
||||
* @dev Sets `value` as the allowance of `spender` over the `owner`'s _tokens.
|
||||
*
|
||||
* This internal function is equivalent to `approve`, and can be used to
|
||||
* e.g. set automatic allowances for certain subsystems, etc.
|
||||
|
||||
@@ -17,18 +17,18 @@ interface IPartyPlanner {
|
||||
/// @param name_ LP token name
|
||||
/// @param symbol_ LP token symbol
|
||||
/// @param _tokens token addresses (n)
|
||||
/// @param _bases scaling bases for each token (n) - used when converting to/from internal 64.64 amounts
|
||||
/// @param _bases scaling _bases for each token (n) - used when converting to/from internal 64.64 amounts
|
||||
/// @param _tradeFrac trade fraction in 64.64 fixed-point (as used by LMSR)
|
||||
/// @param _targetSlippage target slippage in 64.64 fixed-point (as used by LMSR)
|
||||
/// @param _swapFeePpm fee in parts-per-million, taken from swap input amounts before LMSR calculations
|
||||
/// @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 payer address that provides the initial token deposits
|
||||
/// @param receiver address that receives the minted LP tokens
|
||||
/// @param receiver address that receives the minted LP _tokens
|
||||
/// @param initialDeposits amounts of each token to deposit initially
|
||||
/// @param deadline Reverts if nonzero and the current blocktime is later than the deadline
|
||||
/// @return pool Address of the newly created and initialized PartyPool
|
||||
/// @return lpAmount Amount of LP tokens minted to the receiver
|
||||
/// @return lpAmount Amount of LP _tokens minted to the receiver
|
||||
function newPool(
|
||||
// Pool constructor args (legacy)
|
||||
string memory name_,
|
||||
@@ -52,17 +52,17 @@ interface IPartyPlanner {
|
||||
/// @param name_ LP token name
|
||||
/// @param symbol_ LP token symbol
|
||||
/// @param _tokens token addresses (n)
|
||||
/// @param _bases scaling bases for each token (n) - used when converting to/from internal 64.64 amounts
|
||||
/// @param _bases scaling _bases for each token (n) - used when converting to/from internal 64.64 amounts
|
||||
/// @param _kappa liquidity parameter κ in 64.64 fixed-point used to derive b = κ * S(q)
|
||||
/// @param _swapFeePpm fee in parts-per-million, taken from swap input amounts before LMSR calculations
|
||||
/// @param _flashFeePpm fee in parts-per-million, taken for flash loans
|
||||
/// @param _stable if true and assets.length==2, then the optimization for 2-asset stablecoin pools is activated
|
||||
/// @param payer address that provides the initial token deposits
|
||||
/// @param receiver address that receives the minted LP tokens
|
||||
/// @param receiver address that receives the minted LP _tokens
|
||||
/// @param initialDeposits amounts of each token to deposit initially
|
||||
/// @param deadline Reverts if nonzero and the current blocktime is later than the deadline
|
||||
/// @return pool Address of the newly created and initialized PartyPool
|
||||
/// @return lpAmount Amount of LP tokens minted to the receiver
|
||||
/// @return lpAmount Amount of LP _tokens minted to the receiver
|
||||
function newPool(
|
||||
// Pool constructor args (kappa-based)
|
||||
string memory name_,
|
||||
@@ -96,8 +96,8 @@ interface IPartyPlanner {
|
||||
/// @return pools Array of pool addresses for the requested page
|
||||
function getAllPools(uint256 offset, uint256 limit) external view returns (IPartyPool[] memory pools);
|
||||
|
||||
/// @notice Returns the total number of unique tokens
|
||||
/// @return The total count of unique tokens
|
||||
/// @notice Returns the total number of unique _tokens
|
||||
/// @return The total count of unique _tokens
|
||||
function tokenCount() external view returns (uint256);
|
||||
|
||||
/// @notice Retrieves a page of token addresses
|
||||
|
||||
@@ -11,12 +11,12 @@ import {IERC20} from "../lib/openzeppelin-contracts/contracts/token/ERC20/IERC20
|
||||
/// @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,
|
||||
/// - 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
|
||||
/// @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).
|
||||
@@ -44,7 +44,7 @@ interface IPartyPool is IERC20Metadata {
|
||||
address indexed payer,
|
||||
address indexed receiver,
|
||||
uint256 indexed inputTokenIndex,
|
||||
uint256 grossTransfer, // total tokens transferred (net + fee)
|
||||
uint256 grossTransfer, // total _tokens transferred (net + fee)
|
||||
uint256 netInput, // net input credited to swaps (after fee)
|
||||
uint256 feeTaken // fee taken (ceil)
|
||||
);
|
||||
@@ -62,10 +62,10 @@ interface IPartyPool is IERC20Metadata {
|
||||
function LMSR() external view returns (LMSRStabilized.State memory);
|
||||
|
||||
/// @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.
|
||||
/// @dev _tokens[i] corresponds to the i-th asset and maps to index i in the internal LMSR arrays.
|
||||
function getToken(uint256) external view returns (IERC20); // get single token
|
||||
|
||||
/// @notice Returns the number of tokens (n) in the pool.
|
||||
/// @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).
|
||||
@@ -75,7 +75,7 @@ interface IPartyPool is IERC20Metadata {
|
||||
function wrapperToken() external view returns (IWETH9);
|
||||
|
||||
/// @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.
|
||||
/// @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 Per-swap fee in parts-per-million (ppm). Fee is taken from input amounts before LMSR computations.
|
||||
@@ -88,10 +88,10 @@ interface IPartyPool is IERC20Metadata {
|
||||
/// @dev This is the fraction (in ppm) of the pool-collected fees that are owed to the protocol.
|
||||
function protocolFeePpm() external view returns (uint256);
|
||||
|
||||
/// @notice Address that will receive collected protocol tokens when collectProtocolFees() is called.
|
||||
/// @notice Address that will receive collected protocol _tokens when collectProtocolFees() is called.
|
||||
function protocolFeeAddress() external view returns (address);
|
||||
|
||||
/// @notice Protocol fee ledger accessor. Returns tokens owed (raw uint token units) from this pool as protocol fees
|
||||
/// @notice Protocol fee ledger accessor. Returns _tokens owed (raw uint token units) from this pool as protocol fees
|
||||
/// that have not yet been transferred out.
|
||||
function allProtocolFeesOwed() external view returns (uint256[] memory);
|
||||
|
||||
@@ -105,28 +105,28 @@ interface IPartyPool is IERC20Metadata {
|
||||
// Initialization / Mint / Burn (LP token managed)
|
||||
|
||||
/// @notice Initial mint to set up pool for the first time.
|
||||
/// @dev Assumes tokens have already been transferred to the pool prior to calling.
|
||||
/// Can only be called when the pool is uninitialized (totalSupply() == 0 or lmsr.nAssets == 0).
|
||||
/// @param receiver address that receives the LP tokens
|
||||
/// @param lpTokens The number of LP tokens to issue for this mint. If 0, then the number of tokens returned will equal the LMSR internal q total
|
||||
/// @dev Assumes _tokens have already been transferred to the pool prior to calling.
|
||||
/// Can only be called when the pool is uninitialized (totalSupply() == 0 or _lmsr.nAssets == 0).
|
||||
/// @param receiver address that receives the LP _tokens
|
||||
/// @param lpTokens The number of LP _tokens to issue for this mint. If 0, then the number of _tokens returned will equal the LMSR internal q total
|
||||
function initialMint(address receiver, uint256 lpTokens) external payable returns (uint256 lpMinted);
|
||||
|
||||
/// @notice Proportional mint (or initial supply if first call).
|
||||
/// @dev - For initial supply: assumes tokens have already been transferred to the pool prior to calling.
|
||||
/// @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)
|
||||
/// @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)
|
||||
/// @param deadline timestamp after which the transaction will revert. Pass 0 to ignore.
|
||||
/// @return lpMinted the actual amount of lpToken minted
|
||||
function mint(address payer, address receiver, uint256 lpTokenAmount, uint256 deadline) external payable returns (uint256 lpMinted);
|
||||
|
||||
/// @notice Burn LP tokens and withdraw the proportional basket to receiver.
|
||||
/// @notice Burn LP _tokens and withdraw the proportional basket to receiver.
|
||||
/// @dev This function forwards the call to the burn implementation via delegatecall
|
||||
/// @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)
|
||||
/// @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)
|
||||
/// @param deadline timestamp after which the transaction will revert. Pass 0 to ignore.
|
||||
/// @param unwrap if true and the native token is being withdrawn, it is unwraped and sent as native currency
|
||||
function burn(address payer, address receiver, uint256 lpAmount, uint256 deadline, bool unwrap) external returns (uint256[] memory withdrawAmounts);
|
||||
@@ -149,9 +149,9 @@ interface IPartyPool is IERC20Metadata {
|
||||
|
||||
/// @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.
|
||||
/// 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 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)
|
||||
@@ -173,7 +173,7 @@ interface IPartyPool is IERC20Metadata {
|
||||
/// @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 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)
|
||||
@@ -193,7 +193,7 @@ interface IPartyPool is IERC20Metadata {
|
||||
/// @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 receiver who receives the minted LP _tokens
|
||||
/// @param inputTokenIndex index of the input token
|
||||
/// @param maxAmountIn maximum uint token input (inclusive of fee)
|
||||
/// @param deadline optional deadline
|
||||
@@ -206,11 +206,11 @@ interface IPartyPool is IERC20Metadata {
|
||||
uint256 deadline
|
||||
) external payable returns (uint256 lpMinted);
|
||||
|
||||
/// @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
|
||||
/// @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 lpAmount amount of LP _tokens to burn
|
||||
/// @param inputTokenIndex index of target asset to receive
|
||||
/// @param deadline optional deadline
|
||||
/// @return amountOutUint uint amount of asset inputTokenIndex sent to receiver
|
||||
@@ -225,9 +225,9 @@ interface IPartyPool is IERC20Metadata {
|
||||
|
||||
/**
|
||||
* @dev Initiate a flash loan.
|
||||
* @param receiver The receiver of the tokens in the loan, and the receiver of the callback.
|
||||
* @param receiver The receiver of the _tokens in the loan, and the receiver of the callback.
|
||||
* @param token The loan currency.
|
||||
* @param amount The amount of tokens lent.
|
||||
* @param amount The amount of _tokens lent.
|
||||
* @param data Arbitrary data structure, intended to contain user-defined parameters.
|
||||
*/
|
||||
function flashLoan(
|
||||
|
||||
@@ -22,9 +22,9 @@ interface IPartyPoolViewer {
|
||||
|
||||
/// @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
|
||||
/// 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 mintAmounts(IPartyPool pool, uint256 lpTokenAmount) external view returns (uint256[] memory depositAmounts);
|
||||
|
||||
@@ -51,7 +51,7 @@ interface IPartyPoolViewer {
|
||||
|
||||
/// @notice Calculate the amounts for a burn swap operation
|
||||
/// @dev This is a pure view function that computes burn swap amounts from provided state
|
||||
/// @param lpAmount amount of LP tokens to burn
|
||||
/// @param lpAmount amount of LP _tokens to burn
|
||||
/// @param inputTokenIndex index of target asset to receive
|
||||
function burnSwapAmounts(IPartyPool pool, uint256 lpAmount, uint256 inputTokenIndex) external view
|
||||
returns (uint256 amountOut);
|
||||
@@ -71,7 +71,7 @@ interface IPartyPoolViewer {
|
||||
|
||||
/**
|
||||
* @dev The fee to be charged for a given loan.
|
||||
* @param amount The amount of tokens lent.
|
||||
* @param amount The amount of _tokens lent.
|
||||
* @return fee The amount of `token` to be charged for the loan, on top of the returned principal.
|
||||
*/
|
||||
function flashFee(IPartyPool pool, address token, uint256 amount) external view returns (uint256 fee);
|
||||
|
||||
@@ -119,7 +119,7 @@ contract PartyPlanner is IPartyPlanner {
|
||||
_allPools.push(pool);
|
||||
_poolSupported[pool] = true;
|
||||
|
||||
// Track tokens and populate mappings
|
||||
// Track _tokens and populate mappings
|
||||
for (uint256 i = 0; i < _tokens.length; i++) {
|
||||
IERC20 token = _tokens[i];
|
||||
|
||||
@@ -135,7 +135,7 @@ contract PartyPlanner is IPartyPlanner {
|
||||
|
||||
emit PartyStarted(pool, name_, symbol_, _tokens);
|
||||
|
||||
// Transfer initial tokens from payer to the pool
|
||||
// Transfer initial _tokens from payer to the pool
|
||||
for (uint256 i = 0; i < _tokens.length; i++) {
|
||||
if (initialDeposits[i] > 0) {
|
||||
IERC20(_tokens[i]).safeTransferFrom(payer, address(pool), initialDeposits[i]);
|
||||
@@ -143,7 +143,7 @@ contract PartyPlanner is IPartyPlanner {
|
||||
}
|
||||
}
|
||||
|
||||
// Call mint on the new pool to initialize it with the transferred tokens
|
||||
// Call mint on the new pool to initialize it with the transferred _tokens
|
||||
lpAmount = pool.initialMint(receiver, initialLpAmount);
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ contract PartyPlanner is IPartyPlanner {
|
||||
return new address[](0);
|
||||
}
|
||||
|
||||
// Calculate actual number of tokens to return (respecting bounds)
|
||||
// Calculate actual number of _tokens to return (respecting bounds)
|
||||
uint256 itemsToReturn = (offset + limit > totalTokens) ? (totalTokens - offset) : limit;
|
||||
|
||||
// Create result array of appropriate size
|
||||
|
||||
@@ -23,12 +23,12 @@ import {IWETH9} from "./IWETH9.sol";
|
||||
/// @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,
|
||||
/// - 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
|
||||
/// @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).
|
||||
@@ -59,12 +59,12 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
|
||||
uint256 private immutable PROTOCOL_FEE_PPM;
|
||||
function protocolFeePpm() external view returns (uint256) { return PROTOCOL_FEE_PPM; }
|
||||
|
||||
/// @notice Address to which collected protocol tokens will be sent on collectProtocolFees()
|
||||
/// @notice Address to which collected protocol _tokens will be sent on collectProtocolFees()
|
||||
address private immutable PROTOCOL_FEE_ADDRESS;
|
||||
function protocolFeeAddress() external view returns (address) { return PROTOCOL_FEE_ADDRESS; }
|
||||
|
||||
// @inheritdoc IPartyPool
|
||||
function allProtocolFeesOwed() external view returns (uint256[] memory) { return protocolFeesOwed; }
|
||||
function allProtocolFeesOwed() external view returns (uint256[] memory) { return _protocolFeesOwed; }
|
||||
|
||||
/// @notice Address of the Mint implementation contract for delegatecall
|
||||
PartyPoolMintImpl private immutable MINT_IMPL;
|
||||
@@ -76,24 +76,24 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
|
||||
|
||||
|
||||
/// @inheritdoc IPartyPool
|
||||
function getToken(uint256 i) external view returns (IERC20) { return tokens[i]; }
|
||||
function getToken(uint256 i) external view returns (IERC20) { return _tokens[i]; }
|
||||
|
||||
/// @inheritdoc IPartyPool
|
||||
function numTokens() external view returns (uint256) { return tokens.length; }
|
||||
function numTokens() external view returns (uint256) { return _tokens.length; }
|
||||
|
||||
/// @inheritdoc IPartyPool
|
||||
function allTokens() external view returns (IERC20[] memory) { return tokens; }
|
||||
function allTokens() external view returns (IERC20[] memory) { return _tokens; }
|
||||
|
||||
/// @inheritdoc IPartyPool
|
||||
function denominators() external view returns (uint256[] memory) { return bases; }
|
||||
function denominators() external view returns (uint256[] memory) { return _bases; }
|
||||
|
||||
function LMSR() external view returns (LMSRStabilized.State memory) { return lmsr; }
|
||||
function LMSR() external view returns (LMSRStabilized.State memory) { return _lmsr; }
|
||||
|
||||
|
||||
/// @param name_ LP token name
|
||||
/// @param symbol_ LP token symbol
|
||||
/// @param tokens_ token addresses (n)
|
||||
/// @param bases_ scaling bases for each token (n) - used when converting to/from internal 64.64 amounts
|
||||
/// @param 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
|
||||
@@ -107,8 +107,8 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
|
||||
int128 kappa_,
|
||||
uint256 swapFeePpm_,
|
||||
uint256 flashFeePpm_,
|
||||
uint256 protocolFeePpm_, // NEW: protocol share of fees (ppm)
|
||||
address protocolFeeAddress_, // NEW: recipient for collected protocol tokens
|
||||
uint256 protocolFeePpm_,
|
||||
address protocolFeeAddress_,
|
||||
IWETH9 wrapperToken_,
|
||||
PartyPoolSwapImpl swapImpl_,
|
||||
PartyPoolMintImpl mintImpl_
|
||||
@@ -118,14 +118,16 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
|
||||
{
|
||||
require(tokens_.length > 1, "Pool: need >1 asset");
|
||||
require(tokens_.length == bases_.length, "Pool: lengths mismatch");
|
||||
tokens = tokens_;
|
||||
bases = bases_;
|
||||
_tokens = tokens_;
|
||||
_bases = bases_;
|
||||
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_;
|
||||
require(protocolFeePpm_ < 1_000_000, "Pool: protocol fee >= ppm");
|
||||
// If the protocolFeePpm_ is set, then also require the fee address to be nonzero
|
||||
require(protocolFeePpm_ == 0 || protocolFeeAddress_ != address(0));
|
||||
PROTOCOL_FEE_PPM = protocolFeePpm_;
|
||||
PROTOCOL_FEE_ADDRESS = protocolFeeAddress_;
|
||||
SWAP_IMPL = swapImpl_;
|
||||
@@ -134,17 +136,17 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
|
||||
uint256 n = tokens_.length;
|
||||
|
||||
// Initialize LMSR state nAssets; full init occurs on first mint when quantities are known.
|
||||
lmsr.nAssets = n;
|
||||
_lmsr.nAssets = n;
|
||||
|
||||
// Initialize token address to index mapping
|
||||
for (uint i = 0; i < n;) {
|
||||
tokenAddressToIndexPlusOne[tokens_[i]] = i + 1;
|
||||
_tokenAddressToIndexPlusOne[tokens_[i]] = i + 1;
|
||||
unchecked {i++;}
|
||||
}
|
||||
|
||||
// Initialize caches to zero and protocol ledger
|
||||
cachedUintBalances = new uint256[](n);
|
||||
protocolFeesOwed = new uint256[](n);
|
||||
_cachedUintBalances = new uint256[](n);
|
||||
_protocolFeesOwed = new uint256[](n);
|
||||
}
|
||||
|
||||
|
||||
@@ -167,9 +169,9 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
|
||||
|
||||
/// @notice Proportional mint for existing pool.
|
||||
/// @dev This function forwards the call to the mint implementation via delegatecall
|
||||
/// @param payer address that provides the input tokens
|
||||
/// @param receiver address that receives the LP tokens
|
||||
/// @param lpTokenAmount desired amount of LP tokens to mint
|
||||
/// @param payer address that provides the input _tokens
|
||||
/// @param receiver address that receives the LP _tokens
|
||||
/// @param lpTokenAmount desired amount of LP _tokens to mint
|
||||
/// @param deadline timestamp after which the transaction will revert. Pass 0 to ignore.
|
||||
function mint(address payer, address receiver, uint256 lpTokenAmount, uint256 deadline) external payable
|
||||
returns (uint256 lpMinted) {
|
||||
@@ -231,36 +233,36 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
|
||||
_quoteSwapExactIn(inputTokenIndex, outputTokenIndex, maxAmountIn, limitPrice);
|
||||
|
||||
// Cache token references for fewer SLOADs
|
||||
IERC20 tokenIn = tokens[inputTokenIndex];
|
||||
IERC20 tokenOut = tokens[outputTokenIndex];
|
||||
IERC20 tokenIn = _tokens[inputTokenIndex];
|
||||
IERC20 tokenOut = _tokens[outputTokenIndex];
|
||||
|
||||
// Transfer tokens in via centralized helper
|
||||
// Transfer _tokens in via centralized helper
|
||||
_receiveTokenFrom(payer, tokenIn, totalTransferAmount);
|
||||
|
||||
// Compute on-chain balances as: onchain = cached + owed (+/- transfer)
|
||||
uint256 balIAfter = cachedUintBalances[inputTokenIndex] + protocolFeesOwed[inputTokenIndex] + totalTransferAmount;
|
||||
uint256 balJAfter = cachedUintBalances[outputTokenIndex] + protocolFeesOwed[outputTokenIndex] - amountOutUint;
|
||||
|
||||
// Transfer output to receiver via centralized helper
|
||||
_sendTokenTo(tokenOut, receiver, amountOutUint, unwrap);
|
||||
uint256 balIAfter = _cachedUintBalances[inputTokenIndex] + _protocolFeesOwed[inputTokenIndex] + totalTransferAmount;
|
||||
uint256 balJAfter = _cachedUintBalances[outputTokenIndex] + _protocolFeesOwed[outputTokenIndex] - amountOutUint;
|
||||
|
||||
// Accrue protocol share (floor) from the fee on input token
|
||||
if (PROTOCOL_FEE_PPM > 0 && feeUint > 0) {
|
||||
uint256 protoShare = (feeUint * PROTOCOL_FEE_PPM) / 1_000_000; // floor
|
||||
if (protoShare > 0) {
|
||||
protocolFeesOwed[inputTokenIndex] += protoShare;
|
||||
_protocolFeesOwed[inputTokenIndex] += protoShare;
|
||||
}
|
||||
}
|
||||
|
||||
// Inline _recordCachedBalance: ensure onchain >= owed then set cached = onchain - owed
|
||||
require(balIAfter >= protocolFeesOwed[inputTokenIndex], "balance < protocol owed");
|
||||
cachedUintBalances[inputTokenIndex] = balIAfter - protocolFeesOwed[inputTokenIndex];
|
||||
require(balIAfter >= _protocolFeesOwed[inputTokenIndex], "balance < protocol owed");
|
||||
_cachedUintBalances[inputTokenIndex] = balIAfter - _protocolFeesOwed[inputTokenIndex];
|
||||
|
||||
require(balJAfter >= protocolFeesOwed[outputTokenIndex], "balance < protocol owed");
|
||||
cachedUintBalances[outputTokenIndex] = balJAfter - protocolFeesOwed[outputTokenIndex];
|
||||
require(balJAfter >= _protocolFeesOwed[outputTokenIndex], "balance < protocol owed");
|
||||
_cachedUintBalances[outputTokenIndex] = balJAfter - _protocolFeesOwed[outputTokenIndex];
|
||||
|
||||
// Apply swap to LMSR state with the internal amounts actually used
|
||||
lmsr.applySwap(inputTokenIndex, outputTokenIndex, amountInInternalUsed, amountOutInternal);
|
||||
_lmsr.applySwap(inputTokenIndex, outputTokenIndex, amountInInternalUsed, amountOutInternal);
|
||||
|
||||
// Transfer output to receiver near the end
|
||||
_sendTokenTo(tokenOut, receiver, amountOutUint, unwrap);
|
||||
|
||||
emit Swap(payer, receiver, tokenIn, tokenOut, totalTransferAmount, amountOutUint);
|
||||
|
||||
@@ -289,13 +291,13 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
|
||||
uint256 feeUint
|
||||
)
|
||||
{
|
||||
uint256 n = tokens.length;
|
||||
uint256 n = _tokens.length;
|
||||
|
||||
// Estimate max net input (fee on gross rounded up, then subtract)
|
||||
(, uint256 netUintForSwap) = _computeFee(maxAmountIn, SWAP_FEE_PPM);
|
||||
|
||||
// Convert to internal (floor)
|
||||
int128 deltaInternalI = _uintToInternalFloor(netUintForSwap, bases[inputTokenIndex]);
|
||||
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)
|
||||
@@ -303,7 +305,7 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
|
||||
(amountInInternalUsed, amountOutInternal) = _swapAmountsForExactInput(inputTokenIndex, outputTokenIndex, deltaInternalI, limitPrice);
|
||||
|
||||
// Convert actual used input internal -> uint (ceil)
|
||||
amountInUintNoFee = _internalToUintCeil(amountInInternalUsed, bases[inputTokenIndex]);
|
||||
amountInUintNoFee = _internalToUintCeil(amountInInternalUsed, _bases[inputTokenIndex]);
|
||||
|
||||
// Compute gross transfer including fee on the used input (ceil)
|
||||
feeUint = 0;
|
||||
@@ -317,7 +319,7 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
|
||||
require(grossIn <= maxAmountIn, "swap: transfer exceeds max");
|
||||
|
||||
// Compute output (floor)
|
||||
amountOutUint = _internalToUintFloor(amountOutInternal, bases[outputTokenIndex]);
|
||||
amountOutUint = _internalToUintFloor(amountOutInternal, _bases[outputTokenIndex]);
|
||||
}
|
||||
|
||||
|
||||
@@ -351,7 +353,7 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
|
||||
/// @notice Single-token mint: deposit a single token, charge swap-LMSR cost, and mint LP.
|
||||
/// @dev This function forwards the call to the swapMint implementation via delegatecall
|
||||
/// @param payer who transfers the input token
|
||||
/// @param receiver who receives the minted LP tokens
|
||||
/// @param receiver who receives the minted LP _tokens
|
||||
/// @param inputTokenIndex index of the input token
|
||||
/// @param maxAmountIn maximum uint token input (inclusive of fee)
|
||||
/// @param deadline optional deadline
|
||||
@@ -378,11 +380,11 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
|
||||
return abi.decode(result, (uint256));
|
||||
}
|
||||
|
||||
/// @notice Burn LP tokens then swap the redeemed proportional basket into a single asset `inputTokenIndex` and send to receiver.
|
||||
/// @notice Burn LP _tokens then swap the redeemed proportional basket into a single asset `inputTokenIndex` and send to receiver.
|
||||
/// @dev This function forwards the call to the burnSwap implementation via delegatecall
|
||||
/// @param payer who burns LP tokens
|
||||
/// @param payer who burns LP _tokens
|
||||
/// @param receiver who receives the single asset
|
||||
/// @param lpAmount amount of LP tokens to burn
|
||||
/// @param lpAmount amount of LP _tokens to burn
|
||||
/// @param inputTokenIndex index of target asset to receive
|
||||
/// @param deadline optional deadline
|
||||
/// @return amountOutUint uint amount of asset i sent to receiver
|
||||
@@ -414,10 +416,10 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
|
||||
bytes32 internal constant FLASH_CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan");
|
||||
|
||||
/**
|
||||
* @dev Loan `amount` tokens to `receiver`, and takes it back plus a `flashFee` after the callback.
|
||||
* @param receiver The contract receiving the tokens, needs to implement the `onFlashLoan(address user, uint256 amount, uint256 fee, bytes calldata)` interface.
|
||||
* @dev Loan `amount` _tokens to `receiver`, and takes it back plus a `flashFee` after the callback.
|
||||
* @param receiver The contract receiving the _tokens, needs to implement the `onFlashLoan(address user, uint256 amount, uint256 fee, bytes calldata)` interface.
|
||||
* @param tokenAddr The loan currency.
|
||||
* @param amount The amount of tokens lent.
|
||||
* @param amount The amount of _tokens lent.
|
||||
* @param data A data parameter to be passed on to the `receiver` for any custom use.
|
||||
*/
|
||||
function flashLoan(
|
||||
@@ -429,26 +431,28 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
|
||||
{
|
||||
IERC20 token = IERC20(tokenAddr);
|
||||
require(amount <= token.balanceOf(address(this)));
|
||||
uint256 tokenIndex = tokenAddressToIndexPlusOne[token] - 1;
|
||||
uint256 tokenIndex = _tokenAddressToIndexPlusOne[token];
|
||||
require(tokenIndex != 0, 'flash: token not in pool');
|
||||
tokenIndex -= 1;
|
||||
(uint256 fee, ) = _computeFee(amount, FLASH_FEE_PPM);
|
||||
|
||||
// Compute protocol share of flash fee
|
||||
if (PROTOCOL_FEE_PPM > 0 && fee > 0) {
|
||||
uint256 protoShare = (fee * PROTOCOL_FEE_PPM) / 1_000_000; // floor
|
||||
if (protoShare > 0) {
|
||||
protocolFeesOwed[tokenIndex] += protoShare;
|
||||
_protocolFeesOwed[tokenIndex] += protoShare;
|
||||
}
|
||||
}
|
||||
|
||||
_sendTokenTo(token, address(receiver), amount, false);
|
||||
require(receiver.onFlashLoan(msg.sender, address(token), amount, fee, data) == FLASH_CALLBACK_SUCCESS);
|
||||
require(receiver.onFlashLoan(address(receiver), address(token), amount, fee, data) == FLASH_CALLBACK_SUCCESS);
|
||||
_receiveTokenFrom(address(receiver), token, amount + fee);
|
||||
|
||||
// Update cached balance for the borrowed token
|
||||
uint256 balAfter = token.balanceOf(address(this));
|
||||
// Inline _recordCachedBalance logic
|
||||
require(balAfter >= protocolFeesOwed[tokenIndex], "balance < protocol owed");
|
||||
cachedUintBalances[tokenIndex] = balAfter - protocolFeesOwed[tokenIndex];
|
||||
require(balAfter >= _protocolFeesOwed[tokenIndex], "balance < protocol owed");
|
||||
_cachedUintBalances[tokenIndex] = balAfter - _protocolFeesOwed[tokenIndex];
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -460,23 +464,23 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
|
||||
address dest = PROTOCOL_FEE_ADDRESS;
|
||||
require(dest != address(0), "collect: zero addr");
|
||||
|
||||
uint256 n = tokens.length;
|
||||
uint256 n = _tokens.length;
|
||||
for (uint256 i = 0; i < n; i++) {
|
||||
uint256 owed = protocolFeesOwed[i];
|
||||
uint256 owed = _protocolFeesOwed[i];
|
||||
if (owed == 0) continue;
|
||||
uint256 bal = IERC20(tokens[i]).balanceOf(address(this));
|
||||
uint256 bal = IERC20(_tokens[i]).balanceOf(address(this));
|
||||
require(bal >= owed, "collect: fee > bal");
|
||||
protocolFeesOwed[i] = 0;
|
||||
// transfer owed tokens to protocol destination via centralized helper
|
||||
_sendTokenTo(tokens[i], dest, owed, false);
|
||||
_protocolFeesOwed[i] = 0;
|
||||
// update cached to effective onchain minus owed
|
||||
cachedUintBalances[i] = bal - owed;
|
||||
_cachedUintBalances[i] = bal - owed;
|
||||
// transfer owed _tokens to protocol destination via centralized helper
|
||||
_sendTokenTo(_tokens[i], dest, owed, false);
|
||||
}
|
||||
}
|
||||
|
||||
function _swapAmountsForExactInput(uint256 i, uint256 j, int128 a, int128 limitPrice) internal virtual view
|
||||
returns (int128 amountIn, int128 amountOut) {
|
||||
return lmsr.swapAmountsForExactInput(i, j, a, limitPrice);
|
||||
return _lmsr.swapAmountsForExactInput(i, j, a, limitPrice);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,6 +28,6 @@ contract PartyPoolBalancedPair is PartyPool {
|
||||
|
||||
function _swapAmountsForExactInput(uint256 i, uint256 j, int128 a, int128 limitPrice) internal virtual override view
|
||||
returns (int128 amountIn, int128 amountOut) {
|
||||
return LMSRStabilizedBalancedPair.swapAmountsForExactInput(lmsr, i, j, a, limitPrice);
|
||||
return LMSRStabilizedBalancedPair.swapAmountsForExactInput(_lmsr, i, j, a, limitPrice);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,31 +37,31 @@ abstract contract PartyPoolBase is ERC20Internal, ReentrancyGuard, PartyPoolHelp
|
||||
//
|
||||
|
||||
// LMSR internal state
|
||||
LMSRStabilized.State internal lmsr;
|
||||
LMSRStabilized.State internal _lmsr;
|
||||
|
||||
/// @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).
|
||||
/// @dev LP _tokens are minted in units equal to ABDK.mulu(lastTotalQ64x64, LP_SCALE).
|
||||
uint256 internal constant LP_SCALE = 1e18; // Scale used to convert LMSR lastTotal (Q64.64) into LP token units (uint)
|
||||
|
||||
/// @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.
|
||||
IERC20[] internal tokens; // effectively immutable since there is no interface to change the tokens
|
||||
/// @dev _tokens[i] corresponds to the i-th asset and maps to index i in the internal LMSR arrays.
|
||||
IERC20[] internal _tokens; // effectively immutable since there is no interface to change the _tokens
|
||||
|
||||
/// @notice Amounts of token owed as protocol fees but not yet collected. Subtract this amount from the pool's token
|
||||
/// balances to compute the tokens owned by LP's.
|
||||
uint256[] internal protocolFeesOwed;
|
||||
/// balances to compute the _tokens owned by LP's.
|
||||
uint256[] internal _protocolFeesOwed;
|
||||
|
||||
/// @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
|
||||
/// @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
|
||||
|
||||
/// @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(IERC20=>uint) internal tokenAddressToIndexPlusOne; // Uses index+1 so a result of 0 indicates a failed lookup
|
||||
/// @dev Use index = _tokenAddressToIndexPlusOne[token] - 1 when non-zero.
|
||||
mapping(IERC20=>uint) internal _tokenAddressToIndexPlusOne; // Uses index+1 so a result of 0 indicates a failed lookup
|
||||
|
||||
// Cached on-chain balances (uint) and internal 64.64 representation
|
||||
// balance / base = internal
|
||||
uint256[] internal cachedUintBalances;
|
||||
uint256[] internal _cachedUintBalances;
|
||||
|
||||
|
||||
/* ----------------------
|
||||
@@ -100,9 +100,9 @@ abstract contract PartyPoolBase is ERC20Internal, ReentrancyGuard, PartyPoolHelp
|
||||
Token transfer helpers (includes autowrap)
|
||||
---------------------- */
|
||||
|
||||
/// @notice Receive tokens from `payer` into the pool (address(this)) using SafeERC20 semantics.
|
||||
/// @notice Receive _tokens from `payer` into the pool (address(this)) using SafeERC20 semantics.
|
||||
/// @dev Note: this helper does NOT query the on-chain balance after transfer to save gas.
|
||||
/// Callers should query the balance themselves when they need it (e.g., to detect fee-on-transfer tokens).
|
||||
/// Callers should query the balance themselves when they need it (e.g., to detect fee-on-transfer _tokens).
|
||||
function _receiveTokenFrom(address payer, IERC20 token, uint256 amount) internal {
|
||||
if( token == WRAPPER_TOKEN && msg.value >= amount )
|
||||
WRAPPER_TOKEN.deposit{value:amount}();
|
||||
@@ -110,9 +110,9 @@ abstract contract PartyPoolBase is ERC20Internal, ReentrancyGuard, PartyPoolHelp
|
||||
token.safeTransferFrom(payer, address(this), amount);
|
||||
}
|
||||
|
||||
/// @notice Send tokens from the pool to `receiver` using SafeERC20 semantics.
|
||||
/// @notice Send _tokens from the pool to `receiver` using SafeERC20 semantics.
|
||||
/// @dev Note: this helper does NOT query the on-chain balance after transfer to save gas.
|
||||
/// Callers should query the balance themselves when they need it (e.g., to detect fee-on-transfer tokens).
|
||||
/// Callers should query the balance themselves when they need it (e.g., to detect fee-on-transfer _tokens).
|
||||
function _sendTokenTo(IERC20 token, address receiver, uint256 amount, bool unwrap) internal {
|
||||
if( unwrap && token == WRAPPER_TOKEN ) {
|
||||
WRAPPER_TOKEN.withdraw(amount);
|
||||
|
||||
@@ -3,7 +3,6 @@ pragma solidity ^0.8.30;
|
||||
|
||||
import {ABDKMath64x64} from "../lib/abdk-libraries-solidity/ABDKMath64x64.sol";
|
||||
|
||||
|
||||
abstract contract PartyPoolHelpers {
|
||||
using ABDKMath64x64 for int128;
|
||||
|
||||
@@ -27,21 +26,12 @@ abstract contract PartyPoolHelpers {
|
||||
netUint = gross - feeUint;
|
||||
}
|
||||
|
||||
/// @notice Convenience: return gross = net + fee(net) using ceiling for fee.
|
||||
/// @param netUint net amount
|
||||
/// @param feePpm fee in ppm to apply
|
||||
function _addFee(uint256 netUint, uint256 feePpm) internal pure returns (uint256 gross) {
|
||||
if (feePpm == 0) return netUint;
|
||||
uint256 fee = _ceilFee(netUint, feePpm);
|
||||
return netUint + fee;
|
||||
}
|
||||
|
||||
/// @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_) internal pure returns (int128) {
|
||||
/// @dev Returns the sum of all provided qInternal entries as a Q64.64 value.
|
||||
function _computeSizeMetric(int128[] memory qInternal) internal pure returns (int128) {
|
||||
int128 total = int128(0);
|
||||
for (uint i = 0; i < qInternal_.length; ) {
|
||||
total = total.add(qInternal_[i]);
|
||||
for (uint i = 0; i < qInternal.length; ) {
|
||||
total = total.add(qInternal[i]);
|
||||
unchecked { i++; }
|
||||
}
|
||||
return total;
|
||||
|
||||
@@ -27,27 +27,27 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
|
||||
function initialMint(address receiver, uint256 lpTokens, int128 KAPPA) external payable native nonReentrant
|
||||
returns (uint256 lpMinted) {
|
||||
uint256 n = tokens.length;
|
||||
uint256 n = _tokens.length;
|
||||
|
||||
// Check if this is initial deposit - revert if not
|
||||
bool isInitialDeposit = _totalSupply == 0 || lmsr.nAssets == 0;
|
||||
bool isInitialDeposit = _totalSupply == 0 || _lmsr.nAssets == 0;
|
||||
require(isInitialDeposit, "initialMint: pool already initialized");
|
||||
|
||||
// Update cached balances for all assets
|
||||
int128[] memory newQInternal = new int128[](n);
|
||||
uint256[] memory depositAmounts = new uint256[](n);
|
||||
for (uint i = 0; i < n; ) {
|
||||
uint256 bal = IERC20(tokens[i]).balanceOf(address(this));
|
||||
cachedUintBalances[i] = bal;
|
||||
newQInternal[i] = _uintToInternalFloor(bal, bases[i]);
|
||||
uint256 bal = IERC20(_tokens[i]).balanceOf(address(this));
|
||||
_cachedUintBalances[i] = bal;
|
||||
newQInternal[i] = _uintToInternalFloor(bal, _bases[i]);
|
||||
depositAmounts[i] = bal;
|
||||
unchecked { i++; }
|
||||
}
|
||||
|
||||
// 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)
|
||||
// Compute actual LP _tokens to mint based on size metric (scaled)
|
||||
if( lpTokens != 0 )
|
||||
lpMinted = lpTokens;
|
||||
else {
|
||||
@@ -68,24 +68,24 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
function mint(address payer, address receiver, uint256 lpTokenAmount, uint256 deadline) external payable native nonReentrant
|
||||
returns (uint256 lpMinted) {
|
||||
require(deadline == 0 || block.timestamp <= deadline, "mint: deadline exceeded");
|
||||
uint256 n = tokens.length;
|
||||
uint256 n = _tokens.length;
|
||||
|
||||
// Check if this is NOT initial deposit - revert if it is
|
||||
bool isInitialDeposit = _totalSupply == 0 || lmsr.nAssets == 0;
|
||||
bool isInitialDeposit = _totalSupply == 0 || _lmsr.nAssets == 0;
|
||||
require(!isInitialDeposit, "mint: use initialMint for pool initialization");
|
||||
require(lpTokenAmount > 0, "mint: zero LP amount");
|
||||
|
||||
// Capture old pool size metric (scaled) by computing from current balances
|
||||
int128 oldTotal = _computeSizeMetric(lmsr.qInternal);
|
||||
int128 oldTotal = _computeSizeMetric(_lmsr.qInternal);
|
||||
uint256 oldScaled = ABDKMath64x64.mulu(oldTotal, LP_SCALE);
|
||||
|
||||
// Calculate required deposit amounts for the desired LP tokens
|
||||
uint256[] memory depositAmounts = mintAmounts(lpTokenAmount, lmsr.nAssets, _totalSupply, cachedUintBalances);
|
||||
// Calculate required deposit amounts for the desired LP _tokens
|
||||
uint256[] memory depositAmounts = mintAmounts(lpTokenAmount, _lmsr.nAssets, _totalSupply, _cachedUintBalances);
|
||||
|
||||
// Transfer in all token amounts
|
||||
for (uint i = 0; i < n; ) {
|
||||
if (depositAmounts[i] > 0) {
|
||||
_receiveTokenFrom(payer, tokens[i], depositAmounts[i]);
|
||||
_receiveTokenFrom(payer, _tokens[i], depositAmounts[i]);
|
||||
}
|
||||
unchecked { i++; }
|
||||
}
|
||||
@@ -93,16 +93,16 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
// Update cached balances and internal q for all assets using depositAmounts
|
||||
int128[] memory newQInternal = new int128[](n);
|
||||
for (uint i = 0; i < n; ) {
|
||||
uint256 newBal = cachedUintBalances[i] + depositAmounts[i];
|
||||
cachedUintBalances[i] = newBal;
|
||||
newQInternal[i] = _uintToInternalFloor(newBal, bases[i]);
|
||||
uint256 newBal = _cachedUintBalances[i] + depositAmounts[i];
|
||||
_cachedUintBalances[i] = newBal;
|
||||
newQInternal[i] = _uintToInternalFloor(newBal, _bases[i]);
|
||||
unchecked { i++; }
|
||||
}
|
||||
|
||||
// Update for proportional change
|
||||
lmsr.updateForProportionalChange(newQInternal);
|
||||
_lmsr.updateForProportionalChange(newQInternal);
|
||||
|
||||
// Compute actual LP tokens to mint based on change in size metric (scaled)
|
||||
// Compute actual LP _tokens to mint based on change in size metric (scaled)
|
||||
// floor truncation rounds in favor of the pool
|
||||
int128 newTotal = _computeSizeMetric(newQInternal);
|
||||
uint256 newScaled = ABDKMath64x64.mulu(newTotal, LP_SCALE);
|
||||
@@ -131,18 +131,18 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
return actualLpToMint;
|
||||
}
|
||||
|
||||
/// @notice Burn LP tokens and withdraw the proportional basket to receiver.
|
||||
/// @dev Payer must own or approve the LP tokens being burned. The function updates LMSR state
|
||||
/// @notice Burn LP _tokens and withdraw the proportional basket to receiver.
|
||||
/// @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)
|
||||
/// @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)
|
||||
/// @param deadline timestamp after which the transaction will revert. Pass 0 to ignore.
|
||||
/// @param unwrap if true and the native token is being withdrawn, it is unwraped and sent as native currency
|
||||
function burn(address payer, address receiver, uint256 lpAmount, uint256 deadline, bool unwrap) external nonReentrant
|
||||
returns (uint256[] memory withdrawAmounts) {
|
||||
require(deadline == 0 || block.timestamp <= deadline, "burn: deadline exceeded");
|
||||
uint256 n = tokens.length;
|
||||
uint256 n = _tokens.length;
|
||||
require(lpAmount > 0, "burn: zero lp");
|
||||
|
||||
uint256 supply = _totalSupply;
|
||||
@@ -151,12 +151,12 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
// Use cached balances; assume standard ERC20 transfers without external interference
|
||||
|
||||
// Compute proportional withdrawal amounts for the requested LP amount (rounded down)
|
||||
withdrawAmounts = burnAmounts(lpAmount, lmsr.nAssets, _totalSupply, cachedUintBalances);
|
||||
withdrawAmounts = burnAmounts(lpAmount, _lmsr.nAssets, _totalSupply, _cachedUintBalances);
|
||||
|
||||
// Transfer underlying tokens out to receiver according to computed proportions
|
||||
// Transfer underlying _tokens out to receiver according to computed proportions
|
||||
for (uint i = 0; i < n; ) {
|
||||
if (withdrawAmounts[i] > 0) {
|
||||
_sendTokenTo(tokens[i], receiver, withdrawAmounts[i], unwrap);
|
||||
_sendTokenTo(_tokens[i], receiver, withdrawAmounts[i], unwrap);
|
||||
}
|
||||
unchecked { i++; }
|
||||
}
|
||||
@@ -164,9 +164,9 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
// Update cached balances and internal q for all assets using computed withdrawals
|
||||
int128[] memory newQInternal = new int128[](n);
|
||||
for (uint i = 0; i < n; ) {
|
||||
uint256 newBal = cachedUintBalances[i] - withdrawAmounts[i];
|
||||
cachedUintBalances[i] = newBal;
|
||||
newQInternal[i] = _uintToInternalFloor(newBal, bases[i]);
|
||||
uint256 newBal = _cachedUintBalances[i] - withdrawAmounts[i];
|
||||
_cachedUintBalances[i] = newBal;
|
||||
newQInternal[i] = _uintToInternalFloor(newBal, _bases[i]);
|
||||
unchecked { i++; }
|
||||
}
|
||||
|
||||
@@ -181,9 +181,9 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
}
|
||||
|
||||
if (allZero) {
|
||||
lmsr.deinit();
|
||||
_lmsr.deinit();
|
||||
} else {
|
||||
lmsr.updateForProportionalChange(newQInternal);
|
||||
_lmsr.updateForProportionalChange(newQInternal);
|
||||
}
|
||||
|
||||
// Burn exactly the requested LP amount from payer (authorization via allowance)
|
||||
@@ -199,9 +199,9 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
|
||||
/// @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
|
||||
/// 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 mintAmounts(uint256 lpTokenAmount,
|
||||
uint256 numAssets, uint256 totalSupply, uint256[] memory cachedUintBalances) public pure
|
||||
@@ -209,7 +209,7 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
depositAmounts = new uint256[](numAssets);
|
||||
|
||||
// If this is the first mint or pool is empty, return zeros
|
||||
// For first mint, tokens should already be transferred to the pool
|
||||
// For first mint, _tokens should already be transferred to the pool
|
||||
if (totalSupply == 0 || numAssets == 0) {
|
||||
return depositAmounts; // Return zeros, initial deposit handled differently
|
||||
}
|
||||
@@ -256,11 +256,11 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
/// @param maxAmountIn maximum amount of token to deposit (inclusive of fee)
|
||||
/// @param swapFeePpm fee in parts-per-million
|
||||
/// @param lmsrState current LMSR state
|
||||
/// @param bases_ scaling bases for each token
|
||||
/// @param bases_ scaling _bases for each token
|
||||
/// @param totalSupply_ current total LP token supply
|
||||
/// @return amountInUsed actual input amount used (excluding fee)
|
||||
/// @return fee fee amount charged
|
||||
/// @return lpMinted LP tokens that would be minted
|
||||
/// @return lpMinted LP _tokens that would be minted
|
||||
function swapMintAmounts(
|
||||
uint256 inputTokenIndex,
|
||||
uint256 maxAmountIn,
|
||||
@@ -311,7 +311,7 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
uint256 newScaled = ABDKMath64x64.mulu(newTotal, LP_SCALE);
|
||||
|
||||
if (totalSupply_ == 0) {
|
||||
// If somehow supply zero (shouldn't happen as lmsr.nAssets>0), mint newScaled
|
||||
// If somehow supply zero (shouldn't happen as _lmsr.nAssets>0), mint newScaled
|
||||
lpMinted = newScaled;
|
||||
} else {
|
||||
require(oldScaled > 0, "swapMintAmounts: oldScaled zero");
|
||||
@@ -331,7 +331,7 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
/// @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 receiver who receives the minted LP _tokens
|
||||
/// @param inputTokenIndex index of the input token
|
||||
/// @param maxAmountIn maximum uint token input (inclusive of fee)
|
||||
/// @param deadline optional deadline
|
||||
@@ -346,24 +346,24 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
uint256 swapFeePpm,
|
||||
uint256 protocolFeePpm
|
||||
) external payable native nonReentrant returns (uint256 lpMinted) {
|
||||
uint256 n = tokens.length;
|
||||
uint256 n = _tokens.length;
|
||||
require(inputTokenIndex < n, "swapMint: idx");
|
||||
require(maxAmountIn > 0, "swapMint: input zero");
|
||||
require(deadline == 0 || block.timestamp <= deadline, "swapMint: deadline");
|
||||
require(lmsr.nAssets > 0, "swapMint: uninit pool");
|
||||
require(_lmsr.nAssets > 0, "swapMint: uninit pool");
|
||||
|
||||
// compute fee on gross maxAmountIn to get an initial net estimate (we'll recompute based on actual used)
|
||||
(, uint256 netUintGuess) = _computeFee(maxAmountIn, swapFeePpm);
|
||||
|
||||
// Convert the net guess to internal (floor)
|
||||
int128 netInternalGuess = _uintToInternalFloor(netUintGuess, bases[inputTokenIndex]);
|
||||
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(inputTokenIndex, 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[inputTokenIndex]);
|
||||
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)
|
||||
@@ -371,22 +371,22 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
uint256 totalTransfer = amountInUint + feeUintActual;
|
||||
require(totalTransfer > 0 && totalTransfer <= maxAmountIn, "swapMint: transfer exceeds max");
|
||||
|
||||
// Transfer tokens from payer (assume standard ERC20 without transfer fees) via helper
|
||||
_receiveTokenFrom(payer, tokens[inputTokenIndex], totalTransfer);
|
||||
// Transfer _tokens from payer (assume standard ERC20 without transfer fees) via helper
|
||||
_receiveTokenFrom(payer, _tokens[inputTokenIndex], totalTransfer);
|
||||
|
||||
// Accrue protocol share (floor) from the fee on the input token
|
||||
uint256 protoShare = 0;
|
||||
if (protocolFeePpm > 0 && feeUintActual > 0) {
|
||||
protoShare = (feeUintActual * protocolFeePpm) / 1_000_000;
|
||||
if (protoShare > 0) {
|
||||
protocolFeesOwed[inputTokenIndex] += protoShare;
|
||||
_protocolFeesOwed[inputTokenIndex] += protoShare;
|
||||
}
|
||||
}
|
||||
// Update cached effective balance directly: add totalTransfer minus protocol share
|
||||
cachedUintBalances[inputTokenIndex] += (totalTransfer - protoShare);
|
||||
_cachedUintBalances[inputTokenIndex] += (totalTransfer - protoShare);
|
||||
|
||||
// Compute old and new scaled size metrics to determine LP minted
|
||||
int128 oldTotal = _computeSizeMetric(lmsr.qInternal);
|
||||
int128 oldTotal = _computeSizeMetric(_lmsr.qInternal);
|
||||
uint256 oldScaled = ABDKMath64x64.mulu(oldTotal, LP_SCALE);
|
||||
|
||||
int128 newTotal = oldTotal.add(sizeIncreaseInternal);
|
||||
@@ -396,7 +396,7 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
// Use natural ERC20 function since base contract inherits from ERC20
|
||||
uint256 currentSupply = _totalSupply;
|
||||
if (currentSupply == 0) {
|
||||
// If somehow supply zero (shouldn't happen as lmsr.nAssets>0), mint newScaled
|
||||
// If somehow supply zero (shouldn't happen as _lmsr.nAssets>0), mint newScaled
|
||||
actualLpToMint = newScaled;
|
||||
} else {
|
||||
uint256 delta = (newScaled > oldScaled) ? (newScaled - oldScaled) : 0;
|
||||
@@ -414,11 +414,11 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
int128[] memory newQInternal = new int128[](n);
|
||||
for (uint256 idx = 0; idx < n; idx++) {
|
||||
// newQInternal[idx] = qInternal[idx] * (newTotal / oldTotal)
|
||||
newQInternal[idx] = lmsr.qInternal[idx].mul(newTotal).div(oldTotal);
|
||||
newQInternal[idx] = _lmsr.qInternal[idx].mul(newTotal).div(oldTotal);
|
||||
}
|
||||
|
||||
// Update cached internal and kappa via updateForProportionalChange
|
||||
lmsr.updateForProportionalChange(newQInternal);
|
||||
_lmsr.updateForProportionalChange(newQInternal);
|
||||
|
||||
// Use natural ERC20 function since base contract inherits from ERC20
|
||||
_mint(receiver, actualLpToMint);
|
||||
@@ -435,11 +435,11 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
|
||||
/// @notice Calculate the amounts for a burn swap operation
|
||||
/// @dev This is a pure view function that computes burn swap amounts from provided state
|
||||
/// @param lpAmount amount of LP tokens to burn
|
||||
/// @param lpAmount amount of LP _tokens to burn
|
||||
/// @param inputTokenIndex index of target asset to receive
|
||||
/// @param swapFeePpm fee in parts-per-million
|
||||
/// @param lmsrState current LMSR state
|
||||
/// @param bases_ scaling bases for each token
|
||||
/// @param bases_ scaling _bases for each token
|
||||
/// @param totalSupply_ current total LP token supply
|
||||
/// @return amountOut amount of target asset that would be received
|
||||
function burnSwapAmounts(
|
||||
@@ -467,11 +467,11 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
require(amountOut > 0, "burnSwapAmounts: output zero");
|
||||
}
|
||||
|
||||
/// @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
|
||||
/// @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 lpAmount amount of LP _tokens to burn
|
||||
/// @param inputTokenIndex index of target asset to receive
|
||||
/// @param deadline optional deadline
|
||||
/// @param swapFeePpm fee in parts-per-million for this pool (may be used for future fee logic)
|
||||
@@ -486,7 +486,7 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
uint256 swapFeePpm,
|
||||
uint256 protocolFeePpm
|
||||
) external nonReentrant returns (uint256 amountOutUint) {
|
||||
uint256 n = tokens.length;
|
||||
uint256 n = _tokens.length;
|
||||
require(inputTokenIndex < n, "burnSwap: idx");
|
||||
require(lpAmount > 0, "burnSwap: zero lp");
|
||||
require(deadline == 0 || block.timestamp <= deadline, "burnSwap: deadline");
|
||||
@@ -499,16 +499,16 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
.mul(ABDKMath64x64.divu(1000000-swapFeePpm, 1000000)); // adjusted for fee
|
||||
|
||||
// Use LMSR view to compute single-asset payout and burned size-metric
|
||||
(int128 payoutInternal, ) = lmsr.swapAmountsForBurn(inputTokenIndex, alpha);
|
||||
(int128 payoutInternal, ) = _lmsr.swapAmountsForBurn(inputTokenIndex, alpha);
|
||||
|
||||
// Convert payoutInternal -> uint (floor) to favor pool
|
||||
amountOutUint = _internalToUintFloor(payoutInternal, bases[inputTokenIndex]);
|
||||
amountOutUint = _internalToUintFloor(payoutInternal, _bases[inputTokenIndex]);
|
||||
require(amountOutUint > 0, "burnSwap: output zero");
|
||||
|
||||
// Compute gross payout (no swap fee) so we can determine token-side fee = gross - net
|
||||
int128 alphaGross = ABDKMath64x64.divu(lpAmount, supply); // gross fraction (no swap fee)
|
||||
(int128 payoutGrossInternal, ) = lmsr.swapAmountsForBurn(inputTokenIndex, alphaGross);
|
||||
uint256 payoutGrossUint = _internalToUintFloor(payoutGrossInternal, bases[inputTokenIndex]);
|
||||
(int128 payoutGrossInternal, ) = _lmsr.swapAmountsForBurn(inputTokenIndex, alphaGross);
|
||||
uint256 payoutGrossUint = _internalToUintFloor(payoutGrossInternal, _bases[inputTokenIndex]);
|
||||
uint256 feeTokenUint = (payoutGrossUint > amountOutUint) ? (payoutGrossUint - amountOutUint) : 0;
|
||||
|
||||
// Accrue protocol share (floor) from the token-side fee
|
||||
@@ -516,14 +516,14 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
if (protocolFeePpm > 0 && feeTokenUint > 0) {
|
||||
protoShare = (feeTokenUint * protocolFeePpm) / 1_000_000;
|
||||
if (protoShare > 0) {
|
||||
protocolFeesOwed[inputTokenIndex] += protoShare;
|
||||
_protocolFeesOwed[inputTokenIndex] += protoShare;
|
||||
}
|
||||
}
|
||||
|
||||
// Transfer the payout to receiver via centralized helper
|
||||
_sendTokenTo(tokens[inputTokenIndex], receiver, amountOutUint, unwrap);
|
||||
_sendTokenTo(_tokens[inputTokenIndex], receiver, amountOutUint, unwrap);
|
||||
|
||||
// Burn LP tokens from payer (authorization via allowance)
|
||||
// Burn LP _tokens from payer (authorization via allowance)
|
||||
if (msg.sender != payer) {
|
||||
uint256 allowed = _allowances[payer][msg.sender];
|
||||
_approve(payer, msg.sender, allowed - lpAmount);
|
||||
@@ -533,13 +533,13 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
// Update cached balances using computed payout and protocol fee; no on-chain reads
|
||||
int128[] memory newQInternal = new int128[](n);
|
||||
for (uint256 idx = 0; idx < n; idx++) {
|
||||
uint256 newBal = cachedUintBalances[idx];
|
||||
uint256 newBal = _cachedUintBalances[idx];
|
||||
if (idx == inputTokenIndex) {
|
||||
// Effective LP balance decreases by net payout and increased protocol owed
|
||||
newBal = newBal - amountOutUint - protoShare;
|
||||
}
|
||||
cachedUintBalances[idx] = newBal;
|
||||
newQInternal[idx] = _uintToInternalFloor(newBal, bases[idx]);
|
||||
_cachedUintBalances[idx] = newBal;
|
||||
newQInternal[idx] = _uintToInternalFloor(newBal, _bases[idx]);
|
||||
}
|
||||
|
||||
// Emit BurnSwap with public-facing info only (do not expose ΔS or LP burned)
|
||||
@@ -551,9 +551,9 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
if (newQInternal[idx] != int128(0)) { allZero = false; break; }
|
||||
}
|
||||
if (allZero) {
|
||||
lmsr.deinit();
|
||||
_lmsr.deinit();
|
||||
} else {
|
||||
lmsr.updateForProportionalChange(newQInternal);
|
||||
_lmsr.updateForProportionalChange(newQInternal);
|
||||
}
|
||||
|
||||
emit IPartyPool.Burn(payer, receiver, new uint256[](n), lpAmount);
|
||||
|
||||
@@ -60,49 +60,49 @@ contract PartyPoolSwapImpl is PartyPoolBase {
|
||||
uint256 swapFeePpm,
|
||||
uint256 protocolFeePpm
|
||||
) external payable native returns (uint256 amountInUsed, uint256 amountOut, uint256 fee) {
|
||||
uint256 n = tokens.length;
|
||||
uint256 n = _tokens.length;
|
||||
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[inputTokenIndex]).balanceOf(address(this));
|
||||
uint256 prevBalJ = IERC20(tokens[outputTokenIndex]).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(inputTokenIndex, outputTokenIndex, limitPrice, swapFeePpm);
|
||||
|
||||
// Transfer the exact amount needed from payer and require exact receipt (revert on fee-on-transfer)
|
||||
_receiveTokenFrom(payer, tokens[inputTokenIndex], totalTransferAmount);
|
||||
uint256 balIAfter = IERC20(tokens[inputTokenIndex]).balanceOf(address(this));
|
||||
_receiveTokenFrom(payer, _tokens[inputTokenIndex], 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
|
||||
_sendTokenTo(tokens[outputTokenIndex], receiver, amountOutUint, unwrap);
|
||||
uint256 balJAfter = IERC20(tokens[outputTokenIndex]).balanceOf(address(this));
|
||||
_sendTokenTo(_tokens[outputTokenIndex], receiver, amountOutUint, unwrap);
|
||||
uint256 balJAfter = IERC20(_tokens[outputTokenIndex]).balanceOf(address(this));
|
||||
require(balJAfter == prevBalJ - amountOutUint, "swapToLimit: non-standard tokenOut");
|
||||
|
||||
// Accrue protocol share (floor) from the fee on input token
|
||||
if (protocolFeePpm > 0 && feeUint > 0 ) {
|
||||
uint256 protoShare = (feeUint * protocolFeePpm) / 1_000_000; // floor
|
||||
if (protoShare > 0) {
|
||||
protocolFeesOwed[inputTokenIndex] += protoShare;
|
||||
_protocolFeesOwed[inputTokenIndex] += protoShare;
|
||||
}
|
||||
}
|
||||
|
||||
// Update caches to effective balances (inline _recordCachedBalance)
|
||||
require(balIAfter >= protocolFeesOwed[inputTokenIndex], "balance < protocol owed");
|
||||
cachedUintBalances[inputTokenIndex] = balIAfter - protocolFeesOwed[inputTokenIndex];
|
||||
require(balIAfter >= _protocolFeesOwed[inputTokenIndex], "balance < protocol owed");
|
||||
_cachedUintBalances[inputTokenIndex] = balIAfter - _protocolFeesOwed[inputTokenIndex];
|
||||
|
||||
require(balJAfter >= protocolFeesOwed[outputTokenIndex], "balance < protocol owed");
|
||||
cachedUintBalances[outputTokenIndex] = balJAfter - protocolFeesOwed[outputTokenIndex];
|
||||
require(balJAfter >= _protocolFeesOwed[outputTokenIndex], "balance < protocol owed");
|
||||
_cachedUintBalances[outputTokenIndex] = balJAfter - _protocolFeesOwed[outputTokenIndex];
|
||||
|
||||
// Apply swap to LMSR state with the internal amounts
|
||||
lmsr.applySwap(inputTokenIndex, outputTokenIndex, amountInInternalMax, amountOutInternal);
|
||||
_lmsr.applySwap(inputTokenIndex, outputTokenIndex, amountInInternalMax, amountOutInternal);
|
||||
|
||||
// Maintain original event semantics (logs input without fee)
|
||||
emit IPartyPool.Swap(payer, receiver, tokens[inputTokenIndex], tokens[outputTokenIndex], amountInUsedUint, amountOutUint);
|
||||
emit IPartyPool.Swap(payer, receiver, _tokens[inputTokenIndex], _tokens[outputTokenIndex], amountInUsedUint, amountOutUint);
|
||||
|
||||
return (amountInUsedUint, amountOutUint, feeUint);
|
||||
}
|
||||
@@ -129,10 +129,10 @@ contract PartyPoolSwapImpl is PartyPoolBase {
|
||||
)
|
||||
{
|
||||
// Compute internal maxima at the price limit
|
||||
(amountInInternal, amountOutInternal) = lmsr.swapAmountsForPriceLimit(inputTokenIndex, outputTokenIndex, limitPrice);
|
||||
(amountInInternal, amountOutInternal) = _lmsr.swapAmountsForPriceLimit(inputTokenIndex, outputTokenIndex, limitPrice);
|
||||
|
||||
// Convert input to uint (ceil) and output to uint (floor)
|
||||
amountInUintNoFee = _internalToUintCeil(amountInInternal, bases[inputTokenIndex]);
|
||||
amountInUintNoFee = _internalToUintCeil(amountInInternal, _bases[inputTokenIndex]);
|
||||
require(amountInUintNoFee > 0, "swapToLimit: input zero");
|
||||
|
||||
feeUint = 0;
|
||||
@@ -142,7 +142,7 @@ contract PartyPoolSwapImpl is PartyPoolBase {
|
||||
grossIn += feeUint;
|
||||
}
|
||||
|
||||
amountOutUint = _internalToUintFloor(amountOutInternal, bases[outputTokenIndex]);
|
||||
amountOutUint = _internalToUintFloor(amountOutInternal, _bases[outputTokenIndex]);
|
||||
require(amountOutUint > 0, "swapToLimit: output zero");
|
||||
}
|
||||
|
||||
|
||||
@@ -167,7 +167,7 @@ contract PartyPoolViewer is PartyPoolHelpers, IPartyPoolViewer {
|
||||
|
||||
/**
|
||||
* @dev The fee to be charged for a given loan.
|
||||
* @param amount The amount of tokens lent.
|
||||
* @param amount The amount of _tokens lent.
|
||||
* @return fee The amount of `token` to be charged for the loan, on top of the returned principal.
|
||||
*/
|
||||
function flashFee(
|
||||
|
||||
@@ -114,9 +114,9 @@ contract GasTest is Test {
|
||||
uint256 constant internal INIT_BAL = 1_000_000; // initial token units for each token (internal==amount when base==1)
|
||||
uint256 constant internal BASE = 1; // use base=1 so internal amounts correspond to raw integers (Q64.64 units)
|
||||
|
||||
/// @notice Helper function to create a pool with the specified number of tokens
|
||||
/// @notice Helper function to create a pool with the specified number of _tokens
|
||||
function createPool(uint256 numTokens) internal returns (PartyPool) {
|
||||
// Deploy tokens dynamically
|
||||
// Deploy _tokens dynamically
|
||||
address[] memory tokens = new address[](numTokens);
|
||||
uint256[] memory bases = new uint256[](numTokens);
|
||||
|
||||
@@ -139,7 +139,7 @@ contract GasTest is Test {
|
||||
for (uint i = 0; i < tokens.length; i++) {
|
||||
ierc20Tokens[i] = IERC20(tokens[i]);
|
||||
}
|
||||
// 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);
|
||||
PartyPool newPool = Deploy.newPartyPool(poolName, poolName, ierc20Tokens, bases, computedKappa, feePpm, feePpm, false);
|
||||
|
||||
@@ -156,7 +156,7 @@ contract GasTest is Test {
|
||||
|
||||
/// @notice Helper to create a pool with the stable-pair optimization enabled
|
||||
function createPoolStable(uint256 numTokens) internal returns (PartyPool) {
|
||||
// Deploy tokens dynamically
|
||||
// Deploy _tokens dynamically
|
||||
address[] memory tokens = new address[](numTokens);
|
||||
uint256[] memory bases = new uint256[](numTokens);
|
||||
|
||||
@@ -216,7 +216,7 @@ contract GasTest is Test {
|
||||
// Deploy the borrower contract
|
||||
borrower = new FlashBorrower(address(pool2));
|
||||
|
||||
// Mint tokens to alice to be used for repayments and approve borrower
|
||||
// Mint _tokens to alice to be used for repayments and approve borrower
|
||||
IERC20[] memory tokenAddresses = pool2.allTokens();
|
||||
vm.startPrank(alice);
|
||||
for (uint256 i = 0; i < tokenAddresses.length; i++) {
|
||||
@@ -226,12 +226,12 @@ contract GasTest is Test {
|
||||
vm.stopPrank();
|
||||
}
|
||||
|
||||
/// @notice Helper function: perform 10 swaps back-and-forth between the first two tokens.
|
||||
/// @notice Helper function: perform 10 swaps back-and-forth between the first two _tokens.
|
||||
function _performSwapGasTest(PartyPool testPool) internal {
|
||||
IERC20[] memory tokens = testPool.allTokens();
|
||||
require(tokens.length >= 2, "Pool must have at least 2 tokens");
|
||||
|
||||
// Ensure alice approves pool for both tokens
|
||||
// Ensure alice approves pool for both _tokens
|
||||
vm.prank(alice);
|
||||
TestERC20(address(tokens[0])).approve(address(testPool), type(uint256).max);
|
||||
vm.prank(alice);
|
||||
@@ -252,22 +252,22 @@ contract GasTest is Test {
|
||||
}
|
||||
}
|
||||
|
||||
/// @notice Gas measurement: perform 10 swaps back-and-forth between first two tokens in the 2-token pool.
|
||||
/// @notice Gas measurement: perform 10 swaps back-and-forth between first two _tokens in the 2-token pool.
|
||||
function testSwapGasPair() public {
|
||||
_performSwapGasTest(pool2);
|
||||
}
|
||||
|
||||
/// @notice Gas measurement: perform 10 swaps back-and-forth between first two tokens in the 10-token pool.
|
||||
/// @notice Gas measurement: perform 10 swaps back-and-forth between first two _tokens in the 10-token pool.
|
||||
function testSwapGasTen() public {
|
||||
_performSwapGasTest(pool10);
|
||||
}
|
||||
|
||||
/// @notice Gas measurement: perform 10 swaps back-and-forth between first two tokens in the 20-token pool.
|
||||
/// @notice Gas measurement: perform 10 swaps back-and-forth between first two _tokens in the 20-token pool.
|
||||
function testSwapGasTwenty() public {
|
||||
_performSwapGasTest(pool20);
|
||||
}
|
||||
|
||||
/// @notice Gas measurement: perform 10 swaps back-and-forth between first two tokens in the 100-token pool.
|
||||
/// @notice Gas measurement: perform 10 swaps back-and-forth between first two _tokens in the 100-token pool.
|
||||
function testSwapGasFifty() public {
|
||||
_performSwapGasTest(pool50);
|
||||
}
|
||||
@@ -307,7 +307,7 @@ contract GasTest is Test {
|
||||
uint256 minted = testPool.swapMint(alice, alice, 0, input, 0);
|
||||
// If nothing minted (numerical edge), skip burn step
|
||||
if (minted == 0) continue;
|
||||
// Immediately burn the minted LP back to tokens, targeting the same token index
|
||||
// Immediately burn the minted LP back to _tokens, targeting the same token index
|
||||
testPool.burnSwap(alice, alice, minted, 0, 0, false);
|
||||
}
|
||||
|
||||
@@ -343,7 +343,7 @@ contract GasTest is Test {
|
||||
|
||||
vm.startPrank(alice);
|
||||
|
||||
// Mint additional tokens to alice and approve pool to transfer tokens for proportional mint
|
||||
// Mint additional _tokens to alice and approve pool to transfer _tokens for proportional mint
|
||||
for (uint256 i = 0; i < poolTokens.length; i++) {
|
||||
TestERC20(address(poolTokens[i])).mint(alice, iterations * input * 2);
|
||||
TestERC20(address(poolTokens[i])).approve(address(testPool), type(uint256).max);
|
||||
|
||||
@@ -61,7 +61,7 @@ contract NativeTest is Test {
|
||||
vm.deal(alice, 100 ether);
|
||||
vm.deal(bob, 100 ether);
|
||||
|
||||
// Deploy two regular ERC20 tokens
|
||||
// Deploy two regular ERC20 _tokens
|
||||
token0 = new TestERC20Native("T0", "T0", 0);
|
||||
token1 = new TestERC20Native("T1", "T1", 0);
|
||||
|
||||
@@ -72,7 +72,7 @@ contract NativeTest is Test {
|
||||
token0.mint(address(this), INIT_BAL);
|
||||
token1.mint(address(this), INIT_BAL);
|
||||
|
||||
// For WETH, we deposit native currency to get wrapped tokens
|
||||
// For WETH, we deposit native currency to get wrapped _tokens
|
||||
weth.deposit{value: INIT_BAL}();
|
||||
|
||||
// Configure LMSR parameters
|
||||
@@ -104,7 +104,7 @@ contract NativeTest is Test {
|
||||
// Perform initial mint
|
||||
pool.initialMint(address(this), 0);
|
||||
|
||||
// Mint tokens to alice and bob for testing
|
||||
// Mint _tokens to alice and bob for testing
|
||||
token0.mint(alice, INIT_BAL);
|
||||
token1.mint(alice, INIT_BAL);
|
||||
|
||||
@@ -407,7 +407,7 @@ contract NativeTest is Test {
|
||||
true // unwrap
|
||||
);
|
||||
|
||||
// Bob should receive tokens and native currency
|
||||
// Bob should receive _tokens and native currency
|
||||
assertEq(token0.balanceOf(bob), bobToken0Before + withdraws[0], "Bob token0");
|
||||
assertEq(token1.balanceOf(bob), bobToken1Before + withdraws[1], "Bob token1");
|
||||
assertEq(bob.balance, bobEthBefore + withdraws[2], "Bob should receive ETH");
|
||||
@@ -441,7 +441,7 @@ contract NativeTest is Test {
|
||||
assertTrue(alice.balance <= aliceEthBefore, "Alice ETH should decrease");
|
||||
assertTrue(aliceEthBefore - alice.balance <= maxIn, "Alice spent at most maxIn");
|
||||
|
||||
// Alice should receive LP tokens
|
||||
// Alice should receive LP _tokens
|
||||
assertTrue(pool.balanceOf(alice) >= aliceLpBefore + lpMinted, "Alice should receive LP");
|
||||
|
||||
vm.stopPrank();
|
||||
@@ -567,7 +567,7 @@ contract NativeTest is Test {
|
||||
vm.stopPrank();
|
||||
}
|
||||
|
||||
/// @notice Test that unwrap=false with WETH actually transfers WETH tokens (not native)
|
||||
/// @notice Test that unwrap=false with WETH actually transfers WETH _tokens (not native)
|
||||
function testSwapWithWethNoUnwrap() public {
|
||||
uint256 maxIn = 10_000;
|
||||
|
||||
|
||||
@@ -49,17 +49,17 @@ contract PartyPlannerTest is Test {
|
||||
// Deploy PartyPlanner
|
||||
planner = Deploy.newPartyPlanner();
|
||||
|
||||
// Deploy mock tokens
|
||||
// Deploy mock _tokens
|
||||
tokenA = new MockERC20("Token A", "TKNA", 18);
|
||||
tokenB = new MockERC20("Token B", "TKNB", 18);
|
||||
tokenC = new MockERC20("Token C", "TKNC", 6);
|
||||
|
||||
// Mint tokens to payer
|
||||
// Mint _tokens to payer
|
||||
tokenA.mint(payer, INITIAL_MINT_AMOUNT);
|
||||
tokenB.mint(payer, INITIAL_MINT_AMOUNT);
|
||||
tokenC.mint(payer, INITIAL_MINT_AMOUNT);
|
||||
|
||||
// Approve tokens for PartyPlanner
|
||||
// Approve _tokens for PartyPlanner
|
||||
vm.startPrank(payer);
|
||||
tokenA.approve(address(planner), type(uint256).max);
|
||||
tokenB.approve(address(planner), type(uint256).max);
|
||||
@@ -156,7 +156,7 @@ contract PartyPlannerTest is Test {
|
||||
}
|
||||
assertTrue(poolInTokenB, "Pool should be indexed under tokenB");
|
||||
|
||||
// Verify LP tokens were minted to receiver
|
||||
// Verify LP _tokens were minted to receiver
|
||||
assertEq(pool.balanceOf(receiver), lpAmount, "Receiver should have LP tokens");
|
||||
}
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ contract PartyPoolTest is Test {
|
||||
alice = address(0xA11ce);
|
||||
bob = address(0xB0b);
|
||||
|
||||
// Deploy three ERC20 test tokens and mint initial supplies to this test contract for initial deposit
|
||||
// Deploy three ERC20 test _tokens and mint initial supplies to this test contract for initial deposit
|
||||
token0 = new TestERC20("T0", "T0", 0);
|
||||
token1 = new TestERC20("T1", "T1", 0);
|
||||
token2 = new TestERC20("T2", "T2", 0);
|
||||
@@ -175,7 +175,7 @@ contract PartyPoolTest is Test {
|
||||
int128 kappa3 = LMSRStabilized.computeKappaFromSlippage(tokens.length, tradeFrac, targetSlippage);
|
||||
pool = Deploy.newPartyPool("LP", "LP", tokens, bases, 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
|
||||
token0.transfer(address(pool), INIT_BAL);
|
||||
token1.transfer(address(pool), INIT_BAL);
|
||||
@@ -184,7 +184,7 @@ contract PartyPoolTest is Test {
|
||||
// Perform initial mint (initial deposit); receiver is this contract
|
||||
pool.initialMint(address(this), 0);
|
||||
|
||||
// Set up pool10 with 10 tokens
|
||||
// Set up pool10 with 10 _tokens
|
||||
IERC20[] memory tokens10 = new IERC20[](10);
|
||||
tokens10[0] = IERC20(address(token0));
|
||||
tokens10[1] = IERC20(address(token1));
|
||||
@@ -205,7 +205,7 @@ contract PartyPoolTest is Test {
|
||||
int128 kappa10 = LMSRStabilized.computeKappaFromSlippage(tokens10.length, tradeFrac, targetSlippage);
|
||||
pool10 = Deploy.newPartyPool("LP10", "LP10", tokens10, bases10, kappa10, feePpm, feePpm, false);
|
||||
|
||||
// Mint additional tokens for pool10 initial deposit
|
||||
// Mint additional _tokens for pool10 initial deposit
|
||||
token0.mint(address(this), INIT_BAL);
|
||||
token1.mint(address(this), INIT_BAL);
|
||||
token2.mint(address(this), INIT_BAL);
|
||||
@@ -232,7 +232,7 @@ contract PartyPoolTest is Test {
|
||||
// Perform initial mint for pool10
|
||||
pool10.initialMint(address(this), 0);
|
||||
|
||||
// For later tests we will mint tokens to alice/bob as needed
|
||||
// For later tests we will mint _tokens to alice/bob as needed
|
||||
token0.mint(alice, INIT_BAL);
|
||||
token1.mint(alice, INIT_BAL);
|
||||
token2.mint(alice, INIT_BAL);
|
||||
@@ -258,7 +258,7 @@ contract PartyPoolTest is Test {
|
||||
viewer = Deploy.newViewer();
|
||||
}
|
||||
|
||||
/// @notice Basic sanity: initial mint should have produced LP tokens for this contract and the pool holds tokens.
|
||||
/// @notice Basic sanity: initial mint should have produced LP _tokens for this contract and the pool holds _tokens.
|
||||
function testInitialMintAndLP() public view {
|
||||
uint256 totalLp = pool.totalSupply();
|
||||
assertTrue(totalLp > 0, "Initial LP supply should be > 0");
|
||||
@@ -274,7 +274,7 @@ contract PartyPoolTest is Test {
|
||||
function testProportionalMintZeroLpReverts() public {
|
||||
// Attempt to request a tiny LP amount (1) and expect revert because calculated actualLpToMint will be zero
|
||||
|
||||
// Approve pool to transfer tokens on alice's behalf
|
||||
// Approve pool to transfer _tokens on alice's behalf
|
||||
vm.startPrank(alice);
|
||||
token0.approve(address(pool), type(uint256).max);
|
||||
token1.approve(address(pool), type(uint256).max);
|
||||
@@ -290,7 +290,7 @@ contract PartyPoolTest is Test {
|
||||
/// does not undercharge (no value extraction). This test verifies the request succeeds
|
||||
/// and that computed deposits are at least the proportional floor (ceil >= floor).
|
||||
function testProportionalMintOneWeiSucceedsAndProtectsPool() public {
|
||||
// Request a tiny LP amount (1 wei). Approve pool to transfer tokens on alice's behalf.
|
||||
// Request a tiny LP amount (1 wei). Approve pool to transfer _tokens on alice's behalf.
|
||||
vm.startPrank(alice);
|
||||
token0.approve(address(pool), type(uint256).max);
|
||||
token1.approve(address(pool), type(uint256).max);
|
||||
@@ -406,14 +406,14 @@ contract PartyPoolTest is Test {
|
||||
assertTrue(withdrawAmounts[i] <= poolBal, "withdraw amount cannot exceed pool balance");
|
||||
}
|
||||
|
||||
// Burn by sending LP tokens from this contract (which holds initial LP from setUp)
|
||||
// Burn by sending LP _tokens from this contract (which holds initial LP from setUp)
|
||||
// Call burn(payer=this, receiver=bob, lpAmount=totalLp)
|
||||
pool.burn(address(this), bob, totalLp, 0, false);
|
||||
|
||||
// After burning entire pool, totalSupply should be zero or very small (we expect zero since we withdrew all)
|
||||
assertEq(pool.totalSupply(), 0);
|
||||
|
||||
// Bob should have received the withdrawn tokens
|
||||
// Bob should have received the withdrawn _tokens
|
||||
for (uint i = 0; i < withdrawAmounts.length; i++) {
|
||||
assertTrue(IERC20(pool.allTokens()[i]).balanceOf(bob) >= withdrawAmounts[i], "Bob should receive withdrawn tokens");
|
||||
}
|
||||
@@ -424,7 +424,7 @@ contract PartyPoolTest is Test {
|
||||
// Use alice as payer and bob as receiver
|
||||
uint256 maxIn = 10_000;
|
||||
|
||||
// Ensure alice has tokens and approves pool
|
||||
// Ensure alice has _tokens and approves pool
|
||||
vm.prank(alice);
|
||||
token0.approve(address(pool), type(uint256).max);
|
||||
|
||||
@@ -503,7 +503,7 @@ contract PartyPoolTest is Test {
|
||||
// Compute expected deposit amounts via view
|
||||
uint256[] memory expected = viewer.mintAmounts(pool, req);
|
||||
|
||||
// Ensure alice has tokens and approve pool
|
||||
// Ensure alice has _tokens and approve pool
|
||||
vm.startPrank(alice);
|
||||
token0.approve(address(pool), type(uint256).max);
|
||||
token1.approve(address(pool), type(uint256).max);
|
||||
@@ -548,7 +548,7 @@ contract PartyPoolTest is Test {
|
||||
|
||||
uint256[] memory expected = viewer.mintAmounts(pool10, req);
|
||||
|
||||
// Approve all tokens from alice
|
||||
// Approve all _tokens from alice
|
||||
vm.startPrank(alice);
|
||||
token0.approve(address(pool10), type(uint256).max);
|
||||
token1.approve(address(pool10), type(uint256).max);
|
||||
@@ -614,7 +614,7 @@ contract PartyPoolTest is Test {
|
||||
uint256 myLp = pool.balanceOf(address(this));
|
||||
if (myLp < req) {
|
||||
uint256 topUp = req - myLp;
|
||||
// Have alice supply tokens to mint LP into this contract
|
||||
// Have alice supply _tokens to mint LP into this contract
|
||||
vm.startPrank(alice);
|
||||
token0.approve(address(pool), type(uint256).max);
|
||||
token1.approve(address(pool), type(uint256).max);
|
||||
@@ -754,7 +754,7 @@ contract PartyPoolTest is Test {
|
||||
// Very large input relative to pool
|
||||
uint256 largeInput = 10_000_000_000; // intentionally large
|
||||
|
||||
// Ensure alice has sufficient tokens for this large test input (mint top-up)
|
||||
// Ensure alice has sufficient _tokens for this large test input (mint top-up)
|
||||
token0.mint(alice, largeInput);
|
||||
|
||||
vm.startPrank(alice);
|
||||
@@ -818,12 +818,12 @@ contract PartyPoolTest is Test {
|
||||
// Deploy the borrower contract
|
||||
borrower = new FlashBorrower(address(pool));
|
||||
|
||||
// Mint tokens to alice to be used for repayments
|
||||
// Mint _tokens to alice to be used for repayments
|
||||
token0.mint(alice, INIT_BAL * 2);
|
||||
token1.mint(alice, INIT_BAL * 2);
|
||||
token2.mint(alice, INIT_BAL * 2);
|
||||
|
||||
// Alice approves borrower to transfer tokens on their behalf for repayment
|
||||
// Alice approves borrower to transfer _tokens on their behalf for repayment
|
||||
vm.startPrank(alice);
|
||||
token0.approve(address(borrower), type(uint256).max);
|
||||
token1.approve(address(borrower), type(uint256).max);
|
||||
@@ -998,7 +998,7 @@ contract PartyPoolTest is Test {
|
||||
int128 kappaCustom = LMSRStabilized.computeKappaFromSlippage(tokens.length, tradeFrac, targetSlippage);
|
||||
PartyPool poolCustom = Deploy.newPartyPool("LP_CUSTOM", "LP_CUSTOM", tokens, bases, kappaCustom, feePpm, feePpm, false);
|
||||
|
||||
// Mint additional tokens for both pools
|
||||
// Mint additional _tokens for both pools
|
||||
token0.mint(address(this), INIT_BAL * 2);
|
||||
token1.mint(address(this), INIT_BAL * 2);
|
||||
token2.mint(address(this), INIT_BAL * 2);
|
||||
@@ -1052,7 +1052,7 @@ contract PartyPoolTest is Test {
|
||||
}
|
||||
|
||||
/// @notice Test that minting the same proportion in pools with different initial LP amounts
|
||||
/// returns correctly scaled LP tokens
|
||||
/// returns correctly scaled LP _tokens
|
||||
function testProportionalMintingScaledByInitialAmount() public {
|
||||
// Create two identical pools with different initial LP amounts
|
||||
IERC20[] memory tokens = new IERC20[](3);
|
||||
@@ -1072,7 +1072,7 @@ contract PartyPoolTest is Test {
|
||||
int128 kappaCustom2 = LMSRStabilized.computeKappaFromSlippage(tokens.length, tradeFrac, targetSlippage);
|
||||
PartyPool poolCustom = Deploy.newPartyPool("LP_CUSTOM", "LP_CUSTOM", tokens, bases, kappaCustom2, feePpm, feePpm, false);
|
||||
|
||||
// Mint additional tokens
|
||||
// Mint additional _tokens
|
||||
token0.mint(address(this), INIT_BAL * 4);
|
||||
token1.mint(address(this), INIT_BAL * 4);
|
||||
token2.mint(address(this), INIT_BAL * 4);
|
||||
@@ -1108,7 +1108,7 @@ contract PartyPoolTest is Test {
|
||||
|
||||
vm.startPrank(alice);
|
||||
|
||||
// Approve tokens for both pools
|
||||
// Approve _tokens for both pools
|
||||
token0.approve(address(poolDefault), type(uint256).max);
|
||||
token1.approve(address(poolDefault), type(uint256).max);
|
||||
token2.approve(address(poolDefault), type(uint256).max);
|
||||
|
||||
Reference in New Issue
Block a user