Solidity合约初识

本文将通过一个简单的合约代码示例,对代码结构进行说明。

代码示例

如下代码所示,这是蚂蚁区块链合约平台对积分管理方案的简单实现,主要实现了积分的发放、转账和查询三个方法。

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];
    }
}

代码分析

声明合约版本

首先,合约需要声明其版本,合约具体实现以 contract 关键字声明开始。

如下代码所示(截取自上述代码示例,下同),蚂蚁区块链合约平台基于 Solidity 的 0.4.24 版本进行了修改与设计,支持 0.4.24 版本之前的各种特性。

pragma solidity ^0.4.0;
contract CreditManager {

声明变量

本合约示例中,定义了两个变量来保存积分的总量(creditLimit)和目前发放的数量(issueAmount),并使用 identity 类型来标注每一个用户的身份,如合约的管理员(admin)账户,identity 的长度为 32 字节,每个 identity 在区块链上具有唯一性,所以合约通过 identity 来标注用户的积分。

int256 creditLimit = 1000000000;   // the isuue limit
int256 issueAmount = 0;           // the issue total amount
identity admin;                   // the administrator in contract
mapping(identity=>int256) credit;

声明事件

本合约示例中,声明了两个事件来记录对应的方法执行的情况,一个是积分发放的事件记录(IssueEvent),另一个则是积分转账的事件记录(TransferEvent)。

event IssueEvent(identity indexed to, int256 indexed value);
event TransferEvent(identity indexed from, identity indexed to, int256 indexed value);

构造函数

在构造函数中,设置合约管理员(admin)账户 ID,再使用关键字 modifier 设置管理员权限。关键字的具体说明参见合约关键字

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");
    _;
}

定义实现方法

本示例中,合约实现了积分的发放、转账和查询方法。

如下代码所示,在调用积分发放方法中,通过 onlyAdmin 来保证发放操作只能通过管理员来进行,然后向用户传入的账户中增加相应的积分,发放过程中需要注意积分的溢出问题,发放完毕后,可以触发积分发放事件,用户可以在调用合约发放方法结果的日志中看到该事件记录。

// 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;
    }

合约的转账与发放类似,但是转账不需要有管理员权限即可执行,查询积分也是一样。