# Lossless Staking

This contract manages all staking done over reports.

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

## Variables

* `stakes`
* `Stake`
* `StakeInfo`
* `stakingToken`
* `losslessReporting`
* `losslessGovernance`
* `losslessController`
* `stakingAmount`
* `HUNDRED`
* `MILLION`
* `reportCoefficient`
* `stakedOnReport`
* `PerReportAmount`

### stakes

It contains all the stakes done over a report Id by an address via the Stake structure.

### Stake

It contains all the stake info made by an address related to a report Id via the StakeInfo structure.

### StakeInfo

It contains all the information related to a stake made on a report using the following variables:

* `uint256 timestamp` - Timestamp of the stake
* `uint256 coefficient` - Address coefficient utilized to calculate the rewards
* `uint256 totalStakedOnReport` - Amount staked on the report
* `bool staked` - Indicator if the address has staked
* `bool payed` - Indicator if the address has claimed the rewards

### stakingToken

It refers to the address of the LERC20 token used for staking porpouses.

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

### losslessController

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

### stakingAmount

It refers to the amount of tokens needed to generate a stake.

### HUNDRED

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

### MILLION

Used in order to calculate more precise amount. Constant value of 1000000.

### reportCoefficient

It contains the total coefficient of a report in order to calculate individual stakers rewards.

### stakedOnReport

It contains the total amount staked per report associated with a report Id over the PerReportAmount structure.

### PerReportAmount

It contains a mapping that associates a report Id with the total amount staked on the report.

## Modifiers

* `onlyLosslessAdmin()`
* `onlyPauseAdmin()`
* `notBlacklisted()`

### 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

### notBlacklisted()

This modifiers ensures that the wrapped method can only be executed by an address that is not blacklisted.

## Events

* `NewStake(ILERC20 indexed _token, address indexed _account, uint256 indexed _reportId);`
* `StakerClaim(address indexed _staker, ILERC20 indexed _token, uint256 indexed _reportID, uint256 _amount);`
* `NewStakingAmount(uint256 indexed _newAmount);`
* `NewStakingToken(ILERC20 indexed _newToken);`
* `NewReportingContract(ILssReporting indexed _newContract);`
* `NewGovernanceContract(ILssGovernance indexed _newContract);`

## Functions

* `stake()`
* `stakerClaim()`
* `pause()`
* `unpause()`
* `getVersion()`
* `setStakingToken()`
* `setStakingAmount()`
* `setLssReporting()`
* `setLosslessGovernance()`
* `stakerClaimableAmount()`
* `getIsAccountStaked()`
* `getStakerCoefficient()`

### stake()

```solidity
function stake(uint256 _reportId) override public notBlacklisted whenNotPaused
```

Community stake amount is transferred from the staker’s address to lossless protocol.

Stake info is saved for further references. Stake info must contain stake coefficient **(SC)**. Stake coefficient is calculated like this:

(time when the report was submitted + report lifetime) - time when the stake was submitted.

The sooner the stake is made after the report is submitted the higher coefficient it gets.

| Name        | Type    | Description            |
| ----------- | ------- | ---------------------- |
| `_reportId` | Uint256 | Report Id to stake on. |

### stakerClaim()

```solidity
function stakerClaim(uint256 _reportId) override public whenNotPaused
```

This feature should send part of the retrieved funds (RF) and all community stake amount (CSA) staker’s address.

**CSA** is sent in **staking tokens**. Staker gets back his initially staked tokens back.

Stakers Reward Percentage **(SRP)** is percentage that describes what part of all retrieved funds should be sent to all stakers combined.

* **SRP** is set and controller by Lossless Team

Stakers Reward **(SW)** is how many token the staker receives after the report is resolved positively.

`SW = (RF * SRP)`

Every staker receives only a part of the SW depending on what is his stake coefficient **(SC)**.

One staker’s claimable reward (SWi) is calculated by dividing SW by the sum of all stakers coefficients and multiplying the result by the particular SCi .

`SW(i) = SW / (SC(1) + SC(2) + ... + SC(n)) * SC(i)`

All in all, after the staker claims his reward he should receive both SWi and CSA.

| Name        | Type    | Description                         |
| ----------- | ------- | ----------------------------------- |
| `_reportId` | Uint256 | Report Id to claim staking rewards. |

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

### setStakingToken()

```solidity
function setStakingToken(ILERC20 _stakingToken) override public onlyLosslessAdmin
```

Provided address is used to set new stake token.

Stake token is used in many parts of the protocol.

Called by `Lossless Admin`

| Name            | Type    | Description            |
| --------------- | ------- | ---------------------- |
| `_stakingToken` | ILERC20 | Staking token address. |

### setStakingAmount()

```solidity
function setStakingAmount(uint256 _stakingAmount) override public onlyLosslessAdmin
```

Provided value is used to set report stake amount **(RSA)**.

Called by `Lossless Admin`

| Name             | Type    | Description         |
| ---------------- | ------- | ------------------- |
| `_stakingAmount` | Uint256 | New staking amount. |

### setLssReporting()

```solidity
function setLssReporting(ILssReporting _losslessReporting) override public onlyLosslessAdmin
```

Sets the Lossless Reporting Address to allow interaction.

Called by `Lossless Admin`

| Name                 | Type          | Description                                |
| -------------------- | ------------- | ------------------------------------------ |
| `_losslessReporting` | ILssReporting | Lossless Reporting Smart Contract Address. |

### setLosslessGovernance()

```solidity
function setLosslessGovernance(ILssGovernance _losslessGovernance) override public onlyLosslessAdmin
```

Sets the Lossless Governance Address to allow interaction.

Called by `Lossless Admin`

| Name                  | Type           | Description                                 |
| --------------------- | -------------- | ------------------------------------------- |
| `_losslessGovernance` | ILssGovernance | Lossless Governance Smart Contract Address. |

### stakerClaimableAmount()

```solidity
function stakerClaimableAmount(uint256 _reportId) override public view returns (uint256)
```

Calculates and returns the claimable amount by the stakers

| Name                                                                                                  | Type    | Description                          |
| ----------------------------------------------------------------------------------------------------- | ------- | ------------------------------------ |
| `_reportId`                                                                                           | Uint256 | Report Id to check claimable amount. |
| ### getIsAccountStaked()                                                                              |         |                                      |
| \`\`\`solidity                                                                                        |         |                                      |
| function getIsAccountStaked(uint256 \_reportId, address \_account) override public view returns(bool) |         |                                      |
| \`\`\`                                                                                                |         |                                      |

Returns if an address is already staking on a report

| Name        | Type    | Description                                  |
| ----------- | ------- | -------------------------------------------- |
| `_reportId` | Uint256 | Report Id to check if an address is staking. |
| `_account`  | address | Address to verify if it's staked.            |

### getStakerCoefficient()

```solidity
function getStakerCoefficient(uint256 _reportId, address _address) override public view returns (uint256)
```

Returns the coefficient of a staker in a report

| Name        | Type    | Description                       |
| ----------- | ------- | --------------------------------- |
| `_reportId` | Uint256 | Report Id to get the coefficient. |
| `_address`  | address | Address to get the coefficient.   |
