# Comptroller

@author Compound -> Union Finance @title Comptroller @dev For the time being, only the reward calculation of a single token is supported, and the contract needs to be revised after determining the reward calculation scheme of multiple tokens

### Info

```solidity
struct Info {
  uint256 updatedBlock;
  uint256 inflationIndex;
  uint256 accrued;
}
```

### UserManagerState

```solidity
struct UserManagerState {
  uint256 totalFrozen;
  uint256 totalStaked;
}
```

### UserManagerAccountState

```solidity
struct UserManagerAccountState {
  uint256 totalStaked;
  uint256 totalFrozen;
  uint256 totalLocked;
  uint256 pastBlocksFrozenCoinAge;
  bool isMember;
}
```

### INIT\_INFLATION\_INDEX

```solidity
uint256 INIT_INFLATION_INDEX
```

*Initial inflation index*

### nonMemberRatio

```solidity
uint256 nonMemberRatio
```

*Non member reward multiplier rate (75%)*

### memberRatio

```solidity
uint256 memberRatio
```

*Member reward multiplier rate (100%)*

### halfDecayPoint

```solidity
uint256 halfDecayPoint
```

*Half decay point to reduce rewards at*

### gInflationIndex

```solidity
uint256 gInflationIndex
```

*store the latest inflation index*

### gLastUpdatedBlock

```solidity
uint256 gLastUpdatedBlock
```

*block number when updating the inflation index*

### unionToken

```solidity
contract IERC20Upgradeable unionToken
```

*$UNION token contract*

### marketRegistry

```solidity
contract IMarketRegistry marketRegistry
```

*The market registry contract*

### users

```solidity
mapping(address => mapping(address => struct Comptroller.Info)) users
```

*Map account to token to Info*

### LogWithdrawRewards

```solidity
event LogWithdrawRewards(address account, uint256 amount)
```

@dev Withdraw rewards event @param account The staker's address @param amount The amount of Union tokens to withdraw

### SenderNotUserManager

```solidity
error SenderNotUserManager()
```

### NotZero

```solidity
error NotZero()
```

### FrozenCoinAge

```solidity
error FrozenCoinAge()
```

### InflationIndexTooSmall

```solidity
error InflationIndexTooSmall()
```

### \_\_Comptroller\_init

```solidity
function __Comptroller_init(address unionToken_, address marketRegistry_, uint256 _halfDecayPoint) public
```

### onlyUserManager

```solidity
modifier onlyUserManager(address token)
```

### setHalfDecayPoint

```solidity
function setHalfDecayPoint(uint256 point) public
```

*Set the half decay point*

### getRewardsMultiplier

```solidity
function getRewardsMultiplier(address account, address token) external view returns (uint256)
```

@dev Get the reward multipier based on the account status @param account Account address @param token ERC20 token address @return Multiplier number (in wei)

### calculateRewardsByBlocks

```solidity
function calculateRewardsByBlocks(address account, address token, uint256 futureBlocks) public view returns (uint256)
```

@dev Calculate unclaimed rewards based on blocks @param account User address @param token Staking token address @param futureBlocks Number of blocks in the future @return Unclaimed rewards

### calculateRewards

```solidity
function calculateRewards(address account, address token) external view returns (uint256)
```

@dev Calculate currently unclaimed rewards @param account Account address @param token Staking token address @return Unclaimed rewards

### inflationPerBlock

```solidity
function inflationPerBlock(uint256 effectiveTotalStake) public view returns (uint256)
```

@dev Calculate inflation per block @param effectiveTotalStake Effective total stake @return Inflation amount, div totalSupply is the inflation rate

### withdrawRewards

```solidity
function withdrawRewards(address account, address token) external returns (uint256)
```

@dev Withdraw rewards @param token Staking token address @return Amount of rewards

### updateTotalStaked

```solidity
function updateTotalStaked(address token, uint256 totalStaked) external returns (bool)
```

@dev When total staked change update inflation index @param totalStaked totalStaked amount @return Whether succeeded

### \_getUserManagerState

```solidity
function _getUserManagerState(contract IUserManager userManager) internal view returns (struct Comptroller.UserManagerState)
```

*Get UserManager global state values*

### \_getUserInfoView

```solidity
function _getUserInfoView(contract IUserManager userManager, address account, address token, uint256 futureBlocks) internal view returns (struct Comptroller.UserManagerAccountState, struct Comptroller.Info, uint256)
```

*Get UserManager user specific state (view function does NOT update UserManage state)*

#### Parameters

| Name         | Type                  | Description          |
| ------------ | --------------------- | -------------------- |
| userManager  | contract IUserManager | UserManager contract |
| account      | address               | Account address      |
| token        | address               | Token address        |
| futureBlocks | uint256               | Blocks in the future |

### \_getUserInfo

```solidity
function _getUserInfo(contract IUserManager userManager, address account, address token, uint256 futureBlocks) internal returns (struct Comptroller.UserManagerAccountState, struct Comptroller.Info, uint256)
```

*Get UserManager user specific state (function does update UserManage state)*

#### Parameters

| Name         | Type                  | Description          |
| ------------ | --------------------- | -------------------- |
| userManager  | contract IUserManager | UserManager contract |
| account      | address               | Account address      |
| token        | address               | Token address        |
| futureBlocks | uint256               | Blocks in the future |

### \_calculateRewardsByBlocks

```solidity
function _calculateRewardsByBlocks(address account, address token, uint256 pastBlocks, struct Comptroller.Info userInfo, struct Comptroller.UserManagerState userManagerState, struct Comptroller.UserManagerAccountState userManagerAccountState) internal view returns (uint256)
```

@dev Calculate currently unclaimed rewards @param account Account address @param token Staking token address @param userManagerState User manager global state @return Unclaimed rewards

### \_getInflationIndexNew

```solidity
function _getInflationIndexNew(uint256 totalStaked_, uint256 blockDelta) internal view returns (uint256)
```

@dev Calculate new inflation index based on # of blocks @param totalStaked\_ Number of total staked tokens in the system @param blockDelta Number of blocks @return New inflation index

### \_calculateRewards

```solidity
function _calculateRewards(address account, address token, uint256 totalStaked, uint256 userStaked, uint256 frozenCoinAge, uint256 pastBlocks, uint256 inflationIndex) internal view returns (uint256)
```

### \_getUserManager

```solidity
function _getUserManager(address token) internal view returns (contract IUserManager)
```

*Get the UserManager contract. First try and load it from state if it has been previously saved and fallback to loading it from the marketRegistry*

#### Return Values

| Name | Type                  | Description          |
| ---- | --------------------- | -------------------- |
| \[0] | contract IUserManager | userManager contract |

### \_inflationPerBlock

```solidity
function _inflationPerBlock(uint256 effectiveTotalStake) internal view returns (uint256)
```

@dev See Comptroller.inflationPerBlock

### \_lookup

```solidity
function _lookup(uint256 index) internal pure returns (uint256)
```

### \_getInflationIndex

```solidity
function _getInflationIndex(uint256 effectiveAmount, uint256 inflationIndex, uint256 blockDelta) internal view returns (uint256)
```

### \_getRewardsMultiplier

```solidity
function _getRewardsMultiplier(uint256 userStaked, uint256 lockedStake, uint256 totalFrozen_, bool isMember_) internal pure returns (uint256)
```
