# AI Pack: rewards-contracts

- Description: Rewards contracts and distribution logic.
- Remote: https://github.com/symbioticfi/rewards
- Remote ref: HEAD
- Commit: deb0e5aa14b2e72a75b1d8bf559576859fa0cb5a
- Generated (UTC): 2026-06-02T10:22:21.999Z
- Repomix: 1.14.1
- Preset: contract
- Ignore patterns: .gitignore, .dockerignore, .prettierignore, .npmignore, .nvmrc, .editorconfig, .gitattributes, **/.github/**, **/.husky/**, **/.vscode/**, **/.idea/**, **/.DS_Store, node_modules/, dist/, build/, .turbo/, .next/, out/, cache/, broadcast/, bin/, coverage*, *.test, target/, docs/, abis/, bindings/, test/**, !test/integration/**, script/utils/**, package-lock.json, pnpm-lock.yaml, yarn.lock, bun.lockb, .pre-commit-config.yaml
- Flags: compress

---

This file is a merged representation of a subset of the codebase, containing files not matching ignore patterns, combined into a single document by Repomix.
The content has been processed where content has been compressed (code blocks are separated by ⋮---- delimiter).

# File Summary

## Purpose

This file contains a packed representation of a subset of the repository's contents that is considered the most important context.
It is designed to be easily consumable by AI systems for analysis, code review,
or other automated processes.

## File Format

The content is organized as follows:

1. This summary section
2. Repository information
3. Directory structure
4. Repository files (if enabled)
5. Multiple file entries, each consisting of:
   a. A header with the file path (## File: path/to/file)
   b. The full contents of the file in a code block

## Usage Guidelines

- This file should be treated as read-only. Any changes should be made to the
  original repository files, not this packed version.
- When processing this file, use the file path to distinguish
  between different files in the repository.
- Be aware that this file may contain sensitive information. Handle it with
  the same level of security as you would the original repository.

## Notes

- Some files may have been excluded based on .gitignore rules and Repomix's configuration
- Binary files are not included in this packed representation. Please refer to the Repository Structure section for a complete list of file paths, including binary files
- Files matching these patterns are excluded: .gitignore, .dockerignore, .prettierignore, .npmignore, .nvmrc, .editorconfig, .gitattributes, **/.github/**, **/.husky/**, **/.vscode/**, **/.idea/**, **/.DS_Store, node_modules/, dist/, build/, .turbo/, .next/, out/, cache/, broadcast/, bin/, coverage*, *.test, target/, docs/, abis/, bindings/, test/**, !test/integration/**, script/utils/**, package-lock.json, pnpm-lock.yaml, yarn.lock, bun.lockb, .pre-commit-config.yaml
- Files matching patterns in .gitignore are excluded
- Files matching default ignore patterns are excluded
- Content has been compressed - code blocks are separated by ⋮---- delimiter
- Files are sorted by Git change count (files with more changes are at the bottom)

# Directory Structure

```
cli/
  defaultOperatorRewards/
    data/
      distribution.json.example
      trees.json.example
    distributionToProofs.js
    distributionToRoots.js
    distributionToTrees.js
    treesToDistribution.js
    treesToProofs.js
    treesToRoots.js
script/
  deploy/
    genesis/
      DefaultOperatorRewardsFactory.s.sol
      DefaultRewardsFactories.s.sol
      DefaultStakerRewardsFactory.s.sol
    DefaultOperatorRewards.s.sol
    DefaultStakerRewards.s.sol
specs/
  OperatorRewards.md
  StakerRewards.md
src/
  contracts/
    defaultOperatorRewards/
      DefaultOperatorRewards.sol
      DefaultOperatorRewardsFactory.sol
    defaultStakerRewards/
      DefaultStakerRewards.sol
      DefaultStakerRewardsFactory.sol
  interfaces/
    defaultOperatorRewards/
      IDefaultOperatorRewards.sol
      IDefaultOperatorRewardsFactory.sol
    defaultStakerRewards/
      IDefaultStakerRewards.sol
      IDefaultStakerRewardsFactory.sol
    stakerRewards/
      IStakerRewards.sol
.env.example
.gitmodules
foundry.toml
LICENSE
package.json
README.md
remappings.txt
```

# Files

## File: cli/defaultOperatorRewards/data/distribution.json.example

```
[
  {
    "token": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
    "operators": [
      {
        "operator": "0x0000000000000000000000000000000000000001",
        "reward": "100000000000000000"
      },
      {
        "operator": "0x0000000000000000000000000000000000000002",
        "reward": "300000000000000000"
      },
      {
        "operator": "0x0000000000000000000000000000000000000003",
        "reward": "600000000000000000"
      }
    ]
  },
  {
    "token": "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0",
    "operators": [
      {
        "operator": "0x0000000000000000000000000000000000000002",
        "reward": "200000000000000000"
      },
      {
        "operator": "0x0000000000000000000000000000000000000003",
        "reward": "250000000000000000"
      },
      {
        "operator": "0x0000000000000000000000000000000000000004",
        "reward": "500000000000000000"
      }
    ]
  }
]
```

## File: cli/defaultOperatorRewards/data/trees.json.example

```
[{"token":"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2","tree":{"format":"standard-v1","leafEncoding":["address","uint256"],"tree":["0x1421466e8f910cab140a44dd533adb90ebc2d87e0ab91e851737a77ecd394224","0x54ce56851dece12f32823f4bb940800fb9cf57d68bcdda73e2436bf1e5be661d","0xb77d490dc0f9580cc767909bba59fd55900dec274b637ed820a391c018c8858a","0x92864efb389a13533b2b5d94eda464bce7dbe336d06c6d5feb673c30460c10ee","0x1c93c9b111fdf5d2ab331e2ad2de1d3ffe1c8590f544554a1b0247bd46be37a4"],"values":[{"value":["0x0000000000000000000000000000000000000001","100000000000000000"],"treeIndex":2},{"value":["0x0000000000000000000000000000000000000002","300000000000000000"],"treeIndex":3},{"value":["0x0000000000000000000000000000000000000003","600000000000000000"],"treeIndex":4}]}},{"token":"0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0","tree":{"format":"standard-v1","leafEncoding":["address","uint256"],"tree":["0x4317f898d0c584ac608ed5c819f16cf5307fa2f07d5e1aa995493e46662a7a7f","0x30f6473979500545c8fa671ffec7060e0504909b4977e2a19af00c1c7c72fb49","0xc0151a5b2dc7e51c8ef30cdc65dfbedf3082c5678bad3ba3354827c6c6f52a45","0x5fa8fb18326605f1825c6988667a5162b2d926adb03d1cb670eddccf6a7ea42e","0x5c1aed882581724b9b52eecbc172dbc8f0ff57dde40b93f18139429763e0ccbd"],"values":[{"value":["0x0000000000000000000000000000000000000002","200000000000000000"],"treeIndex":3},{"value":["0x0000000000000000000000000000000000000003","250000000000000000"],"treeIndex":2},{"value":["0x0000000000000000000000000000000000000004","500000000000000000"],"treeIndex":4}]}}]
```

## File: cli/defaultOperatorRewards/distributionToProofs.js

```javascript
function generateMerkleTrees()
⋮----
function findProof(trees, operator)
⋮----
function main()
```

## File: cli/defaultOperatorRewards/distributionToRoots.js

```javascript
function generateMerkleTrees()
⋮----
function main()
```

## File: cli/defaultOperatorRewards/distributionToTrees.js

```javascript
function generateMerkleTrees()
⋮----
function main()
```

## File: cli/defaultOperatorRewards/treesToDistribution.js

```javascript
function parseMerkleTrees()
⋮----
function main()
```

## File: cli/defaultOperatorRewards/treesToProofs.js

```javascript
function parseMerkleTrees()
⋮----
function findProof(trees, operator)
⋮----
function main()
```

## File: cli/defaultOperatorRewards/treesToRoots.js

```javascript
function parseMerkleTrees()
⋮----
function main()
```

## File: script/deploy/genesis/DefaultOperatorRewardsFactory.s.sol

```solidity
// SPDX-License-Identifier: MIT
⋮----
import {console2, Script} from "forge-std/Script.sol";
⋮----
import {SymbioticCoreConstants} from "@symbioticfi/core/test/integration/SymbioticCoreConstants.sol";
⋮----
import {DefaultOperatorRewards} from "../../../src/contracts/defaultOperatorRewards/DefaultOperatorRewards.sol";
import {DefaultOperatorRewardsFactory} from
    "../../../src/contracts/defaultOperatorRewards/DefaultOperatorRewardsFactory.sol";
⋮----
contract DefaultOperatorRewardsFactoryScript is Script {
function run() external {
```

## File: script/deploy/genesis/DefaultRewardsFactories.s.sol

```solidity
// SPDX-License-Identifier: MIT
⋮----
import {console2, Script} from "forge-std/Script.sol";
⋮----
import {SymbioticCoreConstants} from "@symbioticfi/core/test/integration/SymbioticCoreConstants.sol";
⋮----
import {DefaultStakerRewards} from "../../../src/contracts/defaultStakerRewards/DefaultStakerRewards.sol";
import {DefaultStakerRewardsFactory} from "../../../src/contracts/defaultStakerRewards/DefaultStakerRewardsFactory.sol";
⋮----
import {DefaultOperatorRewards} from "../../../src/contracts/defaultOperatorRewards/DefaultOperatorRewards.sol";
import {DefaultOperatorRewardsFactory} from
    "../../../src/contracts/defaultOperatorRewards/DefaultOperatorRewardsFactory.sol";
⋮----
contract DefaultRewardsFactoriesScript is Script {
function run() external {
```

## File: script/deploy/genesis/DefaultStakerRewardsFactory.s.sol

```solidity
// SPDX-License-Identifier: MIT
⋮----
import {console2, Script} from "forge-std/Script.sol";
⋮----
import {SymbioticCoreConstants} from "@symbioticfi/core/test/integration/SymbioticCoreConstants.sol";
⋮----
import {DefaultStakerRewards} from "../../../src/contracts/defaultStakerRewards/DefaultStakerRewards.sol";
import {DefaultStakerRewardsFactory} from "../../../src/contracts/defaultStakerRewards/DefaultStakerRewardsFactory.sol";
⋮----
contract DefaultStakerRewardsFactoryScript is Script {
function run() external {
```

## File: script/deploy/DefaultOperatorRewards.s.sol

```solidity
// SPDX-License-Identifier: MIT
⋮----
import {console2, Script} from "forge-std/Script.sol";
⋮----
import {SymbioticRewardsConstants} from "../../test/integration/SymbioticRewardsConstants.sol";
⋮----
contract DefaultOperatorRewardsScript is Script {
function run() external {
```

## File: script/deploy/DefaultStakerRewards.s.sol

```solidity
// SPDX-License-Identifier: MIT
⋮----
import {console2, Script} from "forge-std/Script.sol";
⋮----
import {SymbioticRewardsConstants} from "../../test/integration/SymbioticRewardsConstants.sol";
⋮----
import {IDefaultStakerRewards} from "../../src/interfaces/defaultStakerRewards/IDefaultStakerRewards.sol";
⋮----
contract DefaultStakerRewardsScript is Script {
function run(
```

## File: specs/OperatorRewards.md

````markdown
## Operator Rewards

The network distributes the operator rewards at its discretion. Here are three examples:

1. The network performs off-chain calculations to determine the reward distributions. After calculating the rewards, the network executes batch transfers to distribute the rewards in a consolidated manner.
2. The network performs off-chain calculations to determine rewards and generates a Merkle tree, allowing operators to claim their rewards.
3. The network performs on-chain reward calculations within its middleware to determine the distribution of rewards.

##### Source of Data for Network On-Chain Reward Calculations

For operator rewards, the delegator module of the vault provides:

- `Delegator.stakeAt(network, operator, timestamp, hint)` - Active stake of an operator in the network.

Additionally, all operators register through the network, providing necessary details such as commission rates, fixed payments, and other relevant conditions. This registration process ensures that networks have the required data to perform accurate on-chain reward calculations in their middleware.

### Deploy

```shell
source .env
```

#### Deploy factory

Deployment script: [click](../script/deploy/genesis/DefaultOperatorRewardsFactory.s.sol)

```shell
forge script script/deploy/genesis/DefaultOperatorRewardsFactory.s.sol:DefaultOperatorRewardsFactoryScript --broadcast --rpc-url=$ETH_RPC_URL
```

#### Deploy entity

Deployment script: [click](../script/deploy/DefaultOperatorRewards.s.sol)

```shell
forge script script/deploy/DefaultOperatorRewards.s.sol:DefaultOperatorRewardsScript --sig "run()" --broadcast --rpc-url=$ETH_RPC_URL
```

### CLI

#### Install packages

```shell
npm install
```

#### Use commands

**distributionToRoots**

```shell
node cli/defaultOperatorRewards/distributionToRoots.js
```

Get a Merkle root for each rewards distribution by token.

_Make sure to save `distribution.json` to `cli/defaultOperatorRewards/data` folder. You can check [an example format here](../cli/defaultOperatorRewards/data/distribution.json.example)._

---

**distributionToProofs**

```shell
node cli/defaultOperatorRewards/distributionToProofs.js OPERATOR
```

Get proofs for all tokens in a rewards distribution for a given operator.

_Make sure to save `distribution.json` to `cli/defaultOperatorRewards/data` folder. You can check [an example format here](../cli/defaultOperatorRewards/data/distribution.json.example)._

Arguments:

- `OPERATOR` - an address of the operator to get proofs for

---

**distributionToTrees**

```shell
node cli/defaultOperatorRewards/distributionToTrees.js
```

Saves OZ Merkle tree structures constructed from the rewards distribution to `cli/defaultOperatorRewards/data/trees.json`.

_Make sure to save `distribution.json` to `cli/defaultOperatorRewards/data` folder. You can check [an example format here](../cli/defaultOperatorRewards/data/distribution.json.example)._

---

**treesToRoots**

```shell
node cli/defaultOperatorRewards/treesToRoots.js
```

Get a Merkle root for each Merkle tree by token.

_Make sure to save `trees.json` to `cli/defaultOperatorRewards/data` folder. You can check [an example format here](../cli/defaultOperatorRewards/data/trees.json.example)._

---

**treesToProofs**

```shell
node cli/defaultOperatorRewards/treesToProofs.js OPERATOR
```

Get proofs for all tokens in Merkle trees for a given operator.

_Make sure to save `trees.json` to `cli/defaultOperatorRewards/data` folder. You can check [an example format here](../cli/defaultOperatorRewards/data/trees.json.example)._

Arguments:

- `OPERATOR` - an address of the operator to get proofs for

---

**treesToDistribution**

```shell
node cli/defaultOperatorRewards/treesToDistribution.js
```

Saves a rewards distribution constructed from the OZ Merkle trees to `cli/defaultOperatorRewards/data/distribution.json`.

_Make sure to save `trees.json` to `cli/defaultOperatorRewards/data` folder. You can check [an example format here](../cli/defaultOperatorRewards/data/trees.json.example)._
````

## File: specs/StakerRewards.md

````markdown
## Staker Rewards

For staker rewards calculation, the vault provides the following data:

- `activeSharesOfAt(account, timestamp, hint)` - $\text{active}$ shares of the user at a specific timestamp
- `activeSharesAt(timestamp, hint)` - total $\text{active}$ shares at a specific timestamp.
- Other checkpointed getters

Reward processing is not integrated into the vault's functionality. Instead, external reward contracts should manage this using the provided data.

However, we created the first version of the `IStakerRewards` interface to facilitate more generic reward distribution across networks.

- `IStakerRewards.version()` - provides a version of the interface that a particular rewards contract uses
- `IStakerRewards.distributeRewards(network, token, amount, data)` - call to distribute `amount` of `token` on behalf of `network` using an arbitrary `data`

### Deploy

```shell
source .env
```

#### Deploy factory

Deployment script: [click](../script/deploy/genesis/DefaultStakerRewardsFactory.s.sol)

```shell
forge script script/deploy/genesis/DefaultStakerRewardsFactory.s.sol:DefaultStakerRewardsFactoryScript --broadcast --rpc-url=$ETH_RPC_URL
```

#### Deploy entity

Deployment script: [click](../script/deploy/DefaultStakerRewards.s.sol)

```shell
forge script script/deploy/DefaultStakerRewards.s.sol:DefaultStakerRewardsScript 0x0000000000000000000000000000000000000000 0 0x0000000000000000000000000000000000000000 0x0000000000000000000000000000000000000000 0x0000000000000000000000000000000000000000 --sig "run(address,uint256,address,address,address)" --broadcast --rpc-url=$ETH_RPC_URL
```
````

## File: src/contracts/defaultOperatorRewards/DefaultOperatorRewards.sol

```solidity
// SPDX-License-Identifier: MIT
⋮----
import {IDefaultOperatorRewards} from "../../interfaces/defaultOperatorRewards/IDefaultOperatorRewards.sol";
⋮----
import {INetworkMiddlewareService} from "@symbioticfi/core/src/interfaces/service/INetworkMiddlewareService.sol";
⋮----
import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
⋮----
contract DefaultOperatorRewards is ReentrancyGuardUpgradeable, IDefaultOperatorRewards {
⋮----
/**
     * @inheritdoc IDefaultOperatorRewards
     */
⋮----
function initialize() public initializer {
⋮----
function distributeRewards(address network, address token, uint256 amount, bytes32 root_) external nonReentrant {
⋮----
function claimRewards(
```

## File: src/contracts/defaultOperatorRewards/DefaultOperatorRewardsFactory.sol

```solidity
// SPDX-License-Identifier: MIT
⋮----
import {DefaultOperatorRewards} from "./DefaultOperatorRewards.sol";
⋮----
import {IDefaultOperatorRewardsFactory} from
    "../../interfaces/defaultOperatorRewards/IDefaultOperatorRewardsFactory.sol";
⋮----
import {Registry} from "@symbioticfi/core/src/contracts/common/Registry.sol";
⋮----
import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
⋮----
contract DefaultOperatorRewardsFactory is Registry, IDefaultOperatorRewardsFactory {
⋮----
/**
     * @inheritdoc IDefaultOperatorRewardsFactory
     */
function create() external returns (address) {
```

## File: src/contracts/defaultStakerRewards/DefaultStakerRewards.sol

```solidity
// SPDX-License-Identifier: MIT
⋮----
import {IDefaultStakerRewards} from "../../interfaces/defaultStakerRewards/IDefaultStakerRewards.sol";
import {IStakerRewards} from "../../interfaces/stakerRewards/IStakerRewards.sol";
⋮----
import {INetworkMiddlewareService} from "@symbioticfi/core/src/interfaces/service/INetworkMiddlewareService.sol";
import {IRegistry} from "@symbioticfi/core/src/interfaces/common/IRegistry.sol";
import {IVault} from "@symbioticfi/core/src/interfaces/vault/IVault.sol";
⋮----
import {AccessControlUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
import {MulticallUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/MulticallUpgradeable.sol";
import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {Time} from "@openzeppelin/contracts/utils/types/Time.sol";
⋮----
contract DefaultStakerRewards is
⋮----
/**
     * @inheritdoc IStakerRewards
     */
⋮----
/**
     * @inheritdoc IDefaultStakerRewards
     */
⋮----
function rewardsLength(address token, address network) external view returns (uint256) {
⋮----
function claimable(
⋮----
// network - a network to claim rewards for
// maxRewards - the maximum amount of rewards to process
⋮----
function initialize(
⋮----
function distributeRewards(
⋮----
// timestamp - a time point stakes must be taken into account at
// maxAdminFee - the maximum admin fee to allow
// activeSharesHint - a hint index to optimize `activeSharesAt()` processing
// activeStakeHint - a hint index to optimize `activeStakeAt()` processing
⋮----
function claimRewards(address recipient, address token, bytes calldata data) external override nonReentrant {
⋮----
// activeSharesOfHints - hint indexes to optimize `activeSharesOf()` processing
⋮----
function claimAdminFee(address recipient, address token) external nonReentrant onlyRole(ADMIN_FEE_CLAIM_ROLE) {
⋮----
function setAdminFee(
⋮----
function _setAdminFee(
```

## File: src/contracts/defaultStakerRewards/DefaultStakerRewardsFactory.sol

```solidity
// SPDX-License-Identifier: MIT
⋮----
import {DefaultStakerRewards} from "./DefaultStakerRewards.sol";
⋮----
import {IDefaultStakerRewardsFactory} from "../../interfaces/defaultStakerRewards/IDefaultStakerRewardsFactory.sol";
⋮----
import {Registry} from "@symbioticfi/core/src/contracts/common/Registry.sol";
⋮----
import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
⋮----
contract DefaultStakerRewardsFactory is Registry, IDefaultStakerRewardsFactory {
⋮----
/**
     * @inheritdoc IDefaultStakerRewardsFactory
     */
function create(
```

## File: src/interfaces/defaultOperatorRewards/IDefaultOperatorRewards.sol

```solidity
// SPDX-License-Identifier: MIT
⋮----
interface IDefaultOperatorRewards {
⋮----
/**
     * @notice Emitted when rewards are distributed by a particular network using a given token by providing a Merkle root.
     * @param network address of the network that distributed rewards
     * @param token address of the token
     * @param amount amount of tokens sent to the contract
     * @param root Merkle root of the rewards distribution
     * @dev The Merkle tree's leaves must represent an account and a claimable amount (the total amount of the reward tokens for the whole time).
     */
event DistributeRewards(address indexed network, address indexed token, uint256 amount, bytes32 root);
⋮----
/**
     * @notice Emitted when rewards are claimed by a particular account for a particular network using a given token.
     * @param recipient address of the rewards' recipient
     * @param network address of the network
     * @param token address of the token
     * @param claimer address of the rewards' claimer
     * @param amount amount of tokens claimed
     */
event ClaimRewards(
⋮----
/**
     * @notice Get the network middleware service's address.
     * @return address of the network middleware service
     */
function NETWORK_MIDDLEWARE_SERVICE() external view returns (address);
⋮----
/**
     * @notice Get a Merkle root of a reward distribution for a particular network and token.
     * @param network address of the network
     * @param token address of the token
     * @return Merkle root of the reward distribution
     */
function root(address network, address token) external view returns (bytes32);
⋮----
/**
     * @notice Get an amount of tokens that can be claimed for a particular network.
     * @param network address of the network
     * @param token address of the token
     * @return amount of tokens that can be claimed
     */
function balance(address network, address token) external view returns (uint256);
⋮----
/**
     * @notice Get a claimed amount of rewards for a particular account, network, and token.
     * @param network address of the network
     * @param token address of the token
     * @param account address of the claimer
     * @return claimed amount of tokens
     */
function claimed(address network, address token, address account) external view returns (uint256);
⋮----
/**
     * @notice Distribute rewards by a particular network using a given token by providing a Merkle root.
     * @param network address of the network
     * @param token address of the token
     * @param amount amount of tokens to send to the contract
     * @param root Merkle root of the reward distribution
     */
function distributeRewards(address network, address token, uint256 amount, bytes32 root) external;
⋮----
/**
     * @notice Claim rewards for a particular network and token by providing a Merkle proof.
     * @param recipient address of the rewards' recipient
     * @param network address of the network
     * @param token address of the token
     * @param totalClaimable total amount of the reward tokens for the whole time
     * @param proof Merkle proof of the reward distribution
     * @return amount amount of tokens claimed
     */
function claimRewards(
```

## File: src/interfaces/defaultOperatorRewards/IDefaultOperatorRewardsFactory.sol

```solidity
// SPDX-License-Identifier: MIT
⋮----
import {IRegistry} from "@symbioticfi/core/src/interfaces/common/IRegistry.sol";
⋮----
interface IDefaultOperatorRewardsFactory is IRegistry {
/**
     * @notice Create a default operator rewards contract.
     * @return address of the created operator rewards contract
     */
function create() external returns (address);
```

## File: src/interfaces/defaultStakerRewards/IDefaultStakerRewards.sol

```solidity
// SPDX-License-Identifier: MIT
⋮----
import {IStakerRewards} from "../stakerRewards/IStakerRewards.sol";
⋮----
interface IDefaultStakerRewards is IStakerRewards {
⋮----
/**
     * @notice Initial parameters needed for a staker rewards contract deployment.
     * @param vault address of the vault to get stakers' data from
     * @param adminFee admin fee (up to ADMIN_FEE_BASE inclusively)
     * @param defaultAdminRoleHolder address of the initial DEFAULT_ADMIN_ROLE holder
     * @param adminFeeClaimRoleHolder address of the initial ADMIN_FEE_CLAIM_ROLE holder
     * @param adminFeeSetRoleHolder address of the initial ADMIN_FEE_SET_ROLE holder
     */
⋮----
/**
     * @notice Structure for a reward distribution.
     * @param amount amount of tokens to be distributed (admin fee is excluded)
     * @param timestamp time point stakes must taken into account at
     */
⋮----
/**
     * @notice Emitted when a vault is initialized.
     * @param vault address of the vault
     */
event InitVault(address vault);
⋮----
/**
     * @notice Emitted when a reward is claimed.
     * @param network network whose rewards are claimed
     * @param token address of the token
     * @param claimer address of the claimer
     * @param firstClaimedRewardIndex first claimed reward index
     * @param rewardsClaimed number of rewards claimed
     */
event ClaimRewardsExtra(
⋮----
/**
     * @notice Emitted when an admin fee is claimed.
     * @param recipient account that received the fee
     * @param amount amount of the fee claimed
     */
event ClaimAdminFee(address indexed recipient, uint256 amount);
⋮----
/**
     * @notice Emitted when the admin fee is set.
     * @param adminFee new admin fee
     */
event SetAdminFee(uint256 adminFee);
⋮----
/**
     * @notice Get the maximum admin fee (= 100%).
     * @return maximum admin fee
     */
function ADMIN_FEE_BASE() external view returns (uint256);
⋮----
/**
     * @notice Get the admin fee claimer's role.
     * @return identifier of the admin fee claimer role
     */
function ADMIN_FEE_CLAIM_ROLE() external view returns (bytes32);
⋮----
/**
     * @notice Get the admin fee setter's role.
     * @return identifier of the admin fee setter role
     */
function ADMIN_FEE_SET_ROLE() external view returns (bytes32);
⋮----
/**
     * @notice Get the vault factory's address.
     * @return address of the vault factory
     */
function VAULT_FACTORY() external view returns (address);
⋮----
/**
     * @notice Get the network middleware service's address.
     * @return address of the network middleware service
     */
function NETWORK_MIDDLEWARE_SERVICE() external view returns (address);
⋮----
/**
     * @notice Get the vault's address.
     * @return address of the vault
     */
function VAULT() external view returns (address);
⋮----
/**
     * @notice Get an admin fee.
     * @return admin fee
     */
function adminFee() external view returns (uint256);
⋮----
/**
     * @notice Get a total number of rewards using a particular token for a given network.
     * @param token address of the token
     * @param network address of the network
     * @return total number of the rewards using the token by the network
     */
function rewardsLength(address token, address network) external view returns (uint256);
⋮----
/**
     * @notice Get a particular reward distribution.
     * @param token address of the token
     * @param network address of the network
     * @param rewardIndex index of the reward distribution using the token
     * @return amount amount of tokens to be distributed
     * @return timestamp time point stakes must taken into account at
     */
function rewards(
⋮----
/**
     * @notice Get the first index of the unclaimed rewards using a particular token by a given account.
     * @param account address of the account
     * @param token address of the token
     * @param network address of the network
     * @return first index of the unclaimed rewards
     */
function lastUnclaimedReward(address account, address token, address network) external view returns (uint256);
⋮----
/**
     * @notice Get a claimable admin fee amount for a particular token.
     * @param token address of the token
     * @return claimable admin fee
     */
function claimableAdminFee(
⋮----
/**
     * @notice Claim an admin fee.
     * @param recipient account that will receive the fee
     * @param token address of the token
     * @dev Only the vault owner can call this function.
     */
function claimAdminFee(address recipient, address token) external;
⋮----
/**
     * @notice Set an admin fee.
     * @param adminFee admin fee (up to ADMIN_FEE_BASE inclusively)
     * @dev Only the ADMIN_FEE_SET_ROLE holder can call this function.
     */
function setAdminFee(
```

## File: src/interfaces/defaultStakerRewards/IDefaultStakerRewardsFactory.sol

```solidity
// SPDX-License-Identifier: MIT
⋮----
import {IDefaultStakerRewards} from "./IDefaultStakerRewards.sol";
⋮----
import {IRegistry} from "@symbioticfi/core/src/interfaces/common/IRegistry.sol";
⋮----
interface IDefaultStakerRewardsFactory is IRegistry {
/**
     * @notice Create a default staker rewards contract for a given vault.
     * @param params initial parameters needed for a staker rewards contract deployment
     * @return address of the created staker rewards contract
     */
function create(
```

## File: src/interfaces/stakerRewards/IStakerRewards.sol

```solidity
// SPDX-License-Identifier: MIT
⋮----
interface IStakerRewards {
/**
     * @notice Emitted when a reward is distributed.
     * @param network network on behalf of which the reward is distributed
     * @param token address of the token
     * @param distributeAmount amount of tokens to distribute
     * @param adminFeeAmount amount of tokens to keep as an admin fee
     * @param timestamp timestamp of the distribution
     */
event DistributeRewards(
⋮----
/**
     * @notice Emitted when a reward is claimed.
     * @param network network whose rewards are claimed
     * @param token address of the token
     * @param claimer address of the claimer
     * @param amount amount of tokens
     * @param recipient address of the tokens' recipient
     */
event ClaimRewards(
⋮----
/**
     * @notice Get a version of the staker rewards contract (different versions mean different interfaces).
     * @return version of the staker rewards contract
     * @dev Must return 2 for this one.
     */
function version() external view returns (uint64);
⋮----
/**
     * @notice Get an amount of rewards claimable by a particular account of a given token.
     * @param token address of the token
     * @param account address of the claimer
     * @param data some data to use
     * @return amount of claimable tokens
     */
function claimable(address token, address account, bytes calldata data) external view returns (uint256);
⋮----
/**
     * @notice Distribute rewards on behalf of a particular network using a given token.
     * @param network network on behalf of which the reward to distribute
     * @param token address of the token
     * @param amount amount of tokens
     * @param data some data to use
     */
function distributeRewards(address network, address token, uint256 amount, bytes calldata data) external;
⋮----
/**
     * @notice Claim rewards using a given token.
     * @param recipient address of the tokens' recipient
     * @param token address of the token
     * @param data some data to use
     */
function claimRewards(address recipient, address token, bytes calldata data) external;
```

## File: .env.example

```
ETH_RPC_URL=
ETH_RPC_URL_HOLESKY=
ETHERSCAN_API_KEY=
```

## File: .gitmodules

```
[submodule "lib/forge-std"]
	path = lib/forge-std
	url = https://github.com/foundry-rs/forge-std
[submodule "lib/openzeppelin-contracts"]
	path = lib/openzeppelin-contracts
	url = https://github.com/OpenZeppelin/openzeppelin-contracts
[submodule "lib/openzeppelin-contracts-upgradeable"]
	path = lib/openzeppelin-contracts-upgradeable
	url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable
[submodule "lib/core"]
	path = lib/core
	url = https://github.com/symbioticfi/core
```

## File: foundry.toml

```toml
[profile.default]
evm_version = "cancun"
solc = "0.8.25"
optimizer = true
optimizer_runs = 200
via_ir = true
src = "src"
out = "out"
libs = ["lib"]
fs_permissions = [{ access = "read-write", path = "./"}]
gas_reports = ["*"]
gas_limit = "18446744073709551615"

[rpc_endpoints]
mainnet = "${ETH_RPC_URL}"
holesky = "${ETH_RPC_URL_HOLESKY}"

[fmt]
bracket_spacing = false
int_types = "long"
line_length = 120
multiline_func_header = "params_first"
number_underscore = "thousands"
quote_style = "double"
tab_width = 4

[fuzz]
runs = 4096
max_test_rejects = 262144


# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
```

## File: LICENSE

```
MIT License

Copyright (c) 2024 Symbiotic

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```

## File: package.json

```json
{
    "name": "@symbioticfi/rewards",
    "version": "2.0.0",
    "description": "Symbiotic Rewards repository contains a Symbiotic Staker Rewards interface providing a standardized way for rewards implementations by different parties, and default implementations of Staker and Operator Rewards.",
    "homepage": "https://symbiotic.fi/",
    "bugs": "https://github.com/symbioticfi/rewards/issues",
    "license": "MIT",
    "author": "Symbiotic Team",
    "files": ["src/**/*", "test/mocks/**/*", "test/integration/**/*", "out/**/*.json", "cli/**/*"],
    "repository": {
        "type": "git",
        "url": "https://github.com/symbioticfi/rewards.git"
    },
    "keywords": ["solidity", "ethereum", "smart", "contracts", "security"],
    "dependencies": {
        "@openzeppelin/contracts": "5.0.2",
        "@openzeppelin/contracts-upgradeable": "5.0.2",
        "@openzeppelin/merkle-tree": "1.0.7",
        "@symbioticfi/core": "1.0.1"
    }
}
```

## File: README.md

````markdown
**[Symbiotic Protocol](https://symbiotic.fi) is an extremely flexible and permissionless shared security system.**

This repository contains a Symbiotic Staker Rewards interface, its default implementation, and a default Operator Rewards.

[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/symbioticfi/rewards)

## Documentation

Can be found [here](https://docs.symbiotic.fi/core-modules/rewards).

## Technical Documentation

Can be found [here](./specs).

## Security

Security audits can be found [here](./audits).

## Usage

### Env

Create `.env` file using a template:

```
ETH_RPC_URL=
ETH_RPC_URL_HOLESKY=
ETHERSCAN_API_KEY=
```

\* ETH_RPC_URL is optional.<br/>\* ETH_RPC_URL_HOLESKY is optional.<br/>\* ETHERSCAN_API_KEY is optional.

### Build

```shell
forge build
```

### Test

```shell
forge test
```

### Format

```shell
forge fmt
```

### Gas Snapshots

```shell
forge snapshot
```
````

## File: remappings.txt

```
forge-std/=lib/forge-std/src/
@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/
@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/
@symbioticfi/core/=lib/core/
```
