# StakeManager

## Contents

## Globals

| Var               | Type                                 |
| ----------------- | ------------------------------------ |
| validatorId       | uint256                              |
| validators        | mapping(address => struct Validator) |
| unstakeId         | uint256                              |
| unstakeQueue      | mapping(uint256 => struct Unstake)   |
| totalLockedAmount | uint256                              |
| activeValidators  | struct ActiveValidator\[]            |
| proposer          | address                              |

## Modifiers

### onlyRouterOrFeePool

No description

**Declaration:**

```solidity
  modifier onlyRouterOrFeePool
```

## Functions

### constructor

No description

**Declaration:**

```solidity
  function constructor(
  ) public Only
```

**Modifiers:**

| Modifier |
| -------- |
| Only     |

### indexedValidatorsLength

Get the indexed validators length.

**Declaration:**

```solidity
  function indexedValidatorsLength(
  ) external returns (uint256)
```

**Modifiers:** No modifiers

### indexedValidatorsExists

Determine whether the index validator exists by id.

**Declaration:**

```solidity
  function indexedValidatorsExists(
    uint256 id
  ) external returns (bool)
```

**Modifiers:** No modifiers

**Args:**

| Arg  | Type    | Description      |
| ---- | ------- | ---------------- |
| `id` | uint256 | The validator id |

### indexedValidatorsByIndex

Get indexed validator address by index.

**Declaration:**

```solidity
  function indexedValidatorsByIndex(
    uint256 index
  ) external returns (address validator)
```

**Modifiers:** No modifiers

**Args:**

| Arg     | Type    | Description         |
| ------- | ------- | ------------------- |
| `index` | uint256 | The validator index |

### indexedValidatorsById

Get indexed validator address by id.

**Declaration:**

```solidity
  function indexedValidatorsById(
    uint256 id
  ) external returns (address)
```

**Modifiers:** No modifiers

**Args:**

| Arg  | Type    | Description      |
| ---- | ------- | ---------------- |
| `id` | uint256 | The validator id |

### getVotingPowerByIndex

Get the voting power by validator index, if index is out of range or validator doesn't exist, return 0.

**Declaration:**

```solidity
  function getVotingPowerByIndex(
    uint256 index
  ) external returns (uint256)
```

**Modifiers:** No modifiers

**Args:**

| Arg     | Type    | Description         |
| ------- | ------- | ------------------- |
| `index` | uint256 | The validator index |

### getVotingPowerById

Get the voting power by validator id, if doesn't exist, return 0.

**Declaration:**

```solidity
  function getVotingPowerById(
    uint256 id
  ) external returns (uint256)
```

**Modifiers:** No modifiers

**Args:**

| Arg  | Type    | Description      |
| ---- | ------- | ---------------- |
| `id` | uint256 | The validator id |

### getVotingPowerByAddress

Get the voting power by validator address, if the validator doesn't exist, return 0.

**Declaration:**

```solidity
  function getVotingPowerByAddress(
    address validator
  ) public returns (uint256)
```

**Modifiers:** No modifiers

**Args:**

| Arg         | Type    | Description       |
| ----------- | ------- | ----------------- |
| `validator` | address | Validator address |

### getTotalLockedAmountAndValidatorCount

Get the total locked amount and the validator count, but no including the `excludes`.

**Declaration:**

```solidity
  function getTotalLockedAmountAndValidatorCount(
    address[] excludes
  ) external returns (uint256 _totalLockedAmount, uint256 validatorCount)
```

**Modifiers:** No modifiers

**Args:**

| Arg        | Type       | Description        |
| ---------- | ---------- | ------------------ |
| `excludes` | address\[] | Excluded addresses |

### activeValidatorsLength

Get the active validators list length.

**Declaration:**

```solidity
  function activeValidatorsLength(
  ) external returns (uint256)
```

**Modifiers:** No modifiers

### estimateSharesToAmount

Estimate how much GXC should be stake, if user wants to get the number of shares, Or estimate how much GXC can be obtained, if user unstake the amount of GXC.

**Declaration:**

```solidity
  function estimateSharesToAmount(
    address validator,
    uint256 shares
  ) public returns (uint256 amount)
```

**Modifiers:** No modifiers

**Args:**

| Arg         | Type    | Description       |
| ----------- | ------- | ----------------- |
| `validator` | address | Validator address |
| `shares`    | uint256 | Number of shares  |

### estimateAmountToShares

Estimate how much shares should be unstake, if user wants to get the amount of GXC. Or estimate how much shares can be obtained, if user stake the amount of GXC. If the validator doesn't exist, return 0.

**Declaration:**

```solidity
  function estimateAmountToShares(
    address validator,
    uint256 amount
  ) public returns (uint256 shares)
```

**Modifiers:** No modifiers

**Args:**

| Arg         | Type    | Description       |
| ----------- | ------- | ----------------- |
| `validator` | address | Validator address |
| `amount`    | uint256 | Number of GXC     |

### estimateUnstakeAmount

Estimate how much GXC can be claim, if unstake the number of shares(when unstake timeout). If the validator doesn't exist, return 0.

**Declaration:**

```solidity
  function estimateUnstakeAmount(
    address validator,
    uint256 shares
  ) external returns (uint256 amount)
```

**Modifiers:** No modifiers

**Args:**

| Arg         | Type    | Description       |
| ----------- | ------- | ----------------- |
| `validator` | address | Validator address |
| `shares`    | uint256 | Number of shares  |

### receive

No description

**Declaration:**

```solidity
  function receive(
  ) external
```

**Modifiers:** No modifiers

### stake

Stake for validator and mint share token to `to` address. It will emit `Stake` event.

**Declaration:**

```solidity
  function stake(
    address validator,
    address to
  ) external nonReentrant returns (uint256 shares)
```

**Modifiers:**

| Modifier     |
| ------------ |
| nonReentrant |

**Args:**

| Arg         | Type    | Description       |
| ----------- | ------- | ----------------- |
| `validator` | address | Validator address |
| `to`        | address | Receiver address  |

### startUnstake

Start unstake shares for validator. Stake manager will burn the shares immediately, but return GXC to `to` address after `config.unstakeDelay`. It will emit `StartUnstake` event.

**Declaration:**

```solidity
  function startUnstake(
    address validator,
    address payable to,
    uint256 shares
  ) external nonReentrant returns (uint256)
```

**Modifiers:**

| Modifier     |
| ------------ |
| nonReentrant |

**Args:**

| Arg         | Type            | Description                   |
| ----------- | --------------- | ----------------------------- |
| `validator` | address         | Validator address             |
| `to`        | address payable | Receiver address              |
| `shares`    | uint256         | Number of shares to be burned |

**Returns:**

| Type                                                                                                                                | Description                                |
| ----------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
| `Unstake`                                                                                                                           | id(if amount is zero, return MAX\_UINT256) |
| ### startClaim                                                                                                                      |                                            |
| Start claim validator reward.                                                                                                       |                                            |
| Stake manager will claim GXC from validator reward manager immediately, but return GXC to `to` address after `config.unstakeDelay`. |                                            |
| It will emit `StartUnstake` event.                                                                                                  |                                            |

**Declaration:**

```solidity
  function startClaim(
    address payable to,
    uint256 amount
  ) external nonReentrant returns (uint256)
```

**Modifiers:**

| Modifier     |
| ------------ |
| nonReentrant |

**Args:**

| Arg      | Type            | Description      |
| -------- | --------------- | ---------------- |
| `to`     | address payable | Receiver address |
| `amount` | uint256         | Number of GXC    |

**Returns:**

| Type                           | Description |
| ------------------------------ | ----------- |
| `Unstake`                      | id          |
| ### setCommissionRate          |             |
| Set validator commission rate. |             |

**Declaration:**

```solidity
  function setCommissionRate(
    uint256 rate
  ) external nonReentrant
```

**Modifiers:**

| Modifier     |
| ------------ |
| nonReentrant |

**Args:**

| Arg    | Type    | Description         |
| ------ | ------- | ------------------- |
| `rate` | uint256 | New commission rate |

### unstake

Unstake by id, return unstake amount.

**Declaration:**

```solidity
  function unstake(
    uint256 id
  ) external nonReentrant returns (uint256 amount)
```

**Modifiers:**

| Modifier     |
| ------------ |
| nonReentrant |

**Args:**

| Arg  | Type    | Description |
| ---- | ------- | ----------- |
| `id` | uint256 | Unstake id  |

### removeIndexedValidator

Remove the validator from `indexedValidators` if the voting power is less than `minIndexVotingPower` This can be called by anyone.

**Declaration:**

```solidity
  function removeIndexedValidator(
    address validator
  ) external nonReentrant
```

**Modifiers:**

| Modifier     |
| ------------ |
| nonReentrant |

**Args:**

| Arg         | Type    | Description       |
| ----------- | ------- | ----------------- |
| `validator` | address | Validator address |

### addIndexedValidator

Add the validator to `indexedValidators` if the voting power is greater than `minIndexVotingPower` This can be called by anyone.

**Declaration:**

```solidity
  function addIndexedValidator(
    address validator
  ) external nonReentrant
```

**Modifiers:**

| Modifier     |
| ------------ |
| nonReentrant |

**Args:**

| Arg         | Type    | Description       |
| ----------- | ------- | ----------------- |
| `validator` | address | Validator address |

### reward

Reward validator, only can be called by system caller

**Declaration:**

```solidity
  function reward(
    address validator
  ) external nonReentrant onlyRouterOrFeePool
```

**Modifiers:**

| Modifier            |
| ------------------- |
| nonReentrant        |
| onlyRouterOrFeePool |

**Args:**

| Arg         | Type    | Description       |
| ----------- | ------- | ----------------- |
| `validator` | address | Validator address |

### slash

Slash validator, only can be called by system caller

**Declaration:**

```solidity
  function slash(
    address validator,
    uint8 reason
  ) external nonReentrant onlyRouter returns (uint256 amount)
```

**Modifiers:**

| Modifier     |
| ------------ |
| nonReentrant |
| onlyRouter   |

**Args:**

| Arg         | Type    | Description       |
| ----------- | ------- | ----------------- |
| `validator` | address | Validator address |
| `reason`    | uint8   | Slash reason      |

### onAfterBlock

After block callback, it will be called by system caller after each block is processed

**Declaration:**

```solidity
  function onAfterBlock(
    address _proposer,
    address[] acValidators,
    int256[] priorities
  ) external nonReentrant onlyRouter
```

**Modifiers:**

| Modifier     |
| ------------ |
| nonReentrant |
| onlyRouter   |

**Args:**

| Arg            | Type       | Description                        |
| -------------- | ---------- | ---------------------------------- |
| `_proposer`    | address    | Proposer address                   |
| `acValidators` | address\[] | Active validators list             |
| `priorities`   | int256\[]  | Priority list of active validators |

## Events

### Reward

Emitted when a validator gets a reward NOTE: this event is never shown in the block, because the `reward` function is only called by the system caller

#### Params:

| Param                                         | Type    |        Indexed       | Description       |
| --------------------------------------------- | ------- | :------------------: | ----------------- |
| `validator`                                   | address | :white\_check\_mark: | Validator address |
| `value`                                       | uint256 | :white\_check\_mark: | Reward amount     |
| ### Slash                                     |         |                      |                   |
| Emitted when a validator is slashed           |         |                      |                   |
| NOTE: this event is never shown in the block, |         |                      |                   |

```
  because the `slash` function is only called by the system caller
```

#### Params:

| Param                        | Type    |        Indexed       | Description       |
| ---------------------------- | ------- | :------------------: | ----------------- |
| `validator`                  | address | :white\_check\_mark: | Validator address |
| `value`                      | uint256 | :white\_check\_mark: | Slashed amount    |
| ### Stake                    |         |                      |                   |
| Emitted when the user stakes |         |                      |                   |

#### Params:

| Param                                | Type    |        Indexed       | Description             |
| ------------------------------------ | ------- | :------------------: | ----------------------- |
| `validator`                          | address | :white\_check\_mark: | Validator address       |
| `value`                              | uint256 | :white\_check\_mark: | Stake value             |
| `to`                                 | address |                      | Receiver address        |
| `shares`                             | uint256 |                      | Number of shares minted |
| ### StartUnstake                     |         |                      |                         |
| Emitted when the user starts unstake |         |                      |                         |

#### Params:

| Param                                | Type    |        Indexed       | Description                           |
| ------------------------------------ | ------- | :------------------: | ------------------------------------- |
| `id`                                 | uint256 | :white\_check\_mark: | Unique unstake id                     |
| `validator`                          | address | :white\_check\_mark: | Validator address                     |
| `value`                              | uint256 | :white\_check\_mark: | Stake value                           |
| `to`                                 | address |                      | Receiver address                      |
| `unstakeShares`                      | uint256 |                      | Number of unstake shares to be burned |
| `timestamp`                          | uint256 |                      | Release timestamp                     |
| ### DoUnstake                        |         |                      |                                       |
| Emitted when stake manager `unstake` |         |                      |                                       |

#### Params:

| Param                                      | Type    |        Indexed       | Description       |
| ------------------------------------------ | ------- | :------------------: | ----------------- |
| `id`                                       | uint256 | :white\_check\_mark: | Unique unstake id |
| `validator`                                | address | :white\_check\_mark: | Validator address |
| `to`                                       | address |                      | Receiver address  |
| `amount`                                   | uint256 |                      | GXC Released      |
| ### SetCommissionRate                      |         |                      |                   |
| Emitted when validator set commission rate |         |                      |                   |

#### Params:

| Param                                   | Type    |        Indexed       | Description         |
| --------------------------------------- | ------- | :------------------: | ------------------- |
| `validator`                             | address | :white\_check\_mark: | Validator address   |
| `rate`                                  | uint256 | :white\_check\_mark: | New commission rate |
| `timestamp`                             | uint256 | :white\_check\_mark: | Update timestamp    |
| ### IndexedValidator                    |         |                      |                     |
| Emitted when a new validator is indexed |         |                      |                     |

#### Params:

| Param                                     | Type    |        Indexed       | Description            |
| ----------------------------------------- | ------- | :------------------: | ---------------------- |
| `validator`                               | address | :white\_check\_mark: | Validator address      |
| `votingPower`                             | uint256 | :white\_check\_mark: | Validator voting power |
| ### UnindexedValidator                    |         |                      |                        |
| Emitted when a new validator is unindexed |         |                      |                        |

#### Params:

| Param       | Type    |        Indexed       | Description       |
| ----------- | ------- | :------------------: | ----------------- |
| `validator` | address | :white\_check\_mark: | Validator address |
