智能合約(一)
bytes用來存儲(chǔ)任意長度的字節(jié)數(shù)據(jù),string用來存儲(chǔ)任意長度的
(UTF-8編碼)的字符串?dāng)?shù)據(jù)。
balance用來查詢賬戶余額,transfer()用來發(fā)送以太幣(以wei為單
位)。
一、數(shù)據(jù)類型
1、布爾類型(bool) true ?false
2、整形 ?
int/uint: 表示有符號(hào)和無符號(hào)不同位數(shù)整數(shù)。支持關(guān)鍵字uint8到uint256 (以8步進(jìn)),
uint 和 int 默認(rèn)對(duì)應(yīng)的是 uint256 和 int256。
整數(shù)除法總是截?cái)嗟?,但如果運(yùn)算符是字面量(字面量稍后講),則不會(huì)截?cái)唷?/p>
3、 定長字節(jié)數(shù)組?
關(guān)鍵字有:bytes1, bytes2, bytes3, ..., bytes32。(以步長1遞增)
byte代表bytes1。
bytes用來存儲(chǔ)任意長度的字節(jié)數(shù)據(jù),string用來存儲(chǔ)任意長度的(UTF-8編碼)的字符串?dāng)?shù)據(jù)。
如果長度可以確定,盡量使用定長的如byte1到byte32中的一個(gè),因?yàn)檫@樣更省空間。
字符串常量與整數(shù)常量
注意:
定長字節(jié)數(shù)組:byte[7] aa ?= [byte(0x11),0x11,0x11,0x11,0x11,0x11,0x11];
變長字節(jié)整數(shù):byte[] cc = new byte[](10);
存儲(chǔ)在內(nèi)存中的無論是定長還是變長都不能改變長度
4、十六進(jìn)制常量
以關(guān)鍵字hex開頭 ?如 hex"001122ff"
5、字符串常量
不可以用下標(biāo)訪問其中的某個(gè)字符,但可以通過將其轉(zhuǎn)換為bytes數(shù)組形式訪問。
6、枚舉類型
在Solidity中,枚舉可以用來自定義類型。它可以顯示的轉(zhuǎn)換與整數(shù)進(jìn)行轉(zhuǎn)換,但不能進(jìn)行隱式轉(zhuǎn)換。枚舉至少應(yīng)有一個(gè)成員。
7、地址類型 address
20字節(jié)
地址類型成員:
balance 屬性及transfer() 函數(shù)這里是地址類型相關(guān)成員的快速索引balance用來查詢賬戶余額,transfer()用來發(fā)送以太幣(以wei為單位)
send()函數(shù):
send 與transfer對(duì)應(yīng),但更底層。如果執(zhí)行失敗,transfer不會(huì)因異常停止,而send會(huì)返回false
call()函數(shù):返回一個(gè)bool值 , 參數(shù)為:
?id = keccak256(?這里面是函數(shù)?)這樣就可以生成函數(shù)id,然后就可以使用對(duì)應(yīng)合約類的地址.call(第一參數(shù)是上面獲取的id,以后的參數(shù)就是函數(shù)的參數(shù))
匿名函數(shù):
一個(gè)合約可以有一個(gè)匿名函數(shù)。此函數(shù)不能有參數(shù),也不能有任何返回值。當(dāng)我們企圖去執(zhí)行一個(gè)合約上沒有的函數(shù)時(shí),那么合約就會(huì)執(zhí)行這個(gè)匿名函數(shù)。
此外,當(dāng)合約在只收到以太幣的時(shí)候,也會(huì)調(diào)用這個(gè)匿名函數(shù),而且一般情況下只會(huì)消耗很少的gas,所以當(dāng)你接受到以太幣后,想要執(zhí)行一些操作的話,你盡可以把你要的操作寫到這個(gè)匿名函數(shù)里,因?yàn)檫@樣做成本非常便宜。
function() public payable{}
構(gòu)造函數(shù)先初始化,再調(diào)用構(gòu)造函數(shù)
五、訪問器函數(shù)
創(chuàng)建的狀態(tài)變量為public時(shí)(uint public data = 10;),
會(huì)自動(dòng)創(chuàng)建get函數(shù) function data() external {}
只能以external方式訪問
2、枚舉訪問器與上述訪問方式相同
3、數(shù)組訪問器 this.array(1) ; ?要用小括號(hào)
4、映射訪問器 ?帶有參數(shù) 參數(shù)為鍵類型的
Mapping(uint => uint) public data ;
this.data(20); ??20為鍵
5、結(jié)構(gòu)體訪問器 ?需要用變量接受結(jié)構(gòu)體中的所有變量
var(a,b,c) = this.s();
Return (a,c);
智能合約(二)
memory ?: 內(nèi)存中,數(shù)據(jù)不是永久存在
storage ?: 永久存貯在區(qū)塊鏈中
memory 數(shù)組 ?不能改長度 無論是bytes 還是 uint
storage 可變數(shù)組 ?可以修改長度 ?無論是bytes 還是 uint
一、存儲(chǔ)位置分析
1、數(shù)據(jù)位置
storage(永遠(yuǎn)存儲(chǔ)在區(qū)塊鏈中):引用類型,局部復(fù)雜變量(數(shù)組,數(shù)據(jù)結(jié)構(gòu))
狀態(tài)變量
memory(內(nèi)存中,不是永久存在):函數(shù)參數(shù),簡單局部變量
calldata(不會(huì)永久存儲(chǔ)的一個(gè)數(shù)據(jù)位置):外部函數(shù)參數(shù),不包括返回參數(shù)只是讀的
storage 在區(qū)塊鏈中是用key/value的形式存儲(chǔ),而memory則表現(xiàn)為字節(jié)數(shù)組
memory 只能用于函數(shù)內(nèi)部,memory 聲明用來告知EVM在運(yùn)行時(shí)創(chuàng)建一塊(固定大?。﹥?nèi)存區(qū)域給變量使用
注意:
不能將memory 賦值給復(fù)雜局部變量。(不明白)
對(duì)于值類型,總是會(huì)進(jìn)行拷貝。
一個(gè)storage的狀態(tài)變量,賦值給一個(gè)storage的局部變量,是通過引用傳遞。所以對(duì)于局部變量的修改,同時(shí)會(huì)修改關(guān)聯(lián)的狀態(tài)變量。
將一個(gè)memory 的引用類型賦值給另一個(gè) memory 的引用,不會(huì)創(chuàng)建拷
貝(即:memory 之間是引用傳遞)。
三種存儲(chǔ)方式內(nèi)存消耗
storage 會(huì)永久保存合約狀態(tài)變量,開銷最大
memory 僅保存臨時(shí)變量,函數(shù)調(diào)用之后釋放,開銷很小
stack 保存很小的局部變量,幾乎免費(fèi)使用,但有數(shù)量限制。
二、數(shù)組的使用
初始化數(shù)組:
uint [] public u = [1,2,3];
uint[] memory m = new uint[](10);
Length:數(shù)組可以指定長度也可以是動(dòng)態(tài)變長。
Data:數(shù)據(jù)類型可以是任意的
數(shù)組作為構(gòu)造函數(shù)參數(shù)時(shí):
如:bytes8[] _name ?傳參:["0x12","0x23","0x45"]
bytes與string區(qū)別:bytes提供length與set數(shù)據(jù) ?而string不提供
三、結(jié)構(gòu)體及映射
結(jié)構(gòu)體內(nèi)數(shù)據(jù)類型可以是任意的,也可以是結(jié)構(gòu)體類型的,即支持結(jié)構(gòu)體嵌套
初始化:
Add memory add = Add("beijing");
?????Person memory p1 = Person("List",30,add); //結(jié)構(gòu)體不能用new
訪問:p1.age = 40 ; //直接使用 . 訪問?
四、solidity常見單位
1、貨幣單位: 1 ether , 3 finney , 6 szabo , 18 wei ,
2、時(shí)間單位:secounds,minutes ...... ?now:表示現(xiàn)在距1970 多久
五、常見的API介紹
錯(cuò)誤處理:
1、assert(bool condition)
用于判斷內(nèi)部錯(cuò)誤,條件不滿足時(shí)拋出異常
2、require(bool condition): ?(常用)
用于判斷輸入或外部組件錯(cuò)誤,條件不滿足時(shí)拋出異常
3、revert():
終止執(zhí)行并還原改變的狀態(tài)
<<以下內(nèi)容能記住就記住,記不住就看看>>
數(shù)學(xué)及加密功能
1、addmod(uint x, uint y, uint k) returns (uint):
計(jì)算(x + y) % k,加法支持任意的精度且不會(huì)在2**256處溢出,從
0.5.0版本開始斷言k != 0。
2、mulmod(uint x, uint y, uint k) returns (uint):
計(jì)算(x * y) % k, 乘法支持任意的精度且不會(huì)在2**256處溢出,
從0.5.0版本開始斷言k != 0。
3、keccak256(...) returns (bytes32):
使用以太坊的(Keccak-256)計(jì)算HASH值。緊密打包參數(shù)。
4、sha256(...) returns (bytes32):
使用SHA-256計(jì)算hash值,緊密打包參數(shù)。
5、sha3(...) returns (bytes32):
keccak256的別名
6、ripemd160(...) returns (bytes20):
使用RIPEMD-160計(jì)算HASH值。緊密打包參數(shù)。
7、ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns
(address):
通過橢圓曲線簽名來恢復(fù)與公鑰關(guān)聯(lián)的地址,或者在錯(cuò)誤時(shí)返回零。
可用于簽名數(shù)據(jù)的校驗(yàn),如果返回結(jié)果是簽名者的公匙地址,那么說明數(shù)
據(jù)是正確的。
地址相關(guān)
1、 balance (uint256):
Address的余額,以wei為單位。
2、 transfer(uint256 amount):
發(fā)送給定數(shù)量的ether到某個(gè)地址,以wei為單位。失敗時(shí)拋出異常。
3、send(uint256 amount) returns (bool):
發(fā)送給定數(shù)量的ether到某個(gè)地址,以wei為單位, 失敗時(shí)返回false。
4、 call(...) returns (bool):
發(fā)起底層的call調(diào)用。失敗時(shí)返回false。
5、callcode(...) returns (bool):
發(fā)起底層的callcode調(diào)用,失敗時(shí)返回false。
不鼓勵(lì)使用,未來可能會(huì)移除。
6、 delegatecall(...) returns (bool):
發(fā)起底層的delegatecall調(diào)用,失敗時(shí)返回false
合約相關(guān)
?1、this(當(dāng)前合約的類型):
表示當(dāng)前合約,可以顯式的轉(zhuǎn)換為Address
2、selfdestruct(address recipient):
銷毀當(dāng)前合約,并把它所有資金發(fā)送到給定的地址。
3、suicide(address recipient):
selfdestruct的別名
另外,當(dāng)前合約里的所有函數(shù)均可支持調(diào)用,包括當(dāng)前函數(shù)本身。