3.11 solidity 函式詳解

尹成發表於2018-11-08

1. Solidity函式、許可權、函式修飾符、事件

        a. 函式

            i. 概念:solidity也是一門函數語言程式設計語言,函式可以做為其引數、變數、返回值

            ii. 函式屬於值型別,支援多個返回值

            iii. 呼叫方式:

                1. 內部呼叫:

                    a. 內部呼叫採用的是EVM跳轉呼叫,所以它能直接使用上下文環境中的資料,因為不用拷貝資料,所以在傳遞資料時會非常高效

                    b. 對合約內的函式,引入的庫函式以及從父合約中繼承的函式都可以進行內部呼叫

                2. 外部呼叫

                    a. 外部呼叫採用外部交易呼叫,使用external時,必須使用外部的方式呼叫其它合約的函式。對於一個外部呼叫,所有函式的引數必須拷貝到記憶體中。

                3. 注意:上面的internal以及external是指函式的呼叫方式,與可見性中的internal、external是兩個概念

            iv. 函式定義型別

                1. View:只讀,不改變合約內部狀態

                    a. 以下操作會修改狀態

                        i. 寫入狀態變數.

                        ii. 觸發事件

                        iii. 建立其它合約.

                        iv. 使用自毀函式.

                        v. 傳送以太幣.

                        vi. 呼叫任何沒有被標記為 view 或者 pure的函式.

                        vii. 底層呼叫.

                        viii. 使用包含一些操作碼的內聯彙編.

                    b. getter函式會預設標記為view

                    c. 注意,如果有修改狀態操作的函式加上view,編譯器不會報錯,只會給出一個警告

                2. Pure:不會修改合約狀態,也不能讀取合約狀態(可以讀取與狀態無關的資料)

                    a. 除去view中的限制,還包括以下內容

                        i. 讀取狀態變數

                        ii. 訪問this.balance或者address.balance

                        iii. 訪問block,tx,msg任何成員(msg.sig以及msg.data除外)

                        iv. 呼叫任何沒有標記為pure的函式

                        v. 使用包含某些操作碼的內聯彙編

                    b. 注意:在版本0.4.17之前,編譯器沒有強制規定pure不能讀取狀態。

                3. Fallback

                    a. 每一個合約中都有一個沒有名字的函式,該函式沒有引數,沒有返回值,這就是回撥函式

                    b. 以下兩種情況下會呼叫回撥函式

                        i. 呼叫合約時,沒有匹配上任何一個函式

                        ii. 給合約傳送ether時,交易中根本沒有提供資料

                    c. 給合約傳送ether時,要注意以下情況

                        i. 合約沒有定義回撥函式的話,接收ehter會觸發異常

                        ii. 如果回撥函式需要接收ehter,必須要有payable修飾符

                4. 函式過載

                    a. 同名函式可以過載

                5. 自毀函式(selfdestruct)

                    a. 自毀函式可以摧毀當前合約,將該合約的以太幣轉移到給定的地址

                    b. 注意:如果合約被自毀後有人傳送以太幣到這個合約地址,那這些以太幣會消失,無法贖回

                6. 常函式(constant)

                    a. 常函式不會修改區塊鏈上的任何狀態(沒有強制規定、會警告)

                7. 訪問函式(getter)

                    a. 編譯器為自動為所有的public的狀態變數建立訪問函式

                    b. 訪問函式有外部(external)可見性。如果通過內部(internal)的方式訪問,比如直接訪問,你可以直接把它當一個變數進行使用,但如果使用外部(external)的方式來訪問,如通過this.,那麼它必須通過函式的方式來呼叫

                8. 其它內建函式

                    a. 加密函式

                        i. Keccak256(…)returns (bytes32);使用以太坊的(keccak-256)計算hash(該函式會先將所有引數進行連線再計算)

                            1. keccka256("ab","cd")

                        ii. Sha3(…)returns(bytes32);同上

                            1. sha3("ab","cd");

                        iii. Ripemd160(…)returns(bytes20):使用ripemd-160計算hash值,返回bytes20

                            1. ripemd160("abc")

                        iv. Sha256(…)returns(bytes32);使用sha-256計算hash值,返回bytes32

                            1. sha256("def");

                        v. ecrecover(bytes32,byte,bytes32,bytes32) return(address);恢復與公鑰相關的地址

                    b. 資料函式

                        i. addmod(uint x,uint y, uint k)returns(uint)// (x+y)%k

                        ii. mulmod(uint x, uint y, uint k)returns(uint)// (x*y)%k

        b. 可見性或許可權

            i. 可見性

                1. Internal:不能在當前合約的上下文環境以外的地方執行,內部函式只能在當前合約內被使用。如在當前的程式碼塊內,包括內部庫函式,和繼承的函式中。預設情況下,函式為internal

                2. external:

                    a. 外部函式由地址和函式方法簽名兩部分組成。可作為外部函式呼叫的引數,或者由外部函式呼叫返回

                    b. external可以通過交易呼叫、也可以通過其它合約呼叫

                    c. 如果是用this呼叫,那它是在通過external的方式呼叫

                    d. 不能在內部呼叫一個外部函式

            ii. 許可權

                1. Public:公開函式是合約介面的一部分,可以通過內部,其它合約、或者訊息來進行呼叫。對於public型別的狀態變數,會自動建立一個訪問器

                2. Private:私有函式和狀態變數僅在當前合約中可以訪問,在繼承的合約內,不可訪問

                3. 注意:所有在合約內的東西對外部的觀察者來說都是可見,將某些東西標記為private僅僅阻止了其它合約來進行訪問和修改,但並不能阻止其它人看到相關的資訊

        c. 函式修改器(Modifier)

            i. 修改器的作用是在函式執行前檢查某種前置條件是否滿足,

            ii. Modifier是一種合約屬性,可以被繼承,還可以被派生的合約重寫

            iii. 一個函式可以有多個修改器,其間採用空格或回車分隔,修改器的生效順序與定義順序是一樣的

        d. 事件(event)

            i. 事件是使用EVM日誌內建功能的方便工具,在DAPP的介面中,它可以反過來呼叫Javascript的監聽事件的回撥。

            ii. 為什麼要有事件?在真實的環境中,傳送交易呼叫智慧合約的過程是如下:

                1. 交易傳送->打包->被執行 在傳送完之後,不會馬上返回執行結棍,只能立刻返回交易HASH。所以我們需要通過事件來通知外部實體。

            iii. 事件在合約中可被繼承。當被呼叫時,會觸發引數儲存到交易的日誌中(一種區塊鏈上的特殊資料結構)。這些日誌與合約的地址關聯,併合併到區塊鏈中,只要區塊可以訪問就一直存在(至少Frontier,Homestead是這樣,但Serenity也許會不一樣)。日誌和事件在合約內不可直接被訪問,即使是建立日誌的合約。

 

相關文章