---
# System prepended metadata

title: Masterchef Staking protocol

---

# Masterchef Staking protocol
Lets briefly see how the masterchef staking contract works;

Each time a state-changing transaction occurs, we count the number of blocks that have passed, multiply that number by the reward per block, and divide the result by the total supply staked. 

This represents the total reward that a token earned during that period, and we add that amount to a global accumulator that began at zero at the beginning of time. 

If we continue this process each time a transaction is received, we will be able to determine the total reward that a single token has earned since the beginning of time.

When a user interacts with the pool (e.g., deposits, withdraws, or harvests), their individual reward is calculated based on their staked amount and the `accumulatedRewardsPerShare`.

## Reward Calculation

Every time a state-changing transaction occurs (e.g., deposit, withdrawal), the contract calculates how many blocks have passed since the last reward update. It multiplies the blocks passed by the reward per block to get the total rewards generated.

It divides the total rewards by the total tokens staked to get the rewards per token accrued over that interval. 

This value is added to the global accumulatedRewardsPerShare, which is a running total of rewards per token since the beginning of the pool.

```
function pendingSushi(uint256 _pid, address _user)
    external
    view
    returns (uint256)
{
    PoolInfo storage pool = poolInfo[_pid];
    UserInfo storage user = userInfo[_pid][_user];
    uint256 accSushiPerShare = pool.accSushiPerShare;
    uint256 lpSupply = pool.lpToken.balanceOf(address(this));
    if (block.number > pool.lastRewardBlock && lpSupply != 0) {
        uint256 multiplier =
            getMultiplier(pool.lastRewardBlock, block.number);
        uint256 sushiReward =
            multiplier.mul(sushiPerBlock).mul(pool.allocPoint).div(
                totalAllocPoint
            );
        accSushiPerShare = accSushiPerShare.add(
            sushiReward.mul(1e12).div(lpSupply)
        );
    }
    return user.amount.mul(accSushiPerShare).div(1e12).sub(user.rewardDebt);
}
```


`accumulatedRewardsPerShare` Formula is a key concept in many staking and farming contracts. It helps in efficiently distributing rewards among stakers without the need to loop through all stakers every time rewards are distributed.

The formula to update accumulatedRewardsPerShare is:

```
accumulatedRewardsPerShare = accumulatedRewardsPerShare +
(rewards×REWARDS_PRECISION / tokensStaked)

accumulatedRewardsPerShare=accumulatedRewardsPerShare+( tokensStakedrewards×REWARDS_PRECISION )
```

Where:

* rewards is the total rewards generated since the last update.
* REWARDS_PRECISION is a large constant (like 1e12) to ensure precision in division operations.
* tokensStaked is the total number of tokens staked in the pool.