---
eip: 4000
title: ERC-4000 Staking-Reward Pool Standard
author: Dotta <https://twitter.com/cryppadotta>,
vfat <https://twitter.com/vfat12>,
DkNinja <https://twitter.com/DkNinja21>,
... you?
type: Standards Track
category: ERC
status: Idea
created: 2021-04-15
---
# ERC-4000 Staking-Reward Pool Standard
| eip | 4000 (*unofficial) |
| ------ | ---- |
| title | ERC-4000 Staking-Reward Pool Standard |
| authors | [Dotta](https://twitter.com/cryppadotta), [vfat](https://twitter.com/vfat12), [DkNinja](https://twitter.com/DkNinja21)|
|type | Standards Track |
|category| ERC |
|status | Idea |
|created | 2021-04-15 |
## :sparkles: Join the Discussion: :sparkles:
- [ERC-4000 Staking-Reward Pool Standard (request for comments) - EIPs - Fellowship of Ethereum Magicians](https://ethereum-magicians.org/t/erc-4000-staking-reward-pool-standard-request-for-comments/6004)
> ## Context
>
> Below is a draft EIP for a staking-reward pool standard. The goal is to define an easy-to-use convention for staking-reward pools.
>
> Staking-reward pools are a common way for projects to incentivize desired behaviors like providing liquidity, bonding, token distribution, or loan origination.
>
> The popularity of the staking-reward pool mechanism can be seen on websites like [vfat.tools](https://vfat.tools/) and [apy.vision](https://apy.vision/) which track hundreds of reward pools across the ecosystem.
>
> Nearly every new project launches reward pool contracts and nearly every project implements the interface differently.
>
> The standard below is based on the author's interactions with hundreds of "Masterchef-" and "Synthetix-"style staking-rewards pools.
>
> Adoption of a standard for staking-reward pools will benefit the ecosystem by composibility, similar to that seen with ERC20 tokens.
>
> ## Request for Comments
>
> The authors request your comments and feedback on this document before submitting for official EIP consideration in late-April 2021.
>
> Blockquotes indicate thoughts and open questions and will be removed from the final EIP draft
> [name=Dotta]
> April 15, 2021
## Simple Summary
A standard interface for staking pools with rewards.
## Abstract
The following standard allows for the implementation of a standard API for staking-rewards pools within smart contracts.
This standard provides basic functionality to stake tokens in smart contracts with multiple pools and inspect the rewards for doing so.
## Motivation
Staking-reward pools are a common way for projects to incentivize desired behaviors such as providing liquidity, bonding, token distribution, or loan origination.
This document specifies a standard interface that allows any staking-reward pools on Ethereum to be re-used by other applications such as wallets, user interfaces, yield aggregators, and other smart contracts.
## Specification
## Pool
### Methods
**NOTES**:
- The following specifications use syntax from Solidity `0.8.3` (or above)
#### poolLength
Returns the total number of pools
``` js
function poolLength() public view returns (uint256)
```
#### poolInfo
Returns the information about a pool.
```js
poolInfo(uint256 poolIdx) public view returns (
address stakingToken,
address rewardToken,
uint256 stakedAmount,
uint256 rewardAmount,
uint256 rewardPerBlock,
uint256 startBlock
)
```
Where:
* `stakingToken` is the address of the token to be staked in `poolIdx`
* `rewardToken` is the address of the token which is rewarded for staking in `poolIdx`
* `stakedAmount` is the total number of tokens currently staked in `poolIdx`
* `rewardAmount` is the total number of tokens currently allocated as rewards to the pool at `poolIdx`
* `rewardPerBlock` is the sum total of reward tokens accrued to all stakers in `poolIdx` for the current block
* `startBlock` is the first block number at which rewards will accrue for the pool at `poolIdx`
#### userInfo
Returns the information about `userAddress` at `poolIdx`
```js
userInfo(uint256 poolIdx, address userAddress) public view returns (
uint256 stakedAmount,
uint256 rewardAmount
)
```
Where:
* `stakedAmount` is the number of tokens `userAddress` has staked in `poolIdx`
* `rewardAmount` is the number of tokens credited to `userAddress` in `poolIdx` that have not yet been withdrawn
#### rewardForBlock
Returns the sum total of reward tokens accrued to all stakers in `poolIdx` at `blockNum`.
OPTIONAL - This method can be used to improve usability, but interfaces and other contracts MUST NOT expect these values to be present.
```js
rewardForBlock(uint256 poolIdx, uint256 blockNum) public view returns (uint256)
```
*Note* - The purpose of this optional method is to allow for calculation of non-linear reward accrual curves.
#### deposit
* Transfers `amount` of staking tokens from the calling user to the pool at `poolIdx` and
* MUST fire the `Deposit` event and
* Transfers all claimable reward tokens from the pool at `poolIdx` to the calling user and
* MUST fire the `Claim` event.
```js
deposit(uint256 poolIdx, uint256 amount) public nonpayable
```
*Note* - `amount` of 0 MUST be allowed, which has the effect of withdrawing all claimable rewards.
#### withdraw
* Transfers `amount` of staking tokens from the pool at `poolIdx` to the calling user and
* MUST fire the `Withdraw` event and
* Transfers all claimable reward tokens from the pool at `poolIdx` to the calling user and
* MUST fire the `Claim` event.
```js
withdraw(uint256 poolIdx, uint256 amount) public nonpayable
```
*Note* - `amount` of 0 MUST be allowed, which has the effect of withdrawing all claimable rewards.
#### claim
* Transfers all claimable reward tokens from the pool at `poolIdx` to the calling user and
* MUST fire the `Claim` event.
```js
claim(uint256 poolIdx) public nonpayable
```
### Events
#### Deposit
MUST trigger when staking tokens are deposited, including zero value deposits.
```js
event Deposit(address indexed user, uint256 indexed poolIdx, uint256 stakeAmount);
```
Where:
* `user` is the address of the depositing user
* `poolIdx` is the index of the pool
* `stakeAmount` is the amount of the stake token deposited
#### Withdraw
MUST trigger when staking tokens are withdrawn, including zero value withdrawals.
```js
event Withdraw(address indexed user, uint256 indexed poolIdx, uint256 stakeAmount);
```
Where:
* `user` is the address of the depositing user
* `poolIdx` is the index of the pool
* `stakeAmount` is the amount of the stake token withdrawn
#### Claim
MUST trigger when reward tokens are withdrawn, including zero value withdrawals.
```js
event Claim(address indexed user, uint256 indexed poolIdx, uint256 rewardAmount);
```
Where:
* `user` is the address of the depositing user
* `poolIdx` is the index of the pool
* `rewardAmount` is the amount of the reward token withdrawn
## Open Questions
>
> Q: Should we specify ERC20 as part of this standard?
> A: Probably not because this ERC might be useful for other sorts of tokens e.g. ERC-721 NFTs
>
> Q: What about `allocPoint`, `getMultiplier`, `lastRewardBlock`, `rewardDebt` etc?
> A: While commonly exposed in "Masterchef" contracts, these values are internals that don't need to be exposed in the standard. A contract can expose them if they desire.
>
> Q: What about a global `rewardPerBlock` that shows the total emission per block for the entire contract?
> A: This standard allows for differnt reward tokens to be emitted for each pool, so a global `rewardPerBlock` would not be useful
>
> Q: What about vesting and locking both stake and rewards?
> A: This standard doesn't address those issues.
>
> Q: What about legacy staking-reward pool contracts that don't conform to this standard?
> A: It should be straightforward to write a Masterchef-to-ERC-4000 proxy-adapter contract (cf. multicall) that adapts the values for any standard Masterchef- or Synthetix-style pool.
## Implementation
#### Example implementations are available at
- TODO - any takers?
## History
Historical links related to this standard:
- [EIP-900: Simple Staking Interface (DRAFT)](https://eips.ethereum.org/EIPS/eip-900) is an earlier attempt at defining a staking interface
- [Masterchef TODO](#TODO) - _What was the very first Masterchef contract? If you know, please comment here_
## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).