Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add custom errors #27

Merged
merged 3 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 20 additions & 24 deletions contracts/BNBPartyFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ contract BNBPartyFactory is BNBPartyInternal, ReentrancyGuard {
function createParty(
string calldata name,
string calldata symbol
) external payable override nonReentrant returns (IERC20 newToken) {
require(
msg.value >= party.createTokenFee,
"BNBPartyFactory: insufficient BNB"
);
require(
address(BNBPositionManager) != address(0),
"BNBPartyFactory: BNBPositionManager not set"
);
)
external
payable
override
nonReentrant
insufficientBNB
notZeroAddress(address(BNBPositionManager))
returns (IERC20 newToken)
{
// create new token
newToken = new ERC20Token(name, symbol, party.initialTokenAmount);
// create First Liquidity Pool
Expand All @@ -37,9 +37,9 @@ contract BNBPartyFactory is BNBPartyInternal, ReentrancyGuard {
emit StartParty(address(newToken), msg.sender, liquidityPool);
}

function handleSwap(address recipient) external override {
require(isParty[msg.sender], "LP is not at the party");

function handleSwap(
address recipient
) external override onlyParty notZeroAddress(recipient) {
uint256 WBNBBalance = WBNB.balanceOf(msg.sender);
if (WBNBBalance < party.partyTarget) return;

Expand All @@ -52,33 +52,29 @@ contract BNBPartyFactory is BNBPartyInternal, ReentrancyGuard {

function joinParty(
address tokenOut,
uint256 amountOutMinimum,
uint256 deadline
) external payable {
uint256 amountOutMinimum
) external payable notZeroAddress(tokenOut) notZeroValue {
_executeSwap(
address(WBNB),
tokenOut,
msg.sender,
amountOutMinimum,
deadline,
msg.value
);
}

function leaveParty(
IERC20 tokenIn,
address tokenIn,
uint256 amountIn,
uint256 amountOutMinimum,
uint256 deadline
) external {
tokenIn.safeTransferFrom(msg.sender, address(this), amountIn);
tokenIn.safeIncreaseAllowance(address(swapRouter), amountIn);
uint256 amountOutMinimum
) external notZeroAddress(tokenIn) notZeroAmount(amountIn) {
IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);
IERC20(tokenIn).safeIncreaseAllowance(address(swapRouter), amountIn);
_executeSwap(
address(tokenIn),
tokenIn,
address(WBNB),
address(swapRouter),
amountOutMinimum,
deadline,
amountIn
);
IPeripheryPayments(address(swapRouter)).unwrapWETH9(
Expand Down
16 changes: 6 additions & 10 deletions contracts/BNBPartyInternal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ pragma solidity ^0.8.0;

import "./token/ERC20Token.sol";
import "./interfaces/IUniswapV3Pool.sol";
import "./BNBPartyState.sol";
abstract contract BNBPartyInternal is BNBPartyState {
import "./BNBPartyModifiers.sol";

abstract contract BNBPartyInternal is BNBPartyModifiers {
function _createFLP(
address _token
) internal returns (address liquidityPool) {
Expand Down Expand Up @@ -99,26 +100,21 @@ abstract contract BNBPartyInternal is BNBPartyState {

function _executeSwap(address tokenOut) internal {
uint256 amountIn = msg.value - party.createTokenFee;
_executeSwap(address(WBNB), tokenOut, msg.sender, 0, block.timestamp, amountIn);
_executeSwap(address(WBNB), tokenOut, msg.sender, 0, amountIn);
}

function _executeSwap(
address tokenIn,
address tokenOut,
address recipient,
uint256 amountOutMinimum,
uint256 deadline,
uint256 amountIn
) internal {
require(
address(swapRouter) != address(0),
"BNBPartyFactory: swapRouter not set"
);
) internal notZeroAddress(address(swapRouter)) {
ISwapRouter.ExactInputParams memory params = ISwapRouter
.ExactInputParams({
path: abi.encodePacked(tokenIn, party.partyLpFee, tokenOut),
recipient: recipient,
deadline: deadline,
deadline: block.timestamp,
amountIn: amountIn,
amountOutMinimum: amountOutMinimum
});
Expand Down
31 changes: 31 additions & 0 deletions contracts/BNBPartyModifiers.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./BNBPartyState.sol";

abstract contract BNBPartyModifiers is BNBPartyState {
modifier onlyParty() {
if (!isParty[msg.sender]) revert LPNotAtParty();
_;
}

modifier notZeroAddress(address _address) {
if (_address == address(0)) revert ZeroAddress();
_;
}

modifier insufficientBNB() {
if (msg.value < party.createTokenFee) revert InsufficientBNB();
_;
}

modifier notZeroAmount(uint256 _amount) {
if (_amount == 0) revert ZeroAmount();
_;
}

modifier notZeroValue() {
if (msg.value == 0) revert ZeroAmount();
_;
}
}
37 changes: 21 additions & 16 deletions contracts/BNBPartyState.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,21 @@ abstract contract BNBPartyState is IBNBPartyFactory, Ownable {
IWBNB public immutable WBNB;

constructor(Party memory _party, IWBNB _WBNB) Ownable(_msgSender()) {
require(_party.partyTarget > 0, "buyLimit is zero");
require(_party.initialTokenAmount > 0, "initialTokenAmount is zero");
require(
_party.partyTarget > _party.bonusPartyCreator,
"partyTarget is less than bonusParty"
);
require(_party.sqrtPriceX96 > 0, "sqrtPriceX96 is zero");
if (address(_WBNB) == address(0)) {
revert ZeroAddress();
}
if (_party.partyTarget == 0) {
revert ZeroAmount();
}
if (_party.initialTokenAmount == 0) {
revert ZeroAmount();
}
if (_party.partyTarget <= _party.bonusPartyCreator) {
revert BonusGreaterThanTarget();
}
if (_party.sqrtPriceX96 == 0) {
revert ZeroAmount();
}
party = _party;
WBNB = _WBNB;
}
Expand All @@ -35,20 +43,17 @@ abstract contract BNBPartyState is IBNBPartyFactory, Ownable {
INonfungiblePositionManager _BNBPositionManager,
INonfungiblePositionManager _positionManager
) external onlyOwner {
require(
_BNBPositionManager != BNBPositionManager &&
_positionManager != positionManager,
"BNBPartyFactory: positionManager already set"
);
if (_BNBPositionManager == BNBPositionManager && _positionManager == positionManager) {
revert PositionManagerAlreadySet();
}
positionManager = _positionManager;
BNBPositionManager = _BNBPositionManager;
}

function setSwapRouter(ISwapRouter _swapRouter) external onlyOwner {
require(
_swapRouter != swapRouter,
"BNBPartyFactory: swapRouter already set"
);
if (_swapRouter == swapRouter) {
revert SwapRouterAlreadySet();
}
swapRouter = _swapRouter;
}
}
9 changes: 9 additions & 0 deletions contracts/interfaces/IBNBPartyFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,13 @@ interface IBNBPartyFactory {
address indexed owner,
address indexed FLPAddress
);

error InsufficientBNB();
error ZeroAddress();
error ZeroAmount();
error BonusGreaterThanTarget();
error PositionManagerNotSet();
error PositionManagerAlreadySet();
error SwapRouterAlreadySet();
error LPNotAtParty();
}
53 changes: 40 additions & 13 deletions test/BNBPartyFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,16 +124,16 @@ describe("BNBPartyFactory", function () {
})

it("should revert if not enough BNB is sent", async function () {
await expect(bnbPartyFactory.createParty(name, symbol, { value: tokenCreationFee - 1n })).to.be.revertedWith(
"BNBPartyFactory: insufficient BNB"
)
await expect(
bnbPartyFactory.createParty(name, symbol, { value: tokenCreationFee - 1n })
).to.be.revertedWithCustomError(bnbPartyFactory, "InsufficientBNB")
})

it("should revert to Create Party if position manager is not set", async function () {
await bnbPartyFactory.setNonfungiblePositionManager(ethers.ZeroAddress, ethers.ZeroAddress)
await expect(bnbPartyFactory.createParty(name, symbol, { value: tokenCreationFee })).to.be.revertedWith(
"BNBPartyFactory: BNBPositionManager not set"
)
await expect(
bnbPartyFactory.createParty(name, symbol, { value: tokenCreationFee })
).to.be.revertedWithCustomError(bnbPartyFactory, "ZeroAddress")
await bnbPartyFactory.setNonfungiblePositionManager(
await positionManager.getAddress(),
await positionManager.getAddress()
Expand All @@ -143,8 +143,9 @@ describe("BNBPartyFactory", function () {
it("should revert if swap router is not set", async function () {
const amountIn = ethers.parseUnits("1", 18)
await bnbPartyFactory.setSwapRouter(ethers.ZeroAddress)
await expect(bnbPartyFactory.createParty(name, symbol, { value: amountIn })).to.be.revertedWith(
"BNBPartyFactory: swapRouter not set"
await expect(bnbPartyFactory.createParty(name, symbol, { value: amountIn })).to.be.revertedWithCustomError(
bnbPartyFactory,
"ZeroAddress"
)
await bnbPartyFactory.setSwapRouter(await swapRouter.getAddress())
})
Expand All @@ -168,7 +169,7 @@ describe("BNBPartyFactory", function () {
const amountIn = ethers.parseUnits("5", 17)

const lpBalanceBefore = await weth9.balanceOf(lpAddress)
await bnbPartyFactory.joinParty(MEME, 0, deadline, { value: amountIn })
await bnbPartyFactory.joinParty(MEME, 0, { value: amountIn })
const lpBalanceAfter = await weth9.balanceOf(lpAddress)

expect(lpBalanceAfter).to.be.equal(lpBalanceBefore + amountIn)
Expand All @@ -179,7 +180,7 @@ describe("BNBPartyFactory", function () {
const tokenOutContract = await ethers.getContractAt("ERC20", MEME)

const balanceBefore = await tokenOutContract.balanceOf(await signers[0].getAddress())
await bnbPartyFactory.joinParty(MEME, 0, deadline, { value: amountIn })
await bnbPartyFactory.joinParty(MEME, 0, { value: amountIn })
const balanceAfter = await tokenOutContract.balanceOf(await signers[0].getAddress())

expect(balanceAfter).to.be.gt(balanceBefore)
Expand All @@ -191,7 +192,7 @@ describe("BNBPartyFactory", function () {
// approve token
await tokenOutContract.approve(await bnbPartyFactory.getAddress(), amountIn)
const bnbBalanceBefore = await ethers.provider.getBalance(await signers[0].getAddress())
await bnbPartyFactory.leaveParty(MEME, amountIn, 0, deadline)
await bnbPartyFactory.leaveParty(MEME, amountIn, 0)
const bnbBalanceAfter = await ethers.provider.getBalance(await signers[0].getAddress())
expect(bnbBalanceAfter).to.be.gt(bnbBalanceBefore)
})
Expand All @@ -203,7 +204,7 @@ describe("BNBPartyFactory", function () {
await tokenOutContract.approve(await bnbPartyFactory.getAddress(), amountIn)

const lpBalanceBefore = await weth9.balanceOf(lpAddress)
await bnbPartyFactory.leaveParty(MEME, amountIn, 0, deadline)
await bnbPartyFactory.leaveParty(MEME, amountIn, 0)
const lpBalanceAfter = await weth9.balanceOf(lpAddress)

expect(lpBalanceBefore).to.be.gt(lpBalanceAfter)
Expand Down Expand Up @@ -297,7 +298,7 @@ describe("BNBPartyFactory", function () {
expect(liquidityPoolBalance).to.be.equal(amountIn - tokenCreationFee)
})

it("Should increase user tokens with excess party fee", async () => {
it("should increase user tokens with excess party fee", async () => {
const amountIn = ethers.parseUnits("1", 17)
const tx = await bnbPartyFactory.createParty(name, symbol, { value: amountIn })
await tx.wait()
Expand All @@ -311,6 +312,32 @@ describe("BNBPartyFactory", function () {
expect(balance).to.be.gt(0)
})

it("should revert tokenOut zero address on join party", async () => {
await expect(
bnbPartyFactory.joinParty(ethers.ZeroAddress, 0, { value: ethers.parseUnits("1", 17) })
).to.be.revertedWithCustomError(bnbPartyFactory, "ZeroAddress")
})

it("should revert zero msg.value on join party", async () => {
await expect(bnbPartyFactory.joinParty(MEME, 0)).to.be.revertedWithCustomError(
bnbPartyFactory,
"ZeroAmount"
)
})

it('should revert if "amountIn" is zero on leave party', async () => {
await expect(bnbPartyFactory.leaveParty(MEME, 0, 0)).to.be.revertedWithCustomError(
bnbPartyFactory,
"ZeroAmount"
)
})

it("should revert if tokenOut zero address on leave party", async () => {
await expect(
bnbPartyFactory.leaveParty(ethers.ZeroAddress, ethers.parseUnits("1", 16), 0)
).to.be.revertedWithCustomError(bnbPartyFactory, "ZeroAddress")
})

function getDataHexString(token0: string, token1: string) {
return ethers.concat([
ethers.zeroPadValue(token0, 20),
Expand Down