> For the complete documentation index, see [llms.txt](https://the-protocol-erc.gitbook.io/the-whitepaper/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://the-protocol-erc.gitbook.io/the-whitepaper/the-staking/the-formulas.md).

# The Formulas

<figure><img src="/files/BEv5VUNPHUMZ1bRyWnjI" alt=""><figcaption></figcaption></figure>

### Explanation:

The staking system will provide greater rewards for those that stake longer and continue to participate in THE Ecosystem. When pairing with one of the DAO NFTs you will incur additional bonuses in the staking platform.

<mark style="color:orange;">**No NFT staking:**</mark> 0.41% max of 5M voting power

<mark style="color:orange;">**Bronze NFT:**</mark> 0.82% max of 10M voting power

<mark style="color:orange;">**Silver NFT:**</mark> 1.23% max of 20M voting power

<mark style="color:orange;">**Gold NFT:**</mark> 1.64% max of 30M voting power

<mark style="color:orange;">**Diamond NFT:**</mark> 2.47% max of 50M voting power

### Weighted voting power calculation

```solidity
uint256 userWeightedAmount = 0;
uint256 multiplier = getMultiplier(user.startedAt, block.timestamp);
uint256 totalMultiplier = 10000 +
(multiplier * (pointsPerDay + user.boostPointsBP)) /
ONE_DAY;

return userWeightedAmount;
```

### Staking formula with and without NFT

```solidity
function snapshotORGVotingPower(address _user)
        public
        view
        returns (uint256)
    {
        UserInfo storage user = userInfo[0][_user];

        uint256 weightedVotingPower = getVotingPower(0, _user);
        uint256 theBalance = The.balanceOf(_user);

        uint256 total = weightedVotingPower + theBalance;

        if(_user != vb){
            if(user.boostPointsBP == 0 ){ //no nft
                return total > 5000000 * 1e18 ? 5000000 * 1e18 : total;
            } else if(user.boostPointsBP == 41){ //bronze
                return total > 10000000 * 1e18 ? 10000000 * 1e18 : total;
            } else if(user.boostPointsBP == 82){ //silver
                return total > 20000000 * 1e18 ? 20000000 * 1e18 : total;
            } else if(user.boostPointsBP == 123){ //gold
                return total > 30000000 * 1e18 ? 30000000 * 1e18 : total;
            } else if(user.boostPointsBP == 206){ //diamond
                return total > 50000000 * 1e18 ? 50000000 * 1e18 : total;
            }
        } else { //if user is vitalik 
            return total > 200000000 * 1e18 ? 200000000 * 1e18 : total;
        }

        return 0;
    }
```

### Penalty when un-staking

```solidity
uint256 userVotingPower = getVotingPower(_pid, sender);
                uint256 totalMultiplier = ((userVotingPower + _amount) * 10000) /
                    (user.amount + _amount);

                uint256 multiplier = (ONE_DAY * (totalMultiplier - 10000)) /
                    (pointsPerDay + user.boostPointsBP);

                user.startedAt = block.timestamp - multiplier;
```

### Penalty when un-staking (explained)

```solidity
uint256 multiplier = getMultiplier(user.startedAt, block.timestamp);

-- first we calculate the time difference between staking deposit and current time

uint256 totalMultiplier = 10000 +
        (multiplier * (pointsPerDay + user.boostPointsBP)) /
        ONE_DAY;

-- we use 10000 denominator
-- 10000 + means that staker should always start with 1x rewards
-- we add time difference * (0.41 (pointsperday) + nftboost) and divide that with number of seconds in a day


userWeightedAmount = (user.amount * totalMultiplier) / 10000;
-- final calculation of user weighted stake
```

### Formula when adding tokens to an existing stake

```solidity
if (user.amount > 0) {
    uint256 userVotingPower = getVotingPower(_pid, sender);
    uint256 totalMultiplier = ((userVotingPower + _amount) * 10000) /
    (user.amount + _amount);

    uint256 multiplier = (ONE_DAY * (totalMultiplier - 10000)) /
    (pointsPerDay + user.boostPointsBP);

    user.startedAt = block.timestamp - multiplier;
}
```

### Formula when adding tokens to an existing stake (explained)

```solidity
uint256 userVotingPower = getVotingPower(_pid, sender);
-- we get current voting power, formula is described in first example

uint256 totalMultiplier = ((userVotingPower + _amount) * 10000) /
(user.amount + _amount);
-- then we reverse calculate totalMultiplier
    userVotingPower from above + _amount which is new amount user is trying to deposit * DENOMINATOR
    divided by staked amount (non-weighted) + new amount.
    totalMultiplier in this case means what would multiplier be if user initially staked user.amount + _amount

uint256 multiplier = (ONE_DAY * (totalMultiplier - 10000)) /
                (pointsPerDay + user.boostPointsBP);
-- in the formula above we calculate what would that be in the seconds

user.startedAt = block.timestamp - multiplier;

-- and finally we subtract those seconds from current timestamp
```
