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