Skip to main content

Staking ERC20 Tokens

import "@thirdweb-dev/contracts/extension/Staking20.sol";

Setup staking feature for your ERC20 tokens.

The Staking20 smart contract extension implements ERC20 staking mechanism. With this extension you can setup a staking contract for holders of your ERC20 tokens. Users can stake their tokens and earn a different set of ERC20 tokens as rewards.

Availability in base contracts

The Staking20 is already available in the following base contracts.

Implementing the Contract

Import the contract and make your contract inherit it.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@thirdweb-dev/contracts/extension/Staking20.sol";
import "@thirdweb-dev/contracts/eip/interface/IERC20.sol";
import "@thirdweb-dev/contracts/eip/interface/IERC20Metadata.sol";

contract MyContract is Staking20 {
// ERC20 Reward Token address. See {_mintRewards}.
address public rewardToken;

/**
* We store the contract deployer's address only for the purposes of the example
* in the code comment below.
*
* Doing this is not necessary to use the `Staking20` extension.
*/
address public deployer;

constructor(
uint256 _timeUnit,
uint256 _rewardRatioNumerator,
uint256 _rewardRatioDenominator,
address _stakingToken,
address _rewardToken,
address _nativeTokenWrapper
) Staking20(
_nativeTokenWrapper,
_stakingToken,
IERC20Metadata(_stakingToken).decimals(),
IERC20Metadata(_rewardToken).decimals()
) {
_setStakingCondition(_timeUnit, _rewardRatioNumerator, _rewardRatioDenominator);

rewardToken = _rewardToken;
deployer = msg.sender;
}

/**
* @dev Mint/Transfer ERC20 rewards to the staker. Must override.
*
* @param _staker Address for sending rewards to.
* @param _rewards Amount of tokens to be given out as reward.
*
*/
function _mintRewards(address _staker, uint256 _rewards) internal override {
IERC20(rewardToken).transfer(_staker, _rewards);
}

// Returns whether staking restrictions can be set in given execution context.
function _canSetStakeConditions() internal view override returns (bool) {
return msg.sender == deployer;
}
}

Full API Reference

stake

function stake(uint256 amount) external;
  • Lets a user stake a number of ERC20 tokens by passing in amount.
  • Parameter amount: Amount of tokens to stake.

withdraw

function withdraw(uint256 amount) external payable;
  • Un-stake and withdraw tokens from the contract.
  • Parameter amount: Amount of tokens to withdraw.

claimRewards

function claimRewards() external;
  • Claim accumulated rewards. This claim method allows for a pull mechanism where users must initiate claiming of rewards.

getStakeInfo

function getStakeInfo(address staker) external view returns (uint256 tokensStaked, uint256 rewards);
  • View number of tokens staked and total rewards available for a user.
  • Parameter staker: Account address of staker.

setRewardRatio

function setRewardRatio(uint256 numerator, uint256 denominator) external
  • Allows an authorized account to set reward ratio. Interpreted as (numerator/denominator) rewards per second/per day/etc based on time-unit. For e.g., ratio of 1/20 would mean 1 reward token for every 20 tokens staked.
  • Parameter numerator: Reward ratio numerator.
  • Parameter denominator: Reward ratio denominator.

setTimeUnit

function setTimeUnit(uint256 timeUnit) external;
  • Allows an authorized account to set time unit as a number of seconds. For e.g. 1 hour can be set as 3600 seconds - setting the reward frequency as per hour.
  • Parameter timeUnit: New time unit.