# Lossless Controller V3

This contract is the gateway contract that connects LERC20 token contracts with all the lossless hack mitigation system.

Contract can be found here:

[Hack Mitigation Repository](https://github.com/Lossless-Cash/lossless-v3/blob/master/contracts/LosslessControllerV3.sol)

## Variables

* `admin`
* `pauseAdmin`
* `recoveryAdmin`
* `guardian`
* `tokenProtections`
* `Protections`
* `Protection`
* `losslessStaking`
* `losslessReporting`
* `losslessGovernance`
* `tokenScopedLockedFunds`
* `TokenLockedFunds`
* `LocksQueue`
* `ReceiveCheckpoint`
* `HUNDRED`
* `dexTranferThreshold`
* `settlementTimeLock`
* `dexList`
* `whitelist`
* `blacklist`
* `tokenConfig`
* `TokenConfig`

### admin

This address correspondes to the set Lossless Admin. Has different capabilities over the Lossless Environment.

### pauseAdmin

This address has the access to pause and unpause controller contract.

### recoveryAdmin

This is a super admin's address. This wallet is able to change the regular admin and pause admin. This address is the most powerful admin in the whole lossless protocol and we are using a secure and time tested multi-sig (Gnosis Safe) for it. This variable can be changed using `transferRecoveryAdminOwnership` function.

### guardian

The address of the guardian smart contract. Guardian contract has access to control protection strategies on controller contract.

### tokenProtections

This mapping saves info about every address that is protected. It has a flag that shows if the address is protected or not and also has strategy address so that if the address is protected the controller knows which of the protections strategies should be applied.

### Protections

This structure contains a mapping of all the protected addresses related to a LERC20 token and the protection type for each address using the Protection structure.

### Protection

This structure contains a boolean that determines if the vault protection is active and the protection strategy being used.

### losslessStaking

The ILssStaking type refers to the Lossless Staking Interface, the variable itself contains the Smart Contract address of the Lossless Staking to allow interaction.

### losslessReporting

The ILssReporting type refers to the Lossless Reporting Interface, the variable itself contains the Smart Contract address of the Lossless Reporting to allow interaction.

### losslessGovernance

The ILssGovernance type refers to the Lossless Governance Interface, the variable itself contains the Smart Contract address of the Lossless Governance to allow interaction.

### tokenScopedLockedFunds

This mapping contains all the information pertinent to the settlement period of an LERC20 token and the order that the received funds get queued and freed to be used per address by using the TokenLockedFunds structure.

### TokenLockedFunds

The structure contains a mapping that refers an address to its queue of received and available funds. It uses the LocksQueue structure to save the details.

### LocksQueue

The structure contains a mapping numbered by the checkpoints of which the funds were received and freed by using the ReceiveCheckpoint structure. Also it contains a uint256 that determines when was the last time that it was modified as well as two uint256 that determines the first and last item to check.

### ReceiveCheckpoint

Contains the detail of each received transaction, being the amount queued and the timestamp when it was added to the queue.

### HUNDRED

Used in order to calculate percentages. Constant value of 100.

### dexTranferThreshold

It contains the amount of tokens to consider as a threshold over the unsettled tokens when transferring to a Decentralized exchange.

### settlementTimeLock

It refers to the amount in time in seconds that it has to pass between the proposal of a settlement period change for a certain LERC20 token and the time of execution.

### dexList

List containing all the set Decentralized exchanges addresses.

### whitelist

List containing all the set Whitelisted addresses mainly being the Lossless Smart Contracts and environment.

### blacklist

List containing all the set Blacklistedaddresses mainly being the correctly reported addresses.

### tokenConfig

It associates an LERC20 token with a list of variables corresponding to their particular configuration and needed data via the TokenConfig structure.

### TokenConfig

It contains a set of variables corresponding to certain configurations of a LERC20 token.

* uint256 tokenLockTimeframe - Settlement Period of the tokens in seconds
* uint256 proposedTokenLockTimeframe - Settlement period change proposal in seconds
* uint256 changeSettlementTimelock - Settlement Timelock change proposal in seconds
* uint256 emergencyMode - Timestamp of when the emergencyMode got active.

## Modifiers

* `onlyLosslessAdmin()`
* `onlyPauseAdmin()`
* `onlyLosslessRecoveryAdmin()`
* `onlyGuardian()`
* `onlyLosslessEnv()`

### onlyLosslessAdmin()

This modifiers ensures that the wrapped method can only be executed by the `Lossless Admin`

### onlyPauseAdmin()

This modifiers ensures that the wrapped method can only be executed by the `Pause Admin`

### onlyLosslessRecoveryAdmin()

This modifiers ensures that the wrapped method can only be executed by the `Recovery Admin`

### onlyGuardian()

This modifiers ensures that the wrapped method can only be executed by the `Guardian`

### onlyLosslessEnv()

This modifier ensures that the wrapped method can only be executed by the `Lossless Environment`

## Events

* `AdminChange(address indexed _newAdmin)`
* `RecoveryAdminChange(address indexed _newAdmin);`
* `PauseAdminChange(address indexed _newAdmin);`
* `GuardianSet(address indexed _oldGuardian, address indexed _newGuardian);`
* `NewProtectedAddress(ILERC20 indexed _token, address indexed _protectedAddress, address indexed _strategy);`
* `RemovedProtectedAddress(ILERC20 indexed _token, address indexed _protectedAddress);`
* `NewSettlementPeriodProposal(ILERC20 indexed _token, uint256 _seconds);`
* `SettlementPeriodChange(ILERC20 indexed _token, uint256 _proposedTokenLockTimeframe);`
* `NewSettlementTimelock(uint256 indexed _timelock);`
* `NewDexThreshold(uint256 indexed _newThreshold);`
* `NewDex(address indexed _dexAddress);`
* `DexRemoval(address indexed _dexAddress);`
* `NewWhitelistedAddress(address indexed _whitelistAdr);`
* `WhitelistedAddressRemoval(address indexed _whitelistAdr);`
* `NewBlacklistedAddress(address indexed _blacklistedAddres);`
* `AccountBlacklistRemoval(address indexed _adr);`
* `NewStakingContract(ILssStaking indexed _newAdr);`
* `NewReportingContract(ILssReporting indexed _newAdr);`
* `NewGovernanceContract(ILssGovernance indexed _newAdr);`
* `EmergencyActive(ILERC20 indexed _token);`
* `EmergencyDeactivation(ILERC20 indexed _token);`
* `NewMint(ILERC20 indexed token, address indexed account, uint256 indexed amount);`
* `NewMintLimit(ILERC20 indexed token, uint256 indexed limit);`
* `NewMintPeriod(ILERC20 indexed token, uint256 indexed period);`
* `NewBurn(ILERC20 indexed token, address indexed account, uint256 indexed amount);`
* `NewBurnLimit(ILERC20 indexed token, uint256 indexed limit);`
* `NewBurnPeriod(ILERC20 indexed token, uint256 indexed period);`
* `NewExtraordinaryPeriod(uint256 indexed extraordinaryRetrievalProposalPeriod);`

## Functions

* `pause()`
* `unpause()`
* `getVersion()`
* `setAdmin()`
* `setRecoveryAdmin()`
* `setPauseAdmin()`
* `setDexTransferThreshold()`
* `addToBlacklist()`
* `resolvedNegatively()`
* `activateEmergency()`
* `deactivateEmergency()`
* `getLockedAmount()`
* `getAvailableAmount()`
* `retrieveBlacklistedFunds()`
* `setStakingContractAddress()`
* `setReportingContractAddress()`
* `setGovernanceContractAddress()`
* `setDexList()`
* `setWhitelist()`
* `setSettlementTimeLock()`
* `proposeNewSettlementPeriod()`
* `executeNewSettlementPeriod()`
* `beforeTransfer()`
* `beforeTransferFrom()`
* `beforeMint()`
* `beforeApprove()`
* `beforeBurn()`
* `beforeIncreaseAllowance()`
* `beforeDecreaseAllowance()`
* `afterMint()`
* `afterApprove()`
* `afterBurn()`
* `afterIncreaseAllowance()`
* `afterDecreaseAllowance()`
* `afterTransfer()`
* `afterTransferFrom()`
* `isAddressProtected()`
* `getProtectedAddressStrategy()`
* `setGuardian()`
* `setProtectedAddress()`
* `removeProtectedAddress()`

### pause

```solidity
function pause() external onlyPauseAdmin
```

Sets the pause flag to true which in turn pauses some of the contracts functionality. Can be called only by the `pauseAdmin`.

### unpause

```solidity
function unpause() external onlyPauseAdmin
```

Sets the pause flag to false which in turn unpauses some of the contracts functionality. Can be called only by the `pauseAdmin`.

### getVersion()

```solidity
function getVersion() external pure returns (uint256)
```

This method returns the version of the smart contract.

### setAdmin

```solidity
function setAdmin(address newAdmin) external onlyLosslessRecoveryAdmin
```

Sets `admin` address. Can be called only by `recoveryAdmin`.

Parameters:

| Name       | Type    | Description        |
| ---------- | ------- | ------------------ |
| `newAdmin` | address | New admin address. |

### setRecoveryAdmin

```solidity
function setRecoveryAdmin(address newRecoveryAdmin) external onlyLosslessRecoveryAdmin
```

Sets `recoveryAdmin` address. Can be called only by `recoveryAdmin`.

Parameters:

| Name               | Type    | Description                 |
| ------------------ | ------- | --------------------------- |
| `newRecoveryAdmin` | address | New recovery admin address. |

### setPauseAdmin

```solidity
function setPauseAdmin(address newPauseAdmin) external onlyLosslessRecoveryAdmin
```

Sets `pauseAdmin` address. Can be called only by `recoveryAdmin`.

Parameters:

| Name            | Type    | Description              |
| --------------- | ------- | ------------------------ |
| `newPauseAdmin` | address | New pause admin address. |

### setDexTransferThreshold()

```solidity
function setDexTransferThreshold(uint256 _newThreshold) override public onlyLosslessAdmin
```

Sets the transfer threshold for Dexes. Can be called by `admin`

| Name            | Type    | Description           |
| --------------- | ------- | --------------------- |
| `_newThreshold` | uint256 | New threshold amount. |

### addToBlacklist()

```solidity
function addToBlacklist(address _adr) override public onlyLosslessEnv
```

This functions adds an address to the Blacklist. It’s called by `losslessReporting`

| Name   | Type    | Description           |
| ------ | ------- | --------------------- |
| `_adr` | address | Address to blacklist. |

### resolvedNegatively()

```solidity
function resolvedNegatively(address _adr) override public onlyLosslessEnv
```

This functions removes an address to the Blacklist. It’s called by `losslessGovernance` Smart Contract when a report gets solved negatively.

| Name   | Type    | Description                       |
| ------ | ------- | --------------------------------- |
| `_adr` | address | Address to remove from blacklist. |

### activateEmergency()

```solidity
function activateEmergency(ILERC20 _token) override external onlyLosslessEnv
```

This function activates the emergency mode. It is called by the `losslessReporting` Smart Contract when generating a report.

When a report gets generated for a token, it enters an emergency state globally.

The emergency period will be active for one settlement period.

During this time users can only transfer settled tokens

| Name     | Type    | Description                         |
| -------- | ------- | ----------------------------------- |
| `_token` | ILERC20 | Token address to activate emergency |

### deactivateEmergency()

```solidity
function deactivateEmergency(ILERC20 _token) override external onlyLosslessEnv
```

This function activates the emergency mode. Called by `losslessGovernance`

| Name     | Type    | Description                           |
| -------- | ------- | ------------------------------------- |
| `_token` | ILERC20 | Token address to deactivate emergency |

### getLockedAmount()

```solidity
function getLockedAmount(ILERC20 _token, address _adr) override external onlyLosslessEnv
```

This function will return the non-settled tokens amount of the address.

| Name     | Type    | Description                           |
| -------- | ------- | ------------------------------------- |
| `_token` | ILERC20 | Token address to deactivate emergency |
| `_adr`   | address | Address to remove from blacklist      |

### getAvailableAmount()

```solidity
function _getAvailableAmount(ILERC20 _token, address account) private returns (uint256 amount)
```

This function will calculate the available amount that an address has to transfer.

| Name     | Type    | Description                           |
| -------- | ------- | ------------------------------------- |
| `_token` | ILERC20 | Token address to deactivate emergency |
| `_adr`   | address | Address to remove from blacklist      |

### retrieveBlacklistedFunds()

```solidity
function retrieveBlacklistedFunds(address[] calldata _addresses, ILERC20 _token, uint256 _reportId) override public onlyLosslessEnv returns(uint256)
```

This function retrieves the funds of the reported account. It is called from the Lossless Governance Smart Contract when the report gets solved positively.

| Name         | Type          | Description                               |
| ------------ | ------------- | ----------------------------------------- |
| `_addresses` | Address array | Array of addresses to retrieve funds from |
| `_token`     | ILERC20       | Token address to deactivate emergency     |
| `_reportId`  | uint256       | ID of the report                          |

### setStakingContractAddress()

```solidity
function setStakingContractAddress(ILssStaking _adr) override public onlyLosslessAdmin
```

Sets the Lossless Staking Smart Contract Address for interaction. Called by `admin`

| Name   | Type        | Description                           |
| ------ | ----------- | ------------------------------------- |
| `_adr` | ILssStaking | Address of the staking smart contract |

### setReportingContractAddress()

```solidity
function setReportingContractAddress(ILssReporting _adr) override public onlyLosslessAdmin
```

Sets the Lossless Reporting Smart Contract Address for interaction. Called by `admin`

| Name   | Type          | Description                             |
| ------ | ------------- | --------------------------------------- |
| `_adr` | ILssReporting | Address of the Reporting smart contract |

### setGovernanceContractAddress()

```solidity
function setGovernanceContractAddress(ILssGovernance _adr) override public onlyLosslessAdmin
```

Sets the Lossless Governance Smart Contract Address for interaction. Called by `admin`

| Name   | Type           | Description                              |
| ------ | -------------- | ---------------------------------------- |
| `_adr` | ILssGovernance | Address of the Governance smart contract |

### setDexList()

```solidity
function setDexList(address[] calldata _dexList, bool _value) override public onlyLosslessAdmin
```

If list is provide together with value `true` all addresses from the list should be included in the DEX list.

If list is provided together with value `false` all addresses from the list should not be included in the DEX list.

DEX list plays important part in the settlement period functionality.

Called by `admin`

| Name       | Type          | Description                               |
| ---------- | ------------- | ----------------------------------------- |
| `_dexList` | Address array | Array of addresses to add to the dex list |
| `_value`   | bool          | Add or remove from Dex List               |

### setWhitelist()

```solidity
function setWhitelist(address[] calldata _addrList, bool _value) override public onlyLosslessAdmin
```

If list is provide together with value `true` all addresses from the list should be included in the whitelist list.

If list is provided together with value `false` all addresses from the list should not be included in the whitelist list.

Whitelisted addresses cannot be reporter and are entitled to some other benefits.

Called by `admin`

| Name        | Type          | Description                                |
| ----------- | ------------- | ------------------------------------------ |
| `_addrList` | Address array | Array of addresses to add to the whitelist |
| `_value`    | bool          | Add or remove from Dex List                |

### setSettlementTimeLock()

```solidity
function setSettlementTimeLock(uint256 _newTimelock) override public onlyLosslessAdmin
```

Provided value is used to set settlement timelock. This timelock is used when Token Admin wants to change the settlement period changes.

Called by `admin`

| Name           | Type   | Description             |
| -------------- | ------ | ----------------------- |
| `_newTimelock` | uin256 | New settlement Timelock |

### proposeNewSettlementPeriod()

```solidity
function proposeNewSettlementPeriod(ILERC20 _token, uint256 _seconds) override public onlyTokenAdmin(_token)
```

| Name       | Type    | Description                        |
| ---------- | ------- | ---------------------------------- |
| `_token`   | ILERC20 | Token address to create a proposal |
| `_seconds` | uin256  | New proposed settlement period     |

Called by `LERC20 admins`

First provided value defines for which token these setting should be applied.

Period time is used by the settlement period functionality.

If period time is 0 settlement period is off and no rules should be executed.

This proposal is set and can be executed after settlement timelock is over. Settlement timelock start after the proposal is proposed.

* **Tokens Settlement**

1. Tokens Settlement Feature enables Lossless Protocol to stop hacks that both steal the tokens and sell them on a DEX in a single transaction.
2. Tokens Settlement Feature can be enabled and disabled for each token separately by the token admin.
3. Tokens Settlement Feature requires token admin to set settlement period variable.
4. Tokens Settlement Feature works in two different ways when emergency mode is on and off.
5. Tokens settlement feature works like this:
   * Tokens owned by any address are divided into to type of tokens:
     * settled tokens
     * unsettled tokens
   * Transferring of settled tokens is not impacted in any way. Transferring settled tokens is the same as transferring any standard ERC20 token - it’s permissionless and has no checks. (Except those implement by Lossless Vault and Treasury Protection Protocol).
   * Transferring of unsettled tokens however has a ruleset that defines when, where and how many of these tokens can be transferred.
   * When emergency mode is off (which is the case most of the time)
     * If unsettled tokens are being transferred to a decentralised exchange or any other address that is in dex list, these rules apply:
     * If amount of unsettled tokens being transferred to an address that is in dex list is below or equal to dex threshold transaction is allowed to go through.
     * If amount of unsettled tokens being transferred to an address that is in dex list is above dex threshold transaction fails.
   * If unsettled tokens are being transferred to a address that is in not in dex list, these rules apply:
     1. If this is the first transfer of unsettled tokens per settlement period transaction is allowed to go through.
     2. If this is not the first transfer of unsettled tokens per settlement period transaction fails.
   * When emergency mode is on:
     * None of the unsettled tokens can be transferred. No matter if the receiver is in dex list or not. No matter if amount of tokens being transferred is above or above dex threshold.

* **Emergency mode**

1. Emergency mode is boolean flag that can either be on or off.
2. It is scoped in a particular token, meaning that while emergency mode is turned on for one token it could be turned off for another token.
3. It gets turned on initial report is submitted by the finder.
4. While it is on, Tokens Settlement Feature works in a different way that it usually does (check that part of documentation for the specifics)
5. Emergency mode should be turned off after one settlement period after the initial report fast submitted.

### executeNewSettlementPeriod()

```solidity
function executeNewSettlementPeriod(ILERC20 _token) override public onlyTokenAdmin(_token)
```

This activates the initially proposed new settlement period values. Called by `LERC20 admin`

| Name     | Type    | Description                         |
| -------- | ------- | ----------------------------------- |
| `_token` | ILERC20 | Token address to execute a proposal |

### beforeTransfer()

```solidity
function beforeTransfer(address _sender, address _recipient, uint256 _amount) override external
```

If address is protected, transfer validation rules have to be run inside the strategy. Also applies all restrictions for blacklisted addresses and settlement periods.

| Name        | Type    | Description                         |
| ----------- | ------- | ----------------------------------- |
| `sender`    | address | Sender's address.                   |
| `recipient` | address | Recipient's address.                |
| `amount`    | uint256 | Amount of tokens being transferred. |

### beforeTransferFrom()

```solidity
function beforeTransfer(address _sender, address _recipient, uint256 _amount) override external
```

If address is protected, transfer validation rules have to be run inside the strategy. Also applies all restrictions for blacklisted addresses and settlement periods.

| Name        | Type    | Description                                            |
| ----------- | ------- | ------------------------------------------------------ |
| `msgSender` | address | Address that triggered transfer from sender's address. |
| `sender`    | address | Sender's address.                                      |
| `recipient` | address | Recipient's address.                                   |
| `amount`    | uint256 | Amount of tokens being transferred.                    |

### beforeMint()

Placeholder for future logic.

### beforeApprove()

Placeholder for future logic.

### beforeBurn()

Placeholder for future logic.

### beforeIncreaseAllowance()

Placeholder for future logic.

### beforeDecreaseAllowance()

Placeholder for future logic.

### afterMint()

Placeholder to avoid breaking legacy interaction.

### afterApprove()

Placeholder to avoid breaking legacy interaction.

### afterBurn()

Placeholder to avoid breaking legacy interaction.

### afterIncreaseAllowance()

Placeholder to avoid breaking legacy interaction.

### afterDecreaseAllowance()

Placeholder to avoid breaking legacy interaction.

### afterTransfer()

Placeholder to avoid breaking legacy interaction.

### afterTransferFrom()

Placeholder to avoid breaking legacy interaction.

### isAddressProtected

```solidity
function isAddressProtected(address token, address protectedAddress) external view returns (bool)
```

Returns either true or false depending if the address has any protections set up on it.

Parameters:

### getProtectedAddressStrategy

```solidity
function getProtectedAddressStrategy(address token, address protectedAddress) external view returns (address)
```

Returns address of the strategy that the protected address is using. If address is not protected returns zero address.

Parameters:

| Name               | Type    | Description                                   |
| ------------------ | ------- | --------------------------------------------- |
| `token`            | address | Token for which the protection is set.        |
| `protectedAddress` | address | Address to check the protection strategy for. |

### setGuardian

```solidity
function setGuardian(address newGuardian) external onlyLosslessAdmin whenNotPaused
```

Sets `guardian` contract's address. Can be called only by `admin` when contract is not paused.

Parameters:

| Name          | Type    | Description                      |
| ------------- | ------- | -------------------------------- |
| `newGuardian` | address | New guardian contract's address. |

### setProtectedAddress

```solidity
function setProtectedAddress(address token, address protectedAddresss, ProtectionStrategy strategy) external onlyGuardian whenNotPaused
```

Sets token scoped protection on an address. Can be called only by the `guardian` when contract is not paused.

Parameters:

| Name               | Type               | Description                                                       |
| ------------------ | ------------------ | ----------------------------------------------------------------- |
| `token`            | address            | Token for which the protection rules should be applied.           |
| `protectedAddress` | address            | Address to protect.                                               |
| `strategy`         | ProtectionStrategy | Strategy address that should be used when protecting the address. |

### setProtectedAddress()

### removeProtectedAddress

```solidity
function removeProtectedAddress(address token, address protectedAddresss) external onlyGuardian whenNotPaused
```

Removes token scoped protection. Can be called only by `guardian` contract when contract is not paused.

Parameters:

| Name               | Type    | Description                                             |
| ------------------ | ------- | ------------------------------------------------------- |
| `token`            | address | Token for which the protection rules should be removed. |
| `protectedAddress` | address | Address to remove the protection from.                  |
