# Staking Pool

`StakingPool` is one of the most important pieces of the protocol as it handles the liquid staking of tokens. When a user stakes some amount of tokens (such as LINK), they receive liquid staking tokens (such as stLINK) at a 1:1 ratio. These liquid staking tokens represent a user’s staked balance and must be burned to withdraw the underlying tokens they represent.

Once tokens have been staked into the pool, they are deposited into one or more strategy contracts controlled by the pool. These strategies then take the deposited tokens and use them to earn rewards which are distributed to stakers.

*In the case of LINK staking, the tokens are deposited into the Chainlink staking contracts.*

The liquid staking token issued by `StakingPool` is a rebasing token so rewards will be automatically distributed to stakers without any action on their part. This is possible by using a “shares” accounting model where a share represents a certain percentage ownership of the pool. When a user stakes, they receive a number of shares determined by the ratio of total shares to total tokens in the pool. The amount of shares a user owns remains constant unless they stake or withdraw but the ratio of total shares to total tokens changes with each rebase so their shares will be worth more tokens after each rebase. The new token value of their shares will be automatically reflected in their token balance.

While unlikely, it is also possible for a rebase to be negative if strategies earned net negative rewards since the last rebase due to slashing penalties. In this case, each share will be worth less tokens so a user’s token balance will decrease.

## ERC20 Functions

All standard ERC20 functions are implemented for `StakingPool`

## View Functions

### token

Returns the staking token for the pool

```solidity
function token() external view returns (address)
```

#### Return Values

| Name  | Type    | Description              |
| ----- | ------- | ------------------------ |
| token | address | Address of staking token |

### priorityPool

Returns the address of the priority pool for this pool

```solidity
function priorityPool() external view returns (address)
```

#### Return Values

| Name         | Type    | Description              |
| ------------ | ------- | ------------------------ |
| priorityPool | address | address of priority pool |

### totalShares

Returns the total amount of shares in the pool

```solidity
function totalShares() external view returns (uint256)
```

#### Return Values

| Name         | Type    | Description              |
| ------------ | ------- | ------------------------ |
| sharesAmount | uint256 | Total shares in the pool |

### sharesOf

Returns the amount of shares owned by an account

```solidity
function sharesOf(address _account) public view returns (uint256)
```

#### Parameters

| Name      | Type    | Description        |
| --------- | ------- | ------------------ |
| \_account | address | Address of account |

#### Return Values

| Name          | Type    | Description                   |
| ------------- | ------- | ----------------------------- |
| sharesBalance | uint256 | Total shares owned by account |

### getSharesByStake

Returns the amount of shares that corresponds to an amount of stake

```solidity
function getSharesByStake(uint256 _amount) public view returns (uint256)
```

#### Parameters

| Name     | Type    | Description     |
| -------- | ------- | --------------- |
| \_amount | uint256 | Amount of stake |

#### Return Values

| Name         | Type    | Description                    |
| ------------ | ------- | ------------------------------ |
| sharesAmount | uint256 | Corresponding amount of shares |

### getStakeByShares

Returns the amount of stake that corresponds to an amount of shares

```solidity
function getStakeByShares(uint256 _amount) public view returns (uint256)
```

#### Parameters

| Name     | Type    | Description      |
| -------- | ------- | ---------------- |
| \_amount | uint256 | Amount of shares |

#### Return Values

| Name        | Type    | Description                   |
| ----------- | ------- | ----------------------------- |
| stakeAmount | uint256 | Corresponding amount of stake |

### totalStaked

Returns the total amount of tokens in the pool

```solidity
function totalStaked() external view returns (uint256)
```

#### Return Values

| Name         | Type    | Description              |
| ------------ | ------- | ------------------------ |
| stakedAmount | uint256 | Total tokens in the pool |

### getStrategies

Returns a list of all active strategies

```solidity
function getStrategies() external view returns (address[])
```

#### Return Values

| Name       | Type       | Description                         |
| ---------- | ---------- | ----------------------------------- |
| strategies | address\[] | List of strategy contract addresses |

### getFees

Returns a list of all fees

```solidity
function getFees() external view returns (struct StakingPool.Fee[])
```

#### Return Values

| Name | Type          | Description  |
| ---- | ------------- | ------------ |
| fees | struct Fee\[] | list of fees |

### getMaxDeposits

Returns the maximum amount of tokens that the pool can hold

```solidity
function getMaxDeposits() public view returns (uint256)
```

#### Return Values

| Name        | Type    | Description           |
| ----------- | ------- | --------------------- |
| maxDeposits | uint256 | maximum deposit limit |

### getMinDeposits

Returns the minimum amount of tokens that must remain in the pool

```solidity
function getMinDeposits() public view returns (uint256)
```

#### Return Values

| Name        | Type    | Description           |
| ----------- | ------- | --------------------- |
| minDeposits | uint256 | minimum deposit limit |

### getUnusedDeposits

Returns the amount of unused asset tokens sitting in this pool outside a strategy

*These tokens earn no yield and will be deposited ASAP on the next call to \_depositLiquidity*

```solidity
function getUnusedDeposits() external view returns (uint256)
```

#### Return Values

| Name           | Type    | Description             |
| -------------- | ------- | ----------------------- |
| unusedDeposits | uint256 | amount of unused tokens |

### getStrategyDepositRoom

Returns the sum of available deposit room across all strategies

*Does not account for unused deposits sitting in pool*

```solidity
function getStrategyDepositRoom() external view returns (uint256)
```

#### Return Values

| Name                | Type    | Description                          |
| ------------------- | ------- | ------------------------------------ |
| strategyDepositRoom | uint256 | available deposit room in strategies |

### canDeposit

Returns the total available deposit room for this pool

*Accounts for unused deposits sitting in pool*

```solidity
function canDeposit() external view returns (uint256)
```

#### Return Values

| Name       | Type    | Description            |
| ---------- | ------- | ---------------------- |
| canDeposit | uint256 | available deposit room |

### canWithdraw

Returns the total available withdrawal room for this pool

```solidity
function canWithdraw() external view returns (uint256)
```

#### Return Values

| Name        | Type    | Description               |
| ----------- | ------- | ------------------------- |
| canWithdraw | uint256 | available withdrawal room |

### getStrategyRewards

Returns the amount of rewards earned since the last call to updateStrategyRewards and the\
amount of fees that will be paid on the rewards

```solidity
function getStrategyRewards(uint256[] _strategyIdxs) external view returns (int256, uint256)
```

#### Parameters

| Name           | Type       | Description                                   |
| -------------- | ---------- | --------------------------------------------- |
| \_strategyIdxs | uint256\[] | Indexes of strategies to sum rewards/fees for |

#### Return Values

| Name    | Type    | Description   |
| ------- | ------- | ------------- |
| rewards | int256  | Total rewards |
| fees    | uint256 | Total fees    |

## Write Functions

### deposit

Deposits staking tokens and mints liquid staking tokens

```solidity
function deposit(address _account, uint256 _amount, bytes _data) external
```

#### Parameters

| Name      | Type    | Description                               |
| --------- | ------- | ----------------------------------------- |
| \_account | address | address of account to stake for           |
| \_amount  | uint256 | amount to stake                           |
| \_data    | bytes   | list of deposit data passed to strategies |

### withdraw

Withdraws staking tokens and burns liquid staking tokens

```solidity
function withdraw(address _account, address _receiver, uint256 _amount, bytes _data) external
```

#### Parameters

| Name       | Type    | Description                                  |
| ---------- | ------- | -------------------------------------------- |
| \_account  | address | Address of account to withdraw for           |
| \_receiver | address | Address to receive withdrawal                |
| \_amount   | uint256 | Amount to withdraw                           |
| \_data     | bytes   | list of withdrawal data passed to strategies |

### transferAndCall

Transfers tokens to an address and calls `onTokenTransfer` with additional data if the recipient is a contract

```solidity
function transferAndCall(address _to, uint256 _value, bytes _data) external returns (bool)
```

#### Parameters

| Name    | Type    | Description                       |
| ------- | ------- | --------------------------------- |
| \_to    | address | Address to send the tokens to     |
| \_value | uint256 | Value of token transfer           |
| \_data  | bytes   | Calldata included in the transfer |

### strategyDeposit

Manually deposits asset tokens into a specific strategy

```solidity
function strategyDeposit(uint256 _index, uint256 _amount) external
```

#### Parameters

| Name     | Type    | Description       |
| -------- | ------- | ----------------- |
| \_index  | uint256 | Index of strategy |
| \_amount | uint256 | Amount to deposit |

### strategyWithdraw

Manually withdraws asset tokens from a strategy

```solidity
function strategyWithdraw(uint256 _index, uint256 _amount) external
```

#### Parameters

| Name     | Type    | Description        |
| -------- | ------- | ------------------ |
| \_index  | uint256 | Index of strategy  |
| \_amount | uint256 | Amount to withdraw |

### addStrategy

Adds a new strategy

```solidity
function addStrategy(address _strategy) external
```

#### Parameters

| Name       | Type    | Description                  |
| ---------- | ------- | ---------------------------- |
| \_strategy | address | Address of strategy contract |

### removeStrategy

Removes a strategy

```solidity
function removeStrategy(uint256 _index, bytes _strategyUpdateData, bytes _strategyWithdrawalData) external
```

#### Parameters

| Name                     | Type    | Description                        |
| ------------------------ | ------- | ---------------------------------- |
| \_index                  | uint256 | Index of strategy                  |
| \_strategyUpdateData     | bytes   | update data passed to strategy     |
| \_strategyWithdrawalData | bytes   | withdrawal data passed to strategy |

### reorderStrategies

Reorders strategies

```solidity
function reorderStrategies(uint256[] _newOrder) external
```

#### Parameters

| Name       | Type       | Description                                     |
| ---------- | ---------- | ----------------------------------------------- |
| \_newOrder | uint256\[] | List containing strategy indexes in a new order |

### addFee

Adds a new fee

```solidity
function addFee(address _receiver, uint256 _feeBasisPoints) external
```

#### Parameters

| Name             | Type    | Description             |
| ---------------- | ------- | ----------------------- |
| \_receiver       | address | Address of fee receiver |
| \_feeBasisPoints | uint256 | Fee in basis points     |

### updateFee

Updates an existing fee

```solidity
function updateFee(uint256 _index, address _receiver, uint256 _feeBasisPoints) external
```

#### Parameters

| Name             | Type    | Description             |
| ---------------- | ------- | ----------------------- |
| \_index          | uint256 | Index of fee            |
| \_receiver       | address | Address of fee receiver |
| \_feeBasisPoints | uint256 | Fee in basis points     |

### updateStrategyRewards

Distributes rewards/fees based on balance changes in strategies since the last update

```solidity
function updateStrategyRewards(uint256[] _strategyIdxs, bytes _data) public
```

#### Parameters

| Name           | Type       | Description                                 |
| -------------- | ---------- | ------------------------------------------- |
| \_strategyIdxs | uint256\[] | Indexes of strategies to update rewards for |
| \_data         | bytes      | update data passed to each strategy         |

### transferShares

Transfers shares from the sender to another account

```solidity
function transferShares(address _receipient, uint256 _sharesAmount) external
```

#### Parameters

| Name           | Type    | Description                   |
| -------------- | ------- | ----------------------------- |
| \_receipient   | address | account to transfer shares to |
| \_sharesAmount | uint256 | amount of shares to transfer  |

### transferShares

Transfers shares between accounts

```solidity
function transferSharesFrom(address _sender, address _receipient, uint256 _sharesAmount) external
```

#### Parameters

| Name           | Type    | Description                     |
| -------------- | ------- | ------------------------------- |
| \_sender       | address | account to transfer shares from |
| \_receipient   | address | account to transfer shares to   |
| \_sharesAmount | uint256 | amount of shares to transfer    |

### setPriorityPool

Sets the address of the priority pool

```solidity
function setPriorityPool(address _priorityPool) external
```

#### Parameters

| Name           | Type    | Description              |
| -------------- | ------- | ------------------------ |
| \_priorityPool | address | address of priority pool |

### setUnusedDepositLimit

Sets the maximum amount of unused deposits that can sit in the pool

```solidity
function setUnusedDepositLimit(uint256 _unusedDepositLimit) external
```

#### Parameters

| Name                 | Type    | Description                       |
| -------------------- | ------- | --------------------------------- |
| \_unusedDepositLimit | uint256 | maximum amount of unused deposits |

### setRebaseController

Sets the address of the rebase controller

```solidity
function setRebaseController(address _rebaseController) external
```

#### Parameters

| Name               | Type    | Description                  |
| ------------------ | ------- | ---------------------------- |
| \_rebaseController | address | address of rebase controller |

### burn

Burns the sender's liquid staking tokens, effectively donating their underlying stake to the pool

```solidity
function burn(uint256 _amount) external
```

#### Parameters

| Name     | Type    | Description    |
| -------- | ------- | -------------- |
| \_amount | uint256 | amount to burn |

### donateTokens

Deposits asset tokens into the pool without minting liquid staking tokens, effectively donating them to the pool

```solidity
function donateTokens(uint256 _amount) external
```

#### Parameters

| Name     | Type    | Description       |
| -------- | ------- | ----------------- |
| \_amount | uint256 | amount to deposit |
