diff --git a/contracts/BNBPartyCreation.sol b/contracts/BNBPartyCreation.sol index 7be6807..cb67894 100644 --- a/contracts/BNBPartyCreation.sol +++ b/contracts/BNBPartyCreation.sol @@ -2,24 +2,26 @@ pragma solidity ^0.8.0; import "./BNBPartySwaps.sol"; -import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; /// @title BNBPartyCreation /// @notice This abstract contract manages the creation pools within the BNB Party system. abstract contract BNBPartyCreation is BNBPartySwaps { + using SafeERC20 for IERC20; + /// @notice Creates the first liquidity pool (FLP) for a given token. /// @param _token Address of the token to be used in the liquidity pool /// @return liquidityPool Address of the newly created liquidity pool /// @dev Sets the token amounts based on the balance and initializes the pool function _createFLP(address _token) internal returns (address liquidityPool) { - (address tokenA, address tokenB, uint160 sqrtPrice) = _getTokenPairAndPrice(_token); + (address token0, address token1, uint160 sqrtPrice) = _getTokenPairAndPrice(_token); // Determine the token amounts - (uint256 amount0, uint256 amount1) = _calculateAmounts(tokenA); - IERC20(_token).approve(address(BNBPositionManager), party.initialTokenAmount); + (uint256 amount0, uint256 amount1) = _calculateAmounts(token0); + IERC20(_token).safeIncreaseAllowance(address(BNBPositionManager), party.initialTokenAmount); liquidityPool = _createLP( BNBPositionManager, - tokenA, - tokenB, + token0, + token1, amount0, amount1, sqrtPrice, @@ -76,16 +78,15 @@ abstract contract BNBPartyCreation is BNBPartySwaps { ); } - /// @notice Calculates the amounts of token0 and token1 based on the balance of tokenA and tokenB. - /// @param tokenA Address of the first token. + /// @notice Calculates the token amounts for the liquidity pool. + /// @param token0 Address of the first token. /// @return amount0 The amount of token0. /// @return amount1 The amount of token1. - function _calculateAmounts(address tokenA) internal view returns (uint256 amount0, uint256 amount1) { - uint256 balanceA = IERC20(tokenA).balanceOf(address(this)); - if (balanceA == party.initialTokenAmount) { - amount0 = party.initialTokenAmount; // Set amount0 if tokenA balance matches the initial amount + function _calculateAmounts(address token0) internal view returns (uint256 amount0, uint256 amount1) { + if (token0 != address(WBNB)) { + amount0 = party.initialTokenAmount; // Set amount0 if token0 is not WBNB } else { - amount1 = party.initialTokenAmount; // Otherwise, set amount1 + amount1 = party.initialTokenAmount; // Otherwise, set amount1 if token0 is WBNB } } } diff --git a/contracts/BNBPartyFee.sol b/contracts/BNBPartyFee.sol index 1dbf775..e40782d 100644 --- a/contracts/BNBPartyFee.sol +++ b/contracts/BNBPartyFee.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.0; import "./BNBPartyModifiers.sol"; +import "./interfaces/IUniswapV3Pool.sol"; /// @title BNBPartyFee /// @notice This abstract contract provides internal functions for calculating fees in the BNB Party system. diff --git a/contracts/BNBPartyLiquidity.sol b/contracts/BNBPartyLiquidity.sol index 0a5fbe9..216f5fe 100644 --- a/contracts/BNBPartyLiquidity.sol +++ b/contracts/BNBPartyLiquidity.sol @@ -2,11 +2,12 @@ pragma solidity ^0.8.0; import "./BNBPartyLiquidityHelper.sol"; -import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; /// @title BNBPartyLiquidity /// @notice This abstract contract manages the creation and handling of liquidity pools within the BNB Party system. abstract contract BNBPartyLiquidity is BNBPartyLiquidityHelper { + using SafeERC20 for IERC20; + /// @notice Handles liquidity by decreasing the liquidity, collecting tokens, and creating a new liquidity pool. /// @param recipient Address receiving the bonus BNB /// @dev Decreases liquidity, collects tokens, creates a new pool, and sends bonuses @@ -16,12 +17,12 @@ abstract contract BNBPartyLiquidity is BNBPartyLiquidityHelper { address token0 = pool.token0(); address token1 = pool.token1(); uint128 liquidity = pool.liquidity(); + uint256 unwrapAmount = party.bonusTargetReach + party.bonusPartyCreator + party.targetReachFee; + uint160 newSqrtPriceX96; // Decrease liquidity and collect tokens (uint256 amount0, uint256 amount1) = _decreaseAndCollect(lpToTokenId[msg.sender], liquidity); - uint256 unwrapAmount = party.bonusTargetReach + party.bonusPartyCreator + party.targetReachFee; - uint160 newSqrtPriceX96; if (token0 == address(WBNB)) { amount0 -= unwrapAmount; // Deduct unwrap amount from token0 if it is WBNB isTokenOnPartyLP[token1] = false; @@ -43,7 +44,8 @@ abstract contract BNBPartyLiquidity is BNBPartyLiquidityHelper { } // Approve tokens for the new liquidity pool creation - _approveTokens(token0, token1, amount0, amount1); + IERC20(token0).safeIncreaseAllowance(address(positionManager), amount0); + IERC20(token1).safeIncreaseAllowance(address(positionManager), amount1); // Create new Liquidity Pool _createLP(positionManager, token0, token1, amount0, amount1, newSqrtPriceX96, party.lpFee, party.lpTicks); diff --git a/contracts/BNBPartyLiquidityHelper.sol b/contracts/BNBPartyLiquidityHelper.sol index a2f0854..b6b7eaa 100644 --- a/contracts/BNBPartyLiquidityHelper.sol +++ b/contracts/BNBPartyLiquidityHelper.sol @@ -7,7 +7,7 @@ import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; /// @title BNBPartyLiquidityHelper /// @notice This abstract contract provides helper functions for managing liquidity within the BNB Party system /// @dev Inherits from BNBPartyCreation and uses Uniswap's INonfungiblePositionManager for liquidity management -abstract contract BNBPartyLiquidityHelper is BNBPartyCreation { +abstract contract BNBPartyLiquidityHelper is BNBPartyCreation { /// @notice Decreases liquidity from a position and collects the resulting tokens /// @param tokenId The ID of the liquidity position to decrease /// @param liquidity The amount of liquidity to decrease @@ -39,21 +39,6 @@ abstract contract BNBPartyLiquidityHelper is BNBPartyCreation { ); } - /// @notice Approves tokens for the position manager to spend - /// @param token0 The address of the first token - /// @param token1 The address of the second token - /// @param amount0 The amount of token0 to approve - /// @param amount1 The amount of token1 to approve - function _approveTokens( - address token0, - address token1, - uint256 amount0, - uint256 amount1 - ) internal { - IERC20(token0).approve(address(positionManager), amount0); - IERC20(token1).approve(address(positionManager), amount1); - } - /// @notice Burns all MEME tokens held by this contract /// @param token The address of the MEME token to burn function _burnMemeToken(address token) internal { diff --git a/contracts/BNBPartyManageable.sol b/contracts/BNBPartyManageable.sol index 953a20a..313ae5d 100644 --- a/contracts/BNBPartyManageable.sol +++ b/contracts/BNBPartyManageable.sol @@ -27,24 +27,23 @@ abstract contract BNBPartyManageable is BNBPartyModifiers, Pausable { /// @dev Reverts if the new swap router is identical to the current one function setBNBPartySwapRouter( ISwapRouter _swapRouter - ) external onlyOwner SwapRouterAlreadySet(_swapRouter, BNBSwapRouter) { + ) external onlyOwner swapRouterAlreadySet(_swapRouter, BNBSwapRouter) { BNBSwapRouter = _swapRouter; } function setSwapRouter( ISwapRouter _swapRouter - ) external onlyOwner SwapRouterAlreadySet(_swapRouter, swapRouter) { + ) external onlyOwner swapRouterAlreadySet(_swapRouter, swapRouter) { swapRouter = _swapRouter; } /// @notice Withdraws the balance of BNB from token creation fees /// @dev Reverts if the contract balance is zero function withdrawFee() external onlyOwner { - if (address(this).balance == 0) { - revert ZeroAmount(); + if (address(this).balance > 0) { + emit TransferOutBNB(msg.sender, address(this).balance); // Emits an event indicating the transfer of BNB + payable(msg.sender).transfer(address(this).balance); // Transfers the entire BNB balance to the owner } - payable(msg.sender).transfer(address(this).balance); // Transfers the entire BNB balance to the owner - emit TransferOutBNB(msg.sender, address(this).balance); // Emits an event indicating the transfer of BNB } /// @notice Withdraws LP fees from the BNB Party for specified liquidity pools diff --git a/contracts/BNBPartyModifiers.sol b/contracts/BNBPartyModifiers.sol index 7b1229d..39f534e 100644 --- a/contracts/BNBPartyModifiers.sol +++ b/contracts/BNBPartyModifiers.sol @@ -36,14 +36,15 @@ abstract contract BNBPartyModifiers is BNBPartyState { _; } - /// @notice Ensures that some value (ETH) is sent with the transaction + /// @notice Ensures that some value (BNB) is sent with the transaction /// @dev Reverts if no value is sent modifier notZeroValue() { if (msg.value == 0) revert ZeroAmount(); _; } - modifier SwapRouterAlreadySet( + /// @notice Ensures the swap router is not already set + modifier swapRouterAlreadySet( ISwapRouter _swapRouter, ISwapRouter _newSwapRouter ) { diff --git a/contracts/BNBPartyState.sol b/contracts/BNBPartyState.sol index 28dd9f8..1667209 100644 --- a/contracts/BNBPartyState.sol +++ b/contracts/BNBPartyState.sol @@ -6,7 +6,6 @@ import "@bnb-party/v3-periphery/contracts/interfaces/ISwapRouter.sol"; import "./interfaces/ISqrtPriceCalculator.sol"; import "./interfaces/INonfungiblePositionManager.sol"; import "./interfaces/IBNBPartyFactory.sol"; -import "./interfaces/IUniswapV3Pool.sol"; import "./interfaces/IWBNB.sol"; /// @title BNBPartyState @@ -20,11 +19,11 @@ abstract contract BNBPartyState is IBNBPartyFactory, Ownable { mapping(address => uint256) public lpToTokenId; // Mapping from LiquidityPool to its NFT tokenId mapping(address => address) public lpToCreator; // Mapping from LiquidityPool to its creator mapping(address => bool) public isTokenOnPartyLP; // Mapping to track if a token is part of a party - ISqrtPriceCalculator public sqrtPriceCalculator; uint256 constant FEE_GROWTH_GLOBAL_SCALE = 2**128; Party public party; // store party parameters + ISqrtPriceCalculator public immutable sqrtPriceCalculator; // Sqrt price calculator contract IWBNB public immutable WBNB; // Wrapped BNB token contract /// @notice Constructor to initialize the BNBPartyState contract diff --git a/contracts/BNBPartySwaps.sol b/contracts/BNBPartySwaps.sol index c1023cc..ac27a50 100644 --- a/contracts/BNBPartySwaps.sol +++ b/contracts/BNBPartySwaps.sol @@ -24,13 +24,10 @@ abstract contract BNBPartySwaps is BNBPartyView { /// @notice Transfers BNB to the specified recipient /// @param recipient Address receiving the BNB /// @param amount Amount of BNB to transfer - /// @dev Uses call to send BNB and reverts if the transfer fails + /// @dev Uses transfer to send BNB and reverts if the transfer fails function _transferBNB(address recipient, uint256 amount) private { - (bool success, ) = recipient.call{value: amount}(""); - if (!success) { - revert BonusAmountTransferFailed(); - } emit TransferOutBNB(recipient, amount); + payable(recipient).transfer(amount); // Transfer BNB to recipient } /// @notice Executes a swap from WBNB to another token diff --git a/contracts/token/ERC20Token.sol b/contracts/token/ERC20Token.sol index 724f187..951cc5b 100644 --- a/contracts/token/ERC20Token.sol +++ b/contracts/token/ERC20Token.sol @@ -1,22 +1,21 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; /// @title ERC20Token /// @notice This contract is a basic ERC20 token with burnable capabilities, used in the BNB Party system. contract ERC20Token is ERC20, ERC20Burnable { /// @notice Constructs the ERC20 token with a name, symbol, and initial supply. - /// @param name The name of the token - /// @param symbol The symbol of the token + /// @param tokenName The name of the token + /// @param tokenSymbol The symbol of the token /// @param initialAmount The initial amount of tokens to mint to the deployer's address /// @dev The token name ends with " Party" constructor( - string memory name, - string memory symbol, + string memory tokenName, + string memory tokenSymbol, uint256 initialAmount - ) ERC20(string(abi.encodePacked(name, " Party")), symbol) { + ) ERC20(string(abi.encodePacked(tokenName, " Party")), tokenSymbol) { _mint(msg.sender, initialAmount); // Mint the initial supply to the deployer's address } } diff --git a/slither.config.json b/slither.config.json index 09a63c3..a0b19f1 100644 --- a/slither.config.json +++ b/slither.config.json @@ -1,5 +1,5 @@ { "detectors_to_exclude": "solc-version,similar-names", - "filter_paths": "node_modules/@bnb-party,contracts/mock/,contracts/mocks,node_modules/@ironblocks/firewall-consumer/contracts/,node_modules/@poolzfinance/poolz-helper-v2", + "filter_paths": "node_modules/@bnb-party,contracts/mock/,contracts/mocks,node_modules/@ironblocks/firewall-consumer/contracts/,node_modules/@poolzfinance/poolz-helper-v2,node_modules/@openzeppelin/", "compile_force_framework": "hardhat" }