智能合约是什么?智能合约就像法律条文一样的程序代码,合约一旦发布即不可更改。我们先从一个简单的例子开始,如果对合约不理解没关系,我们后面会逐步深入进行讲解。
Storage(数据存储)
pragma solidity^0.4.0;
contract SimpleStorage{
uint storedData;
function set(uintx) public{
storedData=x;
}
function get() public view returns(uint){
return storedData;
}
}
第一行简单地说明源代码使用SOLIDITY 0.4.0版本,同时支持新版本(但不包括0.5.0).通过这样限定了编译的版本,使得同一个合约经过较新的编译器编译时保持一致。关键字PRAGMA,用来指示编译器怎样去处理源代码。
Solidity开发的智能合约是寄存在区块链特定地址上一组代码(函数)和数据(状态)的集合。“uint storedData”这一行声明一个状态变量,命名为storeData,类型为uint(256位的无符号整型),你可以把它看作是一个数据库里的整型字段,通过调用函数来对其进行查询和修改。此合约,可通过set 和get 函数来修改或者检索变量的值。
注意:
所有的标识(合约名称,函数名称,变量名称)被限定为ASCII字符集,所以字符串变量名称可以使用UTF-8编码。
数字币例子
下面的合约会实现一个最简单的加密数子币合约。合约创建者发行任意数量新币,可以使用以太坊账号相互之间可以进行转账。
pragma solidity^0.4.21;
contract Coin{
// 关键字 "public" 使得变量可被合约外部访问
address public minter;
mapping(address=>uint) public balances;
//事件方便UI跟踪交易的改变
event Sent(address from,address to,uint amount);
// 这是一构造函数,当合同创建的时候运行,并且只运行一次。
function Coin() public{
minter=msg.sender;
}
function mint(address receiver,uint amount) public{
if(msg.sender!=minter) return;
balances[receiver]+=amount;
}
function send(address receiver,uint amount) public{
if(balances[msg.sender]
这个合约涉及到一些新的内容,让我们一个个地进行讲解.
“address public minter”这一行声明了一个状态变量,是地址类型(账户地址,也可以叫公钥)。地址类型用来存储是一个二进数160位的地址,但地址类型不可以进行任何的算术运算。这个变量类型适合存储以太坊的账号。“public”自动生成访问变量函数,使变量可被合约外部访问。否则,变量不可被外部访问。自动生成的函数的代码大致如下:
function minter() returns (address) { return minter; }
当然,如果你自己编写一个同样的函数,那么这个函数将不会起作用,因为我们的函数和变量重名了,编译器会自动识别出来。
下一行“ mapping
(address=>uint)
public
balances;”创建了一个公有的状态变量,这是一个复杂的数据类型。这个数据类型通过地址来映射无符号整形。这种类型实际上是已经初始化了,每一个存在的账户,初始值为0。编译器会自动为变量生成一个访问函数,这个函数看上去较为复杂些,代码类似如下:
function balances(address_account) public view returns (uint) {
return balances[_account];
}
正如你看到的,通过这个函数你可以很容易地查询一个账户的余额。
event Sent(address from, address to, uint amount)
上面一行来声明一个事件,当这个事件通过emitted调用时,UI和服务器的程序可以没有太多成本的情况下监听到区块链发出的事件。一旦该事件被发出,监听者可以接受到“from”,“to”,“amount”这几个变量里的值。这使得跟踪交易变得更加方便。UI可以通过下面的代码来监听事件:
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
}
})
注意:UI如何使用自动生成的函数来访问balances。
“Coin”函数是一个构造函数,创建合同被调用,之后不会再被访问,并且把和同创建人的账户永久地保存起来。msg(与tx和block一起)是一个特殊的全局变量,它包含一些访问区块链的属性。“msg.sender”是调用当前函数的账户地址。
“mint”和“send”函数都可以被用户调用。“mint”函数除了合同创建者调用可以发行代币外,其他人调用都是不会起作用的。但是,“send”函数可以被任何人调用,只要拥用了一定该数字币,都可以把拥有的数字币发送给任何人。
注意,如果你使用这合约往一个地址发送币,你通过区块链浏览器查看这个地址是不会看到转账的币,因为这个余额改变只会存储这个特定的合约里。但是,可以使用事件来很容易创建一个类似“区块链浏览器”的功能,来跟踪交易和查询余额。
参考:https://solidity.readthedocs.io/en/v0.4.24/introduction-to-smart-contracts.html