# Lockup Transfer Manager

|                                          |                           |
| ---------------------------------------- | ------------------------- |
| **Introduced in**                        | v3.0.0                    |
| **Contract name**                        | LockupTransferManager.sol |
| **Compatible ST Protocol version range** | ^3.0.0                    |
| **Type**                                 | Transfer Manager Module   |

## How it works

This module is used to limit the volume of tokens to be transacted by the affiliate/investors. That helps in avoiding the material impact on the SecurityToken prices. In other words, it assigns a lockup on the tokens of the affiliates/investors (mainly large amount of percentage of token holders) and only allows them to transact a certain amount of tokens within a given time period.

## Key functionalities (as defined in the Smart Contract)

### Initialization

This module is initialized with no parameters. That means during the creation of this contract there’s no need to call any type of configure() function.

### Using Module

***Step -1 : Add the LockupType first by using\*\*\*\* ****`addNewLockUpType()`**** \*\*\*\*with following parameters***

```
  _lockupAmount → Lockup amount  = 100,000
  _startTime → Start Time of the lockup = now
  _lockUpPeriodSeconds . → Number of seconds lockup will remain active = 4 years(~ 4 * 365 * 24 * 3600).
  _releaseFrequencySeconds → Number of seconds after which a tranche of tokens will be released (This is a recurring process) = 1 year (~ 1 * 365 * 24 * 3600)
  _lockupName → Name of the lockup (Should be unique) = “a_lockup”
```

***Step -2 : Assign “a\_lockup” to Alice using the\*\*\*\* ****`addLockUpByName()`**** \*\*\*\*with following parameters***

```
  _userAddress  → Address of employee/Affiliate whom lockup get assigned = 0xabc..
  _lockupName → Name of the lockup = a_lockup
```

***Day 1: Alice tries to sell 100 tokens***

```
  Current Alice balance : 100,000   
  Calculate the totalRemainingLockedAmount for Alice : LockupAmount - unlockedAmount = 100,000 - 0 = 100,00
  For transfer to proceed, currentBalanceOfAlice - _amount >= totalRemainingLockedAmount
  100,000 - 100 >= 100,00 → false → transaction failed
```

***Day 250: Alice tries to sell 10,000 tokens***

```
  Current Alice balance : 110,000 (Buy 10,000 tokens by any other means ex- Secondary market , OTC etc).
  totalRemainingLockedAmount = 100,000 - 0 = 100,000
  110,000 - 10,000 >= 100,000 —> True, Transaction processed
```

***Day 731: Alice tries to sell 40,000 tokens***

```
   Current Alice balance : 100,000 
   totalRemainingLockedAmount = 100,000 - 50,000 (2 years passed) = 50,000
   100,000 - 40,000 >= 50,000 —> True, Transaction processed
```

continues ...

If Alice has multiple lockups then `totalRemainingLockedAmount` will be calculated by looping all active lockups of Alice. The locked amounts for each lockup will be summed together.

## Transfer Verification

* If `_from` address has been added to the lockups mapping (i.e restricted address in terms of token volume ) then `executeTransfer` function performs a check to calculate the permitted or allowed volume of tokens to transact.
* Transaction is allowed only when the total remaining locked amount is less than equal to the amount remain after the transaction `((currentBalance.sub(_amount)) >= totalRemainingLockedAmount`) (#460 - #462). While the total remaining locked amount is the aggregation of the remaining locked amounts per lockups for a given address (i.e `_from`).
* Lockup restrictions enter in effect as soon as a user is added to them. However, the vesting schedule (release of tokens) starts from `_startTime`.
* If investor/affiliate doesn’t transact the total allowed volume of tokens of a particular period then the remaining amount of tokens will be added into the allowed quota of the following period.
* If `_from` address is the issuance address ( i.e `address(0)` ) then `executeTransfer` will ignored. That means the minting of tokens is not affected by the `LockupVolumeRestrictionTM`. (#89)

  ```
  /** 
   * @dev Used to verify the transfer transaction and prevent locked up tokens from being transferred
   * @param _from Address of the sender
   * @param _amount The amount of tokens to transfer
   */
   function executeTransfer(address  _from, address /* _to*/, uint256  _amount, bytes calldata /* _data */) external returns(Result)
  ```

## Add lockup type

```
  /**
   * @notice Use to add the new lockup type
   * @param _lockupAmount Amount of tokens that need to lock.
   * @param _startTime When this lockup starts (seconds)
   * @param _lockUpPeriodSeconds Total period of lockup (seconds)
   * @param _releaseFrequencySeconds How often to release a tranche of tokens (seconds)
   * @param _lockupName Name of the lockup
   */
   function addNewLockUpType(
      uint256 _lockupAmount,
      uint256 _startTime,
      uint256 _lockUpPeriodSeconds,
      uint256 _releaseFrequencySeconds,
      bytes32 _lockupName
   )
      external
      withPerm(ADMIN)
```

***Note:*** 1. Tokens are locked as soon as the Lockup is created, but only start vesting from \_startTime.\
2\. \_releaseFrequencySeconds can be set to a number greater than \_lockUpPeriodSeconds to disable vesting release cycles (all tokens will be released together when restriction ends).

**For Batch transaction-**

```
  /**
   * @notice Use to add the new lockup type
   * @param _lockupAmounts Array of amount of tokens that need to lock.
   * @param _startTimes Array of startTimes when this lockup starts (seconds)
   * @param _lockUpPeriodsSeconds Array of total period of lockup (seconds)
   * @param _releaseFrequenciesSeconds Array of how often to release a tranche of tokens (seconds)
   * @param _lockupNames Array of names of the lockup
   */
   function addNewLockUpTypeMulti(
      uint256[] _lockupAmounts,
      uint256[] _startTimes,
      uint256[] _lockUpPeriodsSeconds,
      uint256[] _releaseFrequenciesSeconds,
      bytes32[] _lockupNames
   )  
      public
      withPerm(ADMIN)
```

## Assign the lockup to an investor/affiliate using the lockup type\*

**For a particular user-**

```
  /**
   * @notice Add the lockup to a user
   * @param _userAddress Address of the user
   * @param _lockupName Name of the lockup
   */
   function addLockUpByName(
       address _userAddress,
       bytes32 _lockupName
    )
       external
       withPerm(ADMIN)
```

***Note:*** It is not possible to add an investor to an already started lockup (i.e lockup startTime < now).

**For batch transaction**

```
  /**
   * @notice Add the lockup to a user
   * @param _userAddresses Address of the user
   * @param _lockupNames Name of the lockup
   */
   function addLockUpByNameMulti(
      address[] _userAddresses,
      bytes32[] _lockupNames
   )
      public
      withPerm(ADMIN)
```

***Note:*** `addLockUpByNameMulti()` will hit the block gas limit if the no. of addresses is more than 80 - 90 (It is an approximate figure not tested).

## Create a new lockup for an investor/affiliate

```
   /**
    * @notice Lets the admin create a volume restriction lockup for a given address.
    * @param _userAddress Address of the user whose tokens should be locked up
    * @param _lockupAmount Amount of tokens that need to lock.
    * @param _startTime When this lockup starts (seconds)
    * @param _lockUpPeriodSeconds Total period of lockup (seconds)
    * @param _releaseFrequencySeconds How often to release a tranche of tokens (seconds)
    * @param _lockupName Name of the lockup
    */
    function addNewLockUpToUser(
       address _userAddress,
       uint256 _lockupAmount,
       uint256 _startTime,
       uint256 _lockUpPeriodSeconds,
       uint256 _releaseFrequencySeconds,
       bytes32 _lockupName
    ) 
       external 
       withPerm(ADMIN)
```

It works similarly to adding the lockupType first and assign the lockup type to a given address.\
**For batch transaction-**

```
  /**
   * @notice Lets the admin create multiple volume restriction lockups for multiple given addresses.
   * @param _userAddresses Array of the address of the user whose tokens should be locked up
   * @param _lockupAmounts Array of the amounts that need to be locked for the different addresses.
   * @param _startTimes Array of When this lockup starts (seconds)
   * @param _lockUpPeriodsSeconds Array of total periods of lockup (seconds)
   * @param _releaseFrequenciesSeconds Array of how often to release a tranche of tokens (seconds)
   * @param _lockupNames Array of names of the lockup
   */
   function addNewLockUpToUserMulti(
      address[] _userAddresses,
      uint256[] _lockupAmounts,
      uint256[] _startTimes,
      uint256[] _lockUpPeriodsSeconds,
      uint256[] _releaseFrequenciesSeconds,
      bytes32[] _lockupNames
   ) 
      public
      withPerm(ADMIN)
```

## Remove the Lockup restriction of a particular investor/affiliate

An investor/affiliate can have more than one lockup restriction. So for removing a particular lockup restriction, we need to pass the lockupName and the address of the investor/affiliate (whose lockup restriction needs to be removed).

```
  /**
   * @notice Lets the admin remove a user's lock up
   * @param _userAddress Address of the user whose tokens are locked up
   * @param _lockupName Name of the lockup need to be removed.
   */
   function removeLockUpFromUser(address _userAddress, bytes32 _lockupName) external withPerm(ADMIN)
```

**For Batch functions**

```
  /**
   * @notice Use to remove the lockup for multiple users
   * @param _userAddresses Array of addresses of the user whose tokens are locked up
   * @param _lockupNames Array of the names of the lockup that needs to be removed. 
   */
  function removeLockUpFromUserMulti(address[] _userAddresses, bytes32[] _lockupNames) public withPerm(ADMIN)
```

## Remove LockupType in a transaction

Lockup type can only be removed when a given type doesn’t have any associated address with it.

```
  /**
   * @notice Used to remove the lockup type
   * @param _lockupName Name of the lockup
   */
   function removeLockupType(bytes32 _lockupName) external withPerm(ADMIN)
```

**For batch transaction -**

```
  /**
   * @notice Used to remove the multiple lockup type
   * @param _lockupNames Array of the lockup names.
   */
  function removeLockupTypeMulti(bytes32[] _lockupNames) public withPerm(ADMIN)
```

***Note:*** `removeLockUpTypeMulti()` will hit the block gas limit if the no. of addresses is more than 75 (It is an approximate figure not tested).

## Modify a lockup type

Like other functions, the issuer or the designated delegate having `ADMIN` permissions can modify the lockup restriction of a particular investor/affiliate with the help of -

```
  /**
   * @notice Lets the admin modify a lockup.
   * @param _lockupAmount Amount of tokens that needs to be locked
   * @param _startTime When this lockup starts (seconds)
   * @param _lockUpPeriodSeconds Total period of lockup (seconds)
   * @param _releaseFrequencySeconds How often to release a tranche of tokens (seconds)
   * @param _lockupName name of the lockup that needs to be modified.
   */
   function modifyLockUpType(
       uint256 _lockupAmount,
       uint256 _startTime,
       uint256 _lockUpPeriodSeconds,
       uint256 _releaseFrequencySeconds,
       bytes32 _lockupName
   ) 
      external 
      withPerm(ADMIN)
```

**For a batch transaction -**

```
  /**
   * @notice Lets the admin modify a volume restriction lockup for multiple addresses.
   * @param _lockupAmounts Array of the amount of tokens that needs to be locked for the respective addresses.
   * @param _startTimes Array of the start time of the lockups (seconds)
   * @param _lockUpPeriodsSeconds Array of Unix timestamp for the list of lockups (seconds).
   * @param _releaseFrequenciesSeconds How often to release a tranche of tokens (seconds)
   * @param _lockupNames Array of the lockup names that need to be modified 
   */
  function modifyLockUpTypeMulti(
      uint256[] _lockupAmounts,
      uint256[] _startTimes,
      uint256[] _lockUpPeriodsSeconds,
      uint256[] _releaseFrequenciesSeconds,
      bytes32[] _lockupNames
  ) 
      public 
      withPerm(ADMIN)
```

***Note:*** `modifyLockUpTypeMulti()` will hit the block gas limit if the no. of addresses is more than 75 (It is an approximate figure not tested).

## Getters

* `getLockUp(bytes32 _lockUpName)` use to get the details of a particular lockup for a given lockup name.
* `getLockedTokenToUser(address _userAddress)` use to get the total locked tokens for a given user. It will loop to all lockups for a given address and return sum of locked tokens per lockups.
* `getListOfAddresses(bytes32 _lockupName)`  use to get the list of the users of a lockup type.
* `getAllLockups()` use to get the all lockups created by the issuer till now.
* `getLockupsNamesToUser(address _user)` use to get the list of the lockups for a given user.
* `getTokensByPartition(bytes32 _partition, address _tokenHolder, uint256 _additionalBalance)` use to get balance of the tokenHolder for a given partition.
* `getAllLockupData()` use to get the details of all the lockupTypes.


---

# 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://developers.polymath.network/polymath/wiki/lockup-transfer-manager.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.
