Event
https://www.jianshu.com/p/a99375c4e003
- 基本概念
事件是以太坊提供的基本功能,用来将数据记录成日志,保存在区块链上,同时事件也可用于用于和外部交互,例如和前端的交互、异步调用等作用。solidity中,事件是指操作触发的行为,而日志则是触发事件后,将数据记录在区块链上形成日志。
事件event是以太坊提供的基本功能,用于将数据记录成日志保存到区块链上,用户可以自定义需要记录的数据,以及topic和索引;
日志是指事件保存在区块链上的数据。事件强调操作行为,日志强调存储内容,两者是完全不同的概念。
- 特性
- 区块链是打包一系列交易的区块组成的链条,每一个交易“收据”会包含0到多个日志记录,日志代表着智能合约所触发的事件。
- 通过emit来调用一个事件
- 存储合约数据,相比storage要便宜很多(storage存储的大概价格为:每32字节需要消耗20000Gas,而日志存储价格大概为每字节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的应用中,有2种反馈方式:监听回调、持续阻塞式监听的方式。
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 来进行监听查询
由于日志不可被任何合约访问,那么我们应该如何查找日志了。尽管solidity没有提供查询日志的api,但是监听日志时,提供了filter功能,通过filter我们就可以完成查询日志的需求。
var event = myContract.Transfer(object1, object2, callfunction);
object1:json对象,添加indexed属性的参数值,这里需要填具体的值,例如上面的例子,我们可以过滤由指定地址发出的交易{'_from':'0x84d939AD8034c3ce2A7D4D100b939d4523b9E46E'}
object2:json对象,额外的filter参数,由solidit提供,可以指定的参数有:
- fromBlock:数字或字符串,默认为latest,指定过滤的起始位置,值为块的编号
- toBlock:数字或字符串,默认为latest,指定过滤的结束位置,值为块的编号
- address:字符串,接收指定账户地址发出的event
- topics:字符串数组,接收指定topic的event。如果是非匿名事件,其中一个topic就是事件签名:Transfer(address,address,uint),匿名事件是无法通过topic来过滤
- callfunction:回调函数function(error, result){...}
// 只监听向0x84d939AD8034c3ce2A7D4D100b939d4523b9E46E地址转账的事件
var obj1 = {
'_to': '0x84d939AD8034c3ce2A7D4D100b939d4523b9E46E',
}
// block过滤范围0-latest
var obj2 = {
'fromBlock': 0,
'toBlock': 'latest'
}
var event = instance.Transfer(obj1, obj2)
//监听和回调函数
event.watch(function (error, result) {
console.log('transfer log begin')
console.log(JSON.stringify(result))
console.log('transfer log end')
})
多继承
- 当一个合约从多个其它合约那里继承,在区块链上仅会创建一个合约,在父合约里的代码会复制来形成继承合约。
- 派生合约可以访问父类合约里所有非私有成员,包括内部函数和状态变量。 但是这些不能通过
this
从外部访问。
contract named is owned, mortal {
}
- 继承的时候,可以直接给父类构造函数赋值
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) {
}
}
全局变量
区块和交易属性
- block.blockhash(uint blockNumber) returns (bytes32):指定区块的区块哈希——仅可用于最新的 256 个区块且不包括当前区块;而 blocks 从 0.4.22 版本开始已经不推荐使用,由 blockhash(uint blockNumber) 代替
- block.coinbase (address): 挖出当前区块的矿工地址
- block.difficulty (uint): 当前区块难度
- block.gaslimit (uint): 当前区块 gas 限额
- block.number (uint): 当前区块号
- block.timestamp (uint): 自 unix epoch 起始当前区块以秒计的时间戳
- gasleft() returns (uint256):剩余的 gas
- msg.data (bytes): 完整的 calldata
- msg.gas (uint): 剩余 gas - 自 0.4.21 版本开始已经不推荐使用,由 gesleft() 代替
- msg.sender (address): 消息发送者(当前调用)
- msg.sig (bytes4): calldata 的前 4 字节(也就是函数标识符)
- msg.value (uint): 随消息发送的 wei 的数量
- now (uint): 目前区块时间戳(block.timestamp)
- tx.gasprice (uint): 交易的 gas 价格
- tx.origin (address): 交易发起者(完全的调用链)