Cara Membuat Token Lock (Time Locking) untuk CRC20 Coinex Smart Chain


Token Lock adalah sebuah metode untuk mengunci token CRC20 atau Token Liquidity pada exchange DEX dengan tujuan tertentu, biasanya para developer melakukan tokenlock untuk melindungi pengguna, serta untuk meningkatkan kepercayaan dari komunitas. Penguncian token bisa bertujuan untuk mengendalikan supply token dengan sistem penguncian jangka waktu, contoh, investor mendapat alokasi 1000 token, tapi token tersebut di kunci dalam jangka waktu 1 tahun, tujuannya agar investor tidak menjual token sebelum jangan waktu 1 tahun. Setelah waktu 1 tahun selesai, investor bisa melakukan unlock atau withdrawal token dari smart contract atau DApps.

Dalam kasus lain , Token Lock digunakan untuk mengunci Token Liquidity, contoh , project A sedang membangun sebuah token , lalu token tersebut di listing di DEX exchange (dengan memasukan liquidity), agar komunitas percaya terhadap project tersebut, developer akan mengunci token liquidity provider dengan waktu tertentu (misal 2-5 tahun), tujuan nya tidak lain agar komunitas percaya, bahwa developer tidak akan mencabut liquidity dalam jangan waktu tertentu.

Penguncian token juga bisa di gunakan di beberapa aspek lain , seperti distribusi airdrop, alokasi marketing atau alokasi token team. Penguncian token bisa berupa smart contract saja , atau smartcontract + aplikasi front end yang menggunakan cms atau reactJS. Di artikel ini saya akan memberikan tutorial cara membuat penguncian token crc20 coinex smart chain dengan basis waktu. step ini adalah sederhana, karna saya akan menjelaskan di sisi smart contract tanpa menjelaskan di sisi pembuatan frond end.

Cara membuat penguncian token crc20 coinex smart chain

Hal yang perlu anda siapkan adalah untuk membuat token lock crc20 coinex smart chain.

1. Wallet & RPC Coinex

Anda bisa menggunakan wallet metamask chrome atau firefox, jangan lupa untuk setting rpc ke rpc coinex smart chain. di bawah ini adalah detil rpc coinx smart chain

2. Coin CET

CET merupakan coin native dari blockchain coinex smart chain, coin cet digunakan untuk membayar jaringan atau membayar interaksi contract pada blockchain CSC. Untuk mendapatkan coin CET anda bisa membelinya di coinex exchange. jika sudah memiliki coin cet, segera transfer ke wallet anda.

3. Token CRC20

Karna di artikel ini adalah tutorial cara mengunci token crc20, tentunya anda harus memiliki token crc20 dengan decimal 18 (dianjurkan).Jika anda belum memilikinya anda bisa deploy menggunakan smart contract di bawah ini.

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

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

contract CSCTokenTest1 is ERC20 {
constructor() ERC20("CSCTokenTest1", "CTT1") {
_mint(msg.sender, 100000 * 10 ** decimals());
}
}

 

4. Smart Contract Token Lock

Smart contract ini berfungsi mengunci token crc20 dengan jangka waktu tertentu, anda bisa menentukan waktu penguncian sesuai dengan keinginan anda, anda juga bisa upload list penerima token dan jumlah token yang di dapatakan pada tiap address. Buka remix.ethereum.org , buat file .sol (contoh tokenlock.sol) , pastekan smart contract di bawah ini

// SPDX-License-Identifier: MIT

pragma solidity 0.8.11;

import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "openzeppelin-solidity/contracts/utils/math/SafeMath.sol";

contract TokenLOCK {
bool internal locked;
using SafeERC20 for IERC20;
using SafeMath for uint256;
address payable public owner;
bool public allIncomingDepositsFinalised;
uint256 public initialTimestamp;
bool public timestampSet;
uint256 public timePeriod;
mapping(address => uint256) public alreadyWithdrawn;
mapping(address => uint256) public balances;
uint256 public contractBalance;
IERC20 public erc20Contract;
event TokensDeposited(address from, uint256 amount);
event AllocationPerformed(address recipient, uint256 amount);
event TokensUnlocked(address recipient, uint256 amount);

constructor(IERC20 _erc20_contract_address) {
allIncomingDepositsFinalised = false;
owner = payable(msg.sender);
timestampSet = false;
require(address(_erc20_contract_address) != address(0), "_erc20_contract_address address can not be zero");
erc20Contract = _erc20_contract_address;
locked = false;
}

modifier noReentrant() {
require(!locked, "No re-entrancy");
locked = true;
_;
locked = false;
}

modifier incomingDepositsStillAllowed() {
require(allIncomingDepositsFinalised == false, "Incoming deposits have been finalised.");
_;
}

modifier onlyOwner() {
require(msg.sender == owner, "Message sender must be the contract's owner.");
_;
}

modifier timestampNotSet() {
require(timestampSet == false, "The time stamp has already been set.");
_;
}

modifier timestampIsSet() {
require(timestampSet == true, "Please set the time stamp first, then try again.");
_;
}

receive() payable external incomingDepositsStillAllowed {
contractBalance = contractBalance.add(msg.value);
emit TokensDeposited(msg.sender, msg.value);
}

function finalizeAllIncomingDeposits() public onlyOwner timestampIsSet incomingDepositsStillAllowed {
allIncomingDepositsFinalised = true;
}

function setTimestamp(uint256 _timePeriodInSeconds) public onlyOwner timestampNotSet {
timestampSet = true;
initialTimestamp = block.timestamp;
timePeriod = initialTimestamp.add(_timePeriodInSeconds);
}

function withdrawEth(uint256 amount) public onlyOwner noReentrant{
require(amount <= contractBalance, "Insufficient funds");
contractBalance = contractBalance.sub(amount);
owner.transfer(amount);
}

function depositTokens(address recipient, uint256 amount) public onlyOwner timestampIsSet incomingDepositsStillAllowed {
require(recipient != address(0), "ERC20: transfer to the zero address");
balances[recipient] = balances[recipient].add(amount);
emit AllocationPerformed(recipient, amount);
}

function bulkDepositTokens(address[] calldata recipients, uint256[] calldata amounts) external onlyOwner timestampIsSet incomingDepositsStillAllowed {
require(recipients.length == amounts.length, "The recipients and amounts arrays must be the same size in length");
for(uint256 i = 0; i < recipients.length; i++) {
require(recipients[i] != address(0), "ERC20: transfer to the zero address");
balances[recipients[i]] = balances[recipients[i]].add(amounts[i]);
emit AllocationPerformed(recipients[i], amounts[i]);
}
}

function transferTimeLockedTokensAfterTimePeriod(IERC20 token, address to, uint256 amount) public timestampIsSet noReentrant {
require(to != address(0), "ERC20: transfer to the zero address");
require(balances[to] >= amount, "Insufficient token balance, try lesser amount");
require(msg.sender == to, "Only the token recipient can perform the unlock");
require(token == erc20Contract, "Token parameter must be the same as the erc20 contract address which was passed into the constructor");
if (block.timestamp >= timePeriod) {
alreadyWithdrawn[to] = alreadyWithdrawn[to].add(amount);
balances[to] = balances[to].sub(amount);
token.safeTransfer(to, amount);
emit TokensUnlocked(to, amount);
} else {
revert("Tokens are only available after correct time period has elapsed");
}
}

function transferAccidentallyLockedTokens(IERC20 token, uint256 amount) public onlyOwner noReentrant {
require(address(token) != address(0), "Token address can not be zero");
require(token != erc20Contract, "Token address can not be ERC20 address which was passed into the constructor");
token.safeTransfer(owner, amount);
}
}

# Compile dengan Compiler 0.8.11

# Enable Optimization 200

# contract TokenLOCK = adalah nama contract, anda bisa ganti sesuai dengan keinginan, nama ini akan muncul di explorer coinex smart chain.

 

# Deploy, sebelum deploy smart contract TokenLock, anda harus masukan Smart Contract token CRC20 yang sebelum nya anda buat.

 

# Deploy Selesai, smart contract tokenlock sudah jadi

 

5. Verifikasi smart contract

Untuk verifikasi smart contract di explorer coinex smart chain cukup mudah, Caranya adalah memasukan smart contract TokenLock (yang sudah di gabung menggunakan plugin flattener) ke explorer coinex smart chain , gunakan step di bawah ini.

# Aktifkan plugin FLATTENER di remix-ethereum

 

# Gabungkan smart contract TokenLock menggunakan flattener & save smart contract , setelah itu akan muncul file baru dengan nama berbeda, contoh TokenLock_flat.sol . File tersebut kita gunakan untuk verifikasi atau upload ke explorer

 

# Upload ke Explorer Coinex Smart Chain dengan cara Masuk ke “Contract Info” Klik “Verify & Publish”

 

# Masukan “Nama Contract” sesuai dengan smart contract anda,

# “Compiler Type” pilih Solidity Singgle File

# Masukan smart contract flat

# “EVM Version” pilih Default

# “License Type” MIT License

# “Optimization” Yes, 200

# “Compiler Version” pilih sesuai dengan compiler yang anda gunakan di remix-ethereum

# Klik Submit atau Verify

Smart Contract TokenLock sudah sepenuhnya siap digunakan untuk mengunci token crc20 coinex smart chain. Di artikel selanjutnya saya akan membahas bagaimana cara mengunci token , setting waktu kunci, setting alokasi token untuk address tertentu dan cara withdrawal token dari smart contract.

Jika anda mengalami kendala saat verifikasi smart contract di explorer coinex smart chain, silahkan cek ulang, versi compiler , nama contract dan enable optimization. Terkadang smart contract tidak bisa terverifikasi karena ada perbedaan versi compiler antara (contoh) compiler di remix-ethereum dengan explorer, jadi pastikan dengan baik, agar tidak terjadi kesalahan


Alif Fahmi

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