Cara Membuat NFT Staking dengan Fitur Reward : Deploy CRC721 & NFT Staking – Coinex Smart Chain


NFT adalah singkatan dari Non Fungiable Token, NFT adalah jenis token-crc721 yang bersifat unik secara kriptografis dan setiap token nft terkait dengan konten digital (dan terkadang fisik), nft bisa digunakan untuk memberikan bukti kepemilikan suatu karya atau property digital. NFT memiliki banyak  penggunaan, termasuk karya seni, koleksi digital, musik, dan item dalam video game.

NFT adalah salah satu sektor yang kini telah mengalami pertumbuhan tercepat di industri kripto. Token yang tidak dapat dipertukarkan adalah aset digital yang berisi informasi pengenal yang dicatat dalam kontrak pintar blockchain.

Meta data yang tercantum pada setiap nft membuat setiap token nft menjadi unik, dan karena itu, mereka tidak dapat langsung digantikan oleh token lain. Berbeda dengan token crc20, token nft tidak dapat ditukarkan antara satu sama lain, karena setiap token nft benar-benar unik dan tiada duanya.

NFT Staking adalah suatu dapps yang memilik fungsi untuk mempertaruhkan token crc-721 ke dalam smart contract, yang bertujuan untuk mendapatkan reward token (biasanya token crc20). nft staking akan membuat user lebih tertarik untuk mengkoleksi lebih banyak nft, karena fitur reward staking yang menguntungkan user, ini adalah salah satu strategi yang bagus untuk mengembangkan project.

Di artikel ini kami akan memberikan edukasi cara membuat nft staking dengan fitur reward (token crc20), kami akan menggunakan blockchain coinex smart chain untuk menjadi tuan rumah dapps nft staking tersebut. Mengapa memilih coinex smart chain ? karena blockchain CSC (coinex smart chain) mempunyai performa tinggi, pemrosesan transaksi sangat cepat (2-3 detik), ramah lingkungan (Dpos) dan fee transaksi sangat murah.

 

Apa saja yang dibutuhkan ? 
1# Wallet Metamask

Metamask adalah wallet evm yang popuper, karena penggunaanya yang sangat mudah, metamask juga support banyak blockchain seperti ethereum, binance smart chain, near, polygon matic, coinex smart chain, dll. Saya anjurkan anda menggunakan metamask browser. Setelah install metamask, anda perlu setting rpc network ke rpc coinex smart chain.

RPC URL : https://rpc.coinex.net
Network Name : Coinex Smart Chain
ChainID : 52
Symbol : CET
Block Explorer : https://www.coinex.net

 

2# Coin CET (Coin Native Coinex Smart Chain)

Coin CET adalah coin native dari blockchain coinex smart chain, coin cet digunakan untuk membayar semua transaksi di jaringan coinex smart chain. Kita membutuhkan sedikit coin cet untuk membuat smart contract dan interact contract nft staking. Anda bisa membeli coin cet di Coinex Exchange, setelah memiliki coin cet, segera kirim ke wallet address metamask anda.

 

3# Smart Contract CRC20

Token crc20 akan kita gunakan sebagai reward untuk para staker yang melakukan staking nft di smart contract.  Untuk membuat token crc20 anda memerlukan code solidity, anda bisa menggunakan code di bawah ini.

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

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract TokenReward1 is ERC20 {
    constructor() ERC20("Token Reward 1", "TR1") {
        _mint(msg.sender, 1000000000 * 10 ** decimals());
    }
}

 

4# Smart Contract CRC721

Dibawah ini adalah code solidity untuk membuat token crc-721, anda bisa menggunakan code ini atau menggunakan code dari source lain.

 // SPDX-License-Identifier: MIT
pragma solidity 0.8.6;

import "https://github.com/0xcert/ethereum-erc721/blob/master/src/contracts/tokens/nf-token-metadata.sol";
import "https://github.com/0xcert/ethereum-erc721/blob/master/src/contracts/ownership/ownable.sol";

contract CVR1 is NFTokenMetadata, Ownable {

constructor() {
nftName = "CryptoVIR NFT 1";
nftSymbol = "CVR1";
}

function mint(address _to, uint256 _tokenId, string calldata _uri) external onlyOwner {
super._mint(_to, _tokenId);
super._setTokenUri(_tokenId, _uri);
}

}

 

5# Karya Digital (Image/Lukisan/Digital Art)

Anda membutuhkan karya digital seperti lukisan, digital art, foto atau image apa saja untuk token nft crc721. Image/Foto nantinya di unggah ke decentralized storage dengan tujuan agar file tersebut abadi (bisa di akses selamanya) tanpa ada masa expired.

 

6# Decentralized Storage (IPFS/Siacoin)

Untuk membuat nft atau token crc-721 kita membutuhkan metadata, metadata adalah sebuah file json yang berisi informasi dan id unik nft untuk setiap token nft. Metadata harus di upload di hosting yang abadi (tanpa masa expired), contohnya adalah ipfs , siacoin dan bittorent.

The Interplanetary File System (IPFS) adalah salah satu protokol penyimpanan file terdistribusi yang populer, ipfs memungkinkan komputer di seluruh dunia untuk menyimpan dan menyajikan file sebagai bagian dari jaringan peer-to-peer raksasa. Siapapun dapat mengunduh software ipfs dan mulai upload file serta menyajikan file di jaringan ipfs. Ketika seseorang menjalankan node ipfs , maka mereka dapat upload file ke jaringan IPFS, dan file itu dapat dilihat dan diunduh oleh siapa pun di dunia yang juga menjalankan node ipfs.

Siacoin/Sia Network adalah salah satu jaringan penyimpanan cloud berbasis blockchain yang cukup populer, sia network menggunakan penyimpanan terdesentralisasi dengan menggunakan ruang penyimpanan hard drive yang kurang dimanfaatkan, Sia Storage Platform telah menciptakan pasar baru untuk penyimpanan data berbasis blockchain. Ini memberikan tingkat keandalan yang lebih tinggi di pasar cloud storage dan menjadi solusi serta alternatif penyimpanan terpusat. Selain itu, sia network mempunyai biaya rental yang jauh lebih rendah dan lebih andal dari pada platform penyimpanan cloud terpusat.

 

7# Smart Contract NFT Staking
 // SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

contract ERC721Staking is ReentrancyGuard {
    using SafeERC20 for IERC20;
    IERC20 public immutable rewardsToken;
    IERC721 public immutable nftCollection;

    constructor(IERC721 _nftCollection, IERC20 _rewardsToken) {
        nftCollection = _nftCollection;
        rewardsToken = _rewardsToken;
    }

    struct StakedToken {
        address staker;
        uint256 tokenId;
    }

    struct Staker {
        uint256 amountStaked;
        StakedToken[] stakedTokens;
        uint256 timeOfLastUpdate;
        uint256 unclaimedRewards;
    }
    uint256 private rewardsPerHour = 1000000000000000000000;
    mapping(address => Staker) public stakers;
    mapping(uint256 => address) public stakerAddress;
    function stake(uint256 _tokenId) external nonReentrant {
        if (stakers[msg.sender].amountStaked > 0) {
            uint256 rewards = calculateRewards(msg.sender);
            stakers[msg.sender].unclaimedRewards += rewards;
        }

        require(
            nftCollection.ownerOf(_tokenId) == msg.sender,
            "You don't own this token!"
        );


        nftCollection.transferFrom(msg.sender, address(this), _tokenId);
        StakedToken memory stakedToken = StakedToken(msg.sender, _tokenId);
        stakers[msg.sender].stakedTokens.push(stakedToken);
        stakers[msg.sender].amountStaked++;
        stakerAddress[_tokenId] = msg.sender; 
        stakers[msg.sender].timeOfLastUpdate = block.timestamp;
    }
    
    function withdraw(uint256 _tokenId) external nonReentrant {
        // Make sure the user has at least one token staked before withdrawing
        require(
            stakers[msg.sender].amountStaked > 0,
            "You have no tokens staked"
        );
        require(stakerAddress[_tokenId] == msg.sender, "You don't own this token!");
        uint256 rewards = calculateRewards(msg.sender);
        stakers[msg.sender].unclaimedRewards += rewards;

        uint256 index = 0;
        for (uint256 i = 0; i < stakers[msg.sender].stakedTokens.length; i++) { if ( stakers[msg.sender].stakedTokens[i].tokenId == _tokenId && stakers[msg.sender].stakedTokens[i].staker != address(0) ) { index = i; break; } } stakers[msg.sender].stakedTokens[index].staker = address(0); stakers[msg.sender].amountStaked--; stakerAddress[_tokenId] = address(0); nftCollection.transferFrom(address(this), msg.sender, _tokenId); stakers[msg.sender].timeOfLastUpdate = block.timestamp; } function claimRewards() external { uint256 rewards = calculateRewards(msg.sender) + stakers[msg.sender].unclaimedRewards; require(rewards > 0, "You have no rewards to claim");
        stakers[msg.sender].timeOfLastUpdate = block.timestamp;
        stakers[msg.sender].unclaimedRewards = 0;
        rewardsToken.safeTransfer(msg.sender, rewards);
    }


    function availableRewards(address _staker) public view returns (uint256) {
        uint256 rewards = calculateRewards(_staker) +
            stakers[_staker].unclaimedRewards;
        return rewards;
    }

    function getStakedTokens(address _user) public view returns (StakedToken[] memory) {
        // Check if we know this user
        if (stakers[_user].amountStaked > 0) {
            // Return all the tokens in the stakedToken Array for this user that are not -1
            StakedToken[] memory _stakedTokens = new StakedToken[](stakers[_user].amountStaked);
            uint256 _index = 0;

            for (uint256 j = 0; j < stakers[_user].stakedTokens.length; j++) {
                if (stakers[_user].stakedTokens[j].staker != (address(0))) {
                    _stakedTokens[_index] = stakers[_user].stakedTokens[j];
                    _index++;
                }
            }

            return _stakedTokens;
        }
        
        // Otherwise, return empty array
        else {
            return new StakedToken[](0);
        }
    }
 
    function calculateRewards(address _staker)
        internal
        view
        returns (uint256 _rewards)
    {
        return (((
            ((block.timestamp - stakers[_staker].timeOfLastUpdate) *
                stakers[_staker].amountStaked)
        ) * rewardsPerHour) / 3600);
    }
}

 

Cara Membuat NFT Staking dengan Fitur Reward
1# Deploy Token CRC-20

Token CRC20 nantinya akan digunakan sebagai reward untuk para staker yang melakukan staking token crc-721 (nft) di smart contract. Untuk membuat token crc20 anda membutuhkan sedikit coin cet untuk proses deploy

  • Buka website remixIDE dan buat file baru di sana
  • Paste code solidity ke file tersebut, dan jangan lupa untuk edit “contract name“, “symbol token“, “name” dan “total supply” untuk token tersebut

  • Compile code smart contract : Masuk ke menu “Solidity Compiler” pilih versi compiler, “Enable Optimization – 200” . Pastikan muncul status warna hijau , yang artinya compile selesai dan tidak ada error

  • Deploy smart contrat : Masuk menu “Deploy & Run Transaction”, Klik “Environment” dan pilih wallet yang akan anda gunakan
  • Klik Deploy

 

2# Deploy Token CRC-721
  • Buka remixIDE dan buat file baru di sana
  • Pastekan code solidity untuk crc-721
  • Edit di bagian “contract”,  “nama token” “symbol token”
  • Compile dengan compiler yang sesuai
  • Deploy smart contract

 

3# Deploy NFT Staking
  • Buka remixIDE dan buat file baru di sana
  • Pastekan code solidity untuk NFT-Staking
  • Edit di bagian contract :  contract ERC721Staking
  • Edit jumlah reward untuk staker : uint256 private rewardsPerHour = 1000000000000000000000;

  • Karena token menggunakan decimal 18, maka anda perlu menambahkan 18 angka 0
  • Compile file tersebut dengan compiler yang sesuai
  • Masukan smart contract CRC721 di kolom “_NFTCOLLECTION:”
  • Masukan smart contract CRC20 di kolom  “_REWARDSTOKEN:”

  • Deploy smart contract

Lanjut ke Artikel Selanjutnya / Part 2


Alif Fahmi

hi , I'm Alif, I'm a blockchain & cryptocurrency lover, I love writing & learning, my job is web developer & crypto trader