Lesson 4.3: Token Development and Crowd-sales ✨

Welcome back, blockchain innovators! 🚀

In this lesson, we’re diving into the exciting world of token development and crowd-sales. We’ll learn how to create custom ERC20 tokens, write smart contracts for token crowd-sales, and manage token distribution and vesting schedules. Ready to launch your own token? Let’s get started!

Creating Custom ERC20 Tokens

ERC20 tokens are the standard for creating fungible tokens on the Ethereum blockchain. Let’s create your very own custom ERC20 token!

1. Define Your Token Contract: We’ll use OpenZeppelin’s ERC20 implementation to make things easier and more secure.

solidity

pragma solidity ^0.8.0;

import “@openzeppelin/contracts/token/ERC20/ERC20.sol”;
import “@openzeppelin/contracts/access/Ownable.sol”;

contract MyToken is ERC20, Ownable {
constructor(uint256 initialSupply) ERC20(“MyToken”, “MTK”) {
_mint(msg.sender, initialSupply);
}
}

Explanation:

  • ERC20: Inherits the standard ERC20 functionality.
  • Ownable: Adds ownership control to the contract.
  • Constructor: Mints the initial supply of tokens to the contract owner.

Writing Smart Contracts for Token Crowd-sales

Crowd-sales (or ICOs) are a way to distribute your tokens to the public in exchange for Ether. Here’s how you can set up a simple crowd-sale contract.

1. Define Your Crowd-sale Contract: We’ll use OpenZeppelin’s crowd-sale library.

solidity

pragma solidity ^0.8.0;

import “@openzeppelin/contracts/token/ERC20/ERC20.sol”;
import “@openzeppelin/contracts/token/ERC20/IERC20.sol”;
import “@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol”;
import “@openzeppelin/contracts/access/Ownable.sol”;
import “@openzeppelin/contracts/security/ReentrancyGuard.sol”;

contract MyTokenSale is Ownable, ReentrancyGuard {
using SafeERC20 for IERC20;

IERC20 public token;
uint256 public rate;
uint256 public weiRaised;

event TokensPurchased(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);

constructor(uint256 _rate, address _wallet, IERC20 _token) {
require(_rate > 0, “Rate is 0”);
require(_wallet != address(0), “Wallet is the zero address”);
require(address(_token) != address(0), “Token is the zero address”);

rate = _rate;
token = _token;
transferOwnership(_wallet);
}

receive() external payable {
buyTokens(msg.sender);
}

function buyTokens(address beneficiary) public nonReentrant payable {
uint256 weiAmount = msg.value;
require(beneficiary != address(0), “Beneficiary is the zero address”);
require(weiAmount != 0, “Wei amount is 0”);

uint256 tokens = weiAmount * rate;

weiRaised += weiAmount;

token.safeTransfer(beneficiary, tokens);
emit TokensPurchased(msg.sender, beneficiary, weiAmount, tokens);

payable(owner()).transfer(msg.value);
}
}

Explanation:

  • IERC20: Interface for interacting with ERC20 tokens.
  • SafeERC20: Utility for safely handling ERC20 operations.
  • Ownable and ReentrancyGuard: Provide security features.
  • Constructor: Sets the token sale rate, wallet address, and token address.
  • buyTokens Function: Handles the token purchase logic, ensuring safe transfer of tokens and funds.