// SPDX-License-Identifier: MIT // The SPDX-License-Identifier specifies the license for the code. pragma solidity ^0.8.0; // Indicates that the code should be compiled using a Solidity compiler version equal to or higher than 0.8.0. import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; // Imports interfaces for ERC721 and ERC20 tokens, Ownable contract, and SafeMath for safe arithmetic operations. contract NFTStaking is Ownable { using SafeMath for uint256; // The contract inherits from the Ownable contract, and SafeMath is used for safe arithmetic operations. IERC721 public nftToken; IERC20 public nativeToken; // Declarations of interfaces for ERC721 and ERC20 tokens. uint256 public stakingRewardRate = 1; uint256 public totalStakedNFTs; // Public variables to store staking parameters. mapping(address => uint256) public stakedNFTs; mapping(address => uint256) public lastClaimTime; // Mapping to track the number of staked NFTs and the last claim time for each user. event NFTStaked(address indexed user, uint256 amount); event TokensClaimed(address indexed user, uint256 amount); // Events to log NFT staking and token claiming. constructor(address _nftToken, address _nativeToken) { nftToken = IERC721(_nftToken); nativeToken = IERC20(_nativeToken); // Constructor to set the addresses of the ERC721 and ERC20 tokens. } function stakeNFT(uint256 tokenId) external { require(nftToken.ownerOf(tokenId) == msg.sender, "You do not own this NFT"); require(nftToken.getApproved(tokenId) == address(this), "Contract not approved to transfer NFT"); // Checks if the caller owns the NFT and if the contract is approved to transfer the NFT. nftToken.transferFrom(msg.sender, address(this), tokenId); stakedNFTs[msg.sender] = stakedNFTs[msg.sender].add(1); totalStakedNFTs = totalStakedNFTs.add(1); lastClaimTime[msg.sender] = block.timestamp; // Transfers the NFT to the contract, updates staking information, and records the last claim time. emit NFTStaked(msg.sender, tokenId); // Emits an event log for the NFT staking. } function claimTokens() external { uint256 reward = calculateReward(msg.sender); require(reward > 0, "No tokens to claim"); // Checks if there are tokens to claim. lastClaimTime[msg.sender] = block.timestamp; nativeToken.transfer(msg.sender, reward); // Updates the last claim time and transfers the earned tokens to the user. emit TokensClaimed(msg.sender, reward); // Emits an event log for the tokens claimed. } function calculateReward(address user) public view returns (uint256) { uint256 elapsedTime = block.timestamp.sub(lastClaimTime[user]); uint256 stakedAmount = stakedNFTs[user]; return stakedAmount.mul(stakingRewardRate).mul(elapsedTime).div(1 days); // Calculates the reward based on staking parameters and elapsed time. } function setStakingRewardRate(uint256 _stakingRewardRate) external onlyOwner { stakingRewardRate = _stakingRewardRate; // Allows the contract owner to set the staking reward rate. } }
0.4.18