# Smart contract

## Contract Flow

MultiTokenBurnPortal allows users to purchase fee on transfer tokens with smaller fees.\
Managers will create and set discounts and taxes for each fee on transfer tokens.

{% hint style="info" %}
*Example:*\
\&#xNAN;*TokenX is a fee on transfer token with 20% transfer fee.*\
\&#xNAN;*Manager adds TokenX with baseTax=2000 and specifies feeReceiver and discounts*\
\&#xNAN;*If user burns 100 tokens, his discount will be 10%, and he will be able to purchase TokenX with 18% fee*\
\&#xNAN;*If user burns 500 tokens, his discount will be 50%, and he will be able to purchase TokenX with 10% fee*\
\&#xNAN;*If user burns 1000 tokens, his discount will be 100%, and he will be able to purchase TokenX without fee*
{% endhint %}

## Contract functions

### constructor

Creates contract

```solidity
constructor(
        IWETH _WETH,
        uint16 _adminFee,
        address _adminFeeReceiver
    )
```

{% hint style="info" %}
**`_WETH`** WETH address \
\&#xNAN;**`_adminFee`** Admin fee in basis points (10000 = 100%). This fee share will be transferred to admin fee receiver \
\&#xNAN;**`_adminFeeReceiver`** Receiver of admin fees
{% endhint %}

### buyTokensWithBNB

Swaps BNB for Token and sends them to msg.sender

```solidity
function buyTokensWithBNB(
        address router,
        uint256 amountOutMin,
        address[] calldata path,
        uint256 deadline
    ) external payable onlyApprovedRouter(router) returns(uint256 amountOut)
```

{% hint style="info" %}
**`router`** Router address, that should be used for the swap \
\&#xNAN;**`amountOutMin`** Minimum amount of tokens to receive \
\&#xNAN;**`path`** Swap path \
\&#xNAN;**`deadline`** Deadline of swap transaction&#x20;

<mark style="color:blue;">Returns:</mark>\
\&#xNAN;**`amountOut`** Amount of tokens user has received

<mark style="color:red;">Only approved routers are allowed</mark>
{% endhint %}

### buyTokensWithERC20

Swaps ERC20 for token and sends them to msg.sender

```solidity
function buyTokensWithERC20(
        address router,
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        uint256 deadline
    ) external onlyApprovedRouter(router) returns(uint256 amountOut)
```

{% hint style="info" %}
**`router`** Router address, that should be used for the swap \
\&#xNAN;**`amountIn`** Amount tokens to spend\
\&#xNAN;**`amountOutMin`** Minimum amount of tokens to receive \
\&#xNAN;**`path`** Swap path \
\&#xNAN;**`deadline`** Deadline of swap transaction&#x20;

<mark style="color:blue;">Returns:</mark>\
\&#xNAN;**`amountOut`** Amount of tokens user has received

<mark style="color:red;">Only approved routers are allowed</mark>
{% endhint %}

### burnTokens

Burns tokens by sending them to dead wallet

```solidity
function burnTokens(address token, uint128 amount) external
```

{% hint style="info" %}
**`token`** ERC20 token address to burn \
\&#xNAN;**`amount`** Amount of tokens to burn
{% endhint %}

### setManager

Sets manager account

```solidity
function setManager(address account, bool add) external onlyOwner
```

{% hint style="info" %}
**`account`** Account address \
\&#xNAN;**`add`** `true` - add manager, `false` - remove manager

<mark style="color:red;">Can be called only by contract Owner</mark>
{% endhint %}

### setAdminFeeSettings

Sets admin fee and admin fee receiver

```solidity
function setAdminFeeSettings(
        uint16 _adminFee,
        address _adminFeeReceiver
    ) external onlyOwner
```

{% hint style="info" %}
**`_adminFee`** Admin fee in basis points (10000 = 100%). This fee share will be transferred to admin fee receiver\
\&#xNAN;**`_adminFeeReceiver`** Receiver of admin fees

<mark style="color:red;">Can be called only by contract Owner</mark>
{% endhint %}

### addToken

Creates a burn portal for new token

```solidity
function addToken(
        address token,
        uint16 baseTax,
        address feeReceiver,
        Discount[] calldata discounts
    ) external onlyOwnerOrManager
```

{% hint style="info" %}
**`token`** ERC20 token address \
\&#xNAN;**`baseTax`** Base tax for the token, in basis points (10000 = 100%) \
\&#xNAN;**`feeReceiver`** Fee receiver address for the token \
\&#xNAN;**`discounts`** Array of Discount structs, containing discount amount and burn amount to receive that discount

`struct Discount { uint16 discount; uint112 burnAmount; }`

<mark style="color:red;">Can be called only by contract Owner or Manager</mark>
{% endhint %}

### removeToken

Removes token from Burn Portal

```solidity
function removeToken(address token) external onlyOwnerOrManager
```

{% hint style="info" %}
**`token`** ERC20 token address&#x20;

<mark style="color:red;">Can be called only by contract Owner or Manager</mark>
{% endhint %}

### setTokenBaseTax

Sets new base tax for the token. Should be called if token tax was updated

```solidity
function setTokenBaseTax(
        address token,
        uint16 baseTax
    ) external onlyOwnerOrManager
```

{% hint style="info" %}
**`token`** ERC20 token address \
\&#xNAN;**`baseTax`** Base tax for the token, in basis points (10000 = 100%)

<mark style="color:red;">Can be called only by contract Owner or Manager</mark>
{% endhint %}

### setTokenFeeReceiver

Updates fee receiver address for specific token

```solidity
function setTokenFeeReceiver(
        address token,
        address feeReceiver
    ) external onlyOwnerOrManager
```

{% hint style="info" %}
**`token`** ERC20 token address \
\&#xNAN;**`feeReceiver`** Fee receiver address for the token

<mark style="color:red;">Can be called only by contract Owner or Manager</mark>
{% endhint %}

### setTokenDiscounts

Updates discounts for specific token

```solidity
function setTokenDiscounts(
        address token,
        Discount[] calldata discounts
    ) external onlyOwnerOrManager
```

{% hint style="info" %}
**`token`** ERC20 token address \
\&#xNAN;**`discounts`** Array of Discount structs, containing discount amount and burn amount to receive that discount+

`struct Discount { uint16 discount; uint112 burnAmount; }`

<mark style="color:red;">Can be called only by contract Owner or Manager</mark>
{% endhint %}

### approveTokenIn

Approves token to be swapped to Portal Token

```solidity
function approveTokenIn(address token) external onlyOwner
```

{% hint style="info" %}
**`token`** ERC20 token address

<mark style="color:red;">Can be called only by contract Owner</mark>
{% endhint %}

### removeTokenIn

Remove token from the list of approved tokens In

```solidity
function removeTokenIn(address token) external onlyOwner
```

{% hint style="info" %}
**`token`** ERC20 token address

<mark style="color:red;">Can be called only by contract Owner</mark>
{% endhint %}

### approveRouter

Approves Router address

```solidity
function approveRouter(address router, bool approve) external onlyOwner
```

{% hint style="info" %}
**`router`** Router address \
\&#xNAN;**`approve`** `true` - approve, `false` - forbid

<mark style="color:red;">Can be called only by contract Owner</mark>
{% endhint %}

### emergencyWithdrawERC20

Withdraws stuck ERC20 token

```solidity
function emergencyWithdrawERC20(
        IERC20 token,
        address account,
        uint256 amount
    ) external onlyOwner
```

{% hint style="info" %}
**`token`** IERC20 token address \
\&#xNAN;**`account`** Address of receiver \
\&#xNAN;**`amount`** Amount of tokens to withdraw

<mark style="color:red;">Can be called only by contract Owner</mark>
{% endhint %}

### emergencyWithdrawBNB

Withdraws stuck BNB

```solidity
function emergencyWithdrawBNB(
        address account,
        uint256 amount
    ) external onlyOwner
```

{% hint style="info" %}
**`account`** Address of receiver \
\&#xNAN;**`amount`** Amount of BNB to withdraw

<mark style="color:red;">Can be called only by contract Owner</mark>
{% endhint %}

### getDiscounts

View function go get discounts list for specific token

```solidity
function getDiscounts(address token) external view returns(Discount[] memory)
```

{% hint style="info" %}
**`token`** ERC20 token address

<mark style="color:blue;">Returns:</mark>\
List or discounts
{% endhint %}

### getApprovedTokens

View function go get list or approved tokens IN

```solidity
function getApprovedTokens() external view returns(address[] memory)
```

{% hint style="info" %} <mark style="color:blue;">Returns:</mark>\
List or approved tokens
{% endhint %}

### getApprovedRouters

View function go get list or approved routers

```solidity
function getApprovedRouters() external view returns(address[] memory)
```

{% hint style="info" %} <mark style="color:blue;">Returns:</mark>\
List or approved routers
{% endhint %}

### getActiveTokens

View function go get list or active Portal Tokens

```solidity
function getActiveTokens() external view returns(address[] memory)
```

{% hint style="info" %} <mark style="color:blue;">Returns:</mark>\
List or active Portal Tokens
{% endhint %}

### getPortalInfo

View function go collect portal info

```solidity
function getPortalInfo(address token) external view returns(
        uint16 baseTax,
        address feeReceiver,
        uint128 totalBought,
        uint128 totalBurned,
        Discount[] memory discounts
    )
```

{% hint style="info" %}
**`token`** Portal Token address&#x20;

<mark style="color:blue;">Returns:</mark>\
\&#xNAN;**`baseTax`** Token tax in basis points (10000 = 100%) \
\&#xNAN;**`feeReceiver`** Fee receiver for this token\
\&#xNAN;**`totalBought`** Amount of tokens, bought through this portal \
\&#xNAN;**`totalBurned`** Amount of tokens, burned with this portal \
\&#xNAN;**`discounts`** List of token discounts
{% endhint %}

### getManagers

View function to get list or managers

```solidity
function getManagers() external view returns(address[] memory)
```

{% hint style="info" %} <mark style="color:blue;">Returns:</mark>\
List or managers
{% endhint %}

### isManager

View function check if address is manager

```solidity
function isManager(address account) external view returns(bool)
```

{% hint style="info" %}
**`account`** Account address

<mark style="color:blue;">Returns:</mark>\
Is account a manager?
{% endhint %}

### isApprovedTokenIn

View function go determine if token is approved to be swapped to Portal Token

```solidity
function isApprovedTokenIn(address token) external view returns(bool)
```

{% hint style="info" %}
**`token`** ERC20 token address

<mark style="color:blue;">Returns:</mark>\
Is approved to be swapped to Portal Token?
{% endhint %}

### isApprovedRouter

View function go determine if Router is approved to be used to buy Portal Token

```solidity
function isApprovedRouter(address router) external view returns(bool)
```

{% hint style="info" %}
**`router`** Router address

<mark style="color:blue;">Returns:</mark>\
Is approved router?
{% endhint %}

### getPersonalDiscount

View function go get personal discount

```solidity
function getPersonalDiscount(address account, address token) public view returns(uint256)
```

{% hint style="info" %}
**`account`** Account address \
\&#xNAN;**`token`** ERC20 token address

<mark style="color:blue;">Returns:</mark>\
Discount in basis points where 10\_000 is 100% discount = purchase without fee
{% endhint %}
