From 070717959e46f891ee9c91c24a464e2e7283f6f0 Mon Sep 17 00:00:00 2001 From: tim Date: Mon, 15 Sep 2025 18:38:28 -0400 Subject: [PATCH] swap amounts --- bin/mock | 5 +- research/LMSRComparisonAnalysis.py | 2 + script/DeployMock.sol | 3 +- src/IPartyPool.sol | 20 ++- src/PartyPool.sol | 194 +++++++++++++++++++---------- test/PartyPool.t.sol | 44 +++---- 6 files changed, 175 insertions(+), 93 deletions(-) diff --git a/bin/mock b/bin/mock index 939234c..da22baf 100755 --- a/bin/mock +++ b/bin/mock @@ -1,6 +1,9 @@ #!/bin/bash CODE_SIZE_LIMIT=65000 -PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +# Dev account #0 +#PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +# Dev account #4 +PRIVATE_KEY=0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a # Function to cleanup processes cleanup() { diff --git a/research/LMSRComparisonAnalysis.py b/research/LMSRComparisonAnalysis.py index 6d7159d..c1699c0 100644 --- a/research/LMSRComparisonAnalysis.py +++ b/research/LMSRComparisonAnalysis.py @@ -286,6 +286,8 @@ def plot_static(res): plt.ylabel("y per x") plt.legend() plt.tight_layout() + plt.xlim(right=1) + plt.ylim( bottom=.999,top=1) plt.figure(figsize=(10, 6)) plt.plot(q, res["welfare_gap"] / res["p0"] * 1e4) diff --git a/script/DeployMock.sol b/script/DeployMock.sol index 03afbe7..3d60e37 100644 --- a/script/DeployMock.sol +++ b/script/DeployMock.sol @@ -13,7 +13,6 @@ contract DeployMock is Script { address constant devAccount0 = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; // private key 0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356 address constant devAccount7 = 0x14dC79964da2C08b23698B3D3cc7Ca32193d9955; - address constant deployer = devAccount0; function run() public { vm.startBroadcast(); @@ -41,7 +40,7 @@ contract DeployMock is Script { // initial mint mintAll(address(pool), 10_000); - pool.mint(deployer, deployer, 0, 0); + pool.mint(devAccount7, devAccount7, 0, 0); // give tokens to dev7 mintAll(devAccount7, 1_000_000); diff --git a/src/IPartyPool.sol b/src/IPartyPool.sol index 3948158..7966e89 100644 --- a/src/IPartyPool.sol +++ b/src/IPartyPool.sol @@ -60,7 +60,7 @@ interface IPartyPool is IERC20Metadata { /// @notice Calculate the proportional deposit amounts required for a given LP token amount /// @param lpTokenAmount The amount of LP tokens desired /// @return depositAmounts Array of token amounts to deposit (rounded up) - function computeMintAmounts(uint256 lpTokenAmount) external view returns (uint256[] memory depositAmounts); + function mintDepositAmounts(uint256 lpTokenAmount) external view returns (uint256[] memory depositAmounts); /// @notice Proportional mint (or initial supply if first call). /// For initial supply: assumes tokens have already been transferred to the pool @@ -74,7 +74,7 @@ interface IPartyPool is IERC20Metadata { /// @notice Calculate the proportional withdrawal amounts for a given LP token amount /// @param lpTokenAmount The amount of LP tokens to burn /// @return withdrawAmounts Array of token amounts to withdraw (rounded down) - function computeBurnAmounts(uint256 lpTokenAmount) external view returns (uint256[] memory withdrawAmounts); + function burnReceiveAmounts(uint256 lpTokenAmount) external view returns (uint256[] memory withdrawAmounts); /// @notice Burn LP tokens and withdraw the proportional basket to receiver. /// Payer must own the LP tokens; withdraw amounts are computed from current proportions. @@ -86,6 +86,15 @@ interface IPartyPool is IERC20Metadata { // Swaps + + /// @notice External view to quote exact-in swap amounts (gross input incl. fee and output), matching swap() computations + function swapAmounts( + uint256 i, + uint256 j, + uint256 maxAmountIn, + int128 limitPrice + ) external view returns (uint256 amountIn, uint256 amountOut); + function swap( address payer, address receiver, @@ -96,6 +105,13 @@ interface IPartyPool is IERC20Metadata { uint256 deadline ) external returns (uint256 amountIn, uint256 amountOut); + /// @notice External view to quote swap-to-limit amounts (gross input incl. fee and output), matching swapToLimit() computations + function swapToLimitAmounts( + uint256 i, + uint256 j, + int128 limitPrice + ) external view returns (uint256 amountIn, uint256 amountOut); + function swapToLimit( address payer, address receiver, diff --git a/src/PartyPool.sol b/src/PartyPool.sol index 12fbb9a..12b68c9 100644 --- a/src/PartyPool.sol +++ b/src/PartyPool.sol @@ -108,7 +108,7 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard { /// @notice Calculate the proportional deposit amounts required for a given LP token amount /// @param lpTokenAmount The amount of LP tokens desired /// @return depositAmounts Array of token amounts to deposit (rounded up) - function computeMintAmounts(uint256 lpTokenAmount) public view returns (uint256[] memory depositAmounts) { + function mintDepositAmounts(uint256 lpTokenAmount) public view returns (uint256[] memory depositAmounts) { uint256 n = tokens.length; depositAmounts = new uint256[](n); @@ -136,11 +136,11 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard { /// @notice Calculate the proportional withdrawal amounts for a given LP token amount /// @param lpTokenAmount The amount of LP tokens to burn /// @return withdrawAmounts Array of token amounts to withdraw (rounded down) - function computeBurnAmounts(uint256 lpTokenAmount) external view returns (uint256[] memory withdrawAmounts) { - return _computeBurnAmounts(lpTokenAmount); + function burnReceiveAmounts(uint256 lpTokenAmount) external view returns (uint256[] memory withdrawAmounts) { + return _burnReceiveAmounts(lpTokenAmount); } - function _computeBurnAmounts(uint256 lpTokenAmount) internal view returns (uint256[] memory withdrawAmounts) { + function _burnReceiveAmounts(uint256 lpTokenAmount) internal view returns (uint256[] memory withdrawAmounts) { uint256 n = tokens.length; withdrawAmounts = new uint256[](n); @@ -188,7 +188,7 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard { if (!isInitialDeposit) { // Calculate required deposit amounts for the desired LP tokens - depositAmounts = computeMintAmounts(lpTokenAmount); + depositAmounts = mintDepositAmounts(lpTokenAmount); // Transfer in all token amounts for (uint i = 0; i < n; ) { @@ -284,7 +284,7 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard { } // Compute proportional withdrawal amounts for the requested LP amount (rounded down) - uint256[] memory withdrawAmounts = _computeBurnAmounts(lpAmount); + uint256[] memory withdrawAmounts = _burnReceiveAmounts(lpAmount); // Transfer underlying tokens out to receiver according to computed proportions for (uint i = 0; i < n; ) { @@ -334,6 +334,119 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard { Swaps ---------------------- */ + /// @notice Internal quote for exact-input swap that mirrors swap() rounding and fee application + /// @return grossIn amount to transfer in (inclusive of fee), amountOutUint output amount (uint), + /// amountInInternalUsed and amountOutInternal (64.64), amountInUintNoFee input amount excluding fee (uint) + function _quoteSwapExactIn( + uint256 i, + uint256 j, + uint256 maxAmountIn, + int128 limitPrice + ) + internal + view + returns ( + uint256 grossIn, + uint256 amountOutUint, + int128 amountInInternalUsed, + int128 amountOutInternal, + uint256 amountInUintNoFee + ) + { + uint256 n = tokens.length; + require(i < n && j < n, "swap: idx"); + require(maxAmountIn > 0, "swap: input zero"); + require(lmsr.nAssets > 0, "swap: empty pool"); + + // Estimate max net input (fee on gross rounded up, then subtract) + (, uint256 netUintForSwap) = _computeFee(maxAmountIn); + + // Convert to internal (floor) + int128 deltaInternalI = _uintToInternalFloor(netUintForSwap, bases[i]); + require(deltaInternalI > int128(0), "swap: input too small after fee"); + + // Compute internal amounts using LMSR (exact-input with price limit) + (amountInInternalUsed, amountOutInternal) = lmsr.swapAmountsForExactInput(i, j, deltaInternalI, limitPrice); + + // Convert actual used input internal -> uint (ceil) + amountInUintNoFee = _internalToUintCeil(amountInInternalUsed, bases[i]); + require(amountInUintNoFee > 0, "swap: input zero"); + + // Compute gross transfer including fee on the used input (ceil) + grossIn = amountInUintNoFee; + if (swapFeePpm > 0) { + grossIn += _ceilFee(amountInUintNoFee, swapFeePpm); + } + + // Ensure within user max + require(grossIn <= maxAmountIn, "swap: transfer exceeds max"); + + // Compute output (floor) + amountOutUint = _internalToUintFloor(amountOutInternal, bases[j]); + require(amountOutUint > 0, "swap: output zero"); + } + + /// @notice Internal quote for swap-to-limit that mirrors swapToLimit() rounding and fee application + /// @return grossIn amount to transfer in (inclusive of fee), amountOutUint output amount (uint), + /// amountInInternal and amountOutInternal (64.64), amountInUintNoFee input amount excluding fee (uint) + function _quoteSwapToLimit( + uint256 i, + uint256 j, + int128 limitPrice + ) + internal + view + returns ( + uint256 grossIn, + uint256 amountOutUint, + int128 amountInInternal, + int128 amountOutInternal, + uint256 amountInUintNoFee + ) + { + uint256 n = tokens.length; + require(i < n && j < n, "swapToLimit: idx"); + require(limitPrice > int128(0), "swapToLimit: limit <= 0"); + require(lmsr.nAssets > 0, "swapToLimit: pool uninitialized"); + + // Compute internal maxima at the price limit + (amountInInternal, amountOutInternal) = lmsr.swapAmountsForPriceLimit(i, j, limitPrice); + + // Convert input to uint (ceil) and output to uint (floor) + amountInUintNoFee = _internalToUintCeil(amountInInternal, bases[i]); + require(amountInUintNoFee > 0, "swapToLimit: input zero"); + + grossIn = amountInUintNoFee; + if (swapFeePpm > 0) { + grossIn += _ceilFee(amountInUintNoFee, swapFeePpm); + } + + amountOutUint = _internalToUintFloor(amountOutInternal, bases[j]); + require(amountOutUint > 0, "swapToLimit: output zero"); + } + + /// @notice External view to quote exact-in swap amounts (gross input incl. fee and output), matching swap() computations + function swapAmounts( + uint256 i, + uint256 j, + uint256 maxAmountIn, + int128 limitPrice + ) external view returns (uint256 amountIn, uint256 amountOut) { + (uint256 grossIn, uint256 outUint,,,) = _quoteSwapExactIn(i, j, maxAmountIn, limitPrice); + return (grossIn, outUint); + } + + /// @notice External view to quote swap-to-limit amounts (gross input incl. fee and output), matching swapToLimit() computations + function swapToLimitAmounts( + uint256 i, + uint256 j, + int128 limitPrice + ) external view returns (uint256 amountIn, uint256 amountOut) { + (uint256 grossIn, uint256 outUint,,,) = _quoteSwapToLimit(i, j, limitPrice); + return (grossIn, outUint); + } + + /// @notice Swap input token i -> token j. Payer must approve token i. /// @param payer address of the account that pays for the swap /// @param receiver address that will receive the output tokens @@ -361,47 +474,15 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard { uint256 prevBalI = IERC20(tokens[i]).balanceOf(address(this)); uint256 prevBalJ = IERC20(tokens[j]).balanceOf(address(this)); - // Calculate fee (ceiling) and net amount - (, uint256 netUintForSwap) = _computeFee(maxAmountIn); - - // Convert the net amount to internal (floor) - int128 deltaInternalI = _uintToInternalFloor(netUintForSwap, bases[i]); - require(deltaInternalI > int128(0), "swap: input too small after fee"); - - // Make sure LMSR state exists - require(lmsr.nAssets > 0, "swap: empty pool"); - - // Compute swap amounts in internal space using exact-input logic (with limitPrice) - (int128 amountInInternalUsed, int128 amountOutInternal) = lmsr.swapAmountsForExactInput( - i, - j, - deltaInternalI, - limitPrice - ); - - // Convert actual used input internal -> uint (ceiling to protect the pool) - uint256 amountInUint = _internalToUintCeil(amountInInternalUsed, bases[i]); - - // Total transfer amount includes fee calculated on the actual used input (ceiling) - uint256 totalTransferAmount = amountInUint; - if (swapFeePpm > 0) { - uint256 feeOnUsed = _ceilFee(amountInUint, swapFeePpm); - totalTransferAmount += feeOnUsed; - } - - // Ensure we do not attempt to transfer more than the caller specified as maximum - require(totalTransferAmount > 0, 'swap: input zero'); - require(totalTransferAmount <= maxAmountIn, "swap: transfer exceeds max"); + // Compute amounts using the same path as views + (uint256 totalTransferAmount, uint256 amountOutUint, int128 amountInInternalUsed, int128 amountOutInternal, ) = + _quoteSwapExactIn(i, j, maxAmountIn, limitPrice); // Transfer the exact amount from payer and require exact receipt (revert on fee-on-transfer) _safeTransferFrom(tokens[i], payer, address(this), totalTransferAmount); uint256 balIAfter = IERC20(tokens[i]).balanceOf(address(this)); require(balIAfter == prevBalI + totalTransferAmount, "swap: non-standard tokenIn"); - // Compute output uint amount (floor) - uint256 amountOutUint = _internalToUintFloor(amountOutInternal, bases[j]); - require(amountOutUint > 0, "swap: output zero"); - // Transfer output to receiver and verify exact decrease _safeTransfer(tokens[j], receiver, amountOutUint); uint256 balJAfter = IERC20(tokens[j]).balanceOf(address(this)); @@ -411,8 +492,7 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard { cachedUintBalances[i] = balIAfter; cachedUintBalances[j] = balJAfter; - // Apply swap to LMSR state with the internal amounts actually used - // (fee is already accounted for in the reduced input amount) + // Apply swap to LMSR state with the internal amounts actually used lmsr.applySwap(i, j, amountInInternalUsed, amountOutInternal); emit Swap(payer, receiver, tokens[i], tokens[j], totalTransferAmount, amountOutUint); @@ -437,37 +517,19 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard { require(limitPrice > int128(0), "swapToLimit: limit <= 0"); require(deadline == 0 || block.timestamp <= deadline, "swapToLimit: deadline exceeded"); - // Ensure LMSR state exists - require(lmsr.nAssets > 0, "swapToLimit: pool uninitialized"); - // Read previous balances for affected assets uint256 prevBalI = IERC20(tokens[i]).balanceOf(address(this)); uint256 prevBalJ = IERC20(tokens[j]).balanceOf(address(this)); - // Compute maxima in internal space using library - (int128 amountInInternalMax, int128 amountOutInternal) = lmsr.swapAmountsForPriceLimit(i, j, limitPrice); - - // Calculate how much input will be needed with fee included (ceiling to protect the pool) - uint256 amountInUsedUint = _internalToUintCeil(amountInInternalMax, bases[i]); - require(amountInUsedUint > 0, "swapToLimit: input zero"); - - // Total transfer amount is the input amount including what will be taken as fee (ceiling) - uint256 totalTransferAmount = amountInUsedUint; - - if (swapFeePpm > 0) { - uint256 feeOnUsed = _ceilFee(amountInUsedUint, swapFeePpm); - totalTransferAmount += feeOnUsed; - } + // Compute amounts using the same path as views + (uint256 totalTransferAmount, uint256 amountOutUint, int128 amountInInternalMax, int128 amountOutInternal, uint256 amountInUsedUint) = + _quoteSwapToLimit(i, j, limitPrice); // Transfer the exact amount needed from payer and require exact receipt (revert on fee-on-transfer) _safeTransferFrom(tokens[i], payer, address(this), totalTransferAmount); uint256 balIAfter = IERC20(tokens[i]).balanceOf(address(this)); require(balIAfter == prevBalI + totalTransferAmount, "swapToLimit: non-standard tokenIn"); - // Compute output amount (floor) - uint256 amountOutUint = _internalToUintFloor(amountOutInternal, bases[j]); - require(amountOutUint > 0, "swapToLimit: output zero"); - // Transfer output to receiver and verify exact decrease _safeTransfer(tokens[j], receiver, amountOutUint); uint256 balJAfter = IERC20(tokens[j]).balanceOf(address(this)); @@ -478,9 +540,9 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard { cachedUintBalances[j] = balJAfter; // Apply swap to LMSR state with the internal amounts - // (fee is already part of the reduced effective input) lmsr.applySwap(i, j, amountInInternalMax, amountOutInternal); + // Maintain original event semantics (logs input without fee) emit Swap(payer, receiver, tokens[i], tokens[j], amountInUsedUint, amountOutUint); return (amountInUsedUint, amountOutUint); @@ -685,7 +747,7 @@ contract PartyPool is IPartyPool, ERC20, ReentrancyGuard { } - function computeFlashRepaymentAmounts(uint256[] memory loanAmounts) external view + function flashRepaymentAmounts(uint256[] memory loanAmounts) external view returns (uint256[] memory repaymentAmounts) { repaymentAmounts = new uint256[](tokens.length); for (uint256 i = 0; i < tokens.length; i++) { diff --git a/test/PartyPool.t.sol b/test/PartyPool.t.sol index 8f7abd7..6f28d7e 100644 --- a/test/PartyPool.t.sol +++ b/test/PartyPool.t.sol @@ -316,7 +316,7 @@ contract PartyPoolTest is Test { token2.approve(address(pool), type(uint256).max); // Inspect the deposit amounts that the pool will require (these are rounded up) - uint256[] memory deposits = pool.computeMintAmounts(1); + uint256[] memory deposits = pool.mintDepositAmounts(1); // Basic sanity: deposits array length must match token count and not all zero necessarily assertEq(deposits.length, 3); @@ -358,7 +358,7 @@ contract PartyPoolTest is Test { uint256 totalLpBefore = pool.totalSupply(); // Compute required deposits and perform mint for 1 wei - uint256[] memory deposits = pool.computeMintAmounts(1); + uint256[] memory deposits = pool.mintDepositAmounts(1); // Sum deposits as deposited_value uint256 depositedValue = 0; @@ -392,14 +392,14 @@ contract PartyPoolTest is Test { vm.stopPrank(); } - /// @notice computeMintAmounts should round up deposit amounts to protect the pool. - function testComputeMintAmountsRoundingUp() public view { + /// @notice mintDepositAmounts should round up deposit amounts to protect the pool. + function testMintDepositAmountsRoundingUp() public view { uint256 totalLp = pool.totalSupply(); assertTrue(totalLp > 0, "precondition: total supply > 0"); // Request half of LP supply uint256 want = totalLp / 2; - uint256[] memory deposits = pool.computeMintAmounts(want); + uint256[] memory deposits = pool.mintDepositAmounts(want); // We expect each deposit to be roughly half the pool balance, but due to rounding up it should satisfy: // deposits[i] * 2 >= cached balance (i.e., rounding up) @@ -416,7 +416,7 @@ contract PartyPoolTest is Test { assertTrue(totalLp > 0, "precondition: LP > 0"); // Compute amounts required to redeem entire supply (should be current balances) - uint256[] memory withdrawAmounts = pool.computeBurnAmounts(totalLp); + uint256[] memory withdrawAmounts = pool.burnReceiveAmounts(totalLp); // Sanity: withdrawAmounts should equal pool balances (or very close due to rounding) for (uint i = 0; i < withdrawAmounts.length; i++) { @@ -632,8 +632,8 @@ contract PartyPoolTest is Test { vm.stopPrank(); } - /// @notice Verify computeMintAmounts matches the actual token transfers performed by mint() - function testComputeMintAmountsMatchesMint_3TokenPool() public { + /// @notice Verify mintDepositAmounts matches the actual token transfers performed by mint() + function testMintDepositAmountsMatchesMint_3TokenPool() public { // Use a range of LP requests (tiny to large fraction) uint256 totalLp = pool.totalSupply(); uint256[] memory requests = new uint256[](4); @@ -646,7 +646,7 @@ contract PartyPoolTest is Test { if (req == 0) req = 1; // Compute expected deposit amounts via view - uint256[] memory expected = pool.computeMintAmounts(req); + uint256[] memory expected = pool.mintDepositAmounts(req); // Ensure alice has tokens and approve pool vm.startPrank(alice); @@ -660,7 +660,7 @@ contract PartyPoolTest is Test { uint256 a2Before = token2.balanceOf(alice); // Perform mint (may revert for zero-request; ensure req>0 above) - // Guard: if computeMintAmounts returned all zeros, skip (nothing to transfer) + // Guard: if mintDepositAmounts returned all zeros, skip (nothing to transfer) bool allZero = (expected[0] == 0 && expected[1] == 0 && expected[2] == 0); if (!allZero) { uint256 lpBefore = pool.balanceOf(alice); @@ -679,8 +679,8 @@ contract PartyPoolTest is Test { } } - /// @notice Verify computeMintAmounts matches the actual token transfers performed by mint() for 10-token pool - function testComputeMintAmountsMatchesMint_10TokenPool() public { + /// @notice Verify mintDepositAmounts matches the actual token transfers performed by mint() for 10-token pool + function testMintDepositAmountsMatchesMint_10TokenPool() public { uint256 totalLp = pool10.totalSupply(); uint256[] memory requests = new uint256[](4); requests[0] = 1; @@ -691,7 +691,7 @@ contract PartyPoolTest is Test { uint256 req = requests[k]; if (req == 0) req = 1; - uint256[] memory expected = pool10.computeMintAmounts(req); + uint256[] memory expected = pool10.mintDepositAmounts(req); // Approve all tokens from alice vm.startPrank(alice); @@ -742,8 +742,8 @@ contract PartyPoolTest is Test { } } - /// @notice Verify computeBurnAmounts matches actual transfers performed by burn() for 3-token pool - function testComputeBurnAmountsMatchesBurn_3TokenPool() public { + /// @notice Verify burnReceiveAmounts matches actual transfers performed by burn() for 3-token pool + function testBurnReceiveAmountsMatchesBurn_3TokenPool() public { // Use address(this) as payer (holds initial LP from setUp) uint256 totalLp = pool.totalSupply(); uint256[] memory burns = new uint256[](4); @@ -769,7 +769,7 @@ contract PartyPoolTest is Test { } // Recompute withdraw amounts via view after any top-up - uint256[] memory expected = pool.computeBurnAmounts(req); + uint256[] memory expected = pool.burnReceiveAmounts(req); // If expected withdraws are all zero (rounding edge), skip this iteration if (expected[0] == 0 && expected[1] == 0 && expected[2] == 0) { @@ -795,8 +795,8 @@ contract PartyPoolTest is Test { } } - /// @notice Verify computeBurnAmounts matches actual transfers performed by burn() for 10-token pool - function testComputeBurnAmountsMatchesBurn_10TokenPool() public { + /// @notice Verify burnReceiveAmounts matches actual transfers performed by burn() for 10-token pool + function testBurnReceiveAmountsMatchesBurn_10TokenPool() public { uint256 totalLp = pool10.totalSupply(); uint256[] memory burns = new uint256[](4); burns[0] = 1; @@ -826,7 +826,7 @@ contract PartyPoolTest is Test { vm.stopPrank(); } - uint256[] memory expected = pool10.computeBurnAmounts(req); + uint256[] memory expected = pool10.burnReceiveAmounts(req); // If expected withdraws are all zero (rounding edge), skip this iteration bool allZero = true; @@ -1311,8 +1311,8 @@ contract PartyPoolTest is Test { ); } - /// @notice Test computeFlashRepaymentAmounts matches flash implementation - function testComputeFlashRepaymentAmounts() public view { + /// @notice Test flashRepaymentAmounts matches flash implementation + function testFlashRepaymentAmounts() public view { // Create different loan amount scenarios uint256[][] memory testCases = new uint256[][](3); @@ -1336,7 +1336,7 @@ contract PartyPoolTest is Test { for (uint256 i = 0; i < testCases.length; i++) { uint256[] memory loanAmounts = testCases[i]; - uint256[] memory repaymentAmounts = pool.computeFlashRepaymentAmounts(loanAmounts); + uint256[] memory repaymentAmounts = pool.flashRepaymentAmounts(loanAmounts); // Verify each repayment amount is correctly calculated for (uint256 j = 0; j < loanAmounts.length; j++) {