delegated reentrancy lock

This commit is contained in:
tim
2025-10-07 14:37:44 -04:00
parent ef039aa57e
commit 98e80ab6ca
6 changed files with 96 additions and 130 deletions

View File

@@ -144,7 +144,7 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
---------------------- */
/// @inheritdoc IPartyPool
function initialMint(address receiver, uint256 lpTokens) external nonReentrant
function initialMint(address receiver, uint256 lpTokens) external
returns (uint256 lpMinted) {
bytes memory data = abi.encodeWithSignature(
"initialMint(address,uint256,int128)",
@@ -162,7 +162,7 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
/// @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 nonReentrant
function mint(address payer, address receiver, uint256 lpTokenAmount, uint256 deadline) external
returns (uint256 lpMinted) {
bytes memory data = abi.encodeWithSignature(
"mint(address,address,uint256,uint256)",
@@ -181,7 +181,7 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
/// @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.
function burn(address payer, address receiver, uint256 lpAmount, uint256 deadline) external nonReentrant
function burn(address payer, address receiver, uint256 lpAmount, uint256 deadline) external
returns (uint256[] memory withdrawAmounts) {
bytes memory data = abi.encodeWithSignature(
"burn(address,address,uint256,uint256)",
@@ -220,31 +220,20 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
int128 limitPrice,
uint256 deadline
) external nonReentrant returns (uint256 amountIn, uint256 amountOut, uint256 fee) {
uint256 n = tokens.length;
require(inputTokenIndex < n && outputTokenIndex < n, "swap: idx");
require(maxAmountIn > 0, "swap: input zero");
require(deadline == 0 || block.timestamp <= deadline, "swap: deadline exceeded");
// Read previous balances for affected assets
uint256 prevBalI = IERC20(tokens[inputTokenIndex]).balanceOf(address(this));
uint256 prevBalJ = IERC20(tokens[outputTokenIndex]).balanceOf(address(this));
// Compute amounts using the same path as views
(uint256 totalTransferAmount, uint256 amountOutUint, int128 amountInInternalUsed, int128 amountOutInternal, , uint256 feeUint) =
_quoteSwapExactIn(inputTokenIndex, outputTokenIndex, maxAmountIn, limitPrice);
// Transfer the exact amount from payer and require exact receipt (revert on fee-on-transfer)
// Transfer tokens
tokens[inputTokenIndex].safeTransferFrom(payer, address(this), totalTransferAmount);
uint256 balIAfter = IERC20(tokens[inputTokenIndex]).balanceOf(address(this));
require(balIAfter == prevBalI + totalTransferAmount, "swap: non-standard tokenIn");
// Transfer output to receiver and verify exact decrease
tokens[outputTokenIndex].safeTransfer(receiver, amountOutUint);
uint256 balJAfter = IERC20(tokens[outputTokenIndex]).balanceOf(address(this));
require(balJAfter == prevBalJ - amountOutUint, "swap: non-standard tokenOut");
// Accrue protocol share (floor) from the fee on input token
if (PROTOCOL_FEE_PPM > 0 && feeUint > 0 && PROTOCOL_FEE_ADDRESS != address(0)) {
if (PROTOCOL_FEE_PPM > 0 && feeUint > 0) {
uint256 protoShare = (feeUint * PROTOCOL_FEE_PPM) / 1_000_000; // floor
if (protoShare > 0) {
protocolFeesOwed[inputTokenIndex] += protoShare;
@@ -288,7 +277,6 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
uint256 n = tokens.length;
require(inputTokenIndex < n && outputTokenIndex < 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, SWAP_FEE_PPM);
@@ -302,7 +290,6 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
// Convert actual used input internal -> uint (ceil)
amountInUintNoFee = _internalToUintCeil(amountInInternalUsed, bases[inputTokenIndex]);
require(amountInUintNoFee > 0, "swap: input zero");
// Compute gross transfer including fee on the used input (ceil)
feeUint = 0;
@@ -317,7 +304,6 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
// Compute output (floor)
amountOutUint = _internalToUintFloor(amountOutInternal, bases[outputTokenIndex]);
require(amountOutUint > 0, "swap: output zero");
}
@@ -329,7 +315,7 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
uint256 outputTokenIndex,
int128 limitPrice,
uint256 deadline
) external nonReentrant returns (uint256 amountInUsed, uint256 amountOut, uint256 fee) {
) external returns (uint256 amountInUsed, uint256 amountOut, uint256 fee) {
bytes memory data = abi.encodeWithSignature(
'swapToLimit(address,address,uint256,uint256,int128,uint256,uint256,uint256)',
payer,
@@ -426,18 +412,9 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
IERC20 token = IERC20(tokenAddr);
require(amount <= token.balanceOf(address(this)));
(uint256 fee, ) = _computeFee(amount, FLASH_FEE_PPM);
require(
token.transfer(address(receiver), amount),
"FlashLender: Transfer failed"
);
require(
receiver.onFlashLoan(msg.sender, address(token), amount, fee, data) == FLASH_CALLBACK_SUCCESS,
"FlashLender: Callback failed"
);
require(
token.transferFrom(address(receiver), address(this), amount + fee),
"FlashLender: Repay failed"
);
require(token.transfer(address(receiver), amount));
require(receiver.onFlashLoan(msg.sender, address(token), amount, fee, data) == FLASH_CALLBACK_SUCCESS);
require(token.transferFrom(address(receiver), address(this), amount + fee));
return true;
}
@@ -467,15 +444,4 @@ contract PartyPool is PartyPoolBase, ERC20External, IPartyPool {
return lmsr.swapAmountsForExactInput(i, j, a, limitPrice);
}
/// @notice Compute fee and net amounts for a gross input (fee rounded up to favor the pool).
/// @return feeUint fee taken (uint) and netUint remaining for protocol use (uint)
function _computeFee(uint256 gross) internal view returns (uint256 feeUint, uint256 netUint) {
return _computeFee(gross, SWAP_FEE_PPM);
}
/// @notice Convenience: return gross = net + fee(net) using ceiling for fee.
function _addFee(uint256 netUint) internal view returns (uint256 gross) {
return _addFee(netUint, SWAP_FEE_PPM);
}
}