# TokenTimelock

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

**Inherits:** Patchable, StateAware, VotesDelegator, AdminControlled, MezzERC721Upgradeable, ITokenTimelock

**Author:** Daniel Yamagata & Naveen Ailawadi

This contract is used to vest a company's shares for a period of time. It is used by a company's Common Shares and Preferred Shares. The voting power of vesting shares can be delegated and used in governance

\*Invariants:

* \_erc20Vesting\[token] is always greater than or equal to \_erc20Released\[token]
* \_vestingScheduleByTokenId\[tokenId].amount is always greater than or equal to \_erc20ReleasedByTokenId\[tokenId]\[shares]. This is inclusive of when the token's data is deleted upon vesting completion or when the vesting is canceled\*

## State Variables

### TokenTimelockStorageLocation

```solidity
bytes32 private constant TokenTimelockStorageLocation =
    0x35f985dfceb352faec794b4221331a49707dbeacf0ce328e288c0a3b67d6cb00;
```

## Functions

### \_getTokenTimelockStorage

```solidity
function _getTokenTimelockStorage() internal pure returns (TokenTimelockStorage storage $);
```

### constructor

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

### receive

*The Token Timelock should not receive the native token used to pay for gas All native tokens transferred to this contract will be locked forever and effectively burned*

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

### init

Initializes the token timelock contract

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

**Parameters**

| Name           | Type      | Description                          |
| -------------- | --------- | ------------------------------------ |
| `initTreasury` | `address` | The address of the treasury contract |

### \_\_TokenTimelock\_Init

```solidity
function __TokenTimelock_Init(address initTreasury) internal virtual onlyInitializing;
```

### treasury

Returns the address of the treasury, whose signers are the company's board of directors

```solidity
function treasury() public view override(BoardControlled, VotesDelegator, IBoardControlled) returns (ITreasury);
```

### vestShares

Vest shares for a recipient according to a vesting schedule. Vesting is cancellable by the board or a set of admins determined by the board depending on if it is obligatory

*'data.shares' must be tracked by the treasury, otherwise the function call will revert. This function uses an ERC721 safe transfer, which is susceptible to reentrancy. It follows the CEI pattern accordingly. There is no validation of 'data.startDate' being in the past. It is the responsibility of the caller to ensure its validity. If the start date is in the past farther than 'data.duration', the shares will be instantly vested. The max start date is two years into the future, at which point the shares will begin to vest*

```solidity
function vestShares(DataTypes.VestingData calldata data) external virtual returns (uint256);
```

**Parameters**

| Name   | Type                    | Description                                        |
| ------ | ----------------------- | -------------------------------------------------- |
| `data` | `DataTypes.VestingData` | The vesting data as a DataTypes.VestingData struct |

**Returns**

| Name     | Type      | Description                         |
| -------- | --------- | ----------------------------------- |
| `<none>` | `uint256` | The token ID for the vesting shares |

### release

Releases vested tokens to the owner of an ERC721. Can be called by anyone

*This function is not access controlled. Any account can release vested shares for any token ID Vested shares are transferred to the owner of the token*

```solidity
function release(uint256 tokenId) external virtual onlyTokenOwner(tokenId) returns (uint256);
```

**Parameters**

| Name      | Type      | Description                                      |
| --------- | --------- | ------------------------------------------------ |
| `tokenId` | `uint256` | The ID of the token to release vested shares for |

**Returns**

| Name     | Type      | Description                             |
| -------- | --------- | --------------------------------------- |
| `<none>` | `uint256` | The amount of shares that were released |

### cancelVestingAtTimepoint

Cache and Validate

*This function is primarily used by the Payroll Manager when an employee resigns at a timepoint*

```solidity
function cancelVestingAtTimepoint(uint256 tokenId, uint256 timepoint) external virtual returns (uint256);
```

**Returns**

| Name     | Type      | Description                   |
| -------- | --------- | ----------------------------- |
| `<none>` | `uint256` | The amount of canceled shares |

### cancelVesting

Cancels the vesting for a given token. Releases any vested shares and burns the remaining amount allocated to the token.

*This function will revert if the caller is not the token owner nor an admin. If the caller is an admin, this function will revert if the token is obligatory*

```solidity
function cancelVesting(uint256 tokenId) external virtual returns (uint256, uint256);
```

**Parameters**

| Name      | Type      | Description                                   |
| --------- | --------- | --------------------------------------------- |
| `tokenId` | `uint256` | The ID of the token to cancel the vesting for |

**Returns**

| Name     | Type      | Description                                                                                                                                    |
| -------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `<none>` | `uint256` | Returns two arguments. The first is the amount of shares that were released. The second is the amount of shares that were cancelled and burned |
| `<none>` | `uint256` |                                                                                                                                                |

### \_cancelVesting

```solidity
function _cancelVesting(uint256 tokenId) internal virtual returns (uint256, uint256);
```

### \_handleCanceledShares

*If the owner is the payroll manager, transfer the vesting shares back to the treasury Otherwise, burn the shares. This is done to prevent the treasury from having to re-authorize and re-issue shares that were allocated to employees but subsequently canceled*

```solidity
function _handleCanceledShares(uint256 tokenId, address shares, uint256 amountCanceled) internal;
```

### extendVestingDuration

Extends the vesting duration for the given 'tokenId'. Only callable by the token owner

*This function will revert if the token does not exist*

```solidity
function extendVestingDuration(uint256 tokenId, uint256 durationExtension)
    external
    virtual
    onlyTokenOwner(tokenId)
    returns (uint32);
```

**Parameters**

| Name                | Type      | Description                                            |
| ------------------- | --------- | ------------------------------------------------------ |
| `tokenId`           | `uint256` | The ID of the token to extend the vesting duration for |
| `durationExtension` | `uint256` | The amount of time to extend the vesting duration by   |

**Returns**

| Name     | Type     | Description              |
| -------- | -------- | ------------------------ |
| `<none>` | `uint32` | The new vesting duration |

### extendVestingAmount

Increases the vesting amount for 'tokenId' by 'equityExtension'

*This function is not access controlled. It is callable by anyone This function will revert if the token does not exist*

```solidity
function extendVestingAmount(uint256 tokenId, uint256 equityExtension) external virtual returns (uint256);
```

**Parameters**

| Name              | Type      | Description                                            |
| ----------------- | --------- | ------------------------------------------------------ |
| `tokenId`         | `uint256` | The ID of the token to increase the vesting amount for |
| `equityExtension` | `uint256` | The amount to increase the vesting amount by           |

**Returns**

| Name     | Type      | Description            |
| -------- | --------- | ---------------------- |
| `<none>` | `uint256` | The new vesting amount |

### updateDelegate

Updates the delegate of 'delegator' from 'fromDelegate' to 'toDelegate'. Only callable by the Delegate Registry

```solidity
function updateDelegate(address delegator, address fromDelegate, address toDelegate)
    external
    virtual
    override(VotesDelegator, IVotesDelegator)
    onlyDelegateRegistry;
```

### isObligatory

Returns whether or not a given token is obligatory

```solidity
function isObligatory(uint256 tokenId) public view returns (bool);
```

**Parameters**

| Name      | Type      | Description         |
| --------- | --------- | ------------------- |
| `tokenId` | `uint256` | The ID of the token |

**Returns**

| Name     | Type   | Description                            |
| -------- | ------ | -------------------------------------- |
| `<none>` | `bool` | Whether or not the token is obligatory |

### wasCanceled

Returns true if the token was canceled, false otherwise

```solidity
function wasCanceled(uint256 tokenId) public view returns (bool);
```

### hasCompleted

Returns true if the token has completed its vesting, false otherwise

```solidity
function hasCompleted(uint256 tokenId) public view returns (bool);
```

### exists

Returns true if the token exists, false otherwise

```solidity
function exists(uint256 tokenId) public view returns (bool);
```

### getVestingSchedule

Returns the vesting schedule for the given token

```solidity
function getVestingSchedule(uint256 tokenId) public view returns (DataTypes.VestingSchedule memory);
```

**Parameters**

| Name      | Type      | Description         |
| --------- | --------- | ------------------- |
| `tokenId` | `uint256` | The ID of the token |

**Returns**

| Name     | Type                        | Description                                                |
| -------- | --------------------------- | ---------------------------------------------------------- |
| `<none>` | `DataTypes.VestingSchedule` | The vesting schedule as a DataTypes.VestingSchedule struct |

### getRemainingVestingAmount

Returns the remaining vesting amount for the given token

*The remaining vesting amount refers to the difference between the shares attributed to the vesting schedule and how much has been released*

```solidity
function getRemainingVestingAmount(uint256 tokenId) public view returns (uint256);
```

### getVestingEndDate

Returns the Unix-timestamp in seconds at which the vesting schedule will complete

```solidity
function getVestingEndDate(uint256 tokenId) public view returns (uint256);
```

### released

Returns the amount of shares that have been released for a given token

```solidity
function released(uint256 tokenId) public view returns (uint256);
```

**Parameters**

| Name      | Type      | Description         |
| --------- | --------- | ------------------- |
| `tokenId` | `uint256` | The ID of the token |

**Returns**

| Name     | Type      | Description                                                |
| -------- | --------- | ---------------------------------------------------------- |
| `<none>` | `uint256` | The amount of shares that have been released for the token |

### releasable

Returns the amount of shares that are releasable for a given token. 'Releasable' refers to the amount of shares that have vested and have not yet been released

```solidity
function releasable(uint256 tokenId) public view returns (uint256);
```

**Parameters**

| Name      | Type      | Description         |
| --------- | --------- | ------------------- |
| `tokenId` | `uint256` | The ID of the token |

**Returns**

| Name     | Type      | Description                                            |
| -------- | --------- | ------------------------------------------------------ |
| `<none>` | `uint256` | The amount of shares that are releasable for the token |

### getVotesByShareClass

Returns the current number of voting units for 'account' based on 'shares'

*The return value does not adjust for the voting weight of 'shares'*

```solidity
function getVotesByShareClass(address account, address shares) public view virtual returns (uint256);
```

### getPastVotesByShareClass

Returns the voting units for 'account' based on 'shares' at the given 'timepoint'

*The return value does not adjust for the voting weight of 'shares'. This function will revert if 'timepoint' is in the present or the future*

```solidity
function getPastVotesByShareClass(address account, address shares, uint256 timepoint)
    public
    view
    virtual
    returns (uint256);
```

### getERC20VestingByAccount

Returns the current amount of 'shares' that are vesting for 'account'

```solidity
function getERC20VestingByAccount(address account, address shares) public view returns (uint256);
```

### getCumulativeERC20Vesting

Returns the cumlative amount of shares that are vesting or *have been* vested in the token timelock

```solidity
function getCumulativeERC20Vesting(address shares) public view returns (uint256);
```

**Parameters**

| Name     | Type      | Description                        |
| -------- | --------- | ---------------------------------- |
| `shares` | `address` | The address of the shares contract |

**Returns**

| Name     | Type      | Description                                                                       |
| -------- | --------- | --------------------------------------------------------------------------------- |
| `<none>` | `uint256` | The amount of shares that are vesting or *have been* vested in the token timelock |

### getCumulativeERC20Released

Returns the cumlative amount of shares that have been released from the token timelock

```solidity
function getCumulativeERC20Released(address shares) public view returns (uint256);
```

**Parameters**

| Name     | Type      | Description                        |
| -------- | --------- | ---------------------------------- |
| `shares` | `address` | The address of the shares contract |

**Returns**

| Name     | Type      | Description                                                          |
| -------- | --------- | -------------------------------------------------------------------- |
| `<none>` | `uint256` | The amount of shares that have been released from the token timelock |

### name

Returns the name of the token timelock

```solidity
function name() public view virtual override(ERC721Upgradeable, ITokenTimelock) returns (string memory);
```

### symbol

Returns the symbol of the token timelock

```solidity
function symbol() public view virtual override(ERC721Upgradeable, ITokenTimelock) returns (string memory);
```

### 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);
```

### \_release

*Releases the '\_releasableAmount' of vested shares to the owner of the token 'Releasable' refers to the amount vested minus the amount already released*

```solidity
function _release(uint256 tokenId, address shares, uint256 _releasableAmount) internal;
```

**Parameters**

| Name                | Type      | Description                                                                         |
| ------------------- | --------- | ----------------------------------------------------------------------------------- |
| `tokenId`           | `uint256` | The token ID to release tokens for                                                  |
| `shares`            | `address` | The address of the shares that are being released and correspond to the given token |
| `_releasableAmount` | `uint256` | The amount of tokens that are releasable                                            |

### \_releasable

*Returns the amount of tokens that are 'releasable' for a given token 'Releasable' refers to the amount vested minus the amount already released*

```solidity
function _releasable(uint256 tokenId) internal view virtual returns (uint256);
```

**Parameters**

| Name      | Type      | Description  |
| --------- | --------- | ------------ |
| `tokenId` | `uint256` | The token ID |

**Returns**

| Name     | Type      | Description                              |
| -------- | --------- | ---------------------------------------- |
| `<none>` | `uint256` | The amount of tokens that are releasable |

### \_vestedAmount

*Calculates the vested amount of shares for a given vesting schedule. Does not check the released amount of shares Precision loss is possible, but extremely unlikely since shares will always have 18 decimals*

```solidity
function _vestedAmount(DataTypes.VestingSchedule memory vestingScheduleCache) internal view virtual returns (uint256);
```

**Parameters**

| Name                   | Type                        | Description                                             |
| ---------------------- | --------------------------- | ------------------------------------------------------- |
| `vestingScheduleCache` | `DataTypes.VestingSchedule` | The vesting schedule to calculate the vested amount for |

**Returns**

| Name     | Type      | Description                 |
| -------- | --------- | --------------------------- |
| `<none>` | `uint256` | The vested amount of shares |

### \_burnTokenAndDeleteData

*Burn a token with 'tokenId' and deletes it corresponding data in storage*

```solidity
function _burnTokenAndDeleteData(uint256 tokenId, address _shares) internal;
```

**Parameters**

| Name      | Type      | Description                                                  |
| --------- | --------- | ------------------------------------------------------------ |
| `tokenId` | `uint256` | The ID of the token to burn                                  |
| `_shares` | `address` | The address of the shares that correspond to the given token |

### \_validateCallerIsOwnerOrAdminAndNonObligatory

\*Reverts if:

* The caller is not the token owner or an admin
* If the caller is an admin *and* the token is obligatory\*

```solidity
function _validateCallerIsOwnerOrAdminAndNonObligatory(uint256 tokenId) internal view virtual;
```

### \_checkInvariants

*Asserts that the invariants hold true. Panics otherwise*

```solidity
function _checkInvariants(uint256 tokenId) internal view virtual;
```

**Parameters**

| Name      | Type      | Description                              |
| --------- | --------- | ---------------------------------------- |
| `tokenId` | `uint256` | The token ID to check the invariants for |

### \_update

*Overridden updated from '\_ERC721Upgradeable' such that the voting units of a delegate is updated on token transfer, including burning*

```solidity
function _update(address to, uint256 tokenId, address auth) internal virtual override returns (address);
```

**Returns**

| Name     | Type      | Description            |
| -------- | --------- | ---------------------- |
| `<none>` | `address` | The owner of 'tokenId' |

### \_transferVotingUnits

*Transfers the voting units of 'shares' from the delegatee of 'from' to the delegatee of 'to'*

```solidity
function _transferVotingUnits(address from, address to, address shares, uint256 amount) internal virtual;
```

### \_moveDelegateVotes

*Moves delegated votes of 'shares' from one delegate to another*

```solidity
function _moveDelegateVotes(address from, address to, address shares, uint256 amount) internal virtual;
```

### \_push

```solidity
function _push(Checkpoints.Trace208 storage store, function(uint208, uint208) view returns (uint208) op, uint208 delta)
    internal
    returns (uint208, uint208);
```

### \_add

```solidity
function _add(uint208 a, uint208 b) internal pure returns (uint208);
```

### \_subtract

```solidity
function _subtract(uint208 a, uint208 b) internal pure returns (uint208);
```

### supportsInterface

*ERC165 support*

```solidity
function supportsInterface(bytes4 interfaceId)
    public
    view
    virtual
    override(ERC721Upgradeable, 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

### TokenTimelockStorage

```solidity
struct TokenTimelockStorage {
    mapping(address => uint256) _erc20Vesting;
    mapping(address => uint256) _erc20Released;
    mapping(uint256 => DataTypes.VestingSchedule) _vestingScheduleByTokenId;
    mapping(uint256 tokenId => mapping(address erc20 => uint256)) _erc20ReleasedByTokenId;
    mapping(address account => mapping(address erc20 => uint256)) _erc20VestingByAccount;
    mapping(address delegatee => mapping(address shares => Checkpoints.Trace208)) _delegateCheckpointsByShares;
}
```


---

# 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/tokentimelock.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.
