CapitalStack

Git Source

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

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

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

Functions

_getCapitalStackStorage

constructor

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

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

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

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

    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

_addToFrontOfSeniorityLevelList

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

_addToBackOfSeniorityLevelList

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

_addToMiddleOfSeniorityLevelList

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

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.

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

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

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

Parameters

Name
Type
Description

assetToRemove

address

The address of the asset to remove

updateAssetDocument

Updates an asset's document in the document registry

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

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

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

getSeniorityLevelIndexByAsset

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

getNumberOfAssetsInSeniorityLevel

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

Will also returns zero if the seniority level does not exist

isAssetInCapitalStack

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

totalSeniorityLevels

Returns the total number of seniority levels

getDocumentIndexByAsset

Returns the document index for 'asset'

Reverts if 'asset' is not in the stack

_validateAssetIsInStack

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

_addDocumentForAsset

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

_incrementCurrentSeniorityLevelIndex

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

_incrementSeniorityLevelsRemoved

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

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"))

version

Returns the version of the implementation as a uint256

supportsInterface

ERC165 support

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'

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()'

Structs

CapitalStackStorage

Last updated