# SmartTokens

## SmartToken

[Git Source](https://github.com/RiskProtocol/core-protocol/blob/d59ee719f0b8aa5daeb239f6468bda6d3a1b56be/contracts/vaults/SmartToken.sol)

**Inherits:** Initializable, UUPSUpgradeable, OwnableUpgradeable, ERC20Upgradeable, ERC20PermitUpgradeable, BaseContract, IERC4626Upgradeable, ReentrancyGuardUpgradeable, FlashloanSpecifics

*This is a rebalancing token, part of Risk Protocol's system The same contract is used by both RiskON and RiskOFF Whenever a user deposit a unit of underlying in the Vault(TokenFactory), the user is expected to recieve a unit of both RiskON and RiskOFF. At every rebalance operation, the user RiskOn/OFF balances will be aligned with respect to the rebalance math.*

### State Variables

#### tokenFactory

The tokenFactory instance

```solidity
TokenFactory private tokenFactory;
```

#### underlyingToken

The underlyingToken instance

```solidity
IERC20Update private underlyingToken;
```

#### isX

```solidity
bool private isX;
```

#### isNativeToken

```solidity
bool private isNativeToken;
```

#### weth

```solidity
IWETH private weth;
```

#### premiumDenominator

```solidity
uint16 private constant premiumDenominator = 10000;
```

### Functions

#### onlyTokenFactory

*Ensures that the function is only callable by the TokenFactory contract. Calls the helper function `_onlyTokenFactory` to check the caller.*

```solidity
modifier onlyTokenFactory();
```

#### onlyAssetOwner

*Ensures that the function is only callable by the token owner/holder. Calls the helper function `_onlyAssetOwner` to check the caller against the provided token owner/holder address.*

```solidity
modifier onlyAssetOwner(address assetOwner);
```

**Parameters**

| Name         | Type      | Description                            |
| ------------ | --------- | -------------------------------------- |
| `assetOwner` | `address` | The address of the token owner/holder. |

#### validateDepositAmount

*Validates the deposit amount to ensure it is not 0 or more than the receiver can get. Calls the helper function `_validateDepositAmount` to check the deposit amount and receiver.*

```solidity
modifier validateDepositAmount(uint256 assets, address receiver);
```

**Parameters**

| Name       | Type      | Description                        |
| ---------- | --------- | ---------------------------------- |
| `assets`   | `uint256` | The amount of token to deposit.    |
| `receiver` | `address` | The address receiving the deposit. |

#### insufficientUnderlying

*Validates if the underlying locked is always >= than the total supply of riskON/OFF reverts if not*

```solidity
modifier insufficientUnderlying();
```

#### depositLimitHit

*Validates if the user has hit the periodic deposit limit prevents the user from depositing more if hit*

```solidity
modifier depositLimitHit(uint256 amount);
```

**Parameters**

| Name     | Type      | Description                     |
| -------- | --------- | ------------------------------- |
| `amount` | `uint256` | The amount of token to deposit. |

#### withdrawLimitHit

*Validates if the user has hit the periodic withdraw limit prevents the user from withdrawing more if hit*

```solidity
modifier withdrawLimitHit(uint256 amount);
```

**Parameters**

| Name     | Type      | Description                      |
| -------- | --------- | -------------------------------- |
| `amount` | `uint256` | The amount of token to withdraw. |

#### dailyFFUpdate

```solidity
modifier dailyFFUpdate();
```

#### expiryDateCheck

```solidity
modifier expiryDateCheck(uint256 expiryDate);
```

#### constructor

**Note:** oz-upgrades-unsafe-allow: constructor

```solidity
constructor();
```

#### initialize

Initializes(replacement for the constructor) the SmartToken contract with specified parameters.

*This function sets up the initial state of the SmartToken contract. Callable only once. It initializes inherited contracts and sets the initial values for `tokenFactory` and `underlyingToken`.*

```solidity
function initialize(
    string memory tokenName,
    string memory tokenSymbol,
    address factoryAddress,
    address sanctionsContract_,
    bool isX_,
    address owner_
) public initializer;
```

**Parameters**

| Name                 | Type      | Description                                |
| -------------------- | --------- | ------------------------------------------ |
| `tokenName`          | `string`  | The name of the token.                     |
| `tokenSymbol`        | `string`  | The symbol of the token.                   |
| `factoryAddress`     | `address` | The address of the TokenFactory contract.  |
| `sanctionsContract_` | `address` | The address of the SanctionsList contract. |
| `isX_`               | `bool`    |                                            |
| `owner_`             | `address` |                                            |

#### receive

```solidity
receive() external payable;
```

#### drain

method to drain contracts of any ethers

*This function can only be called by the contract owner.*

```solidity
function drain(address receiver) external onlyOwner;
```

**Parameters**

| Name       | Type      | Description                                              |
| ---------- | --------- | -------------------------------------------------------- |
| `receiver` | `address` | The address of the account that will receive the ethers. |

#### \_authorizeUpgrade

Authorizes an upgrade to a new contract implementation.

*This function can only be called by the contract owner. It overrides the `_authorizeUpgrade` function from the `UUPSUpgradeable` contract to include the `onlyOwner` modifier, ensuring only the owner can authorize upgrades.*

```solidity
function _authorizeUpgrade(address) internal override onlyOwner;
```

#### mintAsset

Mints the specified amount of tokens to the receiver.

*This function can only be called by the TokenFactory contract.*

```solidity
function mintAsset(address receiver, uint256 amount) external onlyTokenFactory;
```

**Parameters**

| Name       | Type      | Description                                                     |
| ---------- | --------- | --------------------------------------------------------------- |
| `receiver` | `address` | The address of the account that will receive the minted tokens. |
| `amount`   | `uint256` | The amount of tokens to mint.                                   |

#### burn

Burns the specified amount of tokens from the account.

*This function can only be called by the TokenFactory contract.*

```solidity
function burn(address account, uint256 amount) external onlyTokenFactory;
```

**Parameters**

| Name      | Type      | Description                                                  |
| --------- | --------- | ------------------------------------------------------------ |
| `account` | `address` | The address of the account from which tokens will be burned. |
| `amount`  | `uint256` | The amount of tokens to burn.                                |

#### transfer

Transfers the specified amount of tokens to the specified recipient.

*Overrides the `transfer` function from `ERC20Upgradeable` and `IERC20Upgradeable` contracts. If the sender or receiver has a pending rebalance, it is handled before the transfer. This function can only be called when transfers are not stopped, and neither the sender nor the recipient are on the sanctions list.*

```solidity
function transfer(address recipient, uint256 amount)
    public
    override(ERC20Upgradeable, IERC20Upgradeable)
    stopTransfer
    insufficientUnderlying
    onlyNotSanctioned(recipient)
    onlyNotSanctioned(_msgSender())
    dailyFFUpdate
    returns (bool);
```

**Parameters**

| Name        | Type      | Description                                      |
| ----------- | --------- | ------------------------------------------------ |
| `recipient` | `address` | The address to which tokens will be transferred. |
| `amount`    | `uint256` | The amount of tokens to transfer.                |

**Returns**

| Name     | Type   | Description                        |
| -------- | ------ | ---------------------------------- |
| `<none>` | `bool` | Always return true unless reverted |

#### smartTreasuryTransfer

```solidity
function smartTreasuryTransfer(address treasuryAddress, uint256 amount) external onlyTokenFactory;
```

#### smartBalanceAdjust

```solidity
function smartBalanceAdjust(address account, uint256 amount) external onlyTokenFactory;
```

#### balanceOf

Returns the balance of the specified account

*Overrides the `balanceOf` function from the inherited `ERC20Upgradeable` and `IERC20Upgradeable` contracts. If the account has a pending rebalance, the function calculates the calculated balance post rebalance using the 'calculateRollOverValue' method. Otherwise, it returns the erc20 balance using `unScaledbalanceOf` method.*

```solidity
function balanceOf(address account) public view override(ERC20Upgradeable, IERC20Upgradeable) returns (uint256);
```

**Parameters**

| Name      | Type      | Description                                                 |
| --------- | --------- | ----------------------------------------------------------- |
| `account` | `address` | The address of the account whose balance will be retrieved. |

**Returns**

| Name     | Type      | Description                           |
| -------- | --------- | ------------------------------------- |
| `<none>` | `uint256` | The balance of the specified account. |

#### unScaledbalanceOf

Returns the unscaled(unaffected by pending rebalances) balance of the specified account.

*This function returns the ERC20 balance(unaffected by pending rebalances) of the account.*

```solidity
function unScaledbalanceOf(address account) public view returns (uint256);
```

**Parameters**

| Name      | Type      | Description                 |
| --------- | --------- | --------------------------- |
| `account` | `address` | The address of the account. |

**Returns**

| Name     | Type      | Description                                                                      |
| -------- | --------- | -------------------------------------------------------------------------------- |
| `<none>` | `uint256` | The unscaled(unaffected by pending rebalances) balance of the specified account. |

#### hasPendingRebalance

Checks if the specified account has a pending rebalance.

*Compares the account's last rebalance count with the current scalingfactor length to determine if a rebalance is pending.*

```solidity
function hasPendingRebalance(address account) public view returns (bool);
```

**Parameters**

| Name      | Type      | Description                |
| --------- | --------- | -------------------------- |
| `account` | `address` | The address of the account |

**Returns**

| Name     | Type   | Description                                                                       |
| -------- | ------ | --------------------------------------------------------------------------------- |
| `<none>` | `bool` | A boolean value indicating whether the specified account has a pending rebalance. |

#### getTokenFactory

Retrieves the address of the Vault (TokenFactory) contract.

*This function casts the `tokenFactory` variable to an address and returns it.*

```solidity
function getTokenFactory() public view returns (address);
```

**Returns**

| Name     | Type      | Description                                       |
| -------- | --------- | ------------------------------------------------- |
| `<none>` | `address` | The address of the Vault (TokenFactory) contract. |

#### transferFrom

Transfers the specified amount of tokens from the sender to the recipient.

*Overrides the `transferFrom` function from the inherited `ERC20Upgradeable` and `IERC20Upgradeable` contracts. If the sender or recipient has a pending rebalance, it is handled before the transfer. This function can only be called when transfers are not stopped, and neither the sender nor the recipient are on the sanctions list.*

```solidity
function transferFrom(address sender, address recipient, uint256 amount)
    public
    override(ERC20Upgradeable, IERC20Upgradeable)
    stopTransfer
    insufficientUnderlying
    dailyFFUpdate
    onlyNotSanctioned(recipient)
    onlyNotSanctioned(sender)
    returns (bool);
```

**Parameters**

| Name        | Type      | Description                                        |
| ----------- | --------- | -------------------------------------------------- |
| `sender`    | `address` | The address from which tokens will be transferred. |
| `recipient` | `address` | The address to which tokens will be transferred.   |
| `amount`    | `uint256` | The amount of tokens to transfer.                  |

**Returns**

| Name     | Type   | Description                                                 |
| -------- | ------ | ----------------------------------------------------------- |
| `<none>` | `bool` | A boolean value indicating whether the operation succeeded. |

#### handlePendingRebalance

Handles pending rebalances for the sender and receiver addresses.

*This function checks if the sender or receiver has a pending rebalance and applies the rebalance if needed.*

```solidity
function handlePendingRebalance(address sender, address receiver) public;
```

**Parameters**

| Name       | Type      | Description                                                   |
| ---------- | --------- | ------------------------------------------------------------- |
| `sender`   | `address` | The address of the sender involved in a transfer operation.   |
| `receiver` | `address` | The address of the receiver involved in a transfer operation. |

#### asset

Retrieves the address of the underlying token.

*It overrides the `asset` function from the `IERC4626Upgradeable` interface.*

```solidity
function asset() public view virtual override returns (address);
```

**Returns**

| Name     | Type      | Description                          |
| -------- | --------- | ------------------------------------ |
| `<none>` | `address` | The address of the underlying token. |

#### totalAssets

Retrieves the total amount of assets held by the TokenFactory.

*It overrides the `totalAssets` function from the `IERC4626Upgradeable` interface.*

```solidity
function totalAssets() public view virtual override returns (uint256);
```

**Returns**

| Name     | Type      | Description                                                 |
| -------- | --------- | ----------------------------------------------------------- |
| `<none>` | `uint256` | The total amount of assets held by the Vault(TokenFactory). |

#### convertToShares

Converts a specified amount of underlying assets to shares(RiskOn/Off).

*It overrides the `convertToShares` function from the `IERC4626Upgradeable` interface.*

```solidity
function convertToShares(uint256 assets) public view virtual override returns (uint256 shares);
```

**Parameters**

| Name     | Type      | Description                                |
| -------- | --------- | ------------------------------------------ |
| `assets` | `uint256` | The amount of assets to convert to shares. |

**Returns**

| Name     | Type      | Description                                                |
| -------- | --------- | ---------------------------------------------------------- |
| `shares` | `uint256` | The amount of shares(RiskOn/Off) for the amount of assets. |

#### convertToAssets

Converts a specified amount of shares(RiskOn/Off) to underlying assets.

*It overrides the `convertToAssets` function from the `IERC4626Upgradeable` interface.*

```solidity
function convertToAssets(uint256 shares) public view virtual override returns (uint256 assets);
```

**Parameters**

| Name     | Type      | Description                                |
| -------- | --------- | ------------------------------------------ |
| `shares` | `uint256` | The amount of shares to convert to assets. |

**Returns**

| Name     | Type      | Description                                                |
| -------- | --------- | ---------------------------------------------------------- |
| `assets` | `uint256` | The amount of assets for the amount of shares(RiskOn/Off). |

#### maxDeposit

Calculates the maximum amount of assets that can be deposited by a specific account.

*It overrides the `maxDeposit` function from the `IERC4626Upgradeable` interface.*

```solidity
function maxDeposit(address account) public view virtual override returns (uint256);
```

**Parameters**

| Name      | Type      | Description                                                                   |
| --------- | --------- | ----------------------------------------------------------------------------- |
| `account` | `address` | The address of the account for which to calculate the maximum deposit amount. |

**Returns**

| Name     | Type      | Description                                                        |
| -------- | --------- | ------------------------------------------------------------------ |
| `<none>` | `uint256` | The maximum amount of assets that can be deposited by the account. |

#### previewDeposit

Provides a preview of the number of shares(RiskOn/Off) that would be received for a amount of assets.

*It overrides the `previewDeposit` function from the `IERC4626Upgradeable` interface.*

```solidity
function previewDeposit(uint256 assets) public view virtual override returns (uint256);
```

**Parameters**

| Name     | Type      | Description                                  |
| -------- | --------- | -------------------------------------------- |
| `assets` | `uint256` | The amount of assets to preview the deposit. |

**Returns**

| Name     | Type      | Description                                                          |
| -------- | --------- | -------------------------------------------------------------------- |
| `<none>` | `uint256` | The amount of shares(RiskOn/Off) for the specified amount of assets. |

#### deposit

Deposits an amount of underlying assets, crediting the shares(RiskON/OFF) to the receiver.

*It overrides the `deposit` function from the `IERC4626Upgradeable` interface. The `stopDeposit` circuit breaker can be used to freeze deposits and `validateDepositAmount` modifier to validate the deposit amount*

```solidity
function deposit(uint256 assets, address receiver)
    public
    virtual
    override
    stopDeposit
    insufficientUnderlying
    dailyFFUpdate
    depositLimitHit(assets)
    validateDepositAmount(assets, receiver)
    returns (uint256);
```

**Parameters**

| Name       | Type      | Description                      |
| ---------- | --------- | -------------------------------- |
| `assets`   | `uint256` | The amount of assets to deposit. |
| `receiver` | `address` | The receiver address.            |

**Returns**

| Name     | Type      | Description                                             |
| -------- | --------- | ------------------------------------------------------- |
| `<none>` | `uint256` | The amount of shares(RiskOn/Off) the receiver will get. |

#### depositWithPermit

Deposits an amount of underlying assets, crediting the shares(RiskON/OFF) to the receiver with an EIP-2612 permit for approval.

*It overrides the `deposit` function from the `IERC4626Upgradeable` interface. The `stopDeposit` circuit breaker can be used to freeze deposits and `validateDepositAmount` modifier to validate the deposit amount then calls `permit` on the `underlyingToken` to set the allowance,*

```solidity
function depositWithPermit(uint256 assets, address receiver, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
    public
    stopDeposit
    insufficientUnderlying
    dailyFFUpdate
    depositLimitHit(assets)
    validateDepositAmount(assets, receiver)
    returns (uint256);
```

**Parameters**

| Name       | Type      | Description                                                             |
| ---------- | --------- | ----------------------------------------------------------------------- |
| `assets`   | `uint256` | The amount of underlying assets to deposit.                             |
| `receiver` | `address` | The address of the receiver                                             |
| `deadline` | `uint256` | The deadline for the permit signature to be valid, as a UNIX timestamp. |
| `v`        | `uint8`   | The recovery byte of the signature.                                     |
| `r`        | `bytes32` | part of the ECDSA signature pair.                                       |
| `s`        | `bytes32` | part of the ECDSA signature pair.                                       |

**Returns**

| Name     | Type      | Description                                            |
| -------- | --------- | ------------------------------------------------------ |
| `<none>` | `uint256` | The amount of shares(RiskOn/Off) the receiber will get |

#### depositWithExpiry

Deposits an amount of underlying assets, crediting the shares(RiskON/OFF) to the receiver.

*It overrides the `deposit` function from the `IERC4626Upgradeable` interface. The `stopDeposit` circuit breaker can be used to freeze deposits and `validateDepositAmount` modifier to validate the deposit amount*

```solidity
function depositWithExpiry(uint256 assets, address receiver, uint256 expiryDate)
    public
    virtual
    expiryDateCheck(expiryDate)
    stopDeposit
    insufficientUnderlying
    dailyFFUpdate
    depositLimitHit(assets)
    validateDepositAmount(assets, receiver)
    returns (uint256);
```

**Parameters**

| Name         | Type      | Description                      |
| ------------ | --------- | -------------------------------- |
| `assets`     | `uint256` | The amount of assets to deposit. |
| `receiver`   | `address` | The receiver address.            |
| `expiryDate` | `uint256` | The expiry date for the deposit. |

**Returns**

| Name     | Type      | Description                                             |
| -------- | --------- | ------------------------------------------------------- |
| `<none>` | `uint256` | The amount of shares(RiskOn/Off) the receiver will get. |

#### depositWithNative

Deposits an amount of underlying (NATIVE) assets, crediting the shares(RiskON/OFF) to the receiver.

*It uses msg.value as the deposit amount. The `stopDeposit` circuit breaker can be used to freeze deposits and `validateDepositAmount` modifier to validate the deposit amount*

```solidity
function depositWithNative(address receiver)
    public
    payable
    virtual
    nonReentrant
    stopDeposit
    insufficientUnderlying
    dailyFFUpdate
    depositLimitHit(msg.value)
    validateDepositAmount(msg.value, receiver)
    returns (uint256);
```

**Parameters**

| Name       | Type      | Description           |
| ---------- | --------- | --------------------- |
| `receiver` | `address` | The receiver address. |

**Returns**

| Name     | Type      | Description                                             |
| -------- | --------- | ------------------------------------------------------- |
| `<none>` | `uint256` | The amount of shares(RiskOn/Off) the receiver will get. |

#### maxMint

Calculates the maximum amount of shares(RiskOn/Off) that can be minted for a user.

*It overrides the `maxMint` function from the `IERC4626Upgradeable` interface.*

```solidity
function maxMint(address account) public view virtual override returns (uint256);
```

**Parameters**

| Name      | Type      | Description                                                                         |
| --------- | --------- | ----------------------------------------------------------------------------------- |
| `account` | `address` | The address of user for which to calculate the maximum mintable shares(RiskOn/Off). |

**Returns**

| Name     | Type      | Description                                                               |
| -------- | --------- | ------------------------------------------------------------------------- |
| `<none>` | `uint256` | The maximum amount of shares(RiskOn/Off) that can be minted for the user. |

#### previewMint

Provides a preview of the amount of underlying assets required to mint a number of shares(RiskOn/Off).

*It overrides the `previewMint` function from the `IERC4626Upgradeable` interface.*

```solidity
function previewMint(uint256 shares) public view virtual override returns (uint256);
```

**Parameters**

| Name     | Type      | Description                               |
| -------- | --------- | ----------------------------------------- |
| `shares` | `uint256` | The number of shares(RiskOn/Off) to mint. |

**Returns**

| Name     | Type      | Description                                                                                  |
| -------- | --------- | -------------------------------------------------------------------------------------------- |
| `<none>` | `uint256` | The amount of underlying assets required to mint the specified number of shares(RiskOn/Off). |

#### mint

mints an amount of shares, crediting the shares(RiskON/OFF) to the receiver.

*It overrides the `deposit` function from the `IERC4626Upgradeable` interface. The `stopDeposit` circuit breaker can be used to freeze minting. As opposed to deposit, minting is allowed even if the vault is in a state where the price of a share is zero. In this case, the shares will be minted without requiring any assets to be deposited.*

```solidity
function mint(uint256 shares, address receiver)
    public
    virtual
    override
    stopDeposit
    insufficientUnderlying
    dailyFFUpdate
    depositLimitHit(shares)
    returns (uint256);
```

**Parameters**

| Name       | Type      | Description                               |
| ---------- | --------- | ----------------------------------------- |
| `shares`   | `uint256` | The amount of shares(RiskON/OFF) to mint. |
| `receiver` | `address` | The receiver address.                     |

**Returns**

| Name     | Type      | Description                                                                                  |
| -------- | --------- | -------------------------------------------------------------------------------------------- |
| `<none>` | `uint256` | The amount of assets that were deposited to mint the specified number of shares(RiskON/OFF). |

#### maxWithdraw

Calculates the maximum amount of underlying assets that can be withdrawn by a specified owner.

*It overrides the `maxWithdraw` function from the `IERC4626Upgradeable` interface.*

```solidity
function maxWithdraw(address owner_) public view virtual override returns (uint256);
```

**Parameters**

| Name     | Type      | Description                                                                                 |
| -------- | --------- | ------------------------------------------------------------------------------------------- |
| `owner_` | `address` | The address of the owner for which to calculate the maximum underlying withdrawable assets. |

**Returns**

| Name     | Type      | Description                                                                |
| -------- | --------- | -------------------------------------------------------------------------- |
| `<none>` | `uint256` | The maximum amount of assets that can be withdrawn by the specified owner. |

#### previewWithdraw

Provide a preview of number of shares(RiskOn/Off) required to withdraw an amount of underlying assets.

*It overrides the `previewWithdraw` function from the `IERC4626Upgradeable` interface.*

```solidity
function previewWithdraw(uint256 assets) public view virtual override returns (uint256);
```

**Parameters**

| Name     | Type      | Description                       |
| -------- | --------- | --------------------------------- |
| `assets` | `uint256` | The amount of assets to withdraw. |

**Returns**

| Name     | Type      | Description                                                                           |
| -------- | --------- | ------------------------------------------------------------------------------------- |
| `<none>` | `uint256` | The number of shares(RiskOn/Off) required to withdraw the specified amount of assets. |

#### withdraw

Allows an owner to withdraw a specified amount of underlying assets, transferring them to a receiver.

*This function overrides the `withdraw` function from the `IERC4626Upgradeable` interface, and is guarded by the `stopWithdraw`, `onlyAssetOwner`, and `nonReentrant` modifiers.*

```solidity
function withdraw(uint256 assets, address receiver, address owner_)
    public
    virtual
    override
    stopWithdraw
    insufficientUnderlying
    dailyFFUpdate
    withdrawLimitHit(assets)
    onlyAssetOwner(owner_)
    nonReentrant
    returns (uint256);
```

**Parameters**

| Name       | Type      | Description                                            |
| ---------- | --------- | ------------------------------------------------------ |
| `assets`   | `uint256` | The amount of underlying assets to withdraw.           |
| `receiver` | `address` | The address to which the assets should be transferred. |
| `owner_`   | `address` | The address of the owner making the withdrawal.        |

**Returns**

| Name     | Type      | Description                                                             |
| -------- | --------- | ----------------------------------------------------------------------- |
| `<none>` | `uint256` | The number of shares(RiskON/OFF) corresponding to the withdrawn assets. |

#### withdrawWithExpiry

Allows an owner to withdraw a specified amount of underlying assets, transferring them to a receiver.

*This function overrides the `withdraw` function from the `IERC4626Upgradeable` interface, and is guarded by the `stopWithdraw`, `onlyAssetOwner`, and `nonReentrant` modifiers.*

```solidity
function withdrawWithExpiry(uint256 assets, address receiver, address owner_, uint256 expiryDate)
    public
    virtual
    expiryDateCheck(expiryDate)
    stopWithdraw
    insufficientUnderlying
    dailyFFUpdate
    withdrawLimitHit(assets)
    onlyAssetOwner(owner_)
    nonReentrant
    returns (uint256);
```

**Parameters**

| Name         | Type      | Description                                            |
| ------------ | --------- | ------------------------------------------------------ |
| `assets`     | `uint256` | The amount of underlying assets to withdraw.           |
| `receiver`   | `address` | The address to which the assets should be transferred. |
| `owner_`     | `address` | The address of the owner making the withdrawal.        |
| `expiryDate` | `uint256` | The expiry date for the withdrawal.                    |

**Returns**

| Name     | Type      | Description                                                             |
| -------- | --------- | ----------------------------------------------------------------------- |
| `<none>` | `uint256` | The number of shares(RiskON/OFF) corresponding to the withdrawn assets. |

#### flashLoan

Allows user to take flashloans from the tokenFactory (Vault/POOL)

*This function is guarded by the `nonReentrant` and `stopFlashLoan` modifiers. It makes use of AAVE's flashloan interface to provide backwards compatibility for ease of use*

```solidity
function flashLoan(address receiver, uint256 amount, bytes memory params)
    external
    nonReentrant
    stopFlashLoan
    onlyNotSanctioned(receiver)
    onlyNotSanctioned(_msgSender());
```

**Parameters**

| Name       | Type      | Description                                                                       |
| ---------- | --------- | --------------------------------------------------------------------------------- |
| `receiver` | `address` | The address of the receiver.                                                      |
| `amount`   | `uint256` | The amount of underlying assets to flashloan.                                     |
| `params`   | `bytes`   | The parameters for the flashloan. Used by the receiver contract(Aave's interface) |

#### maxRedeem

Computes the maximum amount of underlying assets that can be redeemed by owner.

*It overrides the `maxRedeem` function from the `IERC4626Upgradeable` interface.*

```solidity
function maxRedeem(address owner_) public view virtual override returns (uint256);
```

**Parameters**

| Name     | Type      | Description               |
| -------- | --------- | ------------------------- |
| `owner_` | `address` | The address of the owner. |

**Returns**

| Name     | Type      | Description                                                        |
| -------- | --------- | ------------------------------------------------------------------ |
| `<none>` | `uint256` | The maximum amount of underlying assets that the owner can redeem. |

#### previewRedeem

Provides a preview of the amount of underlying assets that would be received when redeeming a number of shares(RiskON/OFF).

*It overrides the `previewRedeem` function from the `IERC4626Upgradeable` interface.*

```solidity
function previewRedeem(uint256 shares) public view virtual override returns (uint256);
```

**Parameters**

| Name     | Type      | Description                                                                             |
| -------- | --------- | --------------------------------------------------------------------------------------- |
| `shares` | `uint256` | The number of shares(RiskON/OFF) to compute the equivalent underlying asset amount for. |

**Returns**

| Name     | Type      | Description                                                             |
| -------- | --------- | ----------------------------------------------------------------------- |
| `<none>` | `uint256` | The equivalent asset amount for the given number of shares(RiskON/OFF). |

#### redeem

Allows a user to redeem some amount of underlying assets based on an input amount of shares(RiskON/OFF).

*See IERC4626-redeem.*

*It overrides the `redeem` function from the `IERC4626Upgradeable` interface. and is guarded by the `stopWithdraw`, `onlyAssetOwner`, and `nonReentrant` modifiers.*

```solidity
function redeem(uint256 shares, address receiver, address owner_)
    public
    virtual
    override
    stopWithdraw
    insufficientUnderlying
    dailyFFUpdate
    withdrawLimitHit(shares)
    onlyAssetOwner(owner_)
    nonReentrant
    returns (uint256);
```

**Parameters**

| Name       | Type      | Description                                                       |
| ---------- | --------- | ----------------------------------------------------------------- |
| `shares`   | `uint256` | The number of shares(RiskON/OFF) to redeem for underlying assets. |
| `receiver` | `address` | The address of receiver.                                          |
| `owner_`   | `address` | The address of the owner.                                         |

**Returns**

| Name     | Type      | Description                               |
| -------- | --------- | ----------------------------------------- |
| `<none>` | `uint256` | The amount of underlying assets redeemed. |

#### \_onlyTokenFactory

Helpers for modifiers to reduce size

Checks if the caller is the Vault (tokenFactory)

*This function is utilized by the `onlyTokenFactory` modifier to ensure that only the token factory can call certain functions.*

```solidity
function _onlyTokenFactory() private view;
```

#### \_onlyAssetOwner

Checks if the caller is the asset owner.

*This function is utilized by the `onlyAssetOwner` modifier to ensure that only the asset owner can call certain functions.*

```solidity
function _onlyAssetOwner(address assetOwner) private view;
```

**Parameters**

| Name         | Type      | Description                     |
| ------------ | --------- | ------------------------------- |
| `assetOwner` | `address` | The address of the asset owner. |

#### \_validateDepositAmount

Validates the deposit amount.

*This function is utilized by the `validateDepositAmount` modifier to ensure that the deposit amount is neither zero nor exceeds the maximum allowed deposit for the receiver.*

```solidity
function _validateDepositAmount(uint256 assets, address receiver) private view;
```

**Parameters**

| Name       | Type      | Description                                      |
| ---------- | --------- | ------------------------------------------------ |
| `assets`   | `uint256` | The amount of underlying assets being deposited. |
| `receiver` | `address` | The address of the receiver                      |

#### hasPendingFF

```solidity
function hasPendingFF(address account) public view returns (bool);
```

#### handlePendingFF

```solidity
function handlePendingFF(address sender, address receiver) public;
```

#### \_handleDeposit

```solidity
function _handleDeposit(uint256 assets, address receiver) private returns (uint256);
```

**Parameters**

| Name       | Type      | Description                                                                                             |
| ---------- | --------- | ------------------------------------------------------------------------------------------------------- |
| `assets`   | `uint256` | The amount of underlying assets to deposit.\@note WE can use SHARES as well since it's a 1:1 conversion |
| `receiver` | `address` | The address to which the assets should be transferred.                                                  |

#### \_handleWithdraw

```solidity
function _handleWithdraw(uint256 assets, address receiver, address owner_) private returns (uint256);
```

**Parameters**

| Name       | Type      | Description                                                                                              |
| ---------- | --------- | -------------------------------------------------------------------------------------------------------- |
| `assets`   | `uint256` | The amount of underlying assets to withdraw. @note WE can use SHARES as well since it's a 1:1 conversion |
| `receiver` | `address` | The address to which the assets should be transferred.                                                   |
| `owner_`   | `address` | The address of the owner making the withdrawal.                                                          |

#### getFlashLoanPool

Retrieves the address of the flashloan POOL (TokenFactory) contract.

*This function casts the `tokenFactory` variable to an address and returns it.*

```solidity
function getFlashLoanPool() public view returns (address);
```

**Returns**

| Name     | Type      | Description                                                |
| -------- | --------- | ---------------------------------------------------------- |
| `<none>` | `address` | The address of the flashloan POOL (TokenFactory) contract. |

### Errors

#### SmartToken\_\_NotTokenFactory

```solidity
error SmartToken__NotTokenFactory();
```

#### SmartToken\_\_MethodNotAllowed

```solidity
error SmartToken__MethodNotAllowed();
```

#### SmartToken\_\_DepositMoreThanMax

```solidity
error SmartToken__DepositMoreThanMax();
```

#### SmartToken\_\_MintMoreThanMax

```solidity
error SmartToken__MintMoreThanMax();
```

#### SmartToken\_\_WithdrawMoreThanMax

```solidity
error SmartToken__WithdrawMoreThanMax();
```

#### SmartToken\_\_RedeemMoreThanMax

```solidity
error SmartToken__RedeemMoreThanMax();
```

#### SmartToken\_\_OnlyAssetOwner

```solidity
error SmartToken__OnlyAssetOwner();
```

#### SmartToken\_\_ZeroDeposit

```solidity
error SmartToken__ZeroDeposit();
```

#### SmartToken\_\_InsufficientUnderlying

```solidity
error SmartToken__InsufficientUnderlying();
```

#### SmartToken\_\_DepositLimitHit

```solidity
error SmartToken__DepositLimitHit();
```

#### SmartToken\_\_WithdrawLimitHit

```solidity
error SmartToken__WithdrawLimitHit();
```

#### SmartToken\_\_ExpiryDateReached

```solidity
error SmartToken__ExpiryDateReached();
```

#### SmartToken\_\_WithdrawNativeFailed

```solidity
error SmartToken__WithdrawNativeFailed();
```
