跳至內容
0%

什麼是 Solidity 中的 function visibility?

發布於 2022年10月4日閱讀時間 1 分鐘

Solidity 智能合約程式設計中,有一項機制能讓開發者根據指定的限制,決定誰或哪些其他智能合約可以呼叫自己的函式。這種定義智能合約函式可被如何互動的能力,稱為函式可見性(function visibility)

什麼是函式可見性?

Solidity 智能合約中的函式可見性功能,用來確保函式在指定時,其存取層級(包括 public、external、internal、private)能維持開發者原本的設計意圖。

如果開發者沒有使用正確的函式可見性類型,或程式碼中未指定可見性模式,合約預設的 public 可見性就會暴露在潛在可被利用的安全漏洞之下。除了未指定函式可見性所帶來的安全隱患之外,智能合約也可能無法如預期運作,因為函式會在缺乏正確指示的情況下運作。

誰可以呼叫智能合約函式?

能夠呼叫函式的合約有三種:主合約本身、繼承自主合約的合約(DerivedContract),以及第三方合約(OutsideContract)。

呼叫智能合約是指存取智能合約內的內部程式碼及其中包含的資料,這是一種從合約中取得資料的方式。

1. 主合約(MainContract)

以下是 MainContract 呼叫自身函式的語法:

2. 繼承自主合約的合約(DerivedContract)

以下是 DerivedContract 使用 MainContract 衍生函式的語法:

3. 第三方合約(OutsideContract)

以下是 OutsideContract 從外部函式呼叫主合約的語法。

函式可見性修飾符與繼承如何協同運作?

繼承是指使用「is」關鍵字,將一個合約的內容複製到另一個合約(「衍生合約」)中,函式修飾符的可見性會根據合約被指定的可見性類型,與衍生的子合約產生互動。

函式可見性修飾符與繼承之間的關係說明如下:

  • ParentContract 函式的修飾符為 publicChildContract 可以存取它。
  • ParentContract 函式的修飾符為 internalChildContract 可以存取它。
  • ParentContract 函式的修飾符為 private,繼承的 ChildContract 無法存取它。
  • ParentContract 函式的修飾符為 external,繼承的 ChildContract 無法存取它。

函式可見性修飾符如何協助節省 gas?

由於 external 函式可見性修飾符的參數不會儲存到記憶體中,而是直接從 calldata 讀取,因此智能合約消耗的 gas 較少。相較之下,public 函式的輸入參數會儲存到記憶體中,這會導致部署智能合約時耗費更多 gas。

什麼是函式可見性修飾符?

函式可見性修飾符共有四種類型,依可存取程度由高至低排列為:public、external、internal、private。開發者應根據希望誰能看到並呼叫該函式,來修飾函式使用正確的可見性。

1. Public

public 函式可以被三種呼叫合約中的任何一種存取:主合約、衍生合約,以及第三方合約。函式預設即為 public。

如上方程式碼範例所示,由於「public」的可見性,程式碼庫中任何合約都能存取「functionPublic」函式。

2. External

**external 函式是只能由第三方呼叫的函式。**在 external 函式可見性下,能呼叫該函式的合約必須獨立於主合約之外,且不能是衍生合約。

上方是一個執行某項任務的隨機合約(RandomContract)。下方的程式碼片段是一個外部合約,正在呼叫 RandomContract 上的 external 函式。

3. Internal

**internal 函式可以被主合約及其任何衍生合約呼叫。**internal 函式可以從最初宣告它們的主合約中存取,也可以透過繼承,被延伸自該主合約的合約存取。

4. Private

**private 函式只能被指定它的主合約呼叫。**根據常見做法,private 函式通常會被優先使用,但如果所需的存取範圍比此修飾符類型更廣,則應改用其他合適的修飾符。

Solidity 中預設的函式可見性是什麼?

如果程式碼中沒有明確宣告函式的可見性修飾符,該函式預設會設為 public 可見性。將函式可見性留空、依賴 Solidity 編譯器套用預設可見性,並非建議的最佳做法;明確設定函式可見性能讓程式碼在程式碼審查時更易讀、更容易理解。

函式與狀態變數可見性修飾符有什麼差異?

函式可見性修飾符與狀態變數可見性修飾符的差異在於,狀態變數沒有 external 可見性修飾符這個選項。

狀態變數是其數值永久儲存在合約儲存空間(storage)中的變數,這些資料會在函式呼叫之間持續保存。與函式可見性修飾符相同,狀態變數也有可見性修飾符,分別是 Public、Private 與 Internal。

狀態變數可見性修飾符

狀態變數是在程式的合約區段中宣告的。先指定變數的資料型別,接著再為該變數指定可見性修飾符。

1. Public

具有 public 修飾符的狀態變數可以被應用程式中任何合約存取。如果變數被宣告為 public,其中儲存的資料可以被主合約、衍生合約或外部合約讀取。

2. Internal

使用 internal 修飾符宣告的狀態變數,只能在定義它們的合約內部以及衍生合約中存取。第三方或其他外部合約無法存取被定義為 internal 變數的資料儲存空間。

3. Private

如果狀態變數為 private,只有宣告它的主合約可以呼叫它。private 可見性修飾符會限制主合約以外的其他各方存取,藉此保護其所持有的資料。

Solidity 中預設的變數可見性是什麼?

當變數可見性未被定義時,預設值為 internal。最佳做法是將變數宣告為 private,直到需要擴大其存取範圍為止。

持續學習 Solidity

本文為您介紹 Solidity 的函式可見性,並提供相關說明與資源,供您下一個專案使用。

如果您是 Solidity 語言的新手,並期待打造您的第一個智能合約,歡迎至 Alchemy University 免費的線上 Solidity 程式設計課程搶先報名。

Background gradient

打造區塊鏈魔法

Alchemy 結合最強大的 Web3 開發者產品與工具,並提供資源、社群與卓越的支援。