科普 | 什麼是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成本。

更多關於存儲的內容

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

為了降低成本,我們希望避免將數據寫入存儲,除非絕對必要。有時,這涉及到看似低效的編程邏輯——比如每次調用函數時都要在內存中重新構建數組,而不是簡單地將該數組保存在全局存儲變量中以便快速查找。

因此,建議儘可能使用內存類型,這樣數據就不會永久存儲,從而節省成本。循環在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。

Source:https://medium.com/coinmonks/learn-all-about-solidity-ethereum-45d709c4de77

本文鏈接:https://www.8btc.com/article/6713244

轉載請註明文章出處

(0)
上一篇 2021-12-03 17:42
下一篇 2021-12-03 18:10

相关推荐