Tại sao nên đọc bài này
- Cách token 20 vận hành, dưới góc nhìn của một người có kiến thức về backend, nhưng chưa biết gì về blockchain
- Một cách tìm hiểu về blockchain hoạt động bên dưới như thế nào
ERC-20 là gì?
ERC - Ethereum Request For Comment
Nói chung là vầy, cộng đồng dev trên Ethereum sẽ có một nơi để discuss trao đổi về hệ sinh thái ở đây, mỗi cái thảo luận sẽ có một cái id, nên cái ERC-20 là một thread thảo luận về hệ sinh thái Ethereum mang số hiệu thứ 20.
Vậy trong cái buổi thảo luận số hiệu 20 đó có gì?
The following standard allows for the implementation of a standard API for tokens within smart contracts. This standard provides basic functionality to transfer tokens, as well as allow tokens to be approved so they can be spent by another on-chain third party.****
Là một implement về standard cho token trên smart contract. Nó cung cấp một số standard chung liên quan tới việc tạo ra token, chuyển/nhận token và cả cơ chế approve token đó cho 3rd party.
Tại sao lại cần standard nhỉ? Thì nó giúp cho mọi người dùng nó mà khỏi phải suy nghĩ nhiều, đồng thời cũng giúp cho việc integrate nhanh và scale hơn rất nhiều (Thay vì mỗi đồng token bạn phải integrate một kiểu khác nhau)
Nó giống như là Restful standard vậy, bạn có thể không làm theo standard này, thì vẫn dùng bình thường, chỉ có thằng nào integrate API của bạn sẽ làm vừa mention tới mẹ bạn thôi.
Back lại vụ token, kết quả nó là gì? Nói nhiều thì rườm rà, bạn tưởng tượng token là bạn tạo ra một đồng tiền, mọi người có thể nhận/gửi token đó trên network. Vậy cho đơn giản.
Detail
Khái niệm vậy đủ rồi, show me the code
Vì bài này mục đích để giải thích cho các bạn có kiến thức về Backend hiểu nên mình sẽ giải thích theo kiểu backend nhé
Icon sử dụng ở https://www.flaticon.com/
Hiểu đơn giản là flow code backend Web2 thì là viết code Logic (Bằng Golang, nodejs, rust) rồi deploy ở đâu đó. Code này sẽ xử lý logic rồi lưu data xuống database
Map sang Blockchain, thì bạn sẽ vẫn phải code logic (Bằng Solidity, Rust,…) và deploy nó lên Blockchain network. Code này cũng sẽ xử lý logic rồi lưu data xuống Blockchain network luôn.
function name() public view returns (string)
function symbol() public view returns (string)
function decimals() public view returns (uint8)
function totalSupply() public view returns (uint256)
function balanceOf(address _owner) public view returns (uint256 balance)
function transfer(address _to, uint256 _value) public returns (bool success)
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
function approve(address _spender, uint256 _value) public returns (bool success)
function allowance(address _owner, address _spender) public view returns (uint256 remaining)
event Transfer(address indexed _from, address indexed _to, uint256 _value)
event Approval(address indexed _owner, address indexed _spender, uint256 _value)
Đó, vể cơ bản, nếu code logic của bạn đáp ứng đủ đống interface như trên thì nghĩa là bạn đã phù hợp chuẩn ERC-20 ròi đó.
- name: Tên của token
- symbol: Tên viết tắt
- decimals: Giá trị của token lưu nhỏ nhất là bao nhiêu decimal, thường là 18. Vì token không lưu dưới dạng float nên nó sẽ cần lưu dưới dạng này. Tìm hiểu thêm hoặc Ấn phẩm Dijkstra
- totalSupply: Có tối đa bao nhiêu token
- balanceOf(owner): Thằng owner đang có bao nhiêu balance trong tài khoản
- transfer(to, value): Chuyển cho thằng
to
một lượngvalue
token - transferFrom(from, to, value): Chuyển
value
token của thằngfrom
cho thằngto
- approve(spencer, value): Ủy quyền cho thằng spencer có thể sử dụng
value
token của mình - allowance(owner, spencer): Xem coi thằng
spencer
có đang được ủy quyền sử dụng bao nhiêu token của thằngowner
Nguồn https://bitpanda.com
<aside> 😼 Tại sao có `approve`, `allowance` và `transferFrom` vì nó cần phục vụ use case Smart Contract có thể sử dụng token của bạn. Chắc chắn là khi được phép rồi, do đó nó cần bạn phải approve quyền sử dụng token cho nó, sau đó nó sẽ được phép </aside>Nó chỉ là interface
Cái này mình phải keep in mind là nó chỉ là interface thôi, nghĩa là actually code implement bên dưới có thể là bất cứ thứ gì.
Bạn có thể implement cái abstract chuyển token, nhưng thực tế là chuyển hết về vì của bạn luôn cũng được. Nó là quyền của bạn. Do đó đây cũng là điểm để các ông scammer vào việc, kiểu mua được nhưng bán éo được.
Lừa đảo tiền điện tử honeypot là gì? Làm thế nào để phát hiện và phòng tránh? Sàn Coin Việt
Sample code ERC-20
pragma solidity ^0.8.0; interface IERC20 { function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256); function transfer(address recipient, uint256 amount) external returns (bool); function approve(address spender, uint256 amount) external returns (bool); function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value);
} contract ERC20Basic is IERC20 { string public constant name = "ERC20Basic"; string public constant symbol = "ERC"; uint8 public constant decimals = 18; mapping(address => uint256) balances; mapping(address => mapping (address => uint256)) allowed; uint256 totalSupply_ = 10 ether; constructor() { balances[msg.sender] = totalSupply_; } function totalSupply() public override view returns (uint256) { return totalSupply_; } function balanceOf(address tokenOwner) public override view returns (uint256) { return balances[tokenOwner]; } function transfer(address receiver, uint256 numTokens) public override returns (bool) { require(numTokens <= balances[msg.sender]); balances[msg.sender] = balances[msg.sender]-numTokens; balances[receiver] = balances[receiver]+numTokens; emit Transfer(msg.sender, receiver, numTokens); return true; } function approve(address delegate, uint256 numTokens) public override returns (bool) { allowed[msg.sender][delegate] = numTokens; emit Approval(msg.sender, delegate, numTokens); return true; } function allowance(address owner, address delegate) public override view returns (uint) { return allowed[owner][delegate]; } function transferFrom(address owner, address buyer, uint256 numTokens) public override returns (bool) { require(numTokens <= balances[owner]); require(numTokens <= allowed[owner][msg.sender]); balances[owner] = balances[owner]-numTokens; allowed[owner][msg.sender] = allowed[owner][msg.sender]-numTokens; balances[buyer] = balances[buyer]+numTokens; emit Transfer(owner, buyer, numTokens); return true; }
}
Đó khoảng vài chục dòng như trên là bạo có thể tạo ra một đồng token riêng rồi 😎
Cơ bản logic của bạn sẽ phải care tới chuyện:
- Lưu balance của user làm sao.
- Chuyển tiền thì update lại db như nào
- Cơ chế sinh ra token, approve cho token
Code lưu data đâu?
string public constant name = "ERC20Basic";
string public constant symbol = "ERC";
uint8 public constant decimals = 18; mapping(address => uint256) balances;
mapping(address => mapping (address => uint256)) allowed;
uint256 totalSupply_ = 10 ether;
Nó giống như việc lưu data và memory vậy, nên bạn cũng không cần care nhiều tới kiểu SQL hay database server như trước nữa
Tuy nhiên, chi phí khi lưu data on-chain là cực kì, cực kì tốn gas. Cũng make sense vì data này sẽ bị duplicate và lưu ở tất cả các node mà. Nên thường các smart contract sẽ cực kì care tới chuyện lưu data làm sao, sử dụng type gì cho hiệu quả chứ không thừa mứa như cách chúng ta đang làm ở Web2
Cách tôi tiêu sài memory ở Web2
Tại sao cần có Event?
Thực tế là khi bạn deploy code lên network thì nó đã được compile ra rồi nên về cơ bản bạn sẽ không biết, hoặc rất khó biết bên trong cái Smart Contract đó có logic gì cả. Ngay cả khi bạn gọi các hàm chuyển tiền như trên standard thì nó cũng sẽ phải gọi dưới dạng hash
Tuy nhiên vần cẫn một use case là để thông báo cho thế giới kiểu như A đã chuyển Y tiền cho B, tát nhiên là dưới dạng ai cũng hiểu được. Nên trong smart contract cần emit ra những Event như trên, để mấy tool indexing hay gì đó có thể biết được hiện trạng của nó như thế nào. Bạn sẽ rất khó (không phải là không thể) để đọc được state của một smart contract hiện tại, tuy nhiên lại rất dễ để collect đống Event mà Smart Contract đã nhả ra. Nên đây cũng là một cách mà Smart Contract expose state của nó ra bên ngoài
Blockchain thì có gì tốt hơn?
Với đoạn code ở trên khoảng vài chục dòng là bạn có thể tạo ra một đồng token, lưu thông nó, blockchain thể hiện lợi thế cực kì mạnh ở mô hình tài chính
- Có standard chung để chuyển tiền, integrate với các ứng dụng khác
- Việc build trust, làm tròn số, bảo mật đã ready sẵn rồi, không cần care tới
- Không care tới thiết kế DB, deployment, operation hệ thống. ETH online đó giờ chưa chết bao giờ
Nó chỉ ít vậy thôi nhưng lại là một super big problem ở mô hình tài chính truyền thống. Bạn đủ biết việc integrate một payment gateway hay build cho mình một cổng thành toán, trữ tiền nó khủng khiếp cỡ nào rồi nhỉ? Lại còn phải care về vấn đề vận hành, security,… nữa.
https://twitter.com/ASvanevik/status/1601419734762676224
Tốn hơn 2 ngày để chứng khoán “thật sự” được giao dịch thành công - CEO của Nansen
Tổng kết
Nói theo góc nhìn của một người code backend:
Token ERC-20 là một đoạn code về logic dùng để thực hiện các use case về Token dựa trên một bộ Abstraction đã define ở ERC-20
Mốt số token standard khác
Token Standards | ethereum.org