styling consistency
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user