# ERC1155 多元代幣標準 - ERC20 + ERC721 我全都要
ERC-1155 MULTI-TOKEN STANDARD (opens new window) 定義了一個揉合 ERC20 與 ERC721 的新標準,他可以發行同值性代幣(如:ERC20)也能發行非同值性代幣(如:NFT ERC721)。
# 介面
interface ERC1155 /* is ERC165 */ {
/// 當代幣被轉移時,`TransferSingle` 必須被觸發,即使是轉移 `0` 個代幣也是,轉移的行為包含「鑄造」與「銷毀」。
/// `_operator` 是發起交易的位址,即 `msg.sender`
/// `_from` 是持有者的位址;當「鑄造」新代幣時,此參數為位址 `0x0`
/// `_to` 是接收者的位址;當「銷毀」代幣時,此參數為位址 `0x0`
/// `_id` 為被轉移的 token ID
/// `_value` 為被轉移的 token 數量
event TransferSingle(address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _value);
/// 當代幣被轉移時,`TransferBatch` 必須被觸發,即使是轉移 `0` 個代幣也是,轉移的行為包含「鑄造」與「銷毀」。
/// `_operator` 是發起交易的位址,即 `msg.sender`
/// `_from` 是持有者的位址;當「鑄造」新代幣時,此參數為位址 `0x0`
/// `_to` 是接收者的位址;當「銷毀」代幣時,此參數為位址 `0x0`
/// `_ids` 為被轉移的 token ID 列表
/// `_values` 為被轉移的 token 數量列表,其順序與長度需與 `_ids` 一致。
event TransferBatch(address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _values);
/// 授權事件,當持有者「授權」或「撤銷」第三方位址管理全部代幣的權力時被觸發。
/// `_owner` 為持有者位址
/// `_operator` 為被授權者位址
/// `_approved` 為授權(`true`)或撤銷(`false`)
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
/// URI 更新事件
/// 當代幣的 URI 被更新時,必須觸發此事件
/// `_value` 代表更新後的 URI
/// `_id` 代表被更新的 token ID
event URI(string _value, uint256 indexed _id);
/// 呼叫者(`msg.sender`)從持有者(`_from`)轉移 `_value` 數量的特定代幣(`_id`)給接收者(`_to`)
/// 呼叫者應先獲得持有者的授權,或呼叫者就是持有者本人
/// 特殊情況:
/// 1. 當接收者(`_to`)為位址 `0x0` 時,回朔(revert)交易
/// 2. 當持有者(`_from`)所持有的代幣(`_id`)餘額低於要轉移的數量(`_value`)時,回朔交易
/// 3. 當發生任何錯誤時,回朔交易
/// 當此函式被呼叫時,必須觸發 `TransferSingle` 事件
function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external;
Balance changes and events MUST follow the ordering of the arrays (_ids[0]/_values[0] before _ids[1]/_values[1], etc).
After the above conditions for the transfer(s) in the batch are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call the relevant `ERC1155TokenReceiver` hook(s) on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard).
@param _from Source address
@param _to Target address
@param _ids IDs of each token type (order and length must match _values array)
@param _values Transfer amounts per token type (order and length must match _ids array)
@param _data Additional data with no specified format, MUST be sent unaltered in call to the `ERC1155TokenReceiver` hook(s) on `_to`
*/
/// 呼叫者(`msg.sender`)從持有者(`_from`)轉移 `_values` 數量的多種特定代幣(`_ids`)給接收者(`_to`)
/// 呼叫者應先獲得持有者的授權,或呼叫者就是持有者本人
/// 特殊情況:
/// 1. 當接收者(`_to`)為位址 `0x0` 時,回朔(revert)交易
/// 2. 當持有者(`_from`)所持有的任何一種代幣(`_ids`)餘額低於要轉移的對應數量(`_values`)時,回朔交易
///. 3. 當轉移數量列表的長度與轉移代幣列表的長度不相符時,回朔交易
/// 3. 當發生任何錯誤時,回朔交易
/// 當此函式被呼叫時,必須觸發 `TransferBatch` 或 `TransferSingle` 事件,需特別注意,在事件中的轉移代幣與數量的順序應嚴格與呼叫此函式的代幣與數量順序一致。
function safeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external;
/// 查詢持有者帳戶中特定 token ID 的餘額
/// `_owner` 為持有者帳號
/// `_id` 為想查詢的 token id
/// 回傳該代幣的餘額
function balanceOf(address _owner, uint256 _id) external view returns (uint256);
/// 「帳戶」對「Token ID」的餘額列表
/// `_owners` 為持有者列表
/// `_ids` 為想查詢的 token id 列表
/// 回傳一個列表,每個餘額為對應順序的(持有者,Token ID)的餘額
function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external view returns (uint256[] memory);
/// 呼叫者(`msg.sender`)授權給特定第三方位址管理所有代幣的權力
/// `_operator` 為第三方位址
/// `_approved` 為授權(`true`)或撤銷(`false`)
function setApprovalForAll(address _operator, bool _approved) external;
/// 查詢持有者是否授權給特定第三方位址
/// `_owner` 為持有者位址
/// `_operator` 為第三方位址
/// 回傳 true -> 有授權; false -> 沒有授權
function isApprovedForAll(address _owner, address _operator) external view returns (bool);
}
# 為什麼是我全都要
實際上,ERC1155 算是對 ERC721 的改良。ERC721 只允許每個代幣只能有一個獨一無二的編號且數量為一。而 ERC1155 在建立代幣時,每個代幣可以指定發行的數量,因此就能做出擁有相同代幣編號,且數量超過一個情境。
如果想要發行同值性代幣(ERC20),則只需要在 ERC1155 中發行一種編號為 0
的代幣,數量設定該代幣的總發行量即可。
反之,若想發行非同值性代幣(ERC721),則在 ERC1155 中發行多種相異編號的代幣,每種類的數量都設定為 1
即可。