如何理解Soilidity?
什麼是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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 如何理解Axis?
- 如何理解Generator
- 如何理解 interface 介面
- 如何理解git rebase?Git
- 如何理解nexus
- 如何理解Memory leak
- 如何理解混合雲
- 如何理解systemstate dump
- 如何理解“物件導向”物件
- 如何理解執行緒執行緒
- 如何理解單例模式?單例模式
- 如何理解postgresql toast表SQLAST
- 如何理解介面-Java系列Java
- 如何理解“大資料”大資料
- 如何理解內向的人
- abstract 的 interface ,如何理解?
- Rust 所有權如何理解Rust
- 如何理解插入排序?排序
- 如何理解服務端渲染?服務端
- ps解析度如何理解
- javascript中保留字如何理解JavaScript
- 如何理解物件導向(一)物件
- 如何理解jQuery.on()函式jQuery函式
- 如何通俗的理解散度?
- 什麼是介面,如何理解
- 如何理解 new (...args: any[]) => any
- 如何理解 Laravel 的 IoC 容器Laravel
- 如何通俗地理解 Gradle?Gradle
- Java Eclipse ClassPath如何理解JavaEclipse
- 如何理解高階函式函式
- 這段程式碼如何理解?
- 如何理解OSI七層模型?模型
- 如何理解TCP/IP協議?TCP協議
- 面試題:如何理解閉包面試題
- 如何理解多租戶架構?架構
- 如何理解CSS中的BFC特性CSS
- 如何正確理解棧和堆?
- 如何通俗理解泊松分佈?