如何理解Soilidity?

有看到天上的屋嗎發表於2021-12-03

什麼是Soilidity?


Solidity是一種面向合約的高階程式語言,用於實現智慧合約。Solidity已經被設計用於以太坊虛擬機器。

Solidity===智慧合約。

Solidity的程式碼封裝在合約中。合約是以太坊應用程式的基本構建塊——所有變數和函式都屬於一個合約,這將是所有專案的起點。

pragma solidity >=0.5.0 <0.6.0; 

contract HelloWorld { 

}

在上面的程式碼中,我們提供了考慮到我們的程式碼與b/w 0.5到0.6的任何版本相容的版本。我們還建立了一個名為“HelloWorld”的合約。


狀態變數和整數


狀態變數永久儲存在合約儲存中。這意味著它們被寫入以太坊區塊鏈。可以把它們想象成寫入DB。

contract Example { 

// This will be stored permanently in the blockchain 

uint myUnsignedInteger = 100; 

string name = "vivek"

}

Uint資料型別是一個無符號整數。它應該是非負的。


資料型別


值型別:

Boolean(true / false),Integers(int / uint), Address(以太坊地址的大小),String, enum

引用型別:

陣列、結構、對映

數學運算

Addition: x + y 

Subtraction: x — y, 

Multiplication: x * y 

Division: x / y 

Modulus / remainder: x % y (for example, 13 % 5 is 3, because if you divide 5 into 13, 3 is the remainder)

Exponential Operation uint x = 5 ** 2; // equal to 5² = 25


結構


類似於C語言中的struct。當我們需要建立具有多個屬性的複雜資料型別時,我們使用結構體。

struct Person { 

uint age; 

string name;


陣列


資料的集合稱為陣列。兩種型別:固定陣列和動態陣列。

顧名思義,固定陣列有預定義的大小,而動態陣列沒有大小。

// Array with a fixed length of 2 elements: 

uint[2] fixedArray;

// another fixed Array, can contain 5 

strings: string[5] stringArray;

// a dynamic Array — has no fixed size, can keep growing: 

uint[] dynamicArray;

我們可以組合結構和陣列。建立一個結構,然後擁有一個結構陣列。就像在物件導向範例(如Java)中有一個物件和一個物件陣列一樣。

pragma solidity >=0.5.0 <0.6.0; 

contract StudentFactory { 

struct student { 

string name; 

uint roll; } student[] public students; // creates an array named students of student type objects


函式宣告


function eatHamburgers(string memory _name, uint _amount) public { }

函式的可見性是公開的。有兩種方式可以傳遞引數給Solidity函式:

按值和按引用

eatHamburgers(“vitalik”, 100);


私人/公共函式


在Solidity中,函式預設是公共的,因此任何人都可以在網路中呼叫公共函式。然而,出於安全考慮,我們將函式設為私有,這樣只有所有者才能呼叫函式。

function _eatHamburgers(string memory _name, uint _amount) private { 

}

按照慣例,私有函式的開頭帶有下劃線。


內部/外部關鍵字


還有兩種型別的函式可見性。內部類似於私有,除了它可以被繼承的合約訪問,即繼承。

外部類似於公共。除了宣告瞭這個函式的聯絡人之外,所有的合約都可以呼叫這個函式。


在函式中返回


函式宣告包含返回值的型別。

function sayHi() public view/pure returns (string memory) { 

return “Hi”;

}

這些函式可以標記為pure/view。當我們甚至沒有訪問傳遞的資料時,我們就將函式標記為pure。如果函式不修改資料,只檢視資料,那麼它將被標記為view。


型別轉換


資料型別之間的轉換稱為型別轉換。

uint8 a = 5; 

uint b = 6;

// line below throws an error because a*b returns a uint, not uint8: 

uint8 c = a * b;

// we have to typecast b as a uint8 to make it work: 

uint8 c = a * uint8(b);


事件


事件用於向前端傳達後端區塊鏈網路上發生了一些事情。

// declare the event 

event NotifyOnFrontend(uint x); 

function add(uint _x, uint _y) public returns (uint) { 

uint result = _x + _y; 

//fire an event to let the frontend know the function was called 

emit NotifyOnFrontend(result); 

return result; 

}

我們的前端程式碼應該已經安裝了web3,並且應該監聽“NotifyOnFrontend”事件,這樣才能工作。我們的JavaScript框架或普通JS將不得不監聽這個事件來接收它:

YourContract.NotifyOnFrontend(function(error, result) { 

// do something with result 

})


對映


這是儲存有組織資料(如陣列和結構)的另一種方法

mapping (address => uint) public accountBalance;

這是一個鍵值儲存。address是鍵,accountBalance是值。

這可以用於在區塊鏈中儲存多個物件(資料)。檢查示例如下:

例子:

contract Example { 

struct UserInfo { 

unit age; string dob;

mapping(string => UserInfo) allusers;


function setUserInfo(string _name, uint _age, string _dob) public {

   allusers[_name].age = _age;
   allusers[_name].dob = _dob;
}

function getUserInfo(string  name) public view returns(uint, string) { 

return (allusers[name].age, allusers[_name].dob); 

}

現在,如果可以用不同的值多次呼叫setUserInfo,比如:

setuserInfo("Vivek",26, 25/05/1995) setuserInfo("Supu", 23, 01/09/1998)

要獲得這些值,只需傳遞名稱:

getUserInfo("Vivek"); // 26 25/05/1995 

getuserInfo("Supu"); // 24 01/09/1998


全域性變數


這些變數可用於像msg.sender這樣的所有函式。我們所編寫的任何Solidity程式,都應該由所有者呼叫。傳送者的地址儲存在msg.sender 全域性變數中。


require


require用於驗證這兩個語句,並據此做出決定。如果條件為真,則程式碼成功執行,否則就丟擲錯誤

function sayHi(string memory  name) public returns (string memory) { / Compares if _name equals “Vivek” Throws an error and exits if not true. Solidity doesn’t have native string comparison, so we compare their keccak256 hashes to see if the strings are equaq 

require(keccak256(abi.encodePacked(name)) == keccak256(abi.encodePacked(“Vivek”)));

// If it’s true, proceed with the function: 

return “Hi!”;

sayHi(“Vivek”) // executes successfully 

sayHi(“Supu”) // throws an error

因此,require對於在執行函式之前驗證某些條件必須為真非常有用。


繼承


有時候,與其制定一個非常長的合約,還不如將程式碼邏輯拆分為多個合約來組織程式碼。

contract Animal {

function catchphrase() public returns (string memory) { 

return “Animal”;

} contract Cat is Animal {

function anotherCatchphrase() public returns (string memory) { 

return “Cat is an Animal”;

}

}


import


將程式碼拆分為多個檔案,並使用import來使用另一個檔案中的功能。

這通常是在Solidity專案中處理長程式碼庫的方式。


儲存和記憶體


儲存是指永久儲存在區塊鏈上的變數。記憶體變數是臨時的,在對合約的外部函式呼叫之間會被刪除。可以把它想象成電腦的硬碟與記憶體。


與區塊鏈網路中的其他合約互動


關於這一點,我將寫一篇單獨的文章。現在,保持簡短:

為了與其他合約互動,我們宣告瞭一個類似object的介面。我們建立了一個合約,並在裡面宣告瞭一個函式,我們想要從另一個合約呼叫或使用它。函式只是骨架,它不包含主體。

contract GetNumber { 

function getNum(uint _num) public returns(uint){ 

return _num; 

}

假設有一個合約,我們想要使用上面的getNum函式。為此,我們將在專案中建立一個合約,並宣告一個getNum函式框架(沒有函式體)。

contract NumberInterface { 

function getNum(uint _num) public returns(uint); 

}

現在我們可以從NumberInterface合約中呼叫getNum函式。

在將合約部署到以太坊後,它就變成了不可變的,也就是說它不能被修改。部署到合約中的初始程式碼將永久地停留在區塊鏈上。這就是安全性在Solidity中如此重要的原因之一。如果我們的合約程式碼中有一個缺陷,就沒有辦法在以後修補它。必須告訴我們的使用者開始使用具有修復功能的不同智慧合約地址。


函式修飾符


函式修飾符看起來就像函式,但是使用關鍵字修飾符而不是關鍵字函式。這些用於特殊情況,例如當您只希望您的所有者而不是所有人做某事時。

這有助於更新DApp的關鍵部分,同時防止其他使用者破壞我們的合約。我處理過的一個用例是——當我們想在執行任何用例之前驗證語句時。


gas


使用者支付gas費來在以太坊網路上執行合約。gas以以太(以太坊上的貨幣)為單位計算。我們的函式的總gas成本等於它所有單獨操作的總gas成本。


更多關於儲存的內容


儲存記憶體被永久寫入到區塊鏈中。全世界成千上萬的節點需要將這些資料儲存在它們的硬碟上,並且隨著區塊鏈的增長,這些資料量也會隨著時間的推移而增長。所以這樣做是有代價的。

為了降低成本,我們希望避免將資料寫入儲存,除非絕對必要。有時,這涉及到看似低效的程式設計邏輯——比如每次呼叫函式時都要在記憶體中重新構建陣列,而不是簡單地將該陣列儲存在XM官方平臺xmforextrade.com全域性儲存變數中以便快速查詢。

因此,建議儘可能使用記憶體型別,這樣資料就不會永久儲存,從而節省成本。迴圈在Solidity中將比使用儲存更便宜。所以儘可能for 迴圈中使用記憶體。這與Java、Python等語言中所做的完全相反,因為for迴圈的計算成本更高。


For迴圈


Syntax類似於Javascript。

for (uint i = 1; i <= 10; i++) { // body }


應付修飾符


支付功能是使Solidity和以太坊如此酷的部分原因——它們是一種可以接收以太坊的特殊型別的功能。當我們在一個普通的web伺服器上呼叫一個API函式時,我們不能在呼叫函式的同時傳送美元——也不能傳送比特幣。

但在以太坊中,因為貨幣(以太坊)、資料(交易有效載荷)和合約程式碼本身都在以太坊上,所以我們可以同時呼叫一個函式並向合約支付費用。

這允許一些非常有趣的邏輯,比如為了執行一個函式,需要向合約支付一定的費用。

注意:

在以太坊中,當我們在合約上呼叫一個函式時,我們將其作為交易廣播到網路上的一個或多個節點。節點在網路上收集一些交易,試圖成為第一個解決計算密集型數學問題的“工作證明”,然後將這組交易連同他們的工作證明(PoW)釋出為一個塊到網路的其餘部分。


代幣


所以基本上,代幣只是一個合約,它記錄了誰擁有多少代幣,以及一些函式,以便這些使用者可以將他們的代幣轉移到其他地址。


assert 與 require 的差異


Assert類似於require,如果為false則丟擲錯誤。assert和require之間的區別是,當一個函式失敗時,require會退還使用者剩餘的gas,而assert不會。


Metamask


這是Chrome和Firefox的瀏覽器擴充套件,允許使用者安全地管理他們的以太坊賬戶和私鑰,並使用這些賬戶與使用Web3.js的網站進行互動。


應用程式二進位制介面。


在部署的合約之後,它會在以太坊上得到一個固定的地址,在那裡它將永遠存在。在以太坊網路中部署智慧合約後,還會生成一個ABI。基本上,它是以JSON格式表示的合約方法,告訴Web3.js如何以我們的合約能夠理解的方式格式化函式呼叫。


Web3Js


以太坊的JS前端庫被稱為web3.js。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69995368/viewspace-2845704/,如需轉載,請註明出處,否則將追究法律責任。

相關文章