20,000 USDC
View results
Submission Details
Severity: medium

Lack of Staking Incentives for Late Stakers

Summary

Staking rewards are exponentially decreasing for late stakers. Hence it provides unfair advantage for early users and lack of incentives for late users.

Vulnerability Details

In Staking.sol, rewards are calculated via index as shown below:

function update() public {
uint256 totalSupply = TKN.balanceOf(address(this));
if (totalSupply > 0) {
uint256 _balance = WETH.balanceOf(address(this));
if (_balance > balance) {
uint256 _diff = _balance - balance;
if (_diff > 0) {
uint256 _ratio = _diff * 1e18 / totalSupply; // 10e8 * 1e18 / 100e8 = 1e17 // @audit - Lack of incentive for late users
if (_ratio > 0) {
index = index + _ratio;
balance = _balance;
}
}
}
}
}
...
uint256 _supplied = balances[recipient];
if (_supplied > 0) {
uint256 _supplyIndex = supplyIndex[recipient];
supplyIndex[recipient] = index;
uint256 _delta = index - _supplyIndex;
if (_delta > 0) {
uint256 _share = _supplied * _delta / 1e18;
claimable[recipient] += _share;
}

Problem with these calculations is this:
During early times of staking, index variable will change so fast, for example let's assume every day Fee contract sends 1e8 amount of wETH to the staking contract.First day Alice deposit 1e18 TKN and her supplyIndex is 0. Second day Bob deposit 1e18 TKN after first wETH send to the contract. This time Bob's supplyIndex hence index variable in general will be 0.5e8. So index variable changed 0.5e8 amount within one day.
The problem is index variable's increase rate is decreasing with totalSupply of TKN inside contract as can be shown below:

uint256 _ratio = _diff * 1e18 / totalSupply;
...
index = index + _ratio;

So now let's go to the future and see what happens:
Let's assume now there are 5000e18 TKN is available in contract.Again contract received 1e8 amount of wETH. After this transaction Alice deposits 1e18 TKN. This time _ratio will be 4e3 and index will raise as 4e3 amount. As we can see index's increase rate is exponentially decreasing. So much that if totalSupply in staking contract become %1 percent of the first mint of Beedle token, 1e18 TKN deposit will increase index only by "2".
In this case, first depositor can get "2.5e7" times more than last user as rewards regardless at time. It can even happen in one day (one person deposit large amount of TKN). Such that late users won't have any incentive to stake because index eventually will flatten.

Impact

Staking become increasingly useless with totalSupply deposited to contract. Hence protocol's one of main functionality is broken, so I consider this as medium.

Tools Used

Manual Review

Recommendations

Implement a staking system with an emphasis on time, not totalSupply. Masterchef algorithm can be such example for correct staking implementation.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!