智能合约开发语言solidity快速入门

在本文中,咱们将介绍智能合约的开发语言solidity。数据库

Solidity是一种语法相似JavaScript的高级语言。它被设计成以编译的方式生成以太坊虚拟机代码。在后续内容中你将会发现,使用它很容易建立用于投票、众筹、封闭拍卖、多重签名钱包等等的合约。浏览器

编写第一个合约

让咱们先从一个很是基础的例子开始,不用担忧你如今还一点都不了解,咱们将逐步了解到更多的细节。app

contract SimpleStorage {
    uint storedData;

    function set(uint x) {
        storedData = x;
    }

    function get() constant returns (uint retVal) {
        return storedData;
    }
}

在Solidity中,一个合约由一组代码(合约的函数)和数据(合约的状态)组成。合约位于以太坊区块链上的一个特殊地址。函数

uint storedData; 这行代码声明了一个状态变量,变量名为storedData,类型为 uint (256bits无符号整数)。你能够认为它就像数据库里面的一个存储单元,跟管理数据库同样,能够经过调用函数查询和修改它。在以太坊中,一般只有合约的拥有者才能这样作。在这个例子中,函数 set 和 get 分别用于修改和查询变量的值。学习

跟不少其余语言同样,访问状态变量时,不须要在前面增长 this. 这样的前缀。区块链

这个合约还没法作不少事情(受限于以太坊的基础设施),仅仅是容许任何人储存一个数字。并且世界上任何一我的均可以来存取这个数字,缺乏一个(可靠的)方式来保护你发布的数字。任何人均可以调用set方法设置一个不一样的数字覆盖你发布的数字。可是你的数字将会留存在区块链的历史上。稍后咱们会学习如何增长一个存取限制,使得只有你才能修改这个数字。ui

编写代币合约

接下来的合约将实现一个形式最简单的加密货币。任何人均可以发送货币给其余人,不须要注册用户名和密码,只要有一对以太坊的公私钥便可。this

contract Coin {
//关键字“public”使变量能从合约外部访问。
    address public minter;
    mapping (address => uint) public balances;

//事件让轻客户端能高效的对变化作出反应。
    event Sent(address from, address to, uint amount);

//这个构造函数的代码仅仅只在合约建立的时候被运行。
    function Coin() {
        minter = msg.sender;
    }
    function mint(address receiver, uint amount) {
        if (msg.sender != minter) return;
        balances[receiver] += amount;
    }
    function send(address receiver, uint amount) {
        if (balances[msg.sender] < amount) return;
        balances[msg.sender] -= amount;
        balances[receiver] += amount;
        Sent(msg.sender, receiver, amount);
    }
}

这个合约引入了一些新的概念,让咱们来逐个介绍。加密

address public minter;`

这行代码声明了一个可公开访问的状态变量,类型为address。address类型的值大小为160 bits,不支持任何算术操做。适用于存储合约的地址或其余人的公私钥。public关键字会自动为其修饰的状态变量生成访问函数。没有public关键字的变量将没法被其余合约访问。另外只有本合约内的代码才能写入。自动生成的函数以下:.net

function minter() returns (address) { return minter; }

固然咱们本身增长一个这样的访问函数是行不通的。编译器会报错,指出这个函数与一个状态变量重名。

下一行代码建立了一个public的状态变量,可是其类型更加复杂:

mapping (address => uint) public balances;

该类型将一些address映射到无符号整数。mapping能够被认为是一个哈希表,每个可能的key对应的value被虚拟的初始化为全0.这个类比不是很严谨,对于一个mapping,没法获取一个包含其全部key或者value的链表。因此咱们得本身记着添加了哪些东西到mapping中。更好的方式是维护一个这样的链表,或者使用其余更高级的数据类型。或者只在不受这个缺陷影响的场景中使用mapping,就像这个例子。在这个例子中由public关键字生成的访问函数将会更加复杂,其代码大体以下:

function balances(address _account) returns (uint balance) {
    return balances[_account];
}

咱们能够很方便的经过这个函数查询某个特定帐号的余额。

event Sent(address from, address to, uint value);

这行代码声明了一个“事件”。由send函数的最后一行代码触发。客户端(服务端应用也适用)能够以很低的开销来监听这些由区块链触发的事件。事件触发时,监听者会同时接收到from,to,value这些参数值,能够方便的用于跟踪交易。为了监听这个事件,你可使用以下代码:

Coin.Sent().watch({}, '', function(error, result) {
    if (!error) {
        console.log("Coin transfer: " + result.args.amount +
            " coins were sent from " + result.args.from +
            " to " + result.args.to + ".");
        console.log("Balances now:\n" +
            "Sender: " + Coin.balances.call(result.args.from) +
            "Receiver: " + Coin.balances.call(result.args.to));
    }
}

注意在客户端中是如何调用自动生成的 balances 函数的。

这里有个比较特殊的函数 Coin。它是一个构造函数,会在合约建立的时候运行,以后就没法被调用。它会永久得存储合约建立者的地址。msg(以及tx和block)是一个神奇的全局变量,它包含了一些能够被合约代码访问的属于区块链的属性。msg.sender 老是存放着当前函数的外部调用者的地址。

最后,真正被用户或者其余合约调用,用来完成本合约功能的函数是mint和send。若是合约建立者以外的其余人调用mint,什么都不会发生。而send能够被任何人(拥有必定数量的代币)调用,发送一些币给其余人。注意,当你经过该合约发送一些代币到某个地址,在区块链浏览器中查询该地址将什么也看不到。由于发送代币致使的余额变化只存储在该代币合约的数据存储中。经过事件咱们能够很容易建立一个能够追踪你的新币交易和余额的“区块链浏览器”。

相关文章
相关标签/搜索