Win10下開發部署Dapp(4):solidity快速入門(基礎篇)

基礎篇

Solidity是一門靜態類型的腳本語言,我們可以對照C++的語法進行快速記憶。
###1.基本保留字與基本類型

  • contract:類似於class,定義一個合約,具有構造函數,僅在創建合約時被調用。
  • function:定義一個函數。
  • event:定義一個事件,外部Dapp可以監控這些事件,以獲知合約內的變化。
  • var:聲明變量,類似於C++11的auto,可以在初始化時進行自動類型推導,之後不能更改類型。
  • bool: 布爾類型,有true跟false兩種值。
  • uint8、uint16、。。。uint256:無符號整型,uint是uint256的別名。
  • nint8、int16、。。。int256:有符號整形,int是int256的別名。
  • ufixedMxN:無符號定點小數,M表示整個類型佔用的bit數,N表示小數位數。ufixed64x7:7位小數,剩下的是整數部分
  • fixedMxN:定點小數。
  • address:地址類型,表示賬戶地址或者合約地址。20Byte。
    addr.balance:返回uint256類型的值,表示addr賬戶的餘額(Wei)。
    addr.send(uint256 N):轉給addr地址N Wei數量的以太幣,失敗是返回false。
    addr.transfer(uint256 N):包裝了send方法,失敗時直接拋出異常,會導致整個交易回退。
    addr.call、addr.callcode、addr.delegatecall:調用addr合約的指定的方法,區別稍後詳述。

###2.基本操作符

  • 邏輯操作符:!(邏輯非)、&&(邏輯與)、||(邏輯或)。跟C++完全一致,並且&&與||同樣存在短路求值。
  • 比較操作符:<、<=、>、>=、==、!=,跟C++完全一致。
  • 算術操作符:+(正號)、-(負號)、 +、-、*、/、%(取餘)、<<(左移)、>>(右移)、**(冪)。除了冪,其餘的都跟C++一致。
  • 位操作符:&(與)、|(或)、~(非)、^(異或)。

###3.數組、字符串、結構體、枚舉類型、mapping

  • 數組
  • 定長數組:編譯期長度就固定下來的數組是定長數組,這樣定義一個定常數組:T[k](例如 uint8[ 5 ] arr)。bytes1、bytes2, bytes3, …, bytes32,這些也是定長數組。bytes1可以簡寫成byte。定長數組是值類型(value-type),可以進行比較操作、位操作、索引操作。
  • 動態數組:編譯期長度不固定,類似於C++中的vector,這樣定義一個動態數組:T[] (例如 int256[] arr)。
    string是特殊的動態數組。普通的定長數組、動態數組都可以進行取長度操作:arr.length,以及下標索引操作,但是string暫時不支持這兩種操作。bytes也是動態數組,相當於byte[],但是比byte[]要更、廉價一些,應該儘量使用bytes。另外,動態數組、bytes還可以調用push方法,在數組末尾添加數據,返回最新的長度。
  • 字符串
    string本質上是經過UTF8編碼的byte數組。當前版本的solidity對string的實現十分不完整,無法支持串聯、比較、下標索引等操作,甚至連取長度都不支持。當前的string僅可以用來做mapping的key。
  • 結構體
    跟C++很像,這樣定義一個結構體:
struct MyStruct{
bool flag;
string name;

}
MyStruct a;

	結構體、數組裏未被初始化的元素,都是0。
  • 枚舉
  • mapping
    solidity裏使用頻率比較高的類型。mapping (address => uint256) balanceOf; 定義了一個map,使用地址做索引,值位uint256.

###4.全局可用的單位、函數、對象

  • 以太幣單位
    1 Ether = 1000 Finny
    1 Finny = 1000 Szabo
    1 Szabo = 1000 Gwei
    1 Gwei = 1000 Mwei
    1 Mwei = 1000 Kwei
    1 Kwei = 1000 wei
    1 Ether = 10^18 wei
  • 時間單位
    1 == 1 seconds
    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):返回指定高度的塊的hash值,僅限最近256塊。
    block.coinbase (address):當前塊的礦工
    block.difficulty (uint):當前塊的難度
    block.gaslimit (uint):當前塊的gaslimit
    block.number (uint):當前塊高度
    block.timestamp (uint): 當前塊時間戳
  • msg對象
    msg.data (bytes):當前調用完整的原始數據
    msg.gas (uint): 剩餘的gas,0.4.21版本之後棄用,替換爲gasleft。
    msg.sender (address): 當前調用的發起者。
    msg.sig (bytes4):調用數據的頭四字節
    msg.value (uint):當前消息攜帶的以太幣,單位wei。
  • tx對象
    tx.gasprice (uint):當前交易的gas price
    tx.origin (address): 當前交易的發起者。
  • 數學函數、hash函數
    addmod(uint x, uint y, uint k) returns (uint):
    mulmod(uint x, uint y, uint k) returns (uint):
    keccak256(…) returns (bytes32):
    sha256(…) returns (bytes32):
    sha3(…) returns (bytes32):
    ripemd160(…) returns (bytes20):
    ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address):
  • 異常處理函數
    assert(bool condition):
    require(bool condition):
    revert():
  • 其他
    gasleft() returns (uint256)
    now (uint):
    this
    suicide

###5.contract(合約)
contract類似於class,他有:

  • 構造函數。跟contract名稱相同的function即爲構造函數,在合約創建時被調用,可以有參數,無返回值。
  • 自殺函數。selfdestruct(address)銷燬合約,並把合約賬戶裏的ether轉移到指定的地址,花費比調用transfer小。suicide是selfdestruct的別名。
  • this。在合約內,this可以轉化成address。在合約內部調用自己的external函數也需要用到this。
  • 成員變量。
  • 成員函數。
  • 繼承、被繼承。一個合約可以繼承其他合約。
    ###6.可見性:external、public、internal、private
    合約內的成員變量、成員函數需要使用可見性來修飾,不修飾默認爲public(跟C++剛好相反)。
  • external:只能用來修飾成員函數,這樣的函數只能被外部合約調用,合約內部想要調用該函數,需要使用this.func();
  • public:修飾變量,則編譯器會自動生成一個同名的getter。修飾函數,則外部可以調用該函數。
  • internal:類似於protect,可被合約內部以及子類合約訪問。
  • private:私有的,僅合約內部可以訪問,子類不可訪問。
    ###7.函數及其修飾詞
    函數可以有多個返回值:
    直接通過一個稍微複雜點的例子來看下solidity的函數是啥樣子的。
uint16 uCount; //合約內的成員變量

function add(uint8 a, uint8 b) public pure returns(uint8){
	return a + b; //先忽略溢出。
}

function GetCount() public view returns(uint16){
	return uCount;
}

function setCount(uint16 count) public {
	uCount = count;
}

modifier validAddress(address addr){
	assert(addr != address(0));
	_;
}
modifier validAmount(uint256 amount){
	reqire(amount > 0);
	_;
}

function myTransferFunc(address to, uint256 amount) public validAddress(to) validAmount(amount){
	//無需再檢查參數的合法性,如果不合法,會在modifier中拋出異常,進不到函數體中。
	//........
	//........
}

function deposit(uint256 amount) public payable returns(bool, string){ 
	//........
	return (true, "successfull");
}

function () public payable{
	//.......
}

  從上往下依次看,add方法很簡單,實現了兩個數相加,但是pure是啥意思?GetCount方法的view又是啥意思?SetCount爲啥沒有這兩個東西?pure:不改變合約狀態,也不讀取合約狀態的函數,開發者應當主動使用pure修飾;讀取合約狀態但是不修改合約狀態的函數,使用view修飾;SetCount改變了合約狀態,不能被這兩個中的任何一個修飾。(老版本的solidity沒有view與pure,只有一個constant,凡是不改變狀態的函數需要被constant修飾,後來細化成兩部分view + pure)。
  接下來的modifier,業界普遍翻譯成函數修改器,我覺得應該叫 函數衛詞,它就像是一個衛語句,在函數運行之前過濾參數的合法性。不合法直接拋出異常,退出函數體,整個交易都不會被執行。
  再往下,一個新關鍵詞:payable。被這個修飾的函數,才能夠被轉賬,否則只能是普通調用。
  最後,一個沒有名字的函數,叫回退函數(fallback function)。當且僅當一個合約的回退函數被實現了且被payable修飾了,才能向這個合約地址直接轉賬。
###8.事件
  事件是另一個新東西,可以讓外部dapp監控合約內的變化。這裏先簡單介紹下事件的定義以及觸發,事件的監聽後面補上。

event OnTrasnsfer(address from, address to, uint value);
function myTransferFunc(address to, uint256 amount) public validAddress(to) validAmount(amount){
	//轉賬
	。。。
	//新版本的solidity觸發事件需要使用emit關鍵字,之前的版本不用,但是看起來像是個函數調用。
	emit OnTrasnsfer(address(this), to, amount);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章