Posted By : Ashish
In this article, we provide a step-by-step guide to staking smart contract development, deployment, and testing.
A smart contract is a computer program that executes the rules of a contract automatically when certain conditions are satisfied. These contracts are often kept on a blockchain, ensuring their tamper-proof and transparent nature. Smart contracts can be used for a variety of applications, including financial transactions, supply chain management, and enforcing agreements between parties.
A staking smart contract is a type of blockchain-based contract that enables users to lock up their cryptocurrency holdings for a certain period of time, typically in exchange for rewards or benefits. Staking smart contracts facilitate the staking process by automating the process of locking up cryptocurrency holdings and distributing rewards to users who participate in staking.
Staking smart contracts are a popular tool for blockchain networks that use a proof-of-stake (PoS) consensus mechanism, as they allow users to participate in the consensus process and earn rewards without having to invest in expensive mining hardware. By staking their cryptocurrency holdings, users can earn rewards while helping to secure the network and maintain its integrity.
You may also like | The Increasing Inevitability of Hybrid Smart Contract Development
We need to create two ERC20 tokens. One for reward and one for staking.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract Rtoken is ERC20, Ownable {
constructor() ERC20("MyToken", "MTK") {}
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract Stoken is ERC20, Ownable {
constructor() ERC20("MyToken", "MTK") {}
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
}
Now that we have the token contracts in place, we can create the staking contract that will use the token for staking and reward distribution. Here's a basic implementation of the staking contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
contract Staking {
IERC20 public tokenToStake;
IERC20 public rewardToken;
mapping(address => uint256) public stakedAmount;
mapping(address => uint256) public lastStakeTime;
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);
constructor(address _tokenToStake, address _rewardToken) {
tokenToStake = IERC20(_tokenToStake);
rewardToken = IERC20(_rewardToken);
}
function stake(uint256 amount) external {
require(amount > 0, "Staking amount must be greater than 0");
require(tokenToStake.balanceOf(msg.sender) >= amount, "Insufficient balance");
require(tokenToStake.allowance(msg.sender, address(this)) >= amount, "Insufficient allowance");
if (stakedAmount[msg.sender] == 0) {
lastStakeTime[msg.sender] = block.timestamp;
}
tokenToStake.transferFrom(msg.sender, address(this), amount);
stakedAmount[msg.sender] += amount;
emit Staked(msg.sender, amount);
}
function withdraw(uint256 amount) external {
require(amount > 0, "Withdrawal amount must be greater than 0");
require(stakedAmount[msg.sender] >= amount, "Insufficient staked amount");
uint256 reward = getReward(msg.sender);
if (reward > 0) {
rewardToken.mint(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
stakedAmount[msg.sender] -= amount;
tokenToStake.transfer(msg.sender, amount);
emit Withdrawn(msg.sender, amount);
}
function getReward(address user) public view returns (uint256) {
uint256 timeElapsed = block.timestamp - lastStakeTime[user];
uint256 stakedAmountUser = stakedAmount[user];
if (timeElapsed == 0 || stakedAmountUser == 0) {
return 0;
}
uint256 reward = stakedAmountUser * timeElapsed;
return reward;
}
function getStakedBalance(address user) public view returns (uint256) {
return stakedAmount[user];
}
}
interface IERC20 {
function totalSupply() external view returns (uint);
function balanceOf(address account) external view returns (uint);
function transfer(address recipient, uint amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint amount
) external returns (bool);
function mint(address to, uint256 amount) external;
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
}
Also, Check | Exploring the Potential of Solana Smart Contract Development
Mint some tokens for yourself and approve the staking contract with the number of stokens you want to stake.
Go to the staking contract and use the stake function.
Now. click on withdraw after some time.
You will be able to check your reward token balance.
Suggested Read | Ethereum Smart Contract Development | Discovering the Potential
You may also connect with our skilled smart contract developers if you want to integrate staking smart contract solutions into your projects or have any questions in mind.
September 6, 2024 at 09:14 am
Your comment is awaiting moderation.