深入理解Solidity 三
生活随笔
收集整理的這篇文章主要介紹了
深入理解Solidity 三
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Solidity函數(shù)聲明和類型
- ?函數(shù)的值類型有兩類:內(nèi)部(internal)類型和外部(external)類型
- 內(nèi)部函數(shù)只可以在當(dāng)前合約內(nèi)部被調(diào)用(即在當(dāng)前代碼塊內(nèi),包括內(nèi)部庫(kù)函數(shù)和繼承函數(shù)),因?yàn)樗麄儾荒茉诋?dāng)前合約的上下文中的外部被執(zhí)行。調(diào)用一個(gè)內(nèi)部函數(shù)是通過(guò)跳轉(zhuǎn)到它的入口標(biāo)簽來(lái)實(shí)現(xiàn)的,就像在當(dāng)前合約的內(nèi)部調(diào)用一個(gè)函數(shù)
- 外部函數(shù)是由一個(gè)地址和一個(gè)函數(shù)的簽名組成,可以通過(guò)外部函數(shù)調(diào)用傳遞或者返回
- 調(diào)用內(nèi)部函數(shù),直接使用名字f
- 調(diào)用外部函數(shù):this.f(當(dāng)前合約),a.f(外部合約)
- 除了使用外部函數(shù)調(diào)用外,還可以使用繼承機(jī)制
例子(外部函數(shù)調(diào)用)
contract C{uint a;function f() public{} } contract D{function g() public{C c = new C();c.f();} }例子(繼承機(jī)制)
- 可以使用internal函數(shù)/public函數(shù),不可以使用private函數(shù)
- D繼承C合約,只會(huì)把交叉的函數(shù)編譯上傳
函數(shù)的可見(jiàn)性
- 函數(shù)的可見(jiàn)性可以指定為external、public、internal或者private;對(duì)于狀態(tài)變量,不可以設(shè)置為external,默認(rèn)是internal
- external:外部函數(shù)作為合約接口的一部分,意味著我們可以從其他合約和交易中調(diào)用。一個(gè)外部函數(shù)f不可以從內(nèi)部調(diào)用(即f不起作用,但是this.f可以)。當(dāng)接收到大量的數(shù)據(jù)的時(shí)候,外部函數(shù)有時(shí)候會(huì)更有效率
- public:public函數(shù)是合約接口的一部分,相當(dāng)于定義了一個(gè)view類型的可以返回參數(shù)的函數(shù),可以在內(nèi)部或者通過(guò)消息調(diào)用。對(duì)于public狀態(tài)變量,會(huì)自動(dòng)生成一個(gè)getter函數(shù)
例子
uint public a;//將a聲明為public,就相當(dāng)于為a定義了如下的函數(shù)形式 function a() public view returns (uint){return a; }- internal:這些函數(shù)和狀態(tài)變量只能是內(nèi)部訪問(wèn)(即從當(dāng)前合約內(nèi)部或者從其他派生的合約訪問(wèn)),不可以使用this
- private:private函數(shù)和狀態(tài)變量?jī)H在當(dāng)前定義他們的合約中使用,并且不能被派生合約使用。
函數(shù)狀態(tài)可變性
- payable:允許從消息調(diào)用中接收以太幣Ether
- constant:和view相同,一般只修飾狀態(tài)變量,不允許賦值(除了初始化之外)
- pure:純函數(shù),不允許修改或者訪問(wèn)狀態(tài)
- view:不允許修改狀態(tài)
函數(shù)狀態(tài)可變性
- 修改狀態(tài)變量
- 產(chǎn)生事件
- 創(chuàng)建其他合約
- 使用selfdestruct(自殺/自毀)
- 通過(guò)調(diào)用發(fā)送以太幣
- 調(diào)用任何沒(méi)有標(biāo)記為view或者pure的函數(shù)
- 使用低級(jí)調(diào)用
- 使用包含特定操作嗎的內(nèi)聯(lián)匯編
以下是被認(rèn)為從狀態(tài)中進(jìn)行讀取
- 讀取狀態(tài)變量
- 訪問(wèn)this.balance或者<address>.balance
- 訪問(wèn)block、tx、msg中任意成員(除了msg.sig和msg.data之外)
- 調(diào)用任何未標(biāo)記為pure的函數(shù)
- 使用包含某些操作碼的內(nèi)聯(lián)匯編
函數(shù)修飾器 modifier
- 使用修飾器modifier可以輕松改變函數(shù)的行為。例如,他們可以在執(zhí)行函數(shù)之前自動(dòng)檢查某個(gè)條件。修飾器modifier是合約的可繼承屬性,并可能被派生合約覆蓋
- 如果同一個(gè)函數(shù)有多個(gè)修飾器modifier,他們之間可以使用空格隔開(kāi),修飾器modifier會(huì)依次檢查執(zhí)行。
代碼
contract Purchase{address public seller;constructor() public{seller = msg.sender;}modifier onlySeller(){require(msg.sender == seller,"Only seller");_;}function f() public view onlySeller returns(uint){return 200;} }效果展示
- msg.sender是合約的部署者,只有合約的部署者調(diào)用f函數(shù),返回200,剩余的人會(huì)返回錯(cuò)誤信息,only seller
- require(msg.sender == seller,"Only seller");逗號(hào)之前是檢查條件,之后是返回報(bào)錯(cuò)信息,檢查條件在代碼流程之前執(zhí)行
- _;將代碼流程嵌套到這里,指代檢查條件執(zhí)行之后,執(zhí)行代碼的邏輯。(函數(shù)體)
回退函數(shù)(fallback)
- 回退函數(shù)(fallback function)是合約中的特殊函數(shù);沒(méi)有名字,不能有參數(shù)也不能有返回值
- 如果在一個(gè)到合約的調(diào)用中,沒(méi)有其他函數(shù)與給定的函數(shù)標(biāo)示符匹配(或者沒(méi)有提供調(diào)用函數(shù)),你們這個(gè)函數(shù)(fallbacj函數(shù))會(huì)被執(zhí)行
- 每當(dāng)合約收到以太幣(沒(méi)有任何數(shù)據(jù)),回退函數(shù)就會(huì)執(zhí)行。此外,為了接收以太幣,fallback函數(shù)必須標(biāo)記為payable。如果不存在這樣的函數(shù),則合約不能通過(guò)常規(guī)交易接收以太幣
- 在上下文中只有很少的gas可以用來(lái)完成回退函數(shù)的調(diào)用,所以使fallback函數(shù)的調(diào)用盡量廉價(jià)很重要
代碼
pragma solidity >0.4.99 <0.6.0; contract Sink{function() external payable{} } contract Test{function() external {x=1;}uint x; }contract Caller{function calllTest(Test test)public returns(bool){(bool success,) = address(test).call(abi.encodeWithSignature("nonExistingFunction()"));require(success);address payable testPayable = address(uint160(address(test)));return testPayable.send(2 ether);} }注解
- 調(diào)用合約中不存在的函數(shù)和轉(zhuǎn)錢的時(shí)候會(huì)調(diào)用回退函數(shù)
- 回退函數(shù)適用在合約5.0版本以上
事件(event)
- 事件是以太坊EVM提供的一種日志基礎(chǔ)設(shè)施。事件可以用來(lái)做操作記錄,存儲(chǔ)為日志。也可以用來(lái)實(shí)現(xiàn)一些交互功能,比如通知UI,返回函數(shù)的調(diào)用結(jié)果
- 當(dāng)定義的事件被觸發(fā)時(shí),可以將事件存儲(chǔ)到EVM的交易日志中,日志是區(qū)塊鏈中的一種特殊的數(shù)據(jù)結(jié)構(gòu);日志和合約相互關(guān)聯(lián),與合約的存儲(chǔ)合并存入到區(qū)塊鏈條中,只要某個(gè)區(qū)塊可以訪問(wèn),其相關(guān)的日志就可以訪問(wèn),但是在合約中是不可以之間訪問(wèn)日志和事件數(shù)據(jù)
- 可以通過(guò)日志實(shí)現(xiàn)簡(jiǎn)單支付驗(yàn)證SPV,如果一個(gè)外部實(shí)體提供了一個(gè)帶有這種證明的合約,它可以檢查日志是否真實(shí)存在于區(qū)塊鏈中
異常處理
- 適用狀態(tài)恢復(fù)異常來(lái)處理異常。這樣的異常將會(huì)撤銷對(duì)于當(dāng)前的調(diào)用(及其所有的子調(diào)用)中的狀態(tài)所做的所有的更改,并且向調(diào)用者返回錯(cuò)誤
- 函數(shù)的assert和require用于判斷條件,并且在不滿足條件的時(shí)候拋出異常
- assert()一般只應(yīng)用于測(cè)試內(nèi)部的錯(cuò)誤,并且檢查異常
- require()應(yīng)用于確保滿足有效的條件(如輸入或合約的狀態(tài)變量),或者驗(yàn)證調(diào)用外部合約的返回值
- revert()用于拋出異常,它可以標(biāo)記一個(gè)錯(cuò)誤并且將當(dāng)前調(diào)用回退
單位
- 以太幣單位之間的換算就是在數(shù)字后邊加上wei、finney、szabo或者ether來(lái)實(shí)現(xiàn),如果沒(méi)有單位,缺省為wei
時(shí)間
- 秒是缺省單位,在時(shí)間單位之間,數(shù)字后面帶有seconds、minutes、hours、days、weeks和years的可以進(jìn)行換算?但是這些后綴不可以直接用在變量的后邊,如果需要使用到時(shí)間單位(例如days)來(lái)將輸入變量轉(zhuǎn)換為時(shí)間,可以使用如下方式
?
總結(jié)
以上是生活随笔為你收集整理的深入理解Solidity 三的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 接上文 VM安装的ubuntu系统,配置
- 下一篇: 英语口语 Week14 Monday