การสร้างโทเค็น ERC-20
พัฒนาและนำโทเค็นที่สอดคล้องกับ ERC-20 ของคุณเองไปใช้งาน รวมถึงฟังก์ชันการโอน การอนุมัติ และการอนุญาต
การสร้างโทเค็น ERC-20 เป็นบทเรียน Blockchain Smart Contracts with Solidity ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Blockchain Smart Contracts with Solidity และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Blockchain Smart Contracts with Solidity มีบทเรียนทั้งหมด 4 บทเรียน
บางส่วนของบทเรียนนี้ยังไม่ได้รับการแปล และแสดงเป็นภาษาอังกฤษ
Build Your Own ERC-20 Token
Welcome! In this lesson, you'll learn to implement your very own ERC-20 compliant token. We'll cover the essential functions and variables that make up this widely used standard.
By the end, you'll have a working understanding of how these tokens operate at a fundamental level on the Ethereum blockchain.
Token Identity: Name, Symbol, Decimals
Every ERC-20 token needs basic identifying information: a name, a symbol, and decimals. These are often public state variables.
- name: The full name of your token (e.g., "MyCoddyToken").
- symbol: A short ticker symbol (e.g., "MCT").
- decimals: How many decimal places the token can be divided into (commonly 18, like Ether).
Let's start our contract with these properties:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MyToken {
string public name = "MyCoddyToken";
string public symbol = "MCT";
uint8 public decimals = 18; // Common for ERC-20
}Total Supply & Initial Minting
The totalSupply variable keeps track of all existing tokens. We also need a way to store each user's balance, typically using a mapping.
The constructor is a special function that runs only once when the contract is deployed. We use it to set the initial totalSupply and assign all initial tokens to the deployer's address.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MyToken {
string public name = "MyCoddyToken";
string public symbol = "MCT";
uint8 public decimals = 18;
uint256 public totalSupply; // Total tokens in existence
mapping(address => uint256) private _balances; // User balances
constructor(uint256 initialSupply) {
totalSupply = initialSupply;
_balances[msg.sender] = initialSupply; // Mints to deployer
}
}Checking Balances: `balanceOf`
The balanceOf function allows anyone to query the token balance of a specific address. It's a view function, meaning it doesn't change the contract's state and costs no gas to call off-chain.
We retrieve the balance from our _balances mapping.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MyToken {
string public name = "MyCoddyToken";
string public symbol = "MCT";
uint8 public decimals = 18;
uint256 public totalSupply;
mapping(address => uint256) private _balances;
constructor(uint256 initialSupply) {
totalSupply = initialSupply;
_balances[msg.sender] = initialSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
}Direct Transfers: `transfer`
The transfer function enables a token holder to send tokens directly to another address. It's a core function of the ERC-20 standard.
Before transferring, we must ensure the sender has sufficient balance. After the transfer, we emit a Transfer event, which is vital for blockchain explorers and dApps to track token movements.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MyToken {
string public name = "MyCoddyToken";
string public symbol = "MCT";
uint8 public decimals = 18;
uint256 public totalSupply;
mapping(address => uint256) private _balances;
// ERC-20 events
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
constructor(uint256 initialSupply) {
totalSupply = initialSupply;
_balances[msg.sender] = initialSupply;
emit Transfer(address(0), msg.sender, initialSupply); // Minting event
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public returns (bool) {
require(_balances[msg.sender] >= amount, "Insufficient balance");
_balances[msg.sender] -= amount;
_balances[recipient] += amount;
emit Transfer(msg.sender, recipient, amount);
return true;
}
}Delegated Spending: `approve`
The approve function allows a token holder (the owner) to grant another address (the spender) permission to spend a certain amount of their tokens on their behalf.
This is crucial for interacting with decentralized applications (dApps) where you might want a smart contract to manage your tokens (e.g., for staking or trading). We track these approvals in an _allowances mapping.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MyToken {
string public name = "MyCoddyToken";
string public symbol = "MCT";
uint8 public decimals = 18;
uint256 public totalSupply;
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances; // New: owner => (spender => amount)
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
constructor(uint256 initialSupply) {
totalSupply = initialSupply;
_balances[msg.sender] = initialSupply;
emit Transfer(address(0), msg.sender, initialSupply);
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public returns (bool) {
require(_balances[msg.sender] >= amount, "Insufficient balance");
_balances[msg.sender] -= amount;
_balances[recipient] += amount;
emit Transfer(msg.sender, recipient, amount);
return true;
}
function approve(address spender, uint256 amount) public returns (bool) {
_allowances[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
}Checking Allowance: `allowance`
The allowance function lets you check how many tokens a specific spender is currently permitted to transfer from an owner's balance.
This is a view function, similar to balanceOf, and helps external applications understand the spending limits set by users.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MyToken {
string public name = "MyCoddyToken";
string public symbol = "MCT";
uint8 public decimals = 18;
uint256 public totalSupply;
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
constructor(uint256 initialSupply) {
totalSupply = initialSupply;
_balances[msg.sender] = initialSupply;
emit Transfer(address(0), msg.sender, initialSupply);
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function allowance(address owner, address spender) public view returns (uint256) {
return _allowances[owner][spender];
}
function transfer(address recipient, uint256 amount) public returns (bool) {
require(_balances[msg.sender] >= amount, "Insufficient balance");
_balances[msg.sender] -= amount;
_balances[recipient] += amount;
emit Transfer(msg.sender, recipient, amount);
return true;
}
function approve(address spender, uint256 amount) public returns (bool) {
_allowances[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
}Spending on Behalf: `transferFrom`
The transferFrom function is used by a spender (who has been approved) to move tokens from an owner's balance to a recipient.
It requires checks for both the sender's balance and the allowance granted. After a successful transfer, the allowance is reduced by the transferred amount.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MyToken {
string public name = "MyCoddyToken";
string public symbol = "MCT";
uint8 public decimals = 18;
uint256 public totalSupply;
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
constructor(uint256 initialSupply) {
totalSupply = initialSupply;
_balances[msg.sender] = initialSupply;
emit Transfer(address(0), msg.sender, initialSupply);
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function allowance(address owner, address spender) public view returns (uint256) {
return _allowances[owner][spender];
}
function transfer(address recipient, uint256 amount) public returns (bool) {
require(_balances[msg.sender] >= amount, "Insufficient balance");
_balances[msg.sender] -= amount;
_balances[recipient] += amount;
emit Transfer(msg.sender, recipient, amount);
return true;
}
function approve(address spender, uint256 amount) public returns (bool) {
_allowances[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public returns (bool) {
require(_balances[sender] >= amount, "Insufficient balance from sender");
require(_allowances[sender][msg.sender] >= amount, "Insufficient allowance");
_allowances[sender][msg.sender] -= amount;
_balances[sender] -= amount;
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
return true;
}
}Full Minimal ERC-20 Implementation
Here's a complete, minimal ERC-20 token contract. While more advanced implementations (like OpenZeppelin's) include additional features and safety checks, this code covers all the core functions required by the standard.
You can deploy this contract to a testnet to create your own functional token!
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MyToken {
string public name = "MyCoddyToken";
string public symbol = "MCT";
uint8 public decimals = 18;
uint256 public totalSupply;
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
constructor(uint256 initialSupply) {
totalSupply = initialSupply;
_balances[msg.sender] = initialSupply;
emit Transfer(address(0), msg.sender, initialSupply);
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function allowance(address owner, address spender) public view returns (uint256) {
return _allowances[owner][spender];
}
function transfer(address recipient, uint256 amount) public returns (bool) {
require(_balances[msg.sender] >= amount, "Insufficient balance");
_balances[msg.sender] -= amount;
_balances[recipient] += amount;
emit Transfer(msg.sender, recipient, amount);
return true;
}
function approve(address spender, uint256 amount) public returns (bool) {
_allowances[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public returns (bool) {
require(_balances[sender] >= amount, "Insufficient balance from sender");
require(_allowances[sender][msg.sender] >= amount, "Insufficient allowance");
_allowances[sender][msg.sender] -= amount;
_balances[sender] -= amount;
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
return true;
}
}ERC-20 Core Functions Check
You've learned about the essential functions for an ERC-20 token. Now, let's test your knowledge!
Recap: Your Own Token
Congratulations! You've now implemented the core logic for an ERC-20 token. You learned how to define its properties, manage total supply and individual balances, and enable both direct and delegated token transfers.
Understanding these fundamental building blocks is key to working with any token on the Ethereum blockchain. Next, you might explore how to integrate with existing ERC-20 libraries or add more advanced features!
คำถามที่พบบ่อย
บทเรียน “การสร้างโทเค็น ERC-20” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การสร้างโทเค็น ERC-20” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Blockchain Smart Contracts with Solidity ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Blockchain Smart Contracts with Solidity มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การสร้างโทเค็น ERC-20”
พัฒนาและนำโทเค็นที่สอดคล้องกับ ERC-20 ของคุณเองไปใช้งาน รวมถึงฟังก์ชันการโอน การอนุมัติ และการอนุญาต คุณปฏิบัติ Blockchain Smart Contracts with Solidity ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Blockchain Smart Contracts with Solidity หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Blockchain Smart Contracts with Solidity บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “การสร้างโทเค็น ERC-20” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Blockchain Smart Contracts with Solidity นี้ได้ไหม
ได้ บทเรียน Blockchain Smart Contracts with Solidity ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- มาตรฐานโทเค็นแบบทดแทนกันได้ ERC-20
- การสร้างโทเค็น ERC-20
- โทเค็นแบบไม่ทดแทนกันได้ ERC-721 (NFTs)
- มาตรฐานโทเค็นหลายชนิด ERC-1155