作者:@Web3Mario(https://x.com/web3_mario)
技術介紹的文章,這段時間深入研究了一下TON官方開發文檔,感覺學習起來還是有些門檻,當前的文檔內容似乎更像是一個內部開發文檔,對新入門的開發者來說不太友好,因此試著以自己的學習軌跡,梳理一系列關於TON Chain專案開發的文章,希望可以對大家快速入門TON DApp開發有一些幫助。行文有誤也歡迎大家指正,一起學習。
對於DApp開發者來說通常是最基本的需求。因此我也以此作為學習入口。首先讓我們來了解以下在EVM技術堆疊中開發一個NFT和在TON Chain中的區別。基於EVM的NFT通常會選擇繼承ERC-721的標準。所謂NFT,指的是不可分割的加密資產類型,且每個資產具有唯一性,即存在某些專屬的特性。而ERC-721就是對這個類型的資產的一種通用的開發範式。讓我們來看看一個常見的ERC721合約需要實現哪些函數以及記錄哪些資訊。下圖是一個ERC721介面。可以看到與FT不同,在轉帳介面中需要輸入的是待轉帳的tokenId而非數量。這個tokenId也是NFT資產唯一性最基本的體現,當然為了承載更多的屬性,通常會為每個tokenId記錄一個 是一個外部鏈接,保存了該NFT的其他可擴展數據,例如一張PFP圖片的鏈接,某些屬性名稱等。
對於熟悉Solidity
或者熟悉面向對象的開發者來說,實現這樣一個智能合約是件容易的事,只要定義好合約中需要的映射關係mapping,並根據所需功能開發相應的對這些數據的修改邏輯,即可實現一個NFT。 然而在TON Chain
中這一切變的不太相同,造成不同的核心原因有兩個:
當然關於技術上其他不同點在上一篇文章中有過詳細的論述,本篇文章希望可以聚焦在智能合約開發上,所以不展開討論。上述兩條設計原則讓TON中智能合約開發與EVM產生了很大差異。在開始的論述中,我們知道一個NFT合約中需要定義一些映射關係,也就是mapping,來保存NFT相關的資料。其中最重要的是owners,這個mapping儲存了某個tokenID對應的NFT的擁有者地址的映射關係,決定了地址的對應關係就是對該所有權的修改。由於理論上這是一個可以沒有邊界的資料結構,需要盡量避免。因此官方推薦以是否存在無邊界資料結構作為分片的標準。即當有類似的資料儲存需求時,透過主從合約的範式來替代,透過建立子合約的方式來管理每個key對應的資料。並透過主合約管理全域參數,或協助處理子合約之間的內部資訊互動。 這也意味著在TON中的NFT也需要採用類似的架構來設計,每個NFT都是一個獨立的子地址,metadata等專屬數據,並透過一個主合約來管理全局數據,例如NFT name,symbol,總供應量等。 在明確了架構後,接下來就需要解決核心功能的需求了,由於採用了這個主從合約的方式,因此就需要明確哪些功能由主合約承載,哪些功能由子合約承載,並且兩者之間透過什麼內部資訊溝通,同時當出現執行錯誤時,如何回溯先前的資料。通常情況下,在開發複雜的大型專案之前,透過一個類別圖並明確彼此之間的資訊流,並仔細思考內部呼叫失敗後的回滾邏輯是必要的,當然上述NFT開發雖然簡單,但也可以做類似驗證。 TON選擇了設計一種類型、合約開發語言,那麼接下來就讓我們從源碼來學習如何開發TON智能合約,我選擇了TON官方文檔中的NFT示例來介紹,有興趣的小夥伴可以介紹,有興趣的小夥伴可以介紹,有興趣的小夥伴可以介紹,有興趣的小夥伴可以介紹,有興趣的小夥伴可以介紹,有興趣的小夥伴可以介紹,有興趣的小伙伴自行去查閱。在這個case中實作了一個簡單的TON NFT例。讓我們來看看合約結構,共分為兩個功能合約以及三個必要的庫。 這兩個主要的功能合約即按照上述的原則進行設計,首先讓我們來看下主合約 這引入了第一個知識點,如何在TON智能合約中持久化存儲數據,我們知道在Solidity中數據的持久化存儲是由參數類型自動處理的,通常情況下,智能合約的狀態變數將在執行結束後根據最新值自動被持久化存儲,開發者並不需要考慮這個過程。但在Func中情況並不如此,開發者需要自己來實現相應的處理邏輯,這個情況有點類似於C和C++需要考慮但其他新的開發語言通常會將這部分邏輯自動化處理。我們來看看程式碼,首先引入一些需要的函式庫,然後看到第一個函數load_data用於讀取被持久化儲存的數據,其邏輯為首先透過get_data返回持久化合約儲存cell,注意這是由標準庫stdlib.fc實現的,通常情況下可以將其中的一些函數視為系統函數來使用。 此函數的回傳值類型為cell,這是 TVM中的cell類型。在先前的介紹中,我們已經知道TON 區塊鏈中的所有持久資料都儲存在cell樹中。每個cell最多有 1023 位任意資料和最多四個對其他cell的引用。 cell在基於堆疊的 TVM 中用作記憶體。cell中保存的是緊密編碼後的數據,要獲取其中具體的明文數據,需要將cell轉換為被稱為slice轉換為被稱為slice轉換為被稱為slice轉換為被稱為slice轉換為被稱為slice轉換為被稱為slice的類型。 cell可以透過begin_parse🎜函數轉換成為🎜🎜slice🎜🎜型,然後可以透過從🎜🎜slices來取得的載入資料位和其他對資料位載入🜎 🎜🎜中的數據。注意🎜🎜15🎜🎜行程式碼中的這種呼叫方法是一個🎜🎜func🎜🎜中的語法糖,可以直接呼叫第一個函數的回傳值的第二個函數。並在最後依照資料持久化順序依序載入對應的資料。Note that this process is different from solidity, and is not called based on hashmap, so the order of calls cannot be messed up. In the save_data function, the logic is similar, except that this is a reverse process, which introduces the next knowledge point, a new type builder, this is The type of cell builder. Data bits and references to other cell can be stored in builders, which can then be finalized into new cell. First create a builder through the standard function begin_cell, and store related functions through the store related functions in turn. Note that the calling order above needs to be consistent with the storage order here.Finally, the new cell is constructed through end_cell. At this time, the cell is managed in the memory. Finally, through the outermost set_data, the can be completed. cell's persistent storage. Next, let’s take a look at business-related functions. First, we need to introduce the next knowledge point, how to create a new contract through a contract, which will be frequently used in the master-slave architecture just introduced. We know that in TON, calls between smart contracts are implemented by sending internal messages. This is achieved through a file called send_raw_message. Note that the first parameter is the messageencoded cell, and the second parameter is the identification bit, used to indicate the transaction The difference in execution methods, different execution methods of internal message sending are set in TON, currently has 3 types of messagesModes and 3 types of messagesFlags . A single Mode can be combined with multiple (perhaps none) flags to get the desired mode.Combination just means fill in the sum of their values. The description table of Modes and Flags is given below : So let’s look at the first main function, deploy_nft_item, as the name suggests, this is a function for The function that creates or casts a new NFT instance. After some operations to encode a msg, the internal contract is sent through send_raw_message, and the sending of flag 1 is selected. Identification bit, only the fee specified in the encoding is used as the gas fee for this execution. After the above introduction, we can easily realize that this coding rule should correspond to the way to create a new smart contract. Then let’s see how it is implemented. Let us look directly at the 51 line. The above two functions are auxiliary functions used to generate the information required for message, so we will look at it later. This is an internal message used to create a smart contract In the encoding process, some numbers in the middle are actually some identification bits, used to explain the needs of the internal message. The next knowledge point is introduced here. TON chose a type called TL-B Binary language is used to describe how messages are executed, and internal messages that implement certain specific functions based on setting different flag bits. The two most easily thought of usage scenarios are new contract creation and deployed contract function calls. The method of line 51 corresponds to the former, creating a new nft item contract, which is mainly done through 55, 56, 57 Three lines are specified.First of all, the large series of numbers in the 55 line is a series of identification bits. Note that the first input parameter of store_uint is a numerical value, and the second is a bit length, which determines whether the internal message is created by the contract. are the last three flag bits, and the corresponding binary value bits are 111 (the decimal is 4+2+1), the first two of which indicate that the message will be accompanied by StateInit data, this The data is the source code of the new contract and the data required for initialization. The latter flag bit indicates the internal message attachment, that is, the relevant logic and required parameters are expected to be executed. Therefore, you will see that the three-digit data is not set in line 66, which indicates a function call to the deployed contract. Detailed coding rules can be found here. Then the encoding rules of StateInit correspond to 49 lines of code, calculated through calculate_nft_item_state_init. Note that the encoding of stateinitdata also follows an established TL- BEncoding rules, except for some flag bits, mainly involve two parts of the new contract code and initialization data. The encoding order of data needs to be consistent with the storage order of persistent cell specified by the new contract.As you can see in line 36, the initialization data includes item_index, which is similar to tokenId in ERC721, and the standard function my_ address The current contract address returned is collection_address. The order of this data is consistent with the statement in nft-item. The next knowledge point is that in TON, all ungenerated smart contracts can pre-calculate their generated addresses. This is similar to the create2 function in Solidity. The generation of new addresses in TON consists of two parts, the workchain identification bit and the hash value of stateinit. We already know that the former is for the corresponding TONWhat needs to be specified for the infinite sharding architecture is currently a unified value. Obtained from the standard function workchain. The latter is obtained by the standard function cell_hash. So back to this example, calculate_nft_item_address is a function that pre-calculates the new contract address. And encode the generated value in line 53 into message as the receiving address of the internal message.And nft_content corresponds to the initialization call to the created contract. The specific implementation will be introduced in the next article. As for send_royalty_params, it needs to be a response to the internal message of a read-only request. In the previous introduction, we specially emphasized that the internal message in TON not only contains possible modifications Data operations and read-only operations also need to be implemented in this way, so this contract is such an operation. The first thing to note is that the 67 line indicates the mark of the requester's callback function after responding to the request. Write it down. That is the returned data, which are the requested item index and the corresponding royalty data. Let us introduce the next knowledge point. There are only two unified entrances to smart contracts in TON, named recv_internal and recv_external, where the former is the unification of all internal messages Call entry, the latter is a unified call entry for all external messages. Developers need to use a method similar to switch within the function to respond to different requests based on the different flag bits specified by message. Here The mark bit is the callback function mark of the above line 67. Back to this example, first perform a vacancy check on message, and then parse the information in message respectively. First, parse the 83 line to obtain sender_address. The parameters will be used for subsequent permission checks. Note that the ~ operators here are another syntactic sugar. I won’t expand on it here.Next, the op operation flag bits are parsed, and then the corresponding requests are processed according to different flag bits. Among them, the above functions are called respectively according to certain logic. For example, respond to a request for the royalty parameter, or mint a new nft and increment the global index. The next knowledge point corresponds to line 108. I believe you can also know the processing logic of this function by naming it. It is similar to the require function in Solidity, Func Exceptions are thrown through the standard function throw_unless. The first input parameter is the error code, and the second is to check the bit Boolean value. If the bit is false, an exception will be thrown with the error code. . In this line, equal_slices is used to determine whether the sender_address parsed above is equal to the owner_address stored persistently in the contract, and make permission judgment. Finally, in order to make the code structure clearer, a series of auxiliary functions have been developed to help obtain persistence information. They will not be introduced here. Developers can refer to this structure to develop their own smart contracts. . TONecological DAppdevelopment is really an interesting thing, and it is very different from the development paradigm of EVM, so I will introduce how to develop in TON Chain through a series of articles Developed in DApp. Learn together with everyone and seize this wave of opportunities. You are also welcome to interact with me on twitter to bump into some new and interesting dapp ideas and develop them together. 從源碼學習開發TON智能合約
以上是TON 專案開發教學(一):原始碼角度看如何在 TON Chain 上建立一個NFT的詳細內容。更多資訊請關注PHP中文網其他相關文章!