# Staking Contracts

⚠️ This page only applies to very early farms, though many newer farms share features and function names ⚠️

Based on Synthetix's staking contract:&#x20;

<https://docs.synthetix.io/incentives/>

## Description

Frax users are able to stake in select Uniswap liquidity pool tokens in exchange for FXS rewards. Future pools and incentives can be added by governance.&#x20;

## Deployment

*Liquidity Pool Tokens (LP)*

Uniswap FRAX/WETH LP: `0xFD0A40Bc83C5faE4203DEc7e5929B446b07d1C76`

Uniswap FRAX/USDC LP: `0x97C4adc5d28A86f9470C70DD91Dc6CC2f20d2d4D`

Uniswap FRAX/FXS LP: `0xE1573B9D29e2183B1AF0e743Dc2754979A40D237`

Uniswap FXS/WETH LP: `0xecBa967D84fCF0405F6b32Bc45F4d36BfDBB2E81`

*Staking Contracts*&#x20;

Uniswap FRAX/WETH staking: `0xD875628B942f8970De3CcEaf6417005F68540d4f`

Uniswap FRAX/USDC staking: `0xa29367a3f057F3191b62bd4055845a33411892b6`

Uniswap FRAX/FXS staking: `0xda2c338350a0E59Ce71CDCED9679A3A590Dd9BEC`

Uniswap FXS/WETH staking (deprecated): `0xDc65f3514725206Dd83A8843AAE2aC3D99771C88`

## State Variables

```
FRAXStablecoin private FRAX
```

Instance of the FRAX contract.

```
ERC20 public rewardsToken
```

Instance for the reward token.

```
ERC20 public stakingToken
```

Instance for the staking token.

```
uint256 public periodFinish
```

Block when the staking period will finish.

```
uint256 public rewardRate
```

Maximum reward per second.

```
uint256 public rewardsDuration
```

Reward period, in seconds.

```
uint256 public lastUpdateTime
```

Last timestamp where the contract was updated / state change.

```
uint256 public rewardPerTokenStored
```

Actual reward per token in the current period.

```
uint256 public locked_stake_max_multiplier
```

Maximum boost / weight multiplier for locked stakes.

```
uint256 public locked_stake_time_for_max_multiplier
```

The time, in seconds, to reach `locked_stake_max_multiplier` .

```
uint256 public locked_stake_min_time
```

Minimum staking time for a locked staked, in seconds.

```
string public locked_stake_min_time_str
```

String version is `locked_stake_min_time_str` .

```
uint256 public cr_boost_max_multiplier
```

Maximum boost / weight multiplier from the collateral ratio (CR). This is applied to both locked and unlocked stakes.

```
mapping(address => uint256) public userRewardPerTokenPaid
```

Keeps track of when an address last collected a reward.  If they collect it some time later, they will get the correct amount because `rewardPerTokenStored` is constantly varying.

```
mapping(address => uint256) public rewards
```

Current rewards balance for a given address.

```
uint256 private _staking_token_supply
```

Total amount of pool tokens staked .

```
uint256 private _staking_token_boosted_supply
```

`_staking_token_supply` with the time and CR boosts accounted for. This is not an actual amount of pool tokens, but rather a 'weighed denominator'.

```
mapping(address => uint256) private _balances
```

Balance of pool tokens staked for a given address.

```
mapping(address => uint256) private _boosted_balances
```

`_balances` , but with the time and CR boosts accounted for, like `_staking_token_boosted_supply`.

```
mapping(address => LockedStake[]) private lockedStakes
```

Gives a list of locked stake lots for a given address.

```
struct LockedStake {
        bytes32 kek_id;
        uint256 start_timestamp;
        uint256 amount;
        uint256 ending_timestamp;
        uint256 multiplier; // 6 decimals of precision. 1x = 1000000
    }
```

A locked stake 'lot'.&#x20;

## **View Functions**

**totalSupply**

```
totalSupply() external override view returns (uint256)
```

Get the total number of staked liquidity pool tokens.

**stakingMultiplier**

```
stakingMultiplier(uint256 secs) public view returns (uint256)
```

Get the time-based staking multiplier, given the `secs` length of the stake.

**crBoostMultiplier**

```
crBoostMultiplier() public view returns (uint256)
```

Get the collateral ratio (CR) - based staking multiplier.

**stakingTokenSupply**

```
stakingTokenSupply() external view returns (uint256)
```

same as totalSupply().

**balanceOf**

```
balanceOf(address account) external override view returns (uint256)
```

Get the amount of staked liquidity pool tokens for a given `account`.

**boostedBalanceOf**

```
boostedBalanceOf(address account) external view returns (uint256)
```

Get the boosted amount of staked liquidity pool tokens for a given `account`. Boosted accounts for the CR and time-based multipliers.

**lockedBalanceOf**

```
lockedBalanceOf(address account) public view returns (uint256)
```

Get the amount of locked staked liquidity pool tokens for a given `account` .

**unlockedBalanceOf**

```
unlockedBalanceOf(address account) external view returns (uint256)
```

Get the amount of unlocked / free staked liquidity pool tokens for a given `account` .

**lockedStakesOf**

```
lockedStakesOf(address account) external view returns (LockedStake[] memory)
```

Return an array of all the locked stake 'lots' for&#x20;

**stakingDecimals**

```
stakingDecimals() external view returns (uint256)
```

Returns the `decimals()` for `stakingToken` .

**rewardsFor**

```
rewardsFor(address account) external view returns (uint256)
```

Get the amount of FXS rewards for a given `account` .

**lastTimeRewardApplicable**

```
lastTimeRewardApplicable() public override view returns (uint256)
```

Used internally to keep track of `rewardPerTokenStored` .

**rewardPerToken**

```
rewardPerToken() public override view returns (uint256)
```

The current amount of FXS rewards for staking a liquidity pool token.

**earned**

```
earned(address account) public override view returns (uint256)
```

Returns the amount of unclaimed FXS rewards for a given `account` .

**getRewardForDuration**

```
getRewardForDuration() external override view returns (uint256)
```

Calculates the FXS reward for a given `rewardsDuration` period.

## Mutative Functions

**stake**

```
stake(uint256 amount) external override nonReentrant notPaused updateReward(msg.sender)
```

Stakes some Uniswap liquidity pool tokens. These tokens are freely withdrawable and are only boosted by the `crBoostMultiplier()`**.**

**stakeLocked**

```
stakeLocked(uint256 amount, uint256 secs) external nonReentrant notPaused updateReward(msg.sender)
```

Stakes some Uniswap liquidity pool tokens and also locks them for the specified `secs` . In return for having their tokens locked, the staker's base `amount` will be multiplied by a linear time-based multiplier, which ranges from 1 at `secs` = 0 to  `locked_stake_max_multiplier` at `locked_stake_time_for_max_multiplier`**.** The staked value is also multiplied by the `crBoostMultiplier()` . This multiplied value is added to `_boosted_balances` and acts as a weighted amount when calculating the staker's share of a given period reward.

**withdraw**

```
withdraw(uint256 amount) public override nonReentrant updateReward(msg.sender)
```

Withdraw unlocked Uniswap liquidity pool tokens.

**withdrawLocked**

```
withdrawLocked(bytes32 kek_id) public nonReentrant updateReward(msg.sender)
```

Withdraw locked Uniswap liquidity pool tokens. Will fail if the staking time for the specific `kek_id` staking lot has not elapsed yet.

**getReward**

```
getReward() public override nonReentrant updateReward(msg.sender)
```

Claim FXS rewards.

**exit**

```
exit() external override
```

Withdraw all unlocked pool tokens and also collect rewards.

**renewIfApplicable**

```
renewIfApplicable() external
```

Renew a reward period if the period's finish time has completed. Calls `retroCatchUp()` .

**retroCatchUp**

```
retroCatchUp() internal
```

Renews the period and updates `periodFinish` , `rewardPerTokenStored` , and `lastUpdateTime` .

## Restricted Functions

**notifyRewardAmount**

```
notifyRewardAmount(uint256 reward) external override onlyRewardsDistribution updateReward(address(0))
```

This notifies people (via the event `RewardAdded` ) that the reward is being changed.

**recoverERC20**

```
recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyOwner
```

Added to support recovering LP Rewards from other systems to be distributed to holders.

**setRewardsDuration**

```
setRewardsDuration(uint256 _rewardsDuration) external onlyOwner
```

Set the duration of the rewards period.

**setLockedStakeMaxMultiplierUpdated**

```
setLockedStakeMaxMultiplierUpdated(uint256 _locked_stake_max_multiplier) external onlyOwner
```

Set the maximum multiplier for locked stakes.

**setLockedStakeTimeForMaxMultiplier**

```
setLockedStakeTimeForMaxMultiplier(uint256 _locked_stake_time_for_max_multiplier) external onlyOwner
```

Set the time, in seconds, when the locked stake multiplier reaches `locked_stake_max_multiplier` .

**setLockedStakeMinTime**

```
setLockedStakeMinTime(uint256 _locked_stake_min_time) external onlyOwner
```

Set the minimum time, in seconds, of a locked stake.

**setMaxCRBoostMultiplier**

```
setMaxCRBoostMultiplier(uint256 _max_boost_multiplier) external onlyOwner
```

aaa

**initializeDefault**

```
initializeDefault() external onlyOwner
```

Intended to only be called once in the lifetime of the contract. Initializes `lastUpdateTime` and `periodFinish` .

## Modifiers

**updateReward**

```
updateReward(address account)
```

Calls `retroCatchUp()` , if applicable, and otherwise syncs `rewardPerTokenStored` and `lastUpdateTime` . Also, syncs the `rewards` and `userRewardPerTokenPaid` for the provided `account` .
