# 《Solidity 教程》合約結構 **Published by:** [Samumu.eth](https://paragraph.com/@samumu/) **Published on:** 2022-03-01 **URL:** https://paragraph.com/@samumu/solidity-2 ## Content 在 Solidity 語言中,合約類似於其他面向物件程式設計語言中的類 每個合約中可以包含 狀態變數、 函數、 函數 、事件 Event、 結構體、 和 枚舉類型 的聲明,且合約可以從其他合約繼承。還有一些特殊的合約,例如如庫和介面. 本節用於幫助我們了解合約包含哪些內容,做一個簡單的入門,不會有細節的解釋與範例 Section3. 類型 和 Section6. 合約 章節會比本節包含更多的說明 State Variables 狀態變數是永久地存儲在合約中的值 在 Azuki.sol 中使用: // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract Azuki is Ownable, ERC721A, ReentrancyGuard { uint256 public immutable maxPerAddressDuringMint; uint256 public immutable amountForDevs; uint256 public immutable amountForAuctionAndDev; mapping(address => uint256) public allowlist; //... uint256 public constant AUCTION_START_PRICE = 1 ether; uint256 public constant AUCTION_END_PRICE = 0.15 ether; uint256 public constant AUCTION_PRICE_CURVE_LENGTH = 340 minutes; uint256 public constant AUCTION_DROP_INTERVAL = 20 minutes; uint256 public constant AUCTION_DROP_PER_STEP = (AUCTION_START_PRICE - AUCTION_END_PRICE) / (AUCTION_PRICE_CURVE_LENGTH / AUCTION_DROP_INTERVAL); //... string private _baseTokenURI; } 這些變數宣告便是該合約中所有的狀態變數,下一章節會解釋各種狀態變數如何使用 Functions 函數是代碼的可執行單元, 函數通常在合約內部定義,但也可以在合約外定義,在 Azuki.sol 中我們可以看到所有函數都被包在 Contract Azuki 裡面 在 Azuki.sol 中使用到的函數類型包含: // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract Azuki is Ownable, ERC721A, ReentrancyGuard { function publicSaleMint(uint256 quantity, uint256 callerPublicSaleKey) { //... } function auctionMint(uint256 quantity) external payable callerIsUser { //... } function isPublicSaleOn( uint256 publicPriceWei, uint256 publicSaleKey, uint256 publicSaleStartTime ) public view returns (bool) { //... } function getOwnershipData(uint256 tokenId) external view returns (TokenOwnership memory){ //... } function endAuctionAndSetupNonAuctionSaleInfo( uint64 mintlistPriceWei, uint64 publicPriceWei, uint32 publicSaleStartTime ) external onlyOwner { //... } function _baseURI() internal view virtual override returns (string memory) { //... } function withdrawMoney() external onlyOwner nonReentrant { //... } } 只看函數宣告的話,我們並不能了解這個函數的確切用法,但卻可以了解這個函數: 能夠在哪使用 - 我們可以函數宣告中有些函數帶有 external , public , internal 這表示這個函數的可見性,其中 private 也是一種方式,不過這邊沒有使用到 需要提供什麼類型參數 - () 內所有的參數,可以看到其聲明方法與第一部分狀態變數雷同,以第一個函數 publicSaleMint 為例,他需要 caller 提供 quantity 和 callerPublicSaleKey 的值,且其類型必須是 uint256 會回傳什麼類型的資料 - returns() 內的參數,以 isPublicSaleOn 為例,這個函數會回傳 bool 也就是 True 或 False Functions Modifiers 函數修改器可以用來以聲明的方式修改函數語義, Azuki.sol 中使用: // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract Azuki is Ownable, ERC721A, ReentrancyGuard { //... modifier callerIsUser() { require(tx.origin == msg.sender, "The caller is another contract"); _; } //... } 以上述函數部分 auctionMint 為例,後面 callerIsUser 就是修改器用法 Events 事件是能方便地調用乙太坊虛擬機日誌功能的介面, Azuki.sol 中沒有使用到事件,不過這邊還是簡單說明一下用法 pragma solidity >=0.4.21 <0.9.0; contract TinyAuction { event HighestBidIncreased(address bidder, uint amount); // 事件 function bid() public payable { // ... emit HighestBidIncreased(msg.sender, msg.value); // 觸發事件 } } Struct Types 結構體是可以將幾個變數分組的自定義類型, Azuki.sol 中使用: // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract Azuki is Ownable, ERC721A, ReentrancyGuard { //... struct SaleConfig { uint32 auctionSaleStartTime; uint32 publicSaleStartTime; uint64 mintlistPrice; uint64 publicPrice; uint32 publicSaleKey; } //... } Enum Types 枚舉可用來創建由一定數量的「常量值」構成的自定義類型, Azuki.sol 中沒有使用到事件,不過這邊還是簡單說明一下用法 pragma solidity >=0.4.0 <0.9.0; contract Upchain { enum State { Created, Locked, InValid } // 枚举 } ## Publication Information - [Samumu.eth](https://paragraph.com/@samumu/): Publication homepage - [All Posts](https://paragraph.com/@samumu/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@samumu): Subscribe to updates - [Twitter](https://twitter.com/SamumuClan): Follow on Twitter