paint-brush
Hiểu các tiêu chuẩn mã thông báo trong Ethereum Phần II (ERC721)từ tác giả@zartaj
2,499 lượt đọc
2,499 lượt đọc

Hiểu các tiêu chuẩn mã thông báo trong Ethereum Phần II (ERC721)

từ tác giả Md Zartaj Afser16m2023/03/01
Read on Terminal Reader

dài quá đọc không nổi

Tiêu chuẩn ERC-721 đã được đề xuất cho NFT (Mã thông báo không thể thay thế) NFT đề cập đến các mã thông báo là duy nhất, có nghĩa là mọi mã thông báo bên trong hợp đồng thông minh sẽ khác với các mã thông báo khác. Nó có thể được sử dụng để xác định những thứ độc đáo, chẳng hạn như một số loại hình ảnh, vé số, đồ sưu tầm, tranh vẽ hoặc thậm chí là âm nhạc, v.v.
featured image - Hiểu các tiêu chuẩn mã thông báo trong Ethereum Phần II (ERC721)
Md Zartaj Afser HackerNoon profile picture
0-item
1-item


Tiêu chuẩn ERC-721 đã được đề xuất cho NFT (Mã thông báo không thể thay thế). NFT đề cập đến các mã thông báo là duy nhất, có nghĩa là mọi mã thông báo bên trong hợp đồng thông minh sẽ khác với các mã thông báo khác. Nó có thể được sử dụng để xác định những thứ độc đáo, chẳng hạn như một số loại hình ảnh, vé số, đồ sưu tầm, tranh vẽ hoặc thậm chí là âm nhạc, v.v. Để nhắc nhở bạn, ERC-20 dành cho các mã thông báo có thể thay thế được, nếu bạn chưa đọc bài viết về ERC-20 thì hãy cân nhắc đọc nó trước. Dự án trong thế giới thực tốt nhất cho ví dụ ERC-721 là Cryptokitties . Đây là một trò chơi dựa trên blockchain, hãy xem trò chơi tuyệt vời này để có kiến thức thú vị.


Nhưng làm thế nào để điều này làm việc? Những hình ảnh, âm nhạc và bức tranh này được lưu trữ trong hợp đồng thông minh như thế nào?


Chà, những thứ này không được lưu trữ bên trong hợp đồng thay vào đó hợp đồng chỉ trỏ đến một tài sản bên ngoài. Có một số, tokenId hiển thị quyền sở hữu. Nội dung chính là hình ảnh hoặc một số dữ liệu khác được đính kèm với tokenId thông qua URI. Hãy đi sâu hơn một chút.


Chúng tôi chỉ định một URI, là một văn bản JSON, cho ID mã thông báo. Và văn bản JSON đó chứa chi tiết và đường dẫn đến hình ảnh hoặc bất kỳ nội dung nào khác. Và người dùng chỉ sở hữu tokenid . Ví dụ: địa chỉ của tôi có số dư tokenid là 4, bây giờ hình ảnh hoặc bất kỳ loại dữ liệu nào được đính kèm với tokenid đó sẽ là của tôi. Tôi sở hữu dữ liệu đó vì tôi sở hữu tokenid .


Bây giờ chúng ta phải lưu trữ hai thứ này, tức là Hình ảnh và văn bản JSON (URI) ở đâu đó để bất kỳ thị trường NFT nào cũng có thể tìm nạp hình ảnh và hiển thị nó trên trang web của họ. Bạn có thể nghĩ tại sao chúng ta cần URI siêu dữ liệu, tại sao không gán trực tiếp URI hình ảnh cho id mã thông báo? Chà, bạn có thể nhớ lý do tại sao chúng tôi cần các tiêu chuẩn ERC ngay từ đầu, vâng, để các ứng dụng phía máy khách dễ dàng kết nối với các hợp đồng. Tương tự, siêu dữ liệu mà chúng tôi viết cho NFT phải ở định dạng phù hợp được thị trường NFT đề xuất để họ có thể dễ dàng tìm nạp dữ liệu từ tệp JSON đó và hiển thị dữ liệu trên trang web của họ.


Bây giờ chúng ta hãy xem điều lưu trữ.

Lưu trữ dữ liệu

Có hai cách để lưu trữ hình ảnh và URI. Chúng tôi có thể lưu trữ nó trên chuỗi (bên trong chuỗi khối) hoặc ngoài chuỗi (bên ngoài chuỗi khối).


Dữ liệu trên chuỗi được lưu trữ trong chuỗi khối nhưng nó chiếm rất nhiều dung lượng không phù hợp. Chỉ cần nghĩ đến việc trả hàng ngàn đô la tại thời điểm triển khai hợp đồng của bạn. Nghe không hay. Ngoài ra, blockchain cũng cung cấp dung lượng lưu trữ hạn chế, bạn không thể lưu trữ các tệp lớn trong đó.


Vì vậy, chúng tôi có tùy chọn lưu trữ dữ liệu bên ngoài chuỗi khối. Thông qua trang web của chúng tôi bằng AWS hoặc bất kỳ dịch vụ đám mây nào khác. Nhưng điều này giết chết ý tưởng chính của blockchain, tức là phi tập trung hóa. Điều gì sẽ xảy ra nếu máy chủ gặp sự cố hoặc ai đó hack nó? Vì sẽ có một máy chủ duy nhất lưu trữ tất cả dữ liệu. Vì vậy, chúng tôi cần một thứ khác mạnh mẽ để tấn công và cũng được phân cấp và thứ đó là IPFS (Hệ thống tệp liên hành tinh) là một hệ thống lưu trữ phân tán. IPFS có nhiều nút tương tự như ý tưởng về chuỗi khối lưu trữ dữ liệu. Nhưng bạn không phải trả bất kỳ khoản phí nào. Chúng tôi có thể lưu trữ hình ảnh của mình cũng như tệp JSON (URI) trên IPFS và làm như vậy sẽ cung cấp một CID duy nhất (tiếng vô nghĩa ngẫu nhiên) trỏ trực tiếp đến dữ liệu và chúng tôi chỉ định một CID cụ thể cho Id mã thông báo cụ thể. Chúng ta sẽ nói thêm về phần kỹ thuật sau, trước tiên hãy tìm hiểu giao diện của tiêu chuẩn ERC-721.

GIAO DIỆN ERC-721

Hãy xem giao diện ERC-721 trông như thế nào.

Tiêu chuẩn này có các chức năng sau:

  1. Chuyển mã thông báo từ tài khoản này sang tài khoản khác.

  2. Nhận số dư mã thông báo hiện tại của tài khoản.

  3. Bắt chủ sở hữu của một mã thông báo cụ thể.

  4. Tổng nguồn cung mã thông báo có sẵn trên mạng.

  5. Bên cạnh những chức năng này, nó còn có một số chức năng khác như phê duyệt rằng một lượng mã thông báo từ tài khoản có thể được di chuyển bởi tài khoản bên thứ ba.


Bây giờ hãy xem giao diện của ERC-721.

 pragma solidity ^0.4.20; interface ERC721 { event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); function balanceOf(address _owner) external view returns (uint256); function ownerOf(uint256 _tokenId) external view returns (address); function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable; function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable; function transferFrom(address _from, address _to, uint256 _tokenId) external payable; function approve(address _approved, uint256 _tokenId) external payable; function setApprovalForAll(address _operator, bool _approved) external; function getApproved(uint256 _tokenId) external view returns (address); function isApprovedForAll(address _owner, address _operator) external view returns (bool); } Break

Phá vỡ

  1. balanceOf Trả về số lượng mã thông báo trong tài khoản của chủ sở hữu. Làm thế nào để chúng tôi theo dõi số dư? Chà, nó luôn giống nhau, chúng tôi xác định một ánh xạ theo dõi tổng số mã thông báo trong ví. lập bản đồ (địa chỉ => uint) số dư công cộng; Hãy nhớ rằng, nó chỉ tổng hợp tổng số mã thông báo và trả về giống nhau, ánh xạ này không biết về chủ sở hữu của mã thông báo vì nó chỉ cho biết số id mã thông báo mà một địa chỉ có.

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


2. ownOf Tìm chủ sở hữu của một NFT. Bây giờ, chức năng này cho chúng ta biết về chủ sở hữu của một NFT cụ thể. Chúng tôi giữ dữ liệu này tương tự như trên. lập bản đồ (uint => địa chỉ) số dư công khai; Các NFT được gán cho các địa chỉ bằng 0 được coi là không hợp lệ và các truy vấn về chúng sẽ gây ra lỗi.

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


3. safeTransferFrom Chuyển quyền sở hữu NFT từ địa chỉ này sang địa chỉ khác. Nó chỉ nên đặt chủ sở hữu của tokenId thành địa chỉ mới và cũng cập nhật ánh xạ balances . Nó sẽ đưa ra một lỗi trong các trường hợp sau:


  • msg.sender là chủ sở hữu hiện tại, nhà điều hành được ủy quyền hoặc địa chỉ được phê duyệt cho NFT này
  • _from không phải là chủ sở hữu hiện tại
  • __to_ là địa chỉ số không.
  • __tokenId_ không phải là NFT hợp lệ


Khi quá trình chuyển hoàn tất, chức năng này sẽ kiểm tra xem __to_ có phải là hợp đồng thông minh hay không (kích thước mã > 0). Nếu vậy, nó gọi hàm onERC721Received trên __to_ và ném ra nếu giá trị trả về không bằng giá trị này: bytes4(keccak256("onERC721Received(address, address,uint256, bytes)")).


Nó là cái gì vậy? Đây là lý do tại sao chức năng này được gọi là chuyển giao an toàn, chúng ta sẽ nói thêm về nó sau.


function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;


4. safeTransferFrom : Chức năng này hoạt động giống như chức năng trên với một tham số dữ liệu bổ sung, ngoại trừ chức năng này chỉ đặt dữ liệu thành “ ”.


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




Làm thế nào là hai chức năng này có cùng tên?

Sự thật thú vị: Không giống như Javascript, Solidity hỗ trợ Quá tải chức năng. nghĩa là chúng ta có thể định nghĩa hai hàm trùng tên, điều kiện duy nhất là các tham số phải khác nhau, tạo ra sự khác biệt trong chữ ký của hàm. Không biết chữ ký chức năng là gì? Của bạn đây. Liên kết để trả lời


5. transferFrom chuyển quyền sở hữu một NFT. Hoạt động giống như chức năng safeTransferFrom , điểm khác biệt duy nhất là nó không gọi lệnh gọi an toàn ( onERC721Received ) trên người nhận. Do đó, tạo ra nguy cơ mất NFT.


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



6. phê duyệt khái niệm tương tự như chức năng phê duyệt ERC20 nhưng có nhiều chức năng và logic hơn. Để chức năng này hoạt động, chúng tôi xác định một ánh xạ lồng nhau: mapping(uint =>address) internal allowance; Trong ánh xạ này, uint đề cập đến id mã thông báo và địa chỉ được phê duyệt để thực hiện các thao tác trên mã thông báo Id cụ thể đó. Chức năng phê duyệt này sẽ kiểm tra xem msg.sender có phải là chủ sở hữu hiện tại hoặc người điều hành cho chủ sở hữu của mã thông báo hay không. Nếu bước kiểm tra này vượt qua thì chỉ bản đồ mới được cập nhật. Toán tử ở đây là gì? Xem chức năng tiếp theo.

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




7. setApprovalForAll hoạt động giống như chức năng phê duyệt trước nhưng thay vì phê duyệt một địa chỉ cho một Id mã thông báo duy nhất, chức năng này sẽ phê duyệt và giải quyết để xử lý tất cả các mã thông báo thuộc sở hữu của một địa chỉ cụ thể. Nó có nghĩa là gì? Điều đó có nghĩa là bạn có thể tạo toán tử địa chỉ cho NFT của mình. Địa chỉ đó sẽ là chủ sở hữu NFT của bạn cho đến khi bạn thu hồi quyền sở hữu. Lần này chúng ta lại sử dụng mapping(address => mapping(address=>bool))internal operator; Địa chỉ đầu tiên đặt giá trị boolean đúng hoặc sai cho địa chỉ thứ hai để phê duyệt hoặc thu hồi tương ứng.


function setApprovalForAll(address _operator, bool _approved) external;


8. getApproved tương tự như chức năng trợ cấp trong giao diện ERC-20. Trả về address đã được phê duyệt cho một NFT duy nhất. Nó kiểm tra ánh xạ mà chúng tôi đã cập nhật ở chức năng phê duyệt ở trên.


function getApproved(uint256 _tokenId) external view returns (address);


9. isApprovedForAll tương tự như hàm trên. Nó truy vấn nếu một address là một operator tử được ủy quyền cho một address khác. Thay vì trả về address đã được phê duyệt của một tokenId cụ thể, hàm này sẽ trả về address của operator cho address đã cho mà chúng tôi đã cập nhật tại hàm setApprovalForAll

function isApprovedForAll(address _owner, address _operator) external view returns (bool);

Sự kiện cho ERC-721

Chuyển giao: phát ra khi quyền sở hữu của bất kỳ NFT nào thay đổi theo bất kỳ cơ chế nào. Sự kiện này phát ra khi NFT được tạo (from == 0) và bị hủy (to == 0). Ngoại lệ : Trong quá trình tạo hợp đồng, bất kỳ số lượng NFT nào cũng có thể được tạo và chỉ định mà không phát ra Chuyển khoản. Tại thời điểm chuyển bất kỳ, địa chỉ được phê duyệt cho NFT đó (nếu có) được đặt lại thành không.


event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);


Phê duyệt phát ra khi địa chỉ được phê duyệt cho NFT được thay đổi hoặc xác nhận lại. Địa chỉ số 0 cho biết không có địa chỉ nào được phê duyệt. Khi một sự kiện Chuyển phát ra, điều này cũng cho biết rằng địa chỉ được phê duyệt cho NFT đó (nếu có) được đặt lại thành không.


event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);


ApproveForAll phát ra khi một toán tử được bật hoặc tắt cho chủ sở hữu. Người điều hành có thể quản lý tất cả các NFT của chủ sở hữu.


event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);



Đây là giao diện cho các hợp đồng ERC 721. Bây giờ hãy tìm hiểu thêm về cách triển khai và quy tắc của nó.

Bộ thu mã thông báo ERC721


Trước khi thực hiện, có một điều nữa. Hãy nhớ rằng chúng ta đã nói về một chức năng gọi là onERC721Received khi chúng ta nói về việc chuyển mã thông báo? Hãy nói về điều đó bây giờ. Nếu người nhận mã thông báo ERC-721 là một hợp đồng thì nó cần phải hoạt động với mã thông báo ERC-721. Bởi vì điều gì sẽ xảy ra nếu không có chức năng tương tác với các mã thông báo trong hợp đồng người nhận đó? Các mã thông báo sẽ bị khóa trong hợp đồng đó mãi mãi. Không ai có thể lấy những mã thông báo đó ra bất kỳ địa chỉ nào vì không có chức năng. Để khắc phục lỗ hổng này, người nhận mã thông báo ERC-721 phải triển khai Giao diện người nhận, nếu không thì không phải hợp đồng nào cũng có thể gửi bất kỳ mã thông báo ERC-721 nào tới hợp đồng đó. Hãy nhìn vào giao diện máy thu.


Giao diện này chỉ chứa một chức năng để triển khai và đó là onERC721Received, chức năng này sẽ xử lý việc nhận NFT. Hợp đồng thông minh ERC-721 gọi chức năng này cho người nhận sau khi transfer . Chức năng này CÓ THỂ ném để hoàn nguyên và từ chối chuyển giao. Trả về khác với giá trị kỳ diệu PHẢI dẫn đến giao dịch được hoàn nguyên.


 interface ERC721TokenReceiver { function onERC721Received(address _operator,address _from,uint256 _tokenId,bytes _data) external returns(bytes4); }


Ở đây bạn có thể nghĩ rằng làm thế nào hợp đồng mã thông báo biết liệu người nhận đã triển khai giao diện ERC721TokenReceiver hay chưa? Vì vậy, trước khi gửi mã thông báo, trước tiên bạn phải kiểm tra phần này. Để biết điều này, hãy xem triển khai openzeppelin của ERC-721. Đây là chức năng riêng tư mà bạn nên gọi bên trong safeTransfer() trước khi gửi mã thông báo. Nếu điều này trả về true thì chỉ giao dịch mới xảy ra.



Chà, điều này không đảm bảo chức năng đưa NFT ra khỏi hợp đồng người nhận vì nó chỉ kiểm tra việc thực hiện chức năng người nhận chứ không kiểm tra chức năng chuyển NFT ra khỏi hợp đồng. Vậy ý nghĩa của nó là gì? Phương pháp này có thể cho chúng tôi biết rằng tác giả của hợp đồng người nhận ít nhất đã biết về phương pháp này, điều đó có nghĩa là họ phải triển khai chức năng chuyển NFT ra khỏi hợp đồng. Và tất nhiên, không ai muốn token của họ bị mắc kẹt trong hợp đồng.

ERC721Siêu dữ liệuERC721Enumerable

Các giao diện trên là bắt buộc đối với hợp đồng mã thông báo ERC-721. Bây giờ, một số giao diện là tùy chọn về mặt lý thuyết nhưng làm cho hợp đồng rõ ràng hơn và dễ sử dụng hơn.


Đây là ERC721MetadataERC721Enumerable. Hãy bắt từng người một.


  1. Siêu dữ liệu ERC721: Phần mở rộng siêu dữ liệu được sử dụng để chủ yếu thẩm vấn hợp đồng về tên mã thông báo. Bây giờ hãy xem giao diện Siêu dữ liệu. Điều này khá đơn giản để hiểu.
 interface ERC721Metadata/* is ERC721 */ { /// @notice A descriptive name for a collection of NFTs in this /// contract function name()external view returns (string _name); /// @notice An abbreviated name for NFTs in this contract function symbol()external view returns (string _symbol); /// @notice A distinct Uniform Resource Identifier (URI) for a given /// asset. /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined /// in RFC3986. The URI may point to a JSON file that conforms to /// the "ERC721Metadata JSON Schema". function tokenURI(uint256 _tokenId)external view returns (string);


  1. ERC721Enumerable- Điều này chỉ cung cấp dữ liệu về NFT.

     interface ERC721Enumerable/* is ERC721 */ { /// @notice Count NFTs tracked by this contract /// @return A count of valid NFTs tracked by this contract, where /// each one of them has an assigned and queryable owner not equal /// to the zero address function totalSupply()external view returns (uint256); /// @notice Enumerate valid NFTs /// @dev Throws if `_index` >= `totalSupply()`. /// @param _index A counter less than `totalSupply()` /// @return The token identifier for the `_index`th NFT, /// (sort order not specified) function tokenByIndex(uint256 _index)external view returns (uint256); /// @notice Enumerate NFTs assigned to an owner /// @dev Throws if `_index` >= `balanceOf(_owner)` or if /// `_owner` is the zero address, representing invalid NFTs. /// @param _owner An address where we are interested in NFTs owned /// by them /// @param _index A counter less than `balanceOf(_owner)` /// @return The token identifier for the `_index`th NFT assigned to /// `_owner`, /// (sort order not specified) function tokenOfOwnerByIndex(address _owner,uint256 _index)external view returns(uint256);

ERC165

Bây giờ, làm thế nào chúng ta biết liệu một giao diện đã được thực hiện bởi một hợp đồng hay chưa? Đối với điều này, chúng ta cần phải tắt chủ đề, tức là ERC-165, có chức năng:

function supportsInterface(bytes4 interfaceID) external view returns (bool);


Hàm này lấy interfaceId bạn muốn kiểm tra làm đối số và khớp nó với interfaceId bạn muốn kiểm tra. Tôi sẽ cho bạn biết interfaceId là gì, hãy đồng ý với tôi. Trước tiên, hãy xem việc triển khai chức năng này của openzeppelin.

Hãy hiểu thêm về interfaceId trong hàm này type(IERC721).interfaceId ;



interfaceID đạt được bằng hai thao tác chính.

1. băm keccak 256

2. Thao tác XOR


keccak256 là một thuật toán lấy đầu vào và đưa ra một số chuỗi ngẫu nhiên theo byte. Bây giờ chúng ta hãy tìm hiểu hàm băm keccak cho chức năng này.

function supportsInterface(bytes4 interfaceID) external view returns (bool);

Cú pháp trông giống như ṭhis.

bytes4(keccak256('supportsInterface(bytes4)') ;



Bây giờ chúng ta có hàm băm keccak cho chức năng này. Hãy nhớ rằng, bạn không phải chuyển toàn bộ chức năng bên trong tham số cho keccak256 mà chỉ chuyển chữ ký. Chữ ký chỉ có nghĩa là tên và loại tham số, thậm chí không bao gồm tên của tham số. Sau khi nhận được hàm băm keccak256 của tất cả các hàm, chúng tôi thực hiện thao tác XOR giữa chúng và kết quả chúng tôi nhận được là interfaceId. Hãy xem làm thế nào. Các hoạt động XOR nhận đầu vào và đưa ra một số kết quả đầu ra sau khi so sánh chúng. Nó xuất ra true nếu một và chỉ một trong số các đầu vào là true. Nếu cả hai đầu vào đều sai hoặc cả hai đều đúng, thì đầu ra sẽ là false .


Bạn không cần phải hiểu toán học đằng sau XOR. Chỉ cần nhớ rằng, bạn lấy hàm băm keccak256 của mọi chức năng và chuyển chúng tới cổng XOR và giá trị bạn nhận được là interfaceID. Vì vậy, ý tưởng chính là lấy hàm băm keccak của các hàm và nhận đầu ra XOR của chúng. đầu ra đó là interfaceId và sau đó, bạn có thể kiểm tra hợp đồng xem nó có cùng interfaceID hay không. Nếu có, điều đó có nghĩa là hợp đồng đang triển khai giao diện mong muốn.

Đừng lo lắng solidity đã làm điều này dễ dàng cho bạn. Hãy tìm hiểu bằng cách lấy Giao diện cho Siêu dữ liệu ERC721 làm ví dụ.


 interface ERC721Metadata/* is ERC721 */ { function name()external view returns (string _name); function symbol()external view returns (string _symbol); function tokenURI(uint256 _tokenId)external view returns (string); }


Ở đây chúng ta có ba chức năng. Vì vậy, tôi đã viết đoạn mã này để làm cho bạn hiểu. Lưu ý ở đây ký hiệu dấu mũ ^ . Biểu tượng này đại diện cho hoạt động XOR giữa hai giá trị.

 // SPDX-License-Identifier: MIT pragma solidity ^0.8.16 ; interface metadata { function name()external view returns (string memory _name ); function symbol()external view returns (string memory _symbol); function tokenURI(uint256 _tokenId)external view returns (string memory a); } contract { //old and lengthy way by applying the keccak256 algorithm and performing XOR. function getHashOldWay ()public pure returns(bytes4){ return bytes4(keccak256('name()')) ^ bytes4(keccak256('symbol()'))^ bytes4(keccak256('tokenURI(uint256)')); } //Improved way function getHashNewWay ()public pure returns(bytes4){ metadata a; return a.name.selector ^ a.symbol.selector ^ a.tokenURI.selector; } //this is the latest simplest way to get the interfaceId function getHashLatestWay ()public pure returns(bytes4){ return type(metadata).interfaceId; } }


Ồ, chúng ta đã đi quá sâu vào ERC165 mà quên mất ERC721, hãy quay lại với nó.

Làm cách nào để opensea (hoặc bất kỳ thị trường nào khác) lấy dữ liệu từ hợp đồng thông minh?


Đây là thời điểm thích hợp để hiểu các URI mã thông báo giúp thị trường NFT khác nhau xác định dữ liệu bạn đã chỉ định với một mã thông báo Id cụ thể. Vì Opensea là thị trường nổi tiếng nhất nên chúng tôi sẽ lấy nó làm ví dụ. Opensea mong đợi hợp đồng ERC721 của bạn trả về tokenURI bằng cách gọi hàm tokenURI() . Hãy xem xét hợp đồng openzeppelin cho điều này.

TokenURI có thể có hai loại.


1. URI cơ sở giống nhau cho tất cả các mã thông báo, thay đổi theo mã thông báoId.

Bằng cách này, chúng tôi chỉ định một URI cơ sở cho tất cả các mã thông báo và sau đó nối mã thông báoId với nó, nhận URI siêu dữ liệu. Điều này chỉ khả thi khi bạn đã chỉ định bộ sưu tập của mình theo cách mà liên kết giống nhau đối với mọi tệp JSON siêu dữ liệu, điểm khác biệt duy nhất sẽ là tokenId. Ví dụ,

https://gateway.pinata.cloud/ipfs/QmYLwrqMmzC3k4eZu7qJ4MZJ4SNYMgqbRJFLkyiPtUBZUP/ Liên kết này trỏ đến thư mục, nghĩa là đây là baseURI.

Để có được một siêu dữ liệu, chúng tôi cần truy cập https://gateway.pinata.cloud/ipfs/QmYLwrqMmzC3k4eZu7qJ4MZJ4SNYMgqbRJFLkyiPtUBZUP/1.json

Và bây giờ bạn phải trả lại tokenURI từ hợp đồng theo cách nó trực tiếp chuyển đến siêu dữ liệu của mã thông báo cụ thể đó và thị trường có thể tìm nạp nó. Chúng tôi làm điều đó bằng cách nối baseURI với tokenId và abi mã hóa nó. Nhìn vào chức năng này dưới đây.


 function tokenURI(uint tokenId) override public view returns(string memory) { return (string(abi.encodePacked( "https://gateway.pinata.cloud/ipfs/QmYLwrqMmzC3k4eZu7qJ4MZJ4SNYMgqbRJFLkyiPtUBZUP/",Strings.toString(tokenId),".json")) ); }

Đây là chức năng mà thị trường sẽ gọi để lấy URI và hiển thị tất cả dữ liệu chúng tôi đã cung cấp trong tệp JSON.



2. các URI khác nhau cho mỗi mã thông báo.

Đây là một cách khác mà chúng ta có thể chỉ định các URI nằm ở các vị trí khác nhau. Và liên kết IPFS cho một tệp riêng lẻ trông như thế này. https://ipfs.filebase.io/ipfs/Qma65D75em77UTgP5TYXT4ZK5Scwv9ZaNyJPdX9DNCXRWc Bằng cách này, bạn không thể ghép tokenId với baseURI để nhận liên kết này, thay vào đó, liên kết này phải được gắn trực tiếp vào tokenId trên chuỗi. Và để xem xét hợp đồng ERC721URIStorage ở trên, nơi chúng tôi đang xác định ánh xạ riêng tư để gán URI cho một tokenId cụ thể. Và sau đó cũng xác định một hàm điền vào ánh xạ với một URI đã cho. Và hàm tokenURI sẽ ghi đè hàm gốc bằng cách thêm một chức năng mới để trả về URI được ánh xạ.

Một điều nữa cần lưu ý là định dạng của lược đồ JSON. JSON phải chứa dữ liệu theo cách được tiêu chuẩn hóa để thị trường có thể tìm nạp dữ liệu mong muốn và hiển thị giống nhau.


Lược đồ JSON tiêu chuẩn cho ERC721.

 { "title": "Asset Metadata", "type": "object", "properties": { "name": { "type": "string", "description": "Identifies the asset to which this NFT represents" }, "description": { "type": "string", "description": "Describes the asset to which this NFT represents" }, "image": { "type": "string", "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive." } } }


Vì vậy, đây là những điều bạn phải biết nếu quan tâm đến việc phát triển hợp đồng thông minh ERC-721 (NFT).



vấn đề :

Có một số vấn đề với khả năng mở rộng trong tiêu chuẩn ERC721. Sự cố xảy ra khi chuyển mã thông báo vì ERC-721 cho phép bạn chuyển từng mã thông báo một. Điều này có nghĩa là nếu bạn muốn gửi cho ai đó 5 NFT thì bạn cần thực hiện 5 giao dịch. Điều này khá rõ ràng với bạn rằng nó sẽ chiếm bao nhiêu dung lượng trong chuỗi khối. Đây là lý do tại sao trong các đợt tăng giá, mạng phải đối mặt với các vấn đề, vì có quá nhiều sự vội vàng trong mạng và phí gas tăng nhanh.


ERC-1155 giải quyết những vấn đề này. Làm sao? Hãy nói về điều này trong một bài viết riêng biệt. Nếu bạn đã hiểu hết về tiêu chuẩn ERC721 thì ERC1155 sẽ không khó hiểu lắm.


Cũng được xuất bản ở đây .