> For the complete documentation index, see [llms.txt](https://flowdex-fi.gitbook.io/flowdex/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://flowdex-fi.gitbook.io/flowdex/for-developers/vault-contract.md).

# Vault Contract

The **FlowDex Vault Contract** is the core user-facing implementation of the FlowDex protocol. It manages user deposits, mints FDX tokens as proof of receipt, and facilitates withdrawals. The contract follows the ERC-20 standard, ensuring that FDX tokens are fungible and transferable.

The primary function of the Vault Contract is to direct deposited funds to the relevant staking strategies (e.g., Liquid Staking, Delta Neutral Staking, Leverage Lending). The separation of the Vault and Strategy Contracts ensures that risks in the strategy are isolated from user deposits.

### **View Functions**

**1. `want()`**

Returns the address of the underlying token (e.g., ETH, USDT) used in both the FlowDex Vault and Strategy Contracts.

```solidity
function want() public view returns (IERC20) {
    return IERC20(strategy.want());
}
```

**2. `balance()`**

Returns the total amount of the underlying token stored in the Vault, Strategy, and yield sources.

```solidity
function balance() public view returns (uint) {
    return want().balanceOf(address(this)) + IStrategy(strategy).balanceOf();
}
```

**3. `available()`**

Returns the amount of the underlying token stored in the Vault alone.

```solidity
function available() public view returns (uint256) {
    return want().balanceOf(address(this));
}
```

**4. `totalSupply()`**

Returns the total amount of FDX tokens minted. FDX tokens are always displayed as 18-decimal tokens.

```solidity
function totalSupply() public view virtual override returns (uint256) {
    return _totalSupply;
}
```

**5. `getPricePerFullShare()`**

Returns the current price per share of the Vault (i.e., per FDX token) denominated in the underlying token.\
**Formula:** `Price per Full Share = balance() / totalSupply()`

```solidity
function getPricePerFullShare() public view returns (uint256) {
    return totalSupply() == 0 ? 1e18 : balance() * 1e18 / totalSupply();
}
```

**6. `strategy()`**

Returns the address of the current Strategy Contract used by the Vault to generate yield.

```solidity
function strategy() external view returns (address);
```

### **Write Functions**

**1. `deposit(uint _amount)`**

Executes a transfer of a specified `_amount` of the underlying token from the depositor to the Vault and mints a proportional quantity of FDX tokens.

```solidity
function deposit(uint _amount) public nonReentrant {
    strategy.beforeDeposit();
    uint256 _pool = balance();
    want().safeTransferFrom(msg.sender, address(this), _amount);
    earn();
    uint256 _after = balance();
    _amount = _after - _pool; // Additional check for deflationary tokens
    uint256 shares = 0;
    if (totalSupply() == 0) {
        shares = _amount;
    } else {
        shares = (_amount * totalSupply()) / _pool;
    }
    _mint(msg.sender, shares);
}
```

* **Helper Function:** `depositAll()` deposits the entire balance of the underlying token in the user's wallet.

**2. `withdraw(uint256 _shares)`**

Burns a specified `_shares` of FDX tokens and transfers a proportional quantity of the underlying token to the depositor.

```solidity
function withdraw(uint256 _shares) public {
    uint256 r = (balance() * _shares) / totalSupply();
    _burn(msg.sender, _shares);
    uint b = want().balanceOf(address(this));
    if (b < r) {
        uint _withdraw = r - b;
        strategy.withdraw(_withdraw);
        uint _after = want().balanceOf(address(this));
        uint _diff = _after - b;
        if (_diff < _withdraw) {
            r = b + _diff;
        }
    }
    want().safeTransfer(msg.sender, r);
}
```

* **Helper Function:** `withdrawAll()` withdraws the entire balance of FDX tokens in the user's wallet.

**3. `earn()`**

Transfers the available underlying token from the Vault to the Strategy Contract and triggers the strategy's `deposit()` function to deploy funds and begin earning yield.

```solidity
function earn() public {
    uint _bal = available();
    want().safeTransfer(address(strategy), _bal);
    strategy.deposit();
}
```

**4. `proposeStrat(address _implementation)`**

Writes the address of an alternate Strategy Contract to the Vault's memory in preparation for an upgrade.

```solidity
function proposeStrat(address _implementation) public onlyOwner {
    require(address(this) == IStrategy(_implementation).vault(), "Proposal not valid for this Vault");
    require(want() == IStrategy(_implementation).want(), "Different want");
    stratCandidate = StratCandidate({
        implementation: _implementation,
        proposedTime: block.timestamp
    });
    emit NewStratCandidate(_implementation);
}
```

**5. `upgradeStrat()`**

Replaces the current Strategy Contract with the alternate strategy specified by `proposeStrat()`.

```solidity
function upgradeStrat() public onlyOwner {
    require(stratCandidate.implementation != address(0), "There is no candidate");
    require(stratCandidate.proposedTime + approvalDelay < block.timestamp, "Delay has not passed");
    emit UpgradeStrat(stratCandidate.implementation);
    strategy.retireStrat();
    strategy = IStrategy(stratCandidate.implementation);
    stratCandidate.implementation = address(0);
    stratCandidate.proposedTime = 5000000000;
    earn();
}
```

### **FlowDexVaultV1.sol**

The current release of the FlowDex Vault Contract is **FlowDexVaultV1.sol**, which includes the following improvements:

* **Upgradeability:** Introduced through proxy patterns to facilitate updates without redeployment.
* **Strategy Interface:** Updated to support upgradeable strategies.
* **Gas Optimization:** Removed reliance on the SafeMath library, as its features are now native in Solidity v0.8.
