Staking Mechanics
The staking mechanism of this contract is directly inspired by the Synthetix StakingRewards.sol
(opens in a new tab) implementation. The core mechanic involves the streaming of rewards over a designated period of time.
Each staker earns rewards proportional to their share of the total stake, and each staker earns only while their tokens are staked. Stakers may add or withdraw their stake at any point.
Beneficiaries can claim the rewards they've earned at any point. When a new reward is received, the reward duration restarts, and the rate at which rewards are streamed is updated to include the newly received rewards along with any remaining rewards that have finished streaming since the last time a reward was received.
StakingRewards Resources
The StakingRewards mechanic pioneered by Synthetix has been borrowed and battle tested in the DeFi ecosystem. Rather than rehashing the details, we recommend interested parties who are familiar with it review these and other resources explaining the core mechanic.
- Liquidity Mining on Uniswap v3 (opens in a new tab), by Dan Robinson, on the Paradigm Blog
- Scalable Reward Distribution on the Ethereum Blockchain (opens in a new tab), a brief technical paper by Bogdan Batog, Lucian Boca, & Nick Johnson
- Staking Rewards - Math, Examples and Algorithm (opens in a new tab), a video by Smart Contract Programmer, on YouTube
Differences from StakingRewards
The UniStaker implementation of the StakingRewards mechanism does include some differences from the original implementation. We review these here.
-
UniStaker enfranchises depositors by allowing them to retain their UNI governance rights. It does this by depositing staked tokens to an instance of
DelegationSurrogate
, a dummy contract whose sole purpose is to delegate voting weight to a designated entity. UniStaker requires stakers to delegate to themselves or another address. They cannot delegate to the zero address. -
UniStaker allows depositors to designate the beneficiary of their staking rewards. Effectively, any given deposit can earn rewards on behalf of any designated address.
-
UniStaker tracks stake on a per-deposit basis. Stakers may add to or withdraw UNI from a given deposit balance, or may alter the governance delegation and reward beneficiary associated with that deposit. A given address can have any number of deposit positions which are each tracked and managed independently with a unique identifier that is assigned when the deposit is created.
-
UniStaker has a bevy of small improvements to the Synthetix staking mechanism. These include optimizations for greater precision, lower gas usage, and refactoring for the sake of clearer code. One such change is covered in the greater detail in the Scaling Math section below.
-
UniStaker is designed to accept rewards from any number of reward notifier contracts designated by the admin. While Uniswap V3 protocol fees will be the only source of rewards initially, it is possible to add more in the future. Uniswap Governance will serve as the admin with the ability to add reward sources in the future.
Scaling math
The UniStaker scale factor (opens in a new tab) is 1e36 rather than 1e18. This increases precision.
UniStaker moves the scale factor into the global reward rate (opens in a new tab) variable. This further avoids precision loss when rewards are distributed and the updated rate is calculated. To calculate the human readable global reward rate, one must divide by the scale factor and by the token decimals.
Example: If the scaledRewardRate
variable returned: 70000000000000000000000000000000000000000000000000000`
Assuming a token with 18 decimals, we
would divide the number by 1e18 * 1e36
or 1e54
, producing a value of 0.07 tokens per second.