# Staking

## Overview.

The [uos.finance](https://www.uos.finance) staking application is a decentralized protocol that allows users to stake their liquidity provider (LP) tokens to earn rewards in the form of $uOS tokens. The system is built on Ethereum-compatible networks and implements a flexible rewards distribution mechanism.

### Smart Contract Architecture

#### Core Components

1. **StakingRewards Contract**
   * Main contract handling staking operations and rewards distribution
   * Implements OpenZeppelin's Ownable and ReentrancyGuard for security
   * Manages two token types:
     * Staking Token (LP tokens)
     * Rewards Token (uOS)

#### Key Features

**Staking Mechanism**

* Users can stake their LP tokens using the `stake(uint256 amount)` function
* Staked tokens arent locked and can be withdrawn everytime
* Users can withdraw their staked tokens at any time using `withdraw(uint256 amount)`
* The `exit()` function allows users to withdraw all staked tokens and claim rewards in one transaction

**Rewards Distribution**

* Rewards are distributed over a configurable duration (default: 1 week)
* The reward rate is calculated based on the total amount of rewards and the duration
* Rewards are distributed proportionally to the amount of tokens staked
* Users can claim their earned rewards using the `getReward()` function

**Administrative Functions**

* Contract owner can:
  * Set new reward amounts using `notifyRewardAmount(uint256 reward)`
  * Adjust the rewards duration using `setRewardsDuration(uint256 _rewardsDuration)`
  * Recover accidentally sent tokens using `recoverERC20(address tokenAddress, uint256 tokenAmount)`

#### State Variables

* `rewardsToken`: Address of the token used for rewards (uOS)
* `stakingToken`: Address of the token that can be staked (LP tokens)
* `periodFinish`: Timestamp when the current rewards period ends
* `rewardRate`: Rate at which rewards are distributed
* `rewardsDuration`: Duration of the rewards period
* `lastUpdateTime`: Last time rewards were updated
* `rewardPerTokenStored`: Accumulated rewards per token
* `_totalSupply`: Total amount of tokens staked
* `_balances`: Mapping of user addresses to their staked amounts

#### Events

* `RewardAdded(uint256 reward)`: Emitted when new rewards are added
* `Staked(address indexed user, uint256 amount)`: Emitted when a user stakes tokens
* `Withdrawn(address indexed user, uint256 amount)`: Emitted when a user withdraws tokens
* `RewardPaid(address indexed user, uint256 reward)`: Emitted when rewards are paid to a user
* `RewardsDurationUpdated(uint256 newDuration)`: Emitted when the rewards duration is updated
* `Recovered(address token, uint256 amount)`: Emitted when tokens are recovered

### Frontend Integration

The staking application includes a React-based frontend that interacts with the smart contracts using wagmi hooks. Key components include:

#### Hooks

**useStakingRewards**

* Manages staking-related operations and state
* Provides functions for:
  * Checking LP token balances
  * Managing staking allowances
  * Viewing staked balances
  * Tracking earned rewards
  * Monitoring total LP tokens in staking

#### Contract Interactions

The frontend interacts with the following contract functions:

* `balanceOf`: Check user's staked balance
* `earned`: Calculate earned rewards
* `stake`: Stake LP tokens
* `withdraw`: Withdraw staked tokens
* `getReward`: Claim earned rewards
* `exit`: Withdraw all tokens and claim rewards

### Security Features

1. **Reentrancy Protection**
   * Implements OpenZeppelin's ReentrancyGuard
   * Prevents reentrancy attacks on critical functions
2. **Access Control**
   * Owner-only functions for administrative tasks
   * SafeERC20 implementation for token transfers
3. **Reward Rate Protection**
   * Checks to prevent reward rate overflow
   * Validates reward amounts against contract balance

### Deployment

The staking contract can be deployed to different networks with specific token addresses:

```javascript
// Base Network

stakingToken = "0x1cc5e366ec89b0ca2a30a4b4440c1b1c0b5fb466"; // vAMM-WETH/uOS
rewardsToken = "0xbE8728795b935bf6E2a9253Ce7a2Ef6fA831f51E"; // uOS

// Sepolia Testnet
stakingToken = "0x61bbA7C573248Cc3CcE194E9F48d8396f5A7A9A5"; // UNI-V2
rewardsToken = "0xffC8B69CB5AdD5Ea25E371eB531D9727bCc27d9C"; // uOS
```
