# CapitalStack

[Git Source](https://github.com/EntreDevelopers-Lab-Inc/Mezz-Companies/blob/f7a3e84e3dd5bb33c4bd7f77283983f9e8ba20b2/src/core/ancillary/capital-stack/CapitalStack.sol)

**Inherits:** StateAware, Patchable, BoardControlled, ICapitalStack

**Author:** Daniel Yamagata & Naveen Ailawadi

A smart contract that lays out the logic for the capital stack of a company. The capital stack is the foundation for the mergers, acquistions, recapitalization, and liquidation of companies in the Mezzanine protocol A capital stack is made up of:

* Seniority Levels
* Assets&#x20;

Each seniority level and asset is associated with an 'asset class'. An asset of a given class can be inserted into only one seniority level of the same class. There are three types of asset classes, defined by the following enum:

* 0: Null
* 1: Common Equity
* 2: Preferred Equity
* 3: Debt&#x20;

A seniority level or asset with asset class 'Null' is considered invalid and cannot be added to the stack. Seniority levels must be added, such that a new seniority level's asset class cannot be below the previous's asset class and cannot exceed the next's asset class. For example, a seniority level of 'Common Equity' cannot be inserted above 'Debt' Here is a visual example:

***

| Index | Asset Class      | Assets     |
| ----- | ---------------- | ---------- |
| 2     | Debt             | D, E, F, G |
| 3     | Preferred Equity | B, C       |
| 1     | Common Equity    | A          |

*Seniority levels are represented by a circular, doubly linked list. Their indexes are not assumed to be sequential*

## State Variables

### CapitalStackStorageLocation

```solidity
bytes32 private constant CapitalStackStorageLocation =
    0x36092dfc4ccd895585e40ef098e02e99f066e08bb0ed611f9c0eac213dfb8b00;
```

## Functions

### \_getCapitalStackStorage

```solidity
function _getCapitalStackStorage() internal pure returns (CapitalStackStorage storage $);
```

### constructor

```solidity
constructor(address _mezzHub, address _mezzMigrator) StateAware(_mezzHub) Patchable(_mezzMigrator);
```

### init

Initializes state, inserts a common equity seniority level, adds the common shares to the capital, and creates a document for the common shares in the document registry. Can only be called once

*Called atomically by the MezzDeployer during the deployment of a Mezz Instance*

```solidity
function init(address initTreasury, address commonShares) external virtual initializer;
```

**Parameters**

| Name           | Type      | Description                                  |
| -------------- | --------- | -------------------------------------------- |
| `initTreasury` | `address` | The treasury to be used by the capital stack |
| `commonShares` | `address` | The address of the common shares             |

### \_\_CapitalStack\_init

```solidity
function __CapitalStack_init(address commonShares) internal onlyInitializing;
```

### addSeniorityLevel

Adds a seniority level to the capital stack. Only callable by the company's board of directors, who are the signers of the treasury contract. Seniority levels in a capital stack follow specific rules in how they can be inserted: Each seniority level has an associated 'AssetClass' defined by the following enum:

* 0: Null
* 1: Common Equity
* 2: Preferred Equity
* 3: Debt

A seniority level cannot be inserted if the previous seniority level, associated with 'previousSeniorityLevelIndex', has a higher 'AssetClass' than the proposed seniority level. For example, a seniority level of Common Equity cannot be inserted above a seniority level of Preferred Equity. Once inserted, only assets of that given class can be added to the given seniority level. A Mezzanine company can insert seniority levels above or below seniority levels of the same asset class. For example, a seniority level of Preferred Equity can be inserted above or below another seniority level of Preferred Equity. A company may do this since these different levels may be treated differently during liquidation, recapitalization, etc. Seniority levels with new types of asset classes can be added easily via upgrades

```solidity
function addSeniorityLevel(uint256 previousSeniorityLevelIndex, uint8 proposedAssetClass)
    external
    virtual
    onlyBoard
    pausable
    returns (uint256);
```

**Parameters**

| Name                          | Type      | Description                                                                |
| ----------------------------- | --------- | -------------------------------------------------------------------------- |
| `previousSeniorityLevelIndex` | `uint256` | The index of the previous seniority level, which is the point of insertion |
| `proposedAssetClass`          | `uint8`   | The asset class of the proposed seniority level                            |

**Returns**

| Name     | Type      | Description                                     |
| -------- | --------- | ----------------------------------------------- |
| `<none>` | `uint256` | The index of the newly inserted seniority level |

### \_addSeniorityLevel

Adding a seniority level has four cases:

* (A) The list is empty. Should only be true during initialization
* (B) An insertion at the front of the list
  * 'previousSeniorityLevelIndex' is zero
* (C) An insertion at the back of the list
  * The 'next' of 'previousSeniorityLevelIndex' is zero
* (D) An insertion in the middle of the list

  * 'previousSeniorityLevelIndex' is greater than zero but its 'next' is not equal to zero&#x20;

  The sentinel acts both as a header and a tail. The 'next' of the sentinel indicates the 'front' of the list while the 'previous' of the sentinel indicates the 'back' of the list Cases (A) and (D) are handled the same. Cases are handled differently to optimize for SSTOREs

```solidity
function _addSeniorityLevel(uint256 previousSeniorityLevelIndex, uint8 proposedAssetClass) internal returns (uint256);
```

### \_addToFrontOfSeniorityLevelList

*Case (B): An insertion at the front of the list*

```solidity
function _addToFrontOfSeniorityLevelList(
    uint256 seniorityLevelIndexToAdd,
    uint8 proposedAssetClass,
    uint256 oldNextIndex,
    DataTypes.SeniorityLevel storage oldNextSeniorityLevelPointer,
    CapitalStackStorage storage $
) internal virtual;
```

### \_addToBackOfSeniorityLevelList

*Case (C): An insertion at the back of the list*

```solidity
function _addToBackOfSeniorityLevelList(
    uint256 seniorityLevelIndexToAdd,
    uint8 proposedAssetClass,
    uint256 previousSeniorityLevelIndex,
    DataTypes.SeniorityLevel storage previousSeniorityLevelPointer,
    CapitalStackStorage storage $
) internal virtual;
```

### \_addToMiddleOfSeniorityLevelList

*Cases (A) and (D): An insertion in an empty list or in the middle of the list, respectively*

```solidity
function _addToMiddleOfSeniorityLevelList(
    uint256 seniorityLevelIndexToAdd,
    uint8 proposedAssetClass,
    uint256 previousSeniorityLevelIndex,
    uint256 oldNextIndex,
    DataTypes.SeniorityLevel storage previousSeniorityLevelPointer,
    DataTypes.SeniorityLevel storage oldNextSeniorityLevelPointer,
    CapitalStackStorage storage $
) internal virtual;
```

### removeSeniorityLevel

Removes a seniority level with 'seniorityLevelIndexToRemove' from the capital stack. Only callable by the company's board of directors, who are the signers of the Treasury. The seniority level must be empty, meaning it contains no assets.

```solidity
function removeSeniorityLevel(uint256 seniorityLevelIndexToRemove) external virtual onlyBoard freezable;
```

**Parameters**

| Name                          | Type      | Description                                |
| ----------------------------- | --------- | ------------------------------------------ |
| `seniorityLevelIndexToRemove` | `uint256` | The index of the seniority level to remove |

### addAssetToSeniorityLevel

Adds an asset to a seniority level. Only callable by the company's board of directors, who are the signers of the Treasury The asset must have the same 'AssetClass' as the seniority level it is being added to. This function adds a document to the document registry that is associated with the asset. It can be updated at any time. An asset can only be part of one seniority level and cannot be moved retroactively to a different seniority level.

*A treasury cannot call this function with its multi-sig functionality but instead must call the 'addAssetToCapitalStack' function*

```solidity
function addAssetToSeniorityLevel(
    uint256 seniorityLevelIndex,
    address assetToAdd,
    string memory assetDocumentName,
    string memory assetDocumentUri
) external virtual onlyBoard pausable returns (uint256);
```

**Parameters**

| Name                  | Type      | Description                                          |
| --------------------- | --------- | ---------------------------------------------------- |
| `seniorityLevelIndex` | `uint256` | The index of the seniority level to add the asset to |
| `assetToAdd`          | `address` |                                                      |
| `assetDocumentName`   | `string`  | The name of the asset document                       |
| `assetDocumentUri`    | `string`  | The URI of the asset document                        |

**Returns**

| Name     | Type      | Description                      |
| -------- | --------- | -------------------------------- |
| `<none>` | `uint256` | The document index for the asset |

### \_addAssetToSeniorityLevel

*Adds an asset to the seniority level at 'seniorityLevelIndex' and creates a document for the asset*

```solidity
function _addAssetToSeniorityLevel(
    uint256 seniorityLevelIndex,
    address assetToAdd,
    string memory assetDocumentName,
    string memory assetDocumentUri
) internal virtual returns (uint256);
```

**Returns**

| Name     | Type      | Description                      |
| -------- | --------- | -------------------------------- |
| `<none>` | `uint256` | The document index for the asset |

### removeAsset

Removes an asset from the capital stack. Only callable by the company's board of directors, who are the signers of the Treasury. A company cannot remove their initial common shares from the capital stack. All Mezz assets must implement a 'removable()' function that returns a bool indicating the asset's removability upon certain conditions. For example, Mezz shares are not removable if their total supply is greater than zero. If the 'removable()' of 'assetToRemove' returns false, this function will revert

*A treasury cannot call this function with its multi-sig functionality but instead must call the 'removeAssetFromCapitalStack' function*

```solidity
function removeAsset(address assetToRemove) external onlyBoard freezable;
```

**Parameters**

| Name            | Type      | Description                        |
| --------------- | --------- | ---------------------------------- |
| `assetToRemove` | `address` | The address of the asset to remove |

### updateAssetDocument

Updates an asset's document in the document registry

```solidity
function updateAssetDocument(address asset, string memory updatedDocumentName, string memory updatedDocumentUri)
    public
    virtual
    returns (uint256);
```

**Returns**

| Name     | Type      | Description                                                          |
| -------- | --------- | -------------------------------------------------------------------- |
| `<none>` | `uint256` | The new version of the document, which is originally indexed at zero |

### getSeniorityLevelInfo

Returns information regarding a seniority level as a 'DataTypes.SeniorityLevelInfo' struct

*Returns an empty struct if the seniority level does not exist*

```solidity
function getSeniorityLevelInfo(uint256 seniorityLevelIndex) public view returns (DataTypes.SeniorityLevelInfo memory);
```

### getSeniorityLevels

Returns the seniority levels of the capital stack in ascending order as an array of 'DataTypes.SenioritylevelInfo' structs. For instance, the ith index of the return values would be considered below the ith + 1 index of the return values in the capital stack.

*Seniority level indexes are non-sequential*

```solidity
function getSeniorityLevels() public view virtual returns (DataTypes.SeniorityLevelInfo[] memory);
```

### getAssetsInSeniorityLevel

Returns the assets in the seniority level with 'seniorityLevelIndex' as an array of addresses

*Returns an empty array of addresses if 'seniorityLevelIndex' does not exist*

```solidity
function getAssetsInSeniorityLevel(uint256 seniorityLevelIndex) public view returns (address[] memory);
```

### getSeniorityLevelIndexByAsset

Returns zero if the asset is not in the stack. Otherwise, returns the seniority level index for 'asset'

```solidity
function getSeniorityLevelIndexByAsset(address asset) public view returns (uint256);
```

### getNumberOfAssetsInSeniorityLevel

Returns the number of assets in the seniority level with 'seniorityLevelIndex'

*Will also returns zero if the seniority level does not exist*

```solidity
function getNumberOfAssetsInSeniorityLevel(uint256 seniorityLevelIndex) public view returns (uint256);
```

### isAssetInCapitalStack

Returns true if 'asset' is in the capital stack, false otherwise

```solidity
function isAssetInCapitalStack(address asset) public view returns (bool);
```

### totalSeniorityLevels

Returns the total number of seniority levels

```solidity
function totalSeniorityLevels() public view returns (uint256);
```

### getDocumentIndexByAsset

Returns the document index for 'asset'

*Reverts if 'asset' is not in the stack*

```solidity
function getDocumentIndexByAsset(address asset) public view returns (uint256);
```

### \_validateAssetIsInStack

*Reverts if 'asset' has not been added to the capital stack*

```solidity
function _validateAssetIsInStack(address asset) internal view virtual;
```

### \_addDocumentForAsset

*Creates a new document in the document registry, sets the '\_documentIndexByAsset' mapping, and returns the document index*

```solidity
function _addDocumentForAsset(address asset, string memory documentName, string memory documentUri)
    internal
    virtual
    returns (uint256);
```

### \_incrementCurrentSeniorityLevelIndex

*This function is kept as virtual in case overflow protection is desired in the future*

```solidity
function _incrementCurrentSeniorityLevelIndex() internal virtual returns (uint256);
```

### \_incrementSeniorityLevelsRemoved

*This function is kept as virtual in case overflow protection is desired in the future*

```solidity
function _incrementSeniorityLevelsRemoved() internal virtual;
```

### coreId

Returns the coreId of the implementation as a bytes32

*The core ID is the keccak256 hash of the contract name followed by a version under the following syntax: "mezzanine.coreId.ContractName.vX" For example, the core ID of the 2nd version of the Treasury would be the following: keccak256(abi.encodePacked("mezzanine.coreId.Treasury.v2"))*

```solidity
function coreId() public pure virtual override(Credentialed, ICredentialed) returns (bytes32);
```

### version

Returns the version of the implementation as a uint256

```solidity
function version() public pure virtual override(Credentialed, ICredentialed) returns (uint256);
```

### supportsInterface

*ERC165 support*

```solidity
function supportsInterface(bytes4 interfaceId)
    public
    view
    virtual
    override(MezzUUPSUpgradeable, IERC165)
    returns (bool);
```

### upgradeToNewerVersion

Upgrades 'this' to a newer version via the Mezz Migrator. Only callable by the Treasury, whose signers are the board of directors

*Will revert if the protocol state is 'Paused' or 'Frozen'*

```solidity
function upgradeToNewerVersion(uint256 newVersion, bytes memory data) public virtual onlyProxy onlyBoard;
```

**Parameters**

| Name         | Type      | Description                                                                                              |
| ------------ | --------- | -------------------------------------------------------------------------------------------------------- |
| `newVersion` | `uint256` | The new version to upgrade to                                                                            |
| `data`       | `bytes`   | The data to be passed to the new implementation, which likely should be a reinitializer function if used |

### \_authorizePatch

*Access control for 'resetToPatchedLatestVersion()'*

```solidity
function _authorizePatch(bytes memory) internal view virtual override;
```

## Structs

### CapitalStackStorage

```solidity
struct CapitalStackStorage {
    uint256 _currentSeniorityLevelIndex;
    uint256 _seniorityLevelsRemoved;
    mapping(uint256 => DataTypes.SeniorityLevel) _seniorityLevels;
    mapping(address => uint256) _seniorityLevelIndexByAsset;
    mapping(address => uint256) _documentIndexByAsset;
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.mezzanine.xyz/smart-contracts/source-code/core/capitalstack.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
