1. 程式人生 > >智能合約入門

智能合約入門

一行代碼 聲明 highlight 註冊 constant 構造函數 人的 pan 使用

一個簡單的智能合約

先從一個非常基礎的例子開始

1
2
3
4
5
6
7
8
9
10
11
12
contract ZhaoxiStorage {

    uint storedData;

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

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

在Solidity中,一個合約由一組代碼(合約的函數)和數據(合約的狀態)組成。合約位於以太坊區塊鏈上的一個地址。

uint storedData; 這行代碼聲明了一個狀態變量,變量名為storedData,類型為無符號整數uint。可以看做數據庫裏面的一條記錄,可以通過調用函數查詢和修改它。在以太坊中,通常只有合約的擁有者才能這樣做。在這個例子中,函數 set 和 get 分別用於修改和查詢變量的值。

跟很多其他語言一樣,訪問狀態變量時,不需要在前面增加 this. 這樣的前綴。

任何人都可以調用set方法設置一個不同的數字覆蓋你發布的數字。但是你的數字將會留存在區塊鏈的歷史上。稍後我們會學習如何增加存取限制。

一個加密貨幣列子

接下來的合約將實現一個形式最簡單的加密貨幣。通過這份代碼,任何人都可以發送貨幣給其他人,不需要註冊用戶名和密碼,只要有一對以太坊的公私鑰即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
contract ZhaoxiCoin {

    // 關鍵字“public”使變量能從合約外部訪問。
    address public minter;
    mapping (address => uint) public balances;

    // 事件讓輕客戶端能高效的對變化做出反應。
    event Sent(address from, address to, uint amount);

    // 這個構造函數的代碼僅僅只在合約創建的時候被運行。
    function ZhaoxiCoin() {
        minter = msg.sender;
    }

    // 合約創建者可以調用mint
    function mint(address receiver, uint amount) {
        if (msg.sender != minter) return;
        balances[receiver] += amount;
    }

    // send可以被擁有代幣的任何人調用
    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關鍵字的變量將無法被其他合約訪問。另外只有本合約內的代碼才能寫入。自動生成的函數如下:

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

下一行代碼mapping (address => uint) public balances; 創建了一個public的狀態變量,但是其類型更加的復雜。該類型將一些address映射到無符號整數。mapping可以被認為是一個哈希表,每一個可能的key對應的value被虛擬的初始化為全0。對於一個mapping,無法獲取一個包含其所有key或者value的鏈表。所以我們得自己記著添加了哪些東西到mapping中。在這個例子中由public關鍵字生成的訪問函數將會更加復雜,其代碼大致如下:

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

event Sent(address from, address to, uint value)這行代碼聲明了一個“事件”。由send函數的最後一行代碼觸發。客戶端可以監聽這些由區塊鏈觸發的事件。事件觸發時,監聽者會同時接收到from,to,value這些參數值,可以方便的用於跟蹤交易。為了監聽這個事件,你可以使用如下代碼:

1
2
3
4
5
6
7
8
9
10
ZhaoxiCoin.Sent().watch({}, ‘‘, function(error, result) {
    if (!error) {
        console.log("ZhaoxiCoin transfer: " + result.args.amount +
            " coins were sent from " + result.args.from +
            " to " + result.args.to + ".");
        console.log("Balances now:\n" +
            "Sender: " + ZhaoxiCoin.balances.call(result.args.from) +
            "Receiver: " + ZhaoxiCoin.balances.call(result.args.to));
    }
}

這裏有個比較特殊的函數 ZhaoxiCoin。它是一個構造函數,會在合約創建的時候運行,之後就無法被調用。它會永久得存儲合約創建者的地址。msg(以及tx和block)是一個全局變量,它包含了一些可以被合約代碼訪問的屬於區塊鏈的屬性。msg.sender 總是存放著當前函數的外部調用者的地址。

最後,真正被用戶或者其他合約調用,用來完成本合約功能的函數是mint和send。如果合約創建者之外的其他人調用mint,什麽都不會發生。而send可以被任何人(擁有一定數量的代幣)調用,發送一些幣給其他人。

以上就是一個簡單的加密貨幣的完整代碼和說明

智能合約入門