poolPrice() bugfix; burn() and mint() precision bugfixes
This commit is contained in:
@@ -224,13 +224,13 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
return depositAmounts; // Return zeros, initial deposit handled differently
|
||||
}
|
||||
|
||||
// lpTokenAmount / totalLpSupply = depositAmount / currentBalance
|
||||
// Therefore: depositAmount = (lpTokenAmount * currentBalance) / totalLpSupply
|
||||
// We round up to protect the pool
|
||||
// Compute mint ratio in Q64.64: ratio = lpTokenAmount / totalSupply
|
||||
int128 ratio = ABDKMath64x64.divu(lpTokenAmount, totalSupply);
|
||||
|
||||
// depositAmount_i = ceil(ratio * currentBalance_i)
|
||||
for (uint i = 0; i < numAssets; i++) {
|
||||
uint256 currentBalance = cachedUintBalances[i];
|
||||
// Calculate with rounding up: (a * b + c - 1) / c
|
||||
depositAmounts[i] = (lpTokenAmount * currentBalance + totalSupply - 1) / totalSupply;
|
||||
depositAmounts[i] = _internalToUintCeilPure(ratio, currentBalance);
|
||||
}
|
||||
|
||||
return depositAmounts;
|
||||
@@ -247,10 +247,10 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
return withdrawAmounts; // Return zeros, nothing to withdraw
|
||||
}
|
||||
|
||||
// withdrawAmount = floor(lpTokenAmount * currentBalance / totalLpSupply)
|
||||
int128 ratio = ABDKMath64x64.divu(lpTokenAmount, totalSupply);
|
||||
for (uint i = 0; i < numAssets; i++) {
|
||||
uint256 currentBalance = cachedUintBalances[i];
|
||||
withdrawAmounts[i] = (lpTokenAmount * currentBalance) / totalSupply;
|
||||
withdrawAmounts[i] = ratio.mulu(currentBalance);
|
||||
}
|
||||
|
||||
return withdrawAmounts;
|
||||
@@ -536,7 +536,6 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
IERC20 outputToken = _tokens[outputTokenIndex];
|
||||
_sendTokenTo(outputToken, receiver, amountOut, unwrap);
|
||||
|
||||
|
||||
// Update cached balances using computed payout and protocol fee; no on-chain reads
|
||||
|
||||
int128[] memory newQInternal = new int128[](n);
|
||||
@@ -574,15 +573,24 @@ contract PartyPoolMintImpl is PartyPoolBase {
|
||||
/// @notice Pure version of _internalToUintCeil for use in view functions
|
||||
function _internalToUintCeilPure(int128 amount, uint256 base) internal pure returns (uint256) {
|
||||
// Convert Q64.64 to uint with ceiling: ceil(amount * base)
|
||||
// Use mulu which floors, then add remainder check for ceiling
|
||||
// Fast path: compute floor using mulu, then detect fractional remainder via low 64-bit check
|
||||
uint256 floored = ABDKMath64x64.mulu(amount, base);
|
||||
// Check if there's a fractional part by computing amount * base - floored
|
||||
int128 baseQ64 = ABDKMath64x64.fromUInt(base);
|
||||
int128 flooredQ64 = ABDKMath64x64.fromUInt(floored);
|
||||
int128 product = amount.mul(baseQ64);
|
||||
if (product > flooredQ64) {
|
||||
return floored + 1; // Ceiling
|
||||
|
||||
// Extract fractional 64 bits of `amount`; if zero, product is already an integer after scaling
|
||||
uint64 frac = uint64(uint128(amount));
|
||||
if (frac == 0) {
|
||||
return floored;
|
||||
}
|
||||
|
||||
unchecked {
|
||||
// Remainder exists iff (frac * (base mod 2^64)) mod 2^64 != 0
|
||||
uint64 baseL = uint64(base);
|
||||
uint128 low = uint128(frac) * uint128(baseL);
|
||||
if (uint64(low) != 0) {
|
||||
return floored + 1; // Ceiling
|
||||
}
|
||||
}
|
||||
|
||||
return floored;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user