Event
http://www.reibang.com/p/a99375c4e003
- 基本概念
事件是以太坊提供的基本功能泉褐,用來將數(shù)據(jù)記錄成日志赐写,保存在區(qū)塊鏈上,同時事件也可用于用于和外部交互膜赃,例如和前端的交互挺邀、異步調(diào)用等作用。solidity中,事件是指操作觸發(fā)的行為端铛,而日志則是觸發(fā)事件后泣矛,將數(shù)據(jù)記錄在區(qū)塊鏈上形成日志。
事件event是以太坊提供的基本功能禾蚕,用于將數(shù)據(jù)記錄成日志保存到區(qū)塊鏈上您朽,用戶可以自定義需要記錄的數(shù)據(jù),以及topic和索引换淆;
日志是指事件保存在區(qū)塊鏈上的數(shù)據(jù)哗总。事件強(qiáng)調(diào)操作行為,日志強(qiáng)調(diào)存儲內(nèi)容倍试,兩者是完全不同的概念讯屈。
- 特性
- 區(qū)塊鏈?zhǔn)谴虬幌盗薪灰椎膮^(qū)塊組成的鏈條,每一個交易“收據(jù)”會包含0到多個日志記錄县习,日志代表著智能合約所觸發(fā)的事件涮母。
- 通過emit來調(diào)用一個事件
- 存儲合約數(shù)據(jù),相比storage要便宜很多(storage存儲的大概價(jià)格為:每32字節(jié)需要消耗20000Gas躁愿,而日志存儲價(jià)格大概為每字節(jié)8Gas)
pragma solidity >=0.4.21 <0.6.0;
contract SimpleAuction {
event HighestBidIncreased(address bidder, uint amount); // Event
function bid() public payable {
// ...
emit HighestBidIncreased(msg.sender, msg.value); // Triggering event
}
}
- 在DAPP的應(yīng)用中叛本,有2種反饋方式:監(jiān)聽回調(diào)、持續(xù)阻塞式監(jiān)聽的方式攘已。
var abi = /* abi as generated by the compiler */;
var ClientReceipt = web3.eth.contract(abi);
var clientReceipt = ClientReceipt.at("0x1234...ab67" /* address */);
var event = clientReceipt.Deposit();
// watch for changes
event.watch(function(error, result){
// result contains non-indexed arguments and topics
// given to the `Deposit` call.
if (!error)
console.log(result);
});
// Or pass a callback to start watching immediately
var event = clientReceipt.Deposit(function(error, result) {
if (!error)
console.log(result);
});
日志的查詢
通過web.js 來進(jìn)行監(jiān)聽查詢
由于日志不可被任何合約訪問炮赦,那么我們應(yīng)該如何查找日志了。盡管solidity沒有提供查詢?nèi)罩镜腶pi样勃,但是監(jiān)聽日志時,提供了filter功能性芬,通過filter我們就可以完成查詢?nèi)罩镜男枨蟆?/p>
var event = myContract.Transfer(object1, object2, callfunction);
object1:json對象峡眶,添加indexed屬性的參數(shù)值,這里需要填具體的值植锉,例如上面的例子辫樱,我們可以過濾由指定地址發(fā)出的交易{'_from':'0x84d939AD8034c3ce2A7D4D100b939d4523b9E46E'}
object2:json對象,額外的filter參數(shù),由solidit提供俊庇,可以指定的參數(shù)有:
- fromBlock:數(shù)字或字符串狮暑,默認(rèn)為latest,指定過濾的起始位置辉饱,值為塊的編號
- toBlock:數(shù)字或字符串搬男,默認(rèn)為latest,指定過濾的結(jié)束位置彭沼,值為塊的編號
- address:字符串缔逛,接收指定賬戶地址發(fā)出的event
- topics:字符串?dāng)?shù)組,接收指定topic的event。如果是非匿名事件褐奴,其中一個topic就是事件簽名:Transfer(address,address,uint)按脚,匿名事件是無法通過topic來過濾
- callfunction:回調(diào)函數(shù)function(error, result){...}
// 只監(jiān)聽向0x84d939AD8034c3ce2A7D4D100b939d4523b9E46E地址轉(zhuǎn)賬的事件
var obj1 = {
'_to': '0x84d939AD8034c3ce2A7D4D100b939d4523b9E46E',
}
// block過濾范圍0-latest
var obj2 = {
'fromBlock': 0,
'toBlock': 'latest'
}
var event = instance.Transfer(obj1, obj2)
//監(jiān)聽和回調(diào)函數(shù)
event.watch(function (error, result) {
console.log('transfer log begin')
console.log(JSON.stringify(result))
console.log('transfer log end')
})
多繼承
- 當(dāng)一個合約從多個其它合約那里繼承,在區(qū)塊鏈上僅會創(chuàng)建一個合約敦冬,在父合約里的代碼會復(fù)制來形成繼承合約辅搬。
- 派生合約可以訪問父類合約里所有非私有成員,包括內(nèi)部函數(shù)和狀態(tài)變量脖旱。 但是這些不能通過
this
從外部訪問堪遂。
contract named is owned, mortal {
}
- 繼承的時候,可以直接給父類構(gòu)造函數(shù)賦值
pragma solidity ^0.4.0;
contract Base {
uint x;
function Base(uint _x) { x = _x; }
}
contract Derived is Base(7) {
function Derived(uint _y) Base(_y * _y) {
}
}
全局變量
區(qū)塊和交易屬性
- block.blockhash(uint blockNumber) returns (bytes32):指定區(qū)塊的區(qū)塊哈虾蝗保——僅可用于最新的 256 個區(qū)塊且不包括當(dāng)前區(qū)塊蚤氏;而 blocks 從 0.4.22 版本開始已經(jīng)不推薦使用,由 blockhash(uint blockNumber) 代替
- block.coinbase (address): 挖出當(dāng)前區(qū)塊的礦工地址
- block.difficulty (uint): 當(dāng)前區(qū)塊難度
- block.gaslimit (uint): 當(dāng)前區(qū)塊 gas 限額
- block.number (uint): 當(dāng)前區(qū)塊號
- block.timestamp (uint): 自 unix epoch 起始當(dāng)前區(qū)塊以秒計(jì)的時間戳
- gasleft() returns (uint256):剩余的 gas
- msg.data (bytes): 完整的 calldata
- msg.gas (uint): 剩余 gas - 自 0.4.21 版本開始已經(jīng)不推薦使用踊兜,由 gesleft() 代替
- msg.sender (address): 消息發(fā)送者(當(dāng)前調(diào)用)
- msg.sig (bytes4): calldata 的前 4 字節(jié)(也就是函數(shù)標(biāo)識符)
- msg.value (uint): 隨消息發(fā)送的 wei 的數(shù)量
- now (uint): 目前區(qū)塊時間戳(block.timestamp)
- tx.gasprice (uint): 交易的 gas 價(jià)格
- tx.origin (address): 交易發(fā)起者(完全的調(diào)用鏈)