美文网首页
Solidity撰寫智能合約與注意事項(二)

Solidity撰寫智能合約與注意事項(二)

作者: hellomi001 | 来源:发表于2018-08-02 12:27 被阅读0次

    from:

    https://medium.com/taipei-ethereum-meetup/solidity%E6%92%B0%E5%AF%AB%E6%99%BA%E8%83%BD%E5%90%88%E7%B4%84%E8%88%87%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A0%85-%E4%BA%8C-dd915bdeafa0

    這篇將介紹以太坊的log資料及event的使用

    類似於比特幣的OP_RETURN,以太坊也提供一個把資料永久寫入區塊鏈裡的方法 — event,event所寫入的資料會被記錄在一個Receipt資料裡。

    每一筆transaction都會有一個對應的Receipt,用來記錄這筆transaction的執行結果

    eth.getTransaction()

    getTransaction可以得到這筆transaction的相關資料,這些資料在transaction被製作出來的時候就有了,而Receipt則是直到被執行完(也就是transaction被放進鏈裡)後才會有。

    註:(1)gas是指這次提供的gas總量

    (2)input是合約的code(這是一個部署合約的transaction,所以input就是整份合約的code)。

    用getTransacitonReceipt("hash")來取得transaction對應的Receipt:

    eth.getTransactionReceipt()

    註:(1)gasUsed是這筆transaction所花費的gas(我們提供了4700000,只花了118615,剩下的會退還給我們)

    (2)logs則是我們這篇介紹的log,如果有event被觸發,資料就會被入在這

    那什麼時候會需要用到event呢?

    1. 當作一個額外的儲存空間,而且很便宜。event寫入的成本和用合約變數來儲存的成本相比之下少了很多,如果你開發的dapp需要將使用者的使用紀錄(如付款紀錄)等記錄下來當作證明,與其用一個陣列儲存,不如在每次使用時用event寫進log裡。

    但要注意的是,這些寫進log裡的資料是沒辦法被合約所存取的。

    2. 當成return value來使用。合約裡函式的回傳值並非總是可以使用,假設一個有回傳值的函式:

    contract f00{

    function foo(int _value) returns (int) {

    return _value * _value;

    }

    }

    什麼時候你可以拿到這個回傳值?只有在你使用call在本地進行模擬的時候才會有回傳值,如下:

    var ret = f00.foo.call(25);

    console.log(ret);    //625

    當你使用sendTransaction,真的做出一筆交易的時候,他會回傳你這筆transaction的hash值,所以這時候你可以使用event來將回傳值記錄起來:

    contract f00{

    event retValue(int _value);

    function foo(int _value) returns(int) {

    return _value * _value;

    }

    }

    這時候在前端便可以利用像javascript那樣監聽的功能:

    var retValueEvent = f00.retValue();

    retValueEvent.watch(function(err, result){

    if(err){

    console.log(err);

    return;

    }

    console.log(result.args._value);

    });

    當transaction被收入區塊鏈裡後,就會觸發監聽器然後按照你設定的callback函式執行對應的動作。如果要結束監聽,執行 retValueEvent.stopWatching()。

    3. 最後便是當你開發dapp的時候,藉由觸發event寫入log,再觸發監聽器執行對應動作,如此完成從 外界->鏈->鏈->外界 一個完整的執行過程。對使用者來說就像一個是對資料庫操作的動作,只是這個資料庫變成了區塊鏈。

    接下來以簡單的例子來介紹監聽器更多的功能

    contract depositAccount {

    event Deposit(addressindexed_owner, uint _amount, uint _time);

    function deposit() payable {

    Deposit(msg.sender, msg.value, now);

    }

    }

    首先先介紹第二行的indexed。

    在Receipt裡如果有log,會寫在logs欄位裡,每筆log其中有兩部分:data和topics。一般event寫入的資料都會寫在data裡,但如果在event的變數加入一個indexed屬性,到時候觸發時這個變數對應寫入的值就會寫在topics裡,在topcis裡的值可以用來當作監聽器的篩選條件。

    註:一份Receipt裡面可以有很多筆log(表示一次transaction可以觸發很多次event),一筆log最多只能儲存四個topics,而第一個topic必須是這個event的識別值identifier,代表一個event最多只能有三個變數可以有indexed屬性。

    transaction的logs裡的其中一筆log

    上面這張圖是其中某一筆log,這個event沒有加indexed的變數,值都會寫在data欄位裡(32byte為一單位接在一起,圖中為十六進位的9和19),topcis裡唯一一個值 0x35bd26...是該event的識別值。

    下面這張圖是變數都加上indexed的event的log記錄:

    event有indexed

    因為所有變數都加上indexed,所以data裡沒有值,值都寫在topics裡(十六進位的102和abcde)。

    接下來在前端加入監聽器:

    var depositEvent = depositAccount.Deposit({_owner:null},{fromBlock: 5000, toBlock: ‘latest’});

    depositEvent.watch(function(err, results) {

    if (err) {

    console.log(err);

    return;

    }

    console.log(results.blockNumber);

    });

    第一行的{fromBlock: 5000, toBlock: ‘latest’}是加入的篩選條件,表示監聽從第5000個區塊開始到最新的區塊。如果event被觸發,那callback函式就會印出是發生在第幾個區塊( result.blockNumber )。

    如果我們要用有加上indexed的變數(_owner變數)來當篩選條件的話,就指定_owner應該要是多少,如果給null(像上面的例子),那就是任何address都可以的意思:

    var depositEvent = depositaccount.Deposit({_owner:'0xbd7255b64eeb594ca57652c94249da6a9b37cd2f'});

    depositEvent.watch(function(err, results) {

    if (err) {

    console.log(err);

    return;

    }

    if(results.args._amount > web3.toWei(0.05,"ether")){

    console.log("User: " + results.args._owner +

    " deposits: " + results.args._amount +

    " on: " +

    JSON.stringify(new Date((parseInt(results.args._time)+28800)*1000))

    );

    }

    });

    這個callback會在"0xbd7255b64eeb594ca57652c94249da6a9b37cd2f"這個address存錢的時候被觸發,存入超過0.05 ether的時候會印出存入的金額和存入時間。

    References:

    [1]https://media.consensys.net/technical-introduction-to-events-and-logs-in-ethereum-a074d65dd61e#.u7l9ejta3

    [2]https://github.com/ethereum/wiki/wiki/JavaScript-API#contract-events

    相关文章

      网友评论

          本文标题:Solidity撰寫智能合約與注意事項(二)

          本文链接:https://www.haomeiwen.com/subject/zsvjvftx.html