# Presale.sol

### Issue 01&#x20;

| **Type**      | **Severity**                               | **Location**                  | **Status**                                     |
| ------------- | ------------------------------------------ | ----------------------------- | ---------------------------------------------- |
| Logical Issue | <mark style="color:yellow;">**Low**</mark> | <h4><code>Line 73</code></h4> | <mark style="color:green;">**✔️ Fixed**</mark> |

**Description** &#x20;

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.&#x20;

**Recommendation**

Consider changing the condition to "<="

### Issue 02&#x20;

<table data-header-hidden><thead><tr><th width="227">Type</th><th>Severity</th><th>Location</th><th>Status</th></tr></thead><tbody><tr><td><strong>Type</strong></td><td><strong>Severity</strong></td><td><strong>Location</strong></td><td><strong>Status</strong></td></tr><tr><td>Logical Issue</td><td><mark style="color:red;"><strong>High</strong></mark></td><td><code>join(), withdrawRaisedFunds()</code></td><td><mark style="color:green;"><strong>✔️ Fixed</strong></mark></td></tr></tbody></table>

**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.&#x20;

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

**Recommendation**&#x20;

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

| **Type**         | **Severity**                                        | **Location**    | **Status**                                     |
| ---------------- | --------------------------------------------------- | --------------- | ---------------------------------------------- |
| Gaz optimisation | <mark style="color:green;">**Informational**</mark> | `onlyFactory()` | <mark style="color:green;">**✔️ Fixed**</mark> |

**Description**

`onlyFactory()` modifier is not used.

### Issue 04

| **Type**      | **Severity**                                  | **Location**            | **Status**                                     |
| ------------- | --------------------------------------------- | ----------------------- | ---------------------------------------------- |
| Logical Issue | <mark style="color:orange;">**Medium**</mark> | `withdrawRaisedFunds()` | <mark style="color:green;">**✔️ Fixed**</mark> |

**Description**

&#x20;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

| **Type**      | **Severity**                               | **Location**  | **Status**                                                                                     |
| ------------- | ------------------------------------------ | ------------- | ---------------------------------------------------------------------------------------------- |
| Best Practice | <mark style="color:yellow;">**Low**</mark> | `getRefund()` | <mark style="color:green;">**⚠️**</mark>**&#x20;**<mark style="color:red;">**Consider**</mark> |

**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.

<mark style="color:orange;">**Note**</mark>

<mark style="color:orange;">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.</mark> &#x20;

### Issue 06&#x20;

| **Type**      | **Severity**                                  | **Location** | **Status**                                    |
| ------------- | --------------------------------------------- | ------------ | --------------------------------------------- |
| Logical Issue | <mark style="color:orange;">**Medium**</mark> | `join()`     | <mark style="color:green;">**✔️Fixed**</mark> |

**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&#x20;

| **Type**      | **Severity**                                        | **Location** | **Status**                                    |
| ------------- | --------------------------------------------------- | ------------ | --------------------------------------------- |
| Best Practice | <mark style="color:green;">**Informational**</mark> | `join()`     | <mark style="color:green;">**✔️Fixed**</mark> |

**Description**

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

### Issue 08

| **Type**      | **Severity**                                  | **Location** | **Status**                                    |
| ------------- | --------------------------------------------- | ------------ | --------------------------------------------- |
| Best Practice | <mark style="color:orange;">**Medium**</mark> | `join()`     | <mark style="color:green;">**✔️Fixed**</mark> |

#### **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&#x20;

| **Type**      | **Severity**                             | **Location**                                | **Status**                                    |
| ------------- | ---------------------------------------- | ------------------------------------------- | --------------------------------------------- |
| Logical Issue | <mark style="color:red;">**High**</mark> | <h4><code>withdrawRaisedFunds()</code></h4> | <mark style="color:green;">**✔️Fixed**</mark> |

**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. &#x20;

**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.`

<mark style="color:red;">⚠️ Please note that in this scenario, presale does not support tokens with fees on transfer. This should be communicated to clients.</mark>&#x20;
