# BuildersV4

## Overview

The `BuildersV4` protocol is an on-chain coordination layer designed for distributing MOR token rewards to subnet builders in a scalable and fair manner. It allows anyone to create a Subnet with specific staking parameters and enables users to stake MOR tokens under a particular Subnet. Rewards are calculated globally and distributed to Subnets based on their effective contribution, determined through staked amounts.

Each Subnet is identified by a unique ID derived from its name and the chain ID, allowing for identical Subnet names across multiple blockchains (v1 and v2 Subnets will have previous ID). Subnet builders (admins) and subnet claim admin are the only ones authorized to claim MOR rewards for their Subnets, while users’ rewards are handled off-chain by the builders. The reward calculation is powered by an external emission curve (`RewardPool`) and uses a rate model to determine distribution over time.

Unlike previous versions, v4 removes virtual deposits and multipliers, simplifying staking logic and removing dependency on the claim lock end. Additionally, the system introduces a `networkShare` parameter to control how much of the `RewardPool` output flows to Builders overall.

## Key Features

1. Subnet creation and configuration: anyone can create a pool with custom parameters; the builder (admin) is assigned at creation.
2. User staking: users stake tokens into any subnet.
3. Subnet-controlled reward claiming: only the Subnet admin or Subnet claim admin can claim the MOR rewards, enabling flexible distribution outside the contract scope.
4. Reward calculation: uses a dynamic rate updated with each user action and proportional to the protocol-wide deposits.
5. Fee system: integrated with `FeeConfig` for applying customizable claim and creation fees.
6. Upgradeable and permissioned: built with UUPS and Ownable patterns for controlled upgrades and ownership-based access.

## Storage

### feeConfig

Address of the `FeeConfig` contract used to calculate protocol fees.

```solidity
address public feeConfig;
```

### buildersTreasury

Address of the `BuildersTreasury` contract which stores and distributes reward tokens.

```solidity
address public buildersTreasury;
```

### depositToken

Address of the MOR token users deposit into Subnets.

```solidity
address public depositToken;
```

### unusedStorage1\_V4Update (old editPoolDeadline)

~~The time window (in seconds) before the pool starts, during which pool parameters can still be edited by the pool admin.~~ Deprecated in v4.

```solidity
uint128 public editPoolDeadline;
```

### minimalWithdrawLockPeriod

Minimum duration (in seconds) after a deposit during which withdrawals are locked.

```solidity
uint256 public minimalWithdrawLockPeriod;
```

### allSubnetsData (old totalPoolData)

Aggregated data for all Subnets pools in the system.

```solidity
AllSubnetsData public allSubnetsData;

struct TotalPoolData {
  uint256 distributedRewards;
  uint256 rate;
  uint256 totalDeposited;
  uint256 totalVirtualDeposited;
}
```

| Name                    | Description                                                               |
| ----------------------- | ------------------------------------------------------------------------- |
| `distributedRewards`    | Total amount of rewards distributed across all pools. Wei.                |
| `rate`                  | The current reward rate                                                   |
| `totalDeposited`        | Total tokens deposited without applying any multiplier. Wei.              |
| `totalVirtualDeposited` | Total tokens deposited with multiplier (used in reward calculations). Wei |

### subnets (old builderPools)

Mapping of  `subnetID` to Subnet configuration.

```solidity
mapping(bytes32 subnetId => Subnet) public subnets;

struct Subnet {
  string name;
  address admin;
  uint128 unusedStorage1_V4Update;
  uint128 withdrawLockPeriodAfterDeposit;
  uint128 unusedStorage2_V4Update;
  uint256 minimalDeposit;
  address claimAdmin;
}

```

| Name                                         | Description                                                                                       |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| `name`                                       | The name of the Subnet.                                                                           |
| `admin`                                      | The address of the Subnet administrator.                                                          |
| `unusedStorage1_V4Update (old poolStart)`    | ~~Timestamp when the pool becomes active.~~ Deprecated in v4.                                     |
| `withdrawLockPeriodAfterDeposit`             | Time period after deposit during which withdrawal is locked. Seconds.                             |
| `unusedStorage2_V4Update (old claimLockEnd)` | ~~Timestamp after which rewards can be claimed by the Subnets admin. Seconds.~~ Deprecated in v4. |
| `minimalDeposit`                             | Minimum amount a user must deposit to participate. Wei.                                           |
| `claimAdmin`                                 | This address can claim the Subnet rewards against `admin`.                                        |

### subnetsData (old buildersPoolData)

Mapping of pool ID to the current dynamic pool state.

```solidity
mapping(bytes32 subnetId => SubnetData) public subnetsData;

struct SubnetData {
  uint128 unusedStorage1_V4Update;
  uint256 deposited;
  uint256 unusedStorage2_V4Update;
  uint256 rate;
  uint256 pendingRewards;
}
```

| Name                                             | Description                                                                                                            |
| ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| `unusedStorage1_V4Update (old lastDeposit)`      | ~~Timestamp in seconds of the last deposit into the pool.~~ Deprecated in v4.                                          |
| `deposited`                                      | Total amount deposited MOR. Wei.                                                                                       |
| `unusedStorage2_V4Update (old virtualDeposited)` | ~~Total amount deposited with multipliers applied. Wei.~~ Deprecated in v4.                                            |
| `rate`                                           | Current reward rate for the Subnet                                                                                     |
| `pendingRewards`                                 | Number of rewards accrued to the Subnet. Is not the final reward at a given time. Used for internal calculations. Wei. |

### usersData

Mapping of user address and pool ID to their user-specific data.

```solidity
mapping(address => mapping(bytes32 => UserData)) public usersData;

struct UserData {
  uint128 lastDeposit;
  uint128 unusedStorage1_V4Update;
  uint256 deposited;
  uint256 unusedStorage2_V4Update;
}
```

| Name                                             | Description                                                                       |
| ------------------------------------------------ | --------------------------------------------------------------------------------- |
| `lastDeposit`                                    | Timestamp in seconds of the user's last deposit.                                  |
| `unusedStorage1_V4Update ( old claimLockStart)`  | ~~Timestamp when the user activated the reward lock. Seconds~~. Deprecated in v4. |
| `deposited`                                      | Total tokens the user deposited (raw amount). Wei.                                |
| `unusedStorage2_V4Update (old virtualDeposited)` | ~~Tokens deposited by user with multiplier applied. Wei~~. Deprecated in v4.      |

### rewardPool

The address of the `RewardPool` contract address.

```solidity
address public rewardPool;
```

### subnetCreationFeeAmount

This value in wei is taken from the tx sender when the Subnet created.

```solidity
uint256 public subnetCreationFeeAmount;
```

### networkShare

The `networkShare` is the share of the network rewards that will be distributed to Subnets, e.g. `100% = 10^25`. If global reward curve return `X` amount of rewards, then all Subnets will \* receive `X * networkShare / 10^25`

```solidity
uint256 public networkShare;
```

### networkShareOwner

This address can change the `networkShare` value.

```solidity
address public networkShareOwner;
```

### subnetsMetadata

Contain the metadata about Subnets

```solidity
mapping(bytes32 subnetId => SubnetMetadata) public subnetsMetadata;

struct SubnetMetadata {
  string slug;
  string description;
  string website;
  string image;
}
```

| Name          | Description                    |
| ------------- | ------------------------------ |
| `slug`        | The Subnet slug string.        |
| `description` | The Subnet description string. |
| `website`     | The Subnet website string.     |
| `image`       | The Subnet image link.         |

### allSubnetsDataV4

The variable that stores all Subnets data, addition for `allSubnetsData`.

```solidity
AllSubnetsDataV4 public allSubnetsDataV4;

struct AllSubnetsDataV4 {
  uint256 distributedRewards;
  uint256 undistributedRewards;
  uint256 claimedRewards;
  uint128 lastUpdate;
}
```

| Name                   | Description                                                                           |
| ---------------------- | ------------------------------------------------------------------------------------- |
| `distributedRewards`   | The amount of rewards that calculated and virtually distributed between Subnets. Wei. |
| `undistributedRewards` | The amount of rewards that calculated and stored for the contract owner. Wei          |
| `claimedRewards`       | The total amount of claimed rewards. Wei.                                             |
| `lastUpdate`           | The `AllSubnetsData.rate` last update timestamp.                                      |

### Fee oprations

The lables for fee operations, uses for fee and treasury receiving in the `FeeConfig` contract. `FEE_SUBNET_CREATE` uses only treasury address from the `FeeConfig` contract.

```solidity
// bytes32 private constant FEE_WITHDRAW_OPERATION = "withdraw";
bytes32 public constant FEE_CLAIM_OPERATION = "claim";
bytes32 public constant FEE_SUBNET_CREATE = "buildersV4.fee.subnet.create";
```

## Write functions for the contract owner

### BuildersV4\_init

Initializes the contract with essential parameters and configuration contracts. This function must be called once after deployment.

```solidity
function BuildersV4_init(
  address depositToken_,
  address feeConfig_,
  address treasury_,
  address rewardPool_,
  address networkShareOwner_,
  uint256 minimalWithdrawLockPeriod_
) external initializer
```

| Name                         | Description                                                                          |
| ---------------------------- | ------------------------------------------------------------------------------------ |
| `depositToken_`              | Address of the token that users will deposit in builder pools. MOR token.            |
| `feeConfig_`                 | Address of the `FeeConfig` contract used to calculate protocol fees.                 |
| `treasury_`                  | Address of the `BuildersTreasuryV2` contract used to store and distribute rewards.   |
| `rewardPool_`                | Address of the `RewardPool` contract.                                                |
| `networkShareOwner_`         | The address wich can edit the `networkShare`.                                        |
| `minimalWithdrawLockPeriod_` | Minimum lock duration after deposit in seconds before users can withdraw staked MOR. |

### setFeeConfig

Sets the address of the `FeeConfig` contract.

```solidity
function setFeeConfig(address feeConfig_) public onlyOwner
```

| Name         | Description                                      |
| ------------ | ------------------------------------------------ |
| `feeConfig_` | Address of a contract that implements IFeeConfig |

### setBuildersTreasury

Sets the address of the `BuildersTreasuryV2` contract.

```solidity
function setBuildersTreasury(address buildersTreasury_) public onlyOwner
```

| Name                | Description                                             |
| ------------------- | ------------------------------------------------------- |
| `buildersTreasury_` | Address of a contract that implements IBuildersTreasury |

### setMinimalWithdrawLockPeriod

Sets the minimum lock period that must pass before a user can withdraw MOR after depositing.

```solidity
function setMinimalWithdrawLockPeriod(
  uint256 minimalWithdrawLockPeriod_
) public onlyOwner
```

| Name                         | Description                                                      |
| ---------------------------- | ---------------------------------------------------------------- |
| `minimalWithdrawLockPeriod_` | Minimum lock period (in seconds) after deposit before withdrawal |

### setRewardPool

Sets the address of the `RewardPool` contract.

```solidity
function setRewardPool(address rewardPool_) external onlyOwner;
```

| Name          | Description                                  |
| ------------- | -------------------------------------------- |
| `rewardPool_` | Address of the `RewardPool` contract to set. |

### setNetworkShareOwner

Sets the address that is authorized to change the networkShare value.

```solidity
function setNetworkShareOwner(address networkShareOwner_) external onlyOwner;
```

| Name                 | Description                                                      |
| -------------------- | ---------------------------------------------------------------- |
| `networkShareOwner_` | Address that will be allowed to update the `networkShare` value. |

### setNetworkShare

Sets the percentage of rewards allocated to all Subnets.

```solidity
function setNetworkShare(uint256 networkShare_) external onlyOwner;
```

| Name            | Description                                                            |
| --------------- | ---------------------------------------------------------------------- |
| `networkShare_` | Percentage value where 100% = 1e25. Only owner or `networkShareOwner`. |

### setSubnetCreationFeeAmount

Sets the fee amount (in MOR tokens) required to create a Subnet.

```solidity
function setSubnetCreationFeeAmount(
  uint256 subnetCreationFeeAmount_
) external onlyOwner;
```

| Name                       | Description        |
| -------------------------- | ------------------ |
| `subnetCreationFeeAmount_` | MOR amount in wei. |

## Write functions

### createBuilderPool

Creates a new Subnet with specific parameters. If `subnetCreationFee` set, it will be charged from the tx caller.

```solidity
function createSubnet(
  Subnet calldata subnet_,
  SubnetMetadata calldata metadata_
) external;
```

| Name        | Description                  |
| ----------- | ---------------------------- |
| `subnet_`   | The `Subnet` struct.         |
| `metadata_` | The `SubnetMetadata` struct. |

### editSubnet

Edits an existing Subnet's main configuration. The caller should be the Subnet admin.

```solidity
function editSubnet(
  bytes32 subnetId_,
  Subnet calldata newSubnet_
) external onlySubnetOwner(subnetId_)
```

| Name         | Description          |
| ------------ | -------------------- |
| `subnetId_`  | ID of the Subnet.    |
| `newSubnet_` | The `Subnet` struct. |

### editSubnet

Edits an existing Subnet's metadata configuration. The caller should be the Subnet admin.

```solidity
function editSubnetMetadata(
  bytes32 subnetId_,
  SubnetMetadata calldata metadata_
) public onlySubnetOwner(subnetId_)
```

| Name        | Description                  |
| ----------- | ---------------------------- |
| `subnetId_` | ID of the Subnet.            |
| `metadata_` | The `SubnetMetadata` struct. |

### deposit

Allows a user to deposit tokens into a specific Subnet.

```solidity
function deposit(bytes32 subnetId_, uint256 amount_) external
```

| Name        | Description                       |
| ----------- | --------------------------------- |
| `subnetId_` | ID of the Subnet.                 |
| `amount_`   | Amount of tokens to deposit. Wei. |

### withdraw

Allows a user to withdraws tokens from a specific Subnet.

```solidity
function withdraw(bytes32 subnetId_, uint256 amount_) external
```

| Name        | Description                        |
| ----------- | ---------------------------------- |
| `subnetId_` | ID of the Subnet.                  |
| `amount_`   | Amount of tokens to withdraw. Wei. |

### claim

Allows the Subnet admin or Subnet claim admin to claim the accumulated MOR rewards.

```solidity
function claim(bytes32 subnetId_, address receiver_) external
```

| Name        | Description                                |
| ----------- | ------------------------------------------ |
| `subnetId_` | ID of the Subnet.                          |
| `receiver_` | Address to receive the claimed MOR rewards |

## Read functions

### getCurrentSubnetsRewards<br>

The function calculates the potential claim reward amount for **ALL** Subnets at the current moment in time, based on the current contract parameters. It estimates the unclaimed rewards that would be distributed if a claim were made now.

```solidity
function getCurrentSubnetsRewards() external view returns (uint256)
```

### getCurrentSubnetRewards

The function calculates the potential claim reward amount for the **SPECIFIC** Subnet at the current moment in time, based on the current contract parameters. It estimates the unclaimed rewards that would be distributed if a claim were made now.

```solidity
function getCurrentSubnetRewards(
  bytes32 subnetId_
) external view returns (uint256)
```

| Name        | Description       |
| ----------- | ----------------- |
| `subnetId_` | ID of the Subnet. |

### getSubnetId

Computes the unique ID of a Subnet based on its name and chain ID.

```solidity
function getSubnetId(string memory subnetName_) public view returns (bytes32)
```

| Name          | Description        |
| ------------- | ------------------ |
| `subnetName_` | Name of the Subnet |

### getSubnetIdOld

Computes the unique ID of a Subnet based on its name. Subnets created in the v1 and v2 used this ID.

```solidity
function getSubnetIdOld(string memory subnetName_) public view returns (bytes32)
```

| Name          | Description        |
| ------------- | ------------------ |
| `subnetName_` | Name of the Subnet |

### supportsInterface

Used for interface detection (ERC165). Returns true if the contract supports a specific `interfaceId_`. Supports `IBuildersV2`, `IERC165`.

```solidity
function supportsInterface(bytes4 interfaceId_) external pure returns (bool)
```

### version

Returns the current version of the contract.

```solidity
function version() external pure returns (uint256
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gitbook.mor.org/smart-contracts/documentation/builders-protocol/v4-protocol/contracts/buildersv4.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
