KryptoCamp — Day26 — solidity — 7
經過了幾天 DAO 智能合約研究後,發現其實還是有很多語法是沒見過的,因此趕快再回來補足一下 soildity 的基礎寫法,否則常常要花很多時間研究某個語法的意義,會大幅降低看程式碼的效率,也詳細了解一下 solidity 的運作方式。
以下內容參考自 all in one solidity,想要獲得更詳細的資訊建議可以購買書籍。
傳址 (call by reference) 或是傳值 (call by value)?
關於兩者的區別可以參考這裡。
變數型態的參數(bool
, uint
, bytes
, addres
)會是以傳值(Call by Value)傳入函數,而非變數型態像是我們之後會介紹到的資料結構(array
, struct
, mapping
, string
)們,則是傳址(Call by Reference)。
簡單可以記成只要是資料結構形式的資料都為 call by reference ,其他非資料結構較為單純的資料則為 call by value,這個特性是與 JavaScript 一致的。
Storage、Memory、Calldata 的區別
- Storage 該資料會在區塊鏈上永遠存在,函數可以更改它或是回傳它,修改它需要付 gas。
- Memory 該資料經過生命週期後就會消失,函數可以修改他也可以回傳他,修改他不需要付 gas 。
- Calldata 一個唯讀的參數,可見性為 external 的函數會被預設為這個形式。函數不能修改他但是可以回傳他。
錯誤處理 require、assert、revert、try catch
require
檢查輸入值是否符合條件,會退回 gas,可以帶錯誤訊息。assert
是檢查完全不應該在合約裡面出現的情況,不會退回 gas,可以帶錯誤訊息。revert
直接拋出錯誤,可帶入錯誤訊息。try/catch
用於確認外部執行函數和合約建立時的錯誤,可以利用類條件式選擇來排除錯誤情況。
Event
當一個 event
被 call 之後它的參數就會被置於區塊鏈之中。意思是你將可以在 Transaction Information 中看見你自己觸發的事件以及相關的回傳值,觸發 event 是要耗費 gas 的,不過會比 storage 便宜。
沒有 event 時 log 沒有任何回傳值:
回傳 event 後 log 多了許多關於 event 的資料:
前端的應用程式可以藉由 Ethereum 的 RPC interface 來訂閱這些 event,進而即時知道某個 function 的執行結果,並對此作出反應。
event 的 indexed 、data、topic
indexed
event SomeEvent(address _from indexed, address _to)
被標註為 indexed
的參數將可以讓前端更輕易的找到 ,標記 indexed
的 event 參數將消耗更多 gas ,僅有當你想要某個 event 的參數可以被找到時才需要標記 indexed
。
一個 event 最多只能有三個 indexed 的參數。
data
當一個參數沒有 indexed
屬性時, 他們會被 ABI-encoded
成 log
的 data
部分。
topic
如果一個參數有 indexed
屬性,他們會被包含在 topics
裡面。
這段程式碼的 translation 結果的 log:
這段程式碼的 translation 結果的 log:
可以看到有標記 indexed
的交易的 topics 的部分比較多個,而把相對應的值 hash 解碼後就會得到 1 和 2,可以得知標記 indexed
的值會被寫入 topics 內,沒有標記的則被記錄在 data 裡面。不管是哪個都是實實在在寫在鏈上的資料,後續都可以針對此筆交易追蹤到該筆紀錄的 event 回傳值的。
anonymous (匿名) 事件
event AnonymousEvent (uint _a) anonymous;
在一個非匿名的 event 當中, topics[0]
會是 event 自己的 hash 值,但如果標注為匿名事件,則 topic[0]
將不再是 event 自己的 hash 值,同時前端也無法得知 event 的 name 是什麼,也就將無法監聽到它,想要得知這個 hash 值唯一的辦法就是取得 ABI,如果項目沒有開源或是你不是持有者那麼你將無法監聽匿名事件。
這段程式碼的 translation 結果的 log:
topics[0]
消失了,前端無從得知 name 是什麼,無法進行監聽。