fairLaunch.sol

Issue 01

Description

There is no guarantee that the owner deposits will satisfy the presale and liquidity rates.

Issue 02

Description

Use a modifier instead of the presale require statement for better readability

Issue 03

Description

The investor array's size is limitless. Iterating over an unbounded array may cause the transaction to hit the block gas limit.

Recommendation

Use a mapping to track contributions.

Issue 04

Description

The functions call external contracts, exposing themselves to potential reentrancy attacks.

The code does not follow check effect interactions pattern.

Example:

IBEP20(token).safeTransfer(msg.sender, claimableAmount);
claimed[msg.sender] = claimed[msg.sender] + claimableAmount;
totalClaimedAmount = totalClaimedAmount + claimableAmount;

Recommendation

Add a reentrancy guard or follow check-effect interactions pattern. check-effect interaction pattern is more recommended because reentrancy guard has limitations such us calling other function which has reentrancy guard protection will cause an error.

Issue 05

Description

The function does not change the user's deposit value, hence any user can withdraw their deposit multiple times and drain the contract.

Recommendation

Add a require statements that makes sure the user can withdraw their deposit and set deposits[msg.sender] to 0 after the withdrawal.

Issue 06

Description

The function does not remove the user from the investors array.

Issue 07

Description

The owner can lock funds in the contracts by never calling this function if the presale exceeds softcap

Issue 08

Description

The contract multiplies listingRate by the amount of amount to get the number of tokens. Therefore, listingRate should be calculated as token/ETH (token per ETH). However it is currently calculated as ETH/token (ETH per token)

Issue 09

Description

listingRate does not subtract the fees taken from the total token amount as service fee. Consequently, users may be unable to withdraw their tokens from the contract as the amount of tokens for users does not match the actual amount of tokens in the contract (It will be less).

Issue 10

Description

If a liquidity pool already exists, there may unrecoverable leftover tokens in the contract. The issue was resolved for eth and not for tokens.

Issue 11

Description

The function calls sendValue multiple times. However, these calls may fail by the recipient, reverting the entire transaction.

Recommendation

Consider wrapping these calls inside try-catch or change the transfer mechanism into a withdraw function that will be called by the recipients.

Issue 12

Description

return user.mul(listingRate);

listingRate is multiplied by a factor.

Issue 14

Description

The function may be called anytime. Should the function be called before presaleEndTimestamp, (now - presaleEndTimeStamp) will underflow.

Issue 14

Description

deposits[msg.sender] is zeroed and then sent out as the value, so users will always withdraw 0 tokens - the value must be kept aside before zeroing it out.

deposits[msg.sender] = 0;
Address.sendValue(msg.sender, deposits[msg.sender]);

Issue 15

Description

A malicious user can send extra eth to the contract and prevent this function from ever succeeding.

require(address(this).balance <= maxOwnerReceive, "too much");
Address.sendValue(owner(), address(this).balance);

Recommendation

Find a use for the leftover funds - should they go to blitz? To liquidity? To holders?

General Notes:

  • There are many "magic numbers" scattered in the contract. Consider using constants with meaningful names for better readability and to decrease human errors.

  • There are many functions that accept parameters from users without validating them. When receiving input from external callers, make sure the values meet certain criteria in order to save gas costs and prevent bugs.

Last updated