Solidity合約初識(shí)
本文將通過(guò)一個(gè)簡(jiǎn)單的合約代碼示例,對(duì)代碼結(jié)構(gòu)進(jìn)行說(shuō)明。
代碼示例
如下代碼所示,這是螞蟻區(qū)塊鏈合約平臺(tái)對(duì)積分管理方案的簡(jiǎn)單實(shí)現(xiàn),主要實(shí)現(xiàn)了積分的發(fā)放、轉(zhuǎn)賬和查詢?nèi)齻€(gè)方法。
pragma solidity ^0.4.0;
contract CreditManager {
int256 creditLimit = 1000000000; // the issue limit
int256 issueAmount = 0; // the issue total amount
identity admin; // the administrator in contract
mapping(identity=>int256) credit;
event IssueEvent(identity indexed to, int256 indexed value);
event TransferEvent(identity indexed from, identity indexed to, int256 indexed value);
function CreditManager() {
admin = msg.sender;
}
// modifier
modifier onlyAdmin() {
require(msg.sender == admin,"Permission denied");
_;
}
// issue credit and only admin can
function Issue(identity account, int256 value) public onlyAdmin returns(bool) {
// the value should bigger than 0, and issueAmount add value should small than issueAmount
require(issueAmount + value <= creditLimit && issueAmount + value > issueAmount && value > 0, "Invalid value!");
credit[account] += value;
issueAmount += value;
IssueEvent(account,value);
return true;
}
function Transfer(identity account,int256 value) public returns(bool) {
require(credit[msg.sender] >= value, "balance not enough!");
require(value > 0 && value <= creditLimit, "Invalid value!");
credit[msg.sender] -= value;
credit[account] += value;
TransferEvent(msg.sender,account,value);
return true;
}
function Query(identity account) public returns(int256) {
return credit[account];
}
}
代碼分析
聲明合約版本
首先,合約需要聲明其版本,合約具體實(shí)現(xiàn)以 contract
關(guān)鍵字聲明開(kāi)始。
如下代碼所示(截取自上述代碼示例,下同),螞蟻區(qū)塊鏈合約平臺(tái)基于 Solidity 的 0.4.24 版本進(jìn)行了修改與設(shè)計(jì),支持 0.4.24 版本之前的各種特性。
pragma solidity ^0.4.0;
contract CreditManager {
聲明變量
本合約示例中,定義了兩個(gè)變量來(lái)保存積分的總量(creditLimit)和目前發(fā)放的數(shù)量(issueAmount),并使用 identity
類型來(lái)標(biāo)注每一個(gè)用戶的身份,如合約的管理員(admin)賬戶,identity 的長(zhǎng)度為 32 字節(jié),每個(gè) identity 在區(qū)塊鏈上具有唯一性,所以合約通過(guò) identity 來(lái)標(biāo)注用戶的積分。
int256 creditLimit = 1000000000; // the isuue limit
int256 issueAmount = 0; // the issue total amount
identity admin; // the administrator in contract
mapping(identity=>int256) credit;
聲明事件
本合約示例中,聲明了兩個(gè)事件來(lái)記錄對(duì)應(yīng)的方法執(zhí)行的情況,一個(gè)是積分發(fā)放的事件記錄(IssueEvent),另一個(gè)則是積分轉(zhuǎn)賬的事件記錄(TransferEvent)。
event IssueEvent(identity indexed to, int256 indexed value);
event TransferEvent(identity indexed from, identity indexed to, int256 indexed value);
構(gòu)造函數(shù)
在構(gòu)造函數(shù)中,設(shè)置合約管理員(admin)賬戶 ID,再使用關(guān)鍵字 modifier
設(shè)置管理員權(quán)限。關(guān)鍵字的具體說(shuō)明參見(jiàn)合約關(guān)鍵字。
function CreditManager() {
admin = msg.sender;
}
// modifier,when mas.sender != admin, the contract will show "Permission denied" in output
modifier onlyAdmin() {
require(msg.sender == admin,"Permission denied");
_;
}
定義實(shí)現(xiàn)方法
本示例中,合約實(shí)現(xiàn)了積分的發(fā)放、轉(zhuǎn)賬和查詢方法。
如下代碼所示,在調(diào)用積分發(fā)放方法中,通過(guò) onlyAdmin 來(lái)保證發(fā)放操作只能通過(guò)管理員來(lái)進(jìn)行,然后向用戶傳入的賬戶中增加相應(yīng)的積分,發(fā)放過(guò)程中需要注意積分的溢出問(wèn)題,發(fā)放完畢后,可以觸發(fā)積分發(fā)放事件,用戶可以在調(diào)用合約發(fā)放方法結(jié)果的日志中看到該事件記錄。
// issue credit and only admin can
function Issue(identity account, int256 value) public onlyAdmin returns(bool) {
// the value should bigger than 0, and issueAmount add value should small than issueAmount
require(issueAmount + value <= creditLimit && issueAmount + value > issueAmount && value > 0, "Invalid value!");
credit[account] += value;
issueAmount += value;
IssueEvent(account,value);
return true;
}
合約的轉(zhuǎn)賬與發(fā)放類似,但是轉(zhuǎn)賬不需要有管理員權(quán)限即可執(zhí)行,查詢積分也是一樣。