摘要:舍去小數(shù)位在以太坊中賬戶有兩種類型普通賬戶和智能合約賬戶。報(bào)酬是小額的以太幣,想要運(yùn)行智能合約的人的需要支付報(bào)酬來使合約工作。涉及到以太坊智能合約的攻擊的問題。
智能合約可以簡(jiǎn)單的理解為一段可執(zhí)行的程序片段,具體的代碼經(jīng)過 Solidity 編寫之后,發(fā)布到區(qū)塊鏈上。而以太坊的智能合約也可以理解為一個(gè)特殊的交易(包括可執(zhí)行代碼的),被發(fā)送出去后會(huì)被礦工打包記錄在某一個(gè)區(qū)塊中,當(dāng)需要調(diào)用這個(gè)智能合約的方法時(shí)只需要向這個(gè)智能合約的地址發(fā)送一筆交易即可。 因?yàn)橛|發(fā)的條件和打錢地址都已經(jīng)被編寫在代碼里,存儲(chǔ)在區(qū)塊鏈上,所以可以最大程度的排除人為因素的干擾。
合約的基本結(jié)構(gòu)程序版本(Version Pragma):Solidity 大多都是開源的程序,在代碼中加上程序版本是為了方便社區(qū)合作。描述程序版本的規(guī)則和 npm 的一樣。
pragma solidity ^0.4.19;
合同(contract)聲明:合同類似于面向?qū)ο笳Z(yǔ)言中的類(Class)。
contract SimpleStorage { }
狀態(tài)變量(State variable)聲明:狀態(tài)變量是永久存儲(chǔ)在合同存儲(chǔ)中的值。
contract SimpleStorage { uint storedData; // State variable }
函數(shù)(function)聲明:函數(shù)是合約內(nèi)代碼的可執(zhí)行單元。
contract SimpleStorage { function simpleFn() { } }
返回一個(gè)或多個(gè)參數(shù)
直接賦值返回的命名參數(shù)
// 返回一個(gè)值 function oneParameter() returns(uint){ return 1; } // 返回多個(gè)返回值 function twoParameters() returns(uint, uint) { return (1,2); } // 命名參數(shù)直接賦值 function namedParameter() returns(uint foo, uint bar) { foo = 1; bar = 2; } // 獲取返回值 function get() { uint one = oneParameter(); var (two1, two2) = twoParameters(); var (named1, named2) = namedParameter(); }類型
bool:false / true
操作符:! , && , || , == , !=
uinit/int:無(wú)符整型、有符整型
操作符:
比較:<= , < , == , >= , >
位計(jì)算:& , | , ^ , ~
計(jì)算:+ , - , * , / , % , **
注意:
整型除法運(yùn)行會(huì)舍去小數(shù)位。
solidity 暫時(shí)沒有浮點(diǎn)數(shù)。有定點(diǎn)數(shù),但支持性不好。
int x = 7/4 // 報(bào)錯(cuò)。計(jì)算出來的值是有理數(shù),但 solidity 根本沒有浮點(diǎn)數(shù)等類型來表示有理數(shù),更不能將有理數(shù)轉(zhuǎn)換為 int 類型。 // 正確方法,需先定義類型 int a =7; int b = 4; int c = a/b; c == 1.75 // 報(bào)錯(cuò)。根本沒有浮點(diǎn)數(shù)。 c == 1 // true。舍去小數(shù)位
address:在以太坊中賬戶有兩種類型:普通賬戶和智能合約賬戶。普通賬戶只存儲(chǔ) ETH 的賬戶,智能合約賬戶不僅存儲(chǔ) ETH,同時(shí)也有可以運(yùn)行的代碼。
以太坊地址是 20 字節(jié)的十六進(jìn)制的值,該值范圍在 2^256 以內(nèi)。可以通過isValidAddress檢測(cè)是否有效。
address x = 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF function isValidAddress(address) { return /^0x[0-9a-fA-F]{40}$/.test(address) } isValidAddress(x)
成員:
address.banlance (uint256):地址余額,單位 Wei。banlance 的值是 readonly 的,調(diào)用 payable 函數(shù)入賬,調(diào)用 address.transfer() 等出賬,以太坊自動(dòng)計(jì)算新的余額。
address.transfer(uint256 value) :給 address 轉(zhuǎn)賬 value(Wei),且調(diào)用異常會(huì)拋出。
address.send(value):和 transfer 類似,但調(diào)用后的異常將不會(huì)被返回,只會(huì)返回一個(gè) false。
address.call, address.callcode, address.delegatecall:智能合約相互調(diào)用時(shí)使用
注意:在 solidity 源碼中,address 不需要加雙引號(hào)。但在 Remix 的對(duì)話界面中輸入 address 時(shí),務(wù)必加上雙引號(hào),否則會(huì)報(bào)錯(cuò),且報(bào)錯(cuò)的消息非常詭異。
全局變量ether 變量:1 ether 代表數(shù)字 1*10^x18 ,而不是幣的單位。
wei == 1
szabo == 10^12 wei
finney == 10^15 wei
ether == 10^18 wei
時(shí)間變量:1 seconds 代表數(shù)字 1,而不是時(shí)間的單位。同理 1 years 代表的是數(shù)字 3652460*60, 而不是現(xiàn)實(shí)世界中的一年,因?yàn)楝F(xiàn)實(shí)世界中有會(huì)有 閏秒。如合同中需用到準(zhǔn)確的一年,需要外部預(yù)言機(jī)(oracle)。
1 seconds == 1
1 minutes == 60 seconds
1 hours == 60 minutes
1 days == 24 hours
1 weeks == 7 days
1 years == 365 days
block:塊
block.blockhash(uint blockNumber) returns (bytes32): 傳入 blockNumber,返回塊的哈希值
block.coinbase (address): 挖到當(dāng)前塊礦工的地址
block.difficulty (uint): 當(dāng)前塊的難度
block.gaslimit (uint): 當(dāng)前塊最多的 gas
block.number (uint): 當(dāng)前塊是第幾個(gè)
block.timestamp (uint): 當(dāng)前塊創(chuàng)建的時(shí)間戳
now (uint): block.timestamp 的別名
msg: 當(dāng)執(zhí)行某一個(gè)函數(shù)的時(shí)候,函數(shù)想要知道調(diào)用函數(shù)的數(shù)據(jù)信息
msg.data (bytes): 包括函數(shù)名字等等,一些沒有經(jīng)過加工的信息。
msg.gas (uint): 函數(shù)調(diào)用方攜帶的 gas
msg.sender (address): 函數(shù)調(diào)用方的地址
msg.sig (bytes4): 整個(gè) msg.data 的前 4 個(gè) byte
msg.value (uint): 函數(shù)調(diào)用方攜帶的 gas,以 wei 為單位計(jì)價(jià)。
關(guān)鍵詞constant 用于變量: 表明當(dāng)前變量不可修改。如果修改,編輯器會(huì)報(bào)錯(cuò)。
constant 用于函數(shù): 表明當(dāng)前函數(shù)中,不應(yīng)該修改狀態(tài)。但要十分小心,因?yàn)榧幢阈薷牧耍幾g器也不會(huì)報(bào)錯(cuò)。
view : 和 constant 用于函數(shù)時(shí)功能一樣。另外使用 Remix 時(shí),可以方便查看函數(shù)返回值。使用 view 時(shí),Remix 會(huì)把調(diào)用函數(shù)的輸出值放在函數(shù)右邊顯示,而不是在 details 里。
payable: 表明調(diào)用函數(shù)可以接受以太幣。
this: 指向的是當(dāng)前合同的 address。
revert(): 函數(shù)執(zhí)行失敗,需要通過調(diào)用 revert() 拋異常告訴函數(shù)調(diào)用方。調(diào)用后恢復(fù)合同狀態(tài),并將剩余 gas 返還。等同于 throw。
省幣秘訣當(dāng)你激活一個(gè)智能合約的時(shí)候,你在要求整個(gè)網(wǎng)絡(luò)內(nèi)的每個(gè)礦工個(gè)體分別執(zhí)行里面的運(yùn)算。這會(huì)花費(fèi)他們的時(shí)間和精力,Gas是你為這項(xiàng)服務(wù)向礦工們支付的機(jī)制。 報(bào)酬是小額的以太幣,想要運(yùn)行智能合約的人的需要支付報(bào)酬來使合約工作。付款款項(xiàng)(單位以太幣)= Gas數(shù)量(單位Gas) x Gas price(單位以太幣/Gas) 智能合約越復(fù)雜(計(jì)算步驟的數(shù)量和類型,占用的內(nèi)存等),用來完成運(yùn)行就需要越多Gas。
Gas是由一開始發(fā)起transaction的地址進(jìn)行支付。再比如"合約A調(diào)用合約B再調(diào)用合約C"這個(gè)過程中所產(chǎn)生的所有計(jì)算步驟所消耗的Gas也都是由調(diào)用合約A的人來承擔(dān)的。
用 fn() 代替 this.fn():通過 this.fn() 調(diào)用函數(shù),在 EVM 底層是通過 msg來調(diào)用合約函數(shù)的。相對(duì)于直接調(diào)用 fn() 花費(fèi)的 gas 更多。
減少重復(fù)計(jì)算。Solidity 編譯器沒有對(duì)重復(fù)計(jì)算做優(yōu)化,需開發(fā)者手動(dòng)使用臨時(shí)變量保存重復(fù)計(jì)算的值。
function(int a, int b){ // 錯(cuò)誤。應(yīng)該使用 int x = a + b 減少重復(fù)計(jì)算 if(a + b > 0) { int y = a + b; } }安全
一定要把內(nèi)部變量修改完成之后,再給外部錢。涉及到以太坊智能合約的re-entry攻擊的問題。
frank.transfer(salary); // 錯(cuò)誤,應(yīng)該將先修改內(nèi)部變量,再 transfer。 lastPayday = lastPayday + payDuration;其他
合約是中介:由于調(diào)用函數(shù)的動(dòng)作是在挖礦時(shí)執(zhí)行的,所以Solidity 沒有原生定時(shí)器,不通過合約本身自動(dòng)觸發(fā)函數(shù)執(zhí)行。應(yīng)該將合約看做一個(gè)中介,需要外部來觸發(fā)合約函數(shù)的執(zhí)行。
本地狀態(tài)變量聲明提升:類似于 JS 用 val 聲明變量。
contract SimpleStorage { function set(uint data){ if (true) { uint temp = 1; // 本地狀態(tài)變量 } uint temp; // 報(bào)錯(cuò),因?yàn)槁暶鞅镜貭顟B(tài)變量的作用域是函數(shù),而不是 {}。 } }
代碼見/payroll.sol
參考資料:
solidity-notes
第一課問題整理
Lesson 1 補(bǔ)充學(xué)習(xí)筆記
一個(gè)基礎(chǔ)的以太坊介紹
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/24002.html
摘要:和比特幣協(xié)議有所不同的是,以太坊的設(shè)計(jì)十分靈活,極具適應(yīng)性。超級(jí)賬本區(qū)塊鏈的商業(yè)應(yīng)用超級(jí)賬本超級(jí)賬本是基金會(huì)下的眾多項(xiàng)目中的一個(gè)。證書頒發(fā)機(jī)構(gòu)負(fù)責(zé)簽發(fā)撤 showImg(https://segmentfault.com/img/bV2ge9?w=900&h=385); 從比特幣開始 一個(gè)故事告訴你比特幣的原理及運(yùn)作機(jī)制 這篇文章的定位會(huì)比較科普,盡量用類比的方法將比特幣的基本原理講出來...
摘要:另外只能做狀態(tài)變量,不能做本地局部變量。語(yǔ)法聲明映射類型包括類型包括狀態(tài)變量報(bào)錯(cuò)??梢暥戎傅氖?,決定函數(shù)或者狀態(tài)變量的可以被哪些智能合約可見和調(diào)用。狀態(tài)變量可見性沒有。在中,通過來抽象出狀態(tài)變量自增的代碼,并修飾。 Mapping 映射(Mappings):類似于哈希表。mapping 中任何一個(gè)可能的 key 都對(duì)應(yīng)著一個(gè) value,它的默認(rèn)值是default-value 。底層用...
摘要:錯(cuò)誤檢查拋出異常。用于檢查內(nèi)部錯(cuò)誤,比如上溢和下溢。由于語(yǔ)言完善的問題,支持狀態(tài)變量之間的轉(zhuǎn)換,未來可能會(huì)取消該限制。注意,只能將變量賦值給狀態(tài)變量,而不是本地變量。因?yàn)槲覀冎荒茉跔顟B(tài)變量中分配內(nèi)存空間。 錯(cuò)誤檢查 throw: 拋出異常。已被廢棄。 revert(): 拋出異常,并回滾到調(diào)用前的狀態(tài)。 require(bool): require(false) 拋出異常,并回...
摘要:原文發(fā)表于以太坊智能合約開發(fā)第二篇理解以太坊相關(guān)概念很多人都說比特幣是區(qū)塊鏈,以太坊是區(qū)塊鏈。它是以太坊智能合約的運(yùn)行環(huán)境。是由以太坊節(jié)點(diǎn)提供。以太坊社區(qū)把基于智能合約的應(yīng)用稱為去中心化的應(yīng)用。 原文發(fā)表于:以太坊智能合約開發(fā)第二篇:理解以太坊相關(guān)概念 很多人都說比特幣是區(qū)塊鏈1.0,以太坊是區(qū)塊鏈2.0。在以太坊平臺(tái)上,可以開發(fā)各種各樣的去中心化應(yīng)用,這些應(yīng)用構(gòu)成了以太坊的整個(gè)生態(tài)...
摘要:引言給迷失在如何學(xué)習(xí)區(qū)塊鏈技術(shù)的同學(xué)一個(gè)指引,區(qū)塊鏈技術(shù)是隨比特幣誕生,因此要搞明白區(qū)塊鏈技術(shù),應(yīng)該先了解下比特幣。但區(qū)塊鏈技術(shù)不單應(yīng)用于比特幣,還有非常多的現(xiàn)實(shí)應(yīng)用場(chǎng)景,想做區(qū)塊鏈應(yīng)用開發(fā),可進(jìn)一步閱讀以太坊系列。 本文始發(fā)于深入淺出區(qū)塊鏈社區(qū), 原文:區(qū)塊鏈技術(shù)學(xué)習(xí)指引 原文已更新,請(qǐng)讀者前往原文閱讀 本章的文章越來越多,本文是一個(gè)索引帖,方便找到自己感興趣的文章,你也可以使用左側(cè)...
閱讀 1731·2021-09-26 09:55
閱讀 5687·2021-09-22 15:40
閱讀 2073·2019-08-30 15:53
閱讀 1547·2019-08-30 11:15
閱讀 1765·2019-08-29 15:41
閱讀 1925·2019-08-28 18:13
閱讀 3209·2019-08-26 12:00
閱讀 1723·2019-08-26 10:30