What is Token?

Một token ở trong Ethereum chỉ đơn giản là một smart contract mà tuân thủ một số quy tắc chung.

Cụ thể hơn: một token là một contract mà có lưu lại danh sách ai sở hữu bao nhiêu token đó và chứa một vài hàm cho phép người dùng chuyển token của họ tới các địa chỉ khác.

Có một số chuẩn token1:

  • ERC20: inteface cho các fungible (interchangeable - có thể thay thế) token chẳng hạn như là voting token, staking token hay các loại tiền ảo.
  • ERC721: interface cho các non-fungible token (NFT), đại diện cho quyền sở hữu của các artwork hoặc bài hát. ERC721 không thể thay thế bởi vì mỗi token sẽ được xem là độc nhất và không thể chia nhỏ.
  • ERC1155: cho phép thực hiện các cuộc trao đổi hiệu quả hơn và cho phép đóng gói các giao dịch, giúp tiết kiệm chi phí.

ERC721

Mỗi loại token sẽ có một interface tương ứng, ở đây ta sẽ tập trung vào việc implement của interface ERC721. Interface ERC721 có dạng như sau:

interface ERC721 {
	event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
	event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
	
	function balanceOf(address _owner) external view returns (uint256);
	function ownerOf(uint256 _tokenId) external view returns (address);
	function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
	function approve(address _approved, uint256 _tokenId) external payable;
}

balanceOf & ownerOf

Hàm balanceOf có signature như sau:

function balanceOf(address _owner) external view returns (uint256 _balance);

Hàm này chỉ đơn giản là nhận vào một địa chỉ và trả về số lượng token mà địa chỉ đó sở hữu.

Signature của hàm ownerOf:

function ownerOf(uint256 _tokenId) external view returns (address _owner);

Hàm này sẽ nhận vào ID của token và trả về địa chỉ của chủ sở hữu token.

Chúng ta có thể dễ dàng implement các hàm này bằng cách sử dụng các mapping2.

transferFrom & approve

Hàm transferFrom giúp chuyển token có ID là _tokenId từ địa chỉ _from đến địa chỉ _to:

function transferFrom(address _from, address _to, uint256 _tokenId) external payable;

Hàm approve sẽ thực hiện lưu lại địa chỉ của chủ sở hữu mới của token có ID là _tokenId, thường là vào một mapping. Signature của hàm như sau:

function approve(address _approved, uint256 _tokenId) external payable;

Trước khi gọi hàm transferFrom thì sender cần phải gọi hàm approve để xác minh người nhận. Sau đó, khi transferFrom được gọi, nó sẽ kiểm tra xem địa chỉ gọi thực hiện hàm có phải là địa chỉ đã được approved hay địa chỉ của chủ sở hữu token hay không. Nếu không thì việc chuyển quyền sở hữu token sẽ không xảy ra.

Ví dụ implement:

mapping (uint => address) public zombieToOwner;
mapping (uint => address) zombieApprovals;
 
// Transfers a zombie token from one address to another
function _transfer(address _from, address _to, uint256 _tokenId) private {
	zombieToOwner[_tokenId] = _to;
	emit Transfer(_from, _to, _tokenId);
}
 
// Transfers a zombie token from one address to another, with approval check
function transferFrom(address _from, address _to, uint256 _tokenId) external payable {
	require (zombieToOwner[_tokenId] == msg.sender || zombieApprovals[_tokenId] == msg.sender);
	_transfer(_from, _to, _tokenId);
}
 
// Approves an address to take ownership of a specific zombie token
function approve(address _approved, uint256 _tokenId) external payable onlyOwnerOf(_tokenId) {
	zombieApprovals[_tokenId] = _approved;
	emit Approval(msg.sender, _approved, _tokenId);
}

Như vậy, approve chỉ có thể được gọi bởi chủ sở hữu token và transferFrom thì có thể được gọi bởi địa chỉ của chủ sở hữu token và cả địa chỉ đã được approved.

Có thể thấy, hai sự kiện TransferApproval lần lượt được emit ở trong hàm _transferapprove.

Footnotes

  1. Tham khảo: Token Standards | ethereum.org.

  2. Xem thêm Mappings.