Presale.sol

Issue 01

Description

Line 73 enforces that busdLimits[0] is strictly smaller than busdLimits[1]. Some presales may wish to provide only a single contribution amount, which isn't possible with this condition.

Recommendation

Consider changing the condition to "<="

Issue 02

Description

If a malicious user sends BUSD to the contract, he can make tokenAmount greater than the available tokenX balance, which will make the withdrawal fail.

This issue can also arise if there is no hardcap and the presale contract raised more funds than the owner has tokenX to cover.

Recommendation

Calculate tokenAmount based on raised funds, not on BUSD balance, and make sure the owner has enough tokens to cover all amount of raised funds. Note that in these cases, users will not be able to get refunds until the presale is manually canceled.

Same issue as above on closePresale()

Issue 03

Description

onlyFactory() modifier is not used.

Issue 04

Description

withdrawRaisedFunds() requires that

 block.timestamp >= presaleCloseAt

without checking if hardcap was already reached.

Recommendation

If hardcap was reached before presaleCloseAt, allow withdrawRaisedFunds to continue as the presale has ended de-facto.

Issue 05

Description

If presale was successful (softcap was reached) users' funds are locked until either the presale is canceled or the team calls withdrawRaisedFunds.

Recommendation:

Consider taking a more decentralized approach - if presale wasn't canceled or withdrawRaisedFunds after a set amount of time, users can automatically call getRefund.

Note

After hardcap is reached, investors are still able to withdraw their funds as long as the presale wasn't finalized by calling withdrawRaisedFunds. Please note, that this can create a scenario where presale bounces between filled and not filled, because users can get a refund even after hardcap was reached.

Issue 06

Description

Contract can buy shield-network token to participate in presale, call join function and sell shield network token immediately. By doing that, they can bypass the minimum amount of tokens required to participate.

Recommendation

require tx.origin to be msg.sender in order to prevent contracts from participating in presale

Issue 07

Description

BUSD name is not indicative, since the presale can raise funds in any token and not restricted to be BUSD.

Issue 08

Description

The join function checks the amount of raised BUSD using busd.balanceOf. Thus, if users erroneously send BUSD directly to the contract they will not receive tokens, but the project creator will receive their funds.

Recommendation

In withdrawRaisedFunds transfer all excess BUSD to shield network, and in the join function perform the check using raisedFunds instead of busd balanceOf(address(this)).

Issue 09

Description

if tokenX has fees then when the presale owner transfer tokenX to the contract for distribution in withdrawRaisedFunds, the contract will receive less tokens than expected, which will guarantee that several presale participants won't be able to receive their tokens.

Recommendation

Add a sanity check that ensures that after the tokenX transfer, the tokenX balance of the presale contract is at least the expected tokenXAmount.

⚠️ Please note that in this scenario, presale does not support tokens with fees on transfer. This should be communicated to clients.

Last updated