协议说明
本文档中的关键字“必须”、“不得”、“要求”、“应”、“不得”、“应该”、“不应”、“推荐”、“可以”和“可选”是为了按照 RFC 2119 中的说明进行解释。
每个符合 VIP-3525 的合约都必须实现 VIP-3525、VIP-721 和 VIP-165 接口
pragma solidity ^0.8.0;
/**
* @title VIP-3525 Semi-Fungible Token Standard
* Note: the VIP-165 identifier for this interface is 0xd5358140.
*/
interface IVRC3525 /* is IVRC165, IVRC721 */ {
/**
* @dev MUST emit when value of a token is transferred to another token with the same slot,
* including zero value transfers (_value == 0) as well as transfers when tokens are created
* (`_fromTokenId` == 0) or destroyed (`_toTokenId` == 0).
* @param _fromTokenId The token id to transfer value from
* @param _toTokenId The token id to transfer value to
* @param _value The transferred value
*/
event TransferValue(uint256 indexed _fromTokenId, uint256 indexed _toTokenId, uint256 _value);
/**
* @dev MUST emit when the approval value of a token is set or changed.
* @param _tokenId The token to approve
* @param _operator The operator to approve for
* @param _value The maximum value that `_operator` is allowed to manage
*/
event ApprovalValue(uint256 indexed _tokenId, address indexed _operator, uint256 _value);
/**
* @dev MUST emit when the slot of a token is set or changed.
* @param _tokenId The token of which slot is set or changed
* @param _oldSlot The previous slot of the token
* @param _newSlot The updated slot of the token
*/
event SlotChanged(uint256 indexed _tokenId, uint256 indexed _oldSlot, uint256 indexed _newSlot);
/**
* @notice Get the number of decimals the token uses for value - e.g. 6, means the user
* representation of the value of a token can be calculated by dividing it by 1,000,000.
* Considering the compatibility with third-party wallets, this function is defined as
* `valueDecimals()` instead of `decimals()` to avoid conflict with VIP-20 tokens.
* @return The number of decimals for value
*/
function valueDecimals() external view returns (uint8);
/**
* @notice Get the value of a token.
* @param _tokenId The token for which to query the balance
* @return The value of `_tokenId`
*/
function balanceOf(uint256 _tokenId) external view returns (uint256);
/**
* @notice Get the slot of a token.
* @param _tokenId The identifier for a token
* @return The slot of the token
*/
function slotOf(uint256 _tokenId) external view returns (uint256);
/**
* @notice Allow an operator to manage the value of a token, up to the `_value`.
* @dev MUST revert unless caller is the current owner, an authorized operator, or the approved
* address for `_tokenId`.
* MUST emit the ApprovalValue event.
* @param _tokenId The token to approve
* @param _operator The operator to be approved
* @param _value The maximum value of `_toTokenId` that `_operator` is allowed to manage
*/
function approve(
uint256 _tokenId,
address _operator,
uint256 _value
) external payable;
/**
* @notice Get the maximum value of a token that an operator is allowed to manage.
* @param _tokenId The token for which to query the allowance
* @param _operator The address of an operator
* @return The current approval value of `_tokenId` that `_operator` is allowed to manage
*/
function allowance(uint256 _tokenId, address _operator) external view returns (uint256);
/**
* @notice Transfer value from a specified token to another specified token with the same slot.
* @dev Caller MUST be the current owner, an authorized operator or an operator who has been
* approved the whole `_fromTokenId` or part of it.
* MUST revert if `_fromTokenId` or `_toTokenId` is zero token id or does not exist.
* MUST revert if slots of `_fromTokenId` and `_toTokenId` do not match.
* MUST revert if `_value` exceeds the balance of `_fromTokenId` or its allowance to the
* operator.
* MUST emit `TransferValue` event.
* @param _fromTokenId The token to transfer value from
* @param _toTokenId The token to transfer value to
* @param _value The transferred value
*/
function transferFrom(
uint256 _fromTokenId,
uint256 _toTokenId,
uint256 _value
) external payable;
/**
* @notice Transfer value from a specified token to an address. The caller should confirm that
* `_to` is capable of receiving VIP-3525 tokens.
* @dev This function MUST create a new VIP-3525 token with the same slot for `_to`,
* or find an existing token with the same slot owned by `_to`, to receive the transferred value.
* MUST revert if `_fromTokenId` is zero token id or does not exist.
* MUST revert if `_to` is zero address.
* MUST revert if `_value` exceeds the balance of `_fromTokenId` or its allowance to the
* operator.
* MUST emit `Transfer` and `TransferValue` events.
* @param _fromTokenId The token to transfer value from
* @param _to The address to transfer value to
* @param _value The transferred value
* @return ID of the token which receives the transferred value
*/
function transferFrom(
uint256 _fromTokenId,
address _to,
uint256 _value
) external payable returns (uint256);
}
SLOT的枚举扩展是可选的。这允许您的合约发布其完整的 SLOT 列表并使其可被发现。
pragma solidity ^0.8.0;
/**
* @title VIP-3525 Semi-Fungible Token Standard, optional extension for slot enumeration
* @dev Interfaces for any contract that wants to support enumeration of slots as well as tokens
* with the same slot.
* Note: the VIP-165 identifier for this interface is 0x3b741b9e.
*/
interface IVRC3525SlotEnumerable is IVRC3525 /* , IVRC721Enumerable */ {
/**
* @notice Get the total amount of slots stored by the contract.
* @return The total amount of slots
*/
function slotCount() external view returns (uint256);
/**
* @notice Get the slot at the specified index of all slots stored by the contract.
* @param _index The index in the slot list
* @return The slot at `index` of all slots.
*/
function slotByIndex(uint256 _index) external view returns (uint256);
/**
* @notice Get the total amount of tokens with the same slot.
* @param _slot The slot to query token supply for
* @return The total amount of tokens with the specified `_slot`
*/
function tokenSupplyInSlot(uint256 _slot) external view returns (uint256);
/**
* @notice Get the token at the specified index of all tokens with the same slot.
* @param _slot The slot to query tokens with
* @param _index The index in the token list of the slot
* @return The token ID at `_index` of all tokens with `_slot`
*/
function tokenInSlotByIndex(uint256 _slot, uint256 _index) external view returns (uint256);
}
SLOT级别批准是可选的。这允许任何想要支持SLOT批准的合约,这允许操作员使用相同的SLOT管理自己的代币。
pragma solidity ^0.8.0;
/**
* @title VIP-3525 Semi-Fungible Token Standard, optional extension for approval of slot level
* @dev Interfaces for any contract that wants to support approval of slot level, which allows an
* operator to manage one's tokens with the same slot.
* Note: the VIP-165 identifier for this interface is 0xb688be58.
*/
interface IVRC3525SlotApprovable is IVRC3525 {
/**
* @dev MUST emit when an operator is approved or disapproved to manage all of `_owner`'s
* tokens with the same slot.
* @param _owner The address whose tokens are approved
* @param _slot The slot to approve, all of `_owner`'s tokens with this slot are approved
* @param _operator The operator being approved or disapproved
* @param _approved Identify if `_operator` is approved or disapproved
*/
event ApprovalForSlot(address indexed _owner, uint256 indexed _slot, address indexed _operator, bool _approved);
/**
* @notice Approve or disapprove an operator to manage all of `_owner`'s tokens with the
* specified slot.
* @dev Caller SHOULD be `_owner` or an operator who has been authorized through
* `setApprovalForAll`.
* MUST emit ApprovalSlot event.
* @param _owner The address that owns the VIP-3525 tokens
* @param _slot The slot of tokens being queried approval of
* @param _operator The address for whom to query approval
* @param _approved Identify if `_operator` would be approved or disapproved
*/
function setApprovalForSlot(
address _owner,
uint256 _slot,
address _operator,
bool _approved
) external payable;
/**
* @notice Query if `_operator` is authorized to manage all of `_owner`'s tokens with the
* specified slot.
* @param _owner The address that owns the VIP-3525 tokens
* @param _slot The slot of tokens being queried approval of
* @param _operator The address for whom to query approval
* @return True if `_operator` is authorized to manage all of `_owner`'s tokens with `_slot`,
* false otherwise.
*/
function isApprovedForSlot(
address _owner,
uint256 _slot,
address _operator
) external view returns (bool);
}
VIP-3525 令牌接收器
如果智能合约想要在收到来自其他地址的值时得到通知,它应该实现 IVRC3525Receiver 接口中的所有功能,在实现中它可以决定是接受还是拒绝转账。有关详细信息,请参阅“转移规则”。
pragma solidity ^0.8.0;
/**
* @title VIP-3525 token receiver interface
* @dev Interface for a smart contract that wants to be informed by VIP-3525 contracts when receiving values from ANY addresses or VIP-3525 tokens.
* Note: the VIP-165 identifier for this interface is 0x009ce20b.
*/
interface IVRC3525Receiver {
/**
* @notice Handle the recVIPt of an VIP-3525 token value.
* @dev An VIP-3525 smart contract MUST check whether this function is implemented by the recipient contract, if the
* recipient contract implements this function, the VIP-3525 contract MUST call this function after a
* value transfer (i.e. `transferFrom(uint256,uint256,uint256,bytes)`).
* MUST return 0x009ce20b (i.e. `bytes4(keccak256('onVRC3525Received(address,uint256,uint256,
* uint256,bytes)'))`) if the transfer is accepted.
* MUST revert or return any value other than 0x009ce20b if the transfer is rejected.
* @param _operator The address which triggered the transfer
* @param _fromTokenId The token id to transfer value from
* @param _toTokenId The token id to transfer value to
* @param _value The transferred value
* @param _data Additional data with no specified format
* @return `bytes4(keccak256('onVRC3525Received(address,uint256,uint256,uint256,bytes)'))`
* unless the transfer is rejected.
*/
function onVRC3525Received(address _operator, uint256 _fromTokenId, uint256 _toTokenId, uint256 _value, bytes calldata _data) external returns (bytes4);
}
VIP-3525 元数据扩展是兼容的 VIP-721 元数据扩展。
这个可选接口可以通过 VIP-165 标准接口检测来识别。
pragma solidity ^0.8.0;
/**
* @title VIP-3525 Semi-Fungible Token Standard, optional extension for metadata
* @dev Interfaces for any contract that wants to support query of the Uniform Resource Identifier
* (URI) for the VIP-3525 contract as well as a specified slot.
* Because of the higher reliability of data stored in smart contracts compared to data stored in
* centralized systems, it is recommended that metadata, including `contractURI`, `slotURI` and
* `tokenURI`, be directly returned in JSON format, instead of being returned with a url pointing
* to any resource stored in a centralized system.
* Note: the VIP-165 identifier for this interface is 0xe1600902.
*/
interface IVRC3525Metadata is
IVRC3525 /* , IVRC721Metadata */
{
/**
* @notice Returns the Uniform Resource Identifier (URI) for the current VIP-3525 contract.
* @dev This function SHOULD return the URI for this contract in JSON format, starting with
* header `data:application/json;`.
* @return The JSON formatted URI of the current VIP-3525 contract
*/
function contractURI() external view returns (string memory);
/**
* @notice Returns the Uniform Resource Identifier (URI) for the specified slot.
* @dev This function SHOULD return the URI for `_slot` in JSON format, starting with header
* `data:application/json;`.
* @return The JSON formatted URI of `_slot`
*/
function slotURI(uint256 _slot) external view returns (string memory);
}
VIP-3525 元数据 URI JSON 架构
这是上面引用的“contractURI() 的 VIP-3525 元数据 JSON 模式”。
{
"title": "Contract Metadata",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Contract Name"
},
"description": {
"type": "string",
"description": "Describes the contract"
},
"image": {
"type": "string",
"description": "Optional. Either a base64 encoded imgae data or a URI pointing to a resource with mime type image/* representing what this contract represents."
},
"external_link": {
"type": "string",
"description": "Optional. A URI pointing to an external resource."
},
"valueDecimals": {
"type": "integer",
"description": "The number of decimal places that the balance should display - e.g. 18, means to divide the token value by 1000000000000000000 to get its user representation."
}
}
}
This is the “VIP-3525 Metadata JSON Schema for slotURI(uint)” referenced above.
{
"title": "Slot Metadata",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Identifies the asset category to which this slot represents"
},
"description": {
"type": "string",
"description": "Describes the asset category to which this slot represents"
},
"image": {
"type": "string",
"description": "Optional. Either a base64 encoded imgae data or a URI pointing to a resource with mime type image/* representing the asset category to which this slot represents."
},
"properties": {
"type": "array",
"description": "Each item of `properties` SHOULD be organized in object format, including name, description, value, order (optional), display_type (optional), etc."
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name of this property."
},
"description": {
"type": "string",
"description": "Describes this property."
}
"value": {
"description": "The value of this property, which may be a string or a number."
},
"is_intrinsic": {
"type": "boolean",
"description": "According to the definition of `slot`, one of the best practice to generate the value of a slot is utilizing the `keccak256` algorithm to calculate the hash value of multi properties. In this scenario, the `properties` field should contain all the properties that are used to calculate the value of `slot`, and if a property is used in the calculation, is_intrinsic must be TRUE."
},
"order": {
"type": "integer",
"description": "Optional, related to the value of is_intrinsic. If is_intrinsic is TRUE, it must be the order of this property appeared in the calculation method of the slot."
},
"display_type": {
"type": "string",
"description": "Optional. Specifies in what form this property should be displayed."
}
}
}
}
}
}
This is the “VIP-3525 Metadata JSON Schema for tokenURI(uint)” referenced above.
{
"title": "Token Metadata",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Identifies the asset to which this token represents"
},
"description": {
"type": "string",
"description": "Describes the asset to which this token represents"
},
"image": {
"type": "string",
"description": "Either a base64 encoded imgae data or a URI pointing to a resource with mime type image/* representing the asset to which this token represents."
},
"balance": {
"type": "integer",
"description": "THe value held by this token."
},
"slot": {
"type": "integer",
"description": "The id of the slot that this token belongs to."
},
"properties": {
"type": "object",
"description": "Arbitrary properties. Values may be strings, numbers, objects or arrays. Optional, you can use the same schema as the properties section of VIP-3525 Metadata JSON Schema for slotURI(uint) if you need a better description attribute."
}
}
}
Updated about 2 years ago