区块链开发之Solidity编程基础合约事件
Posted BBinChina
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了区块链开发之Solidity编程基础合约事件相关的知识,希望对你有一定的参考价值。
事件
事件
事件是以太坊虚拟机(EVM)日志基础设施提供的一个便利接口。用于获取当前发生的事件。
事件和日志有三个用途:
- 智能合约返回值给用户接口
- 异步的带数据的触发器
- 一种比较便宜的存储
智能合约返回值给用户接口
我们可以在 dapp 的用户界面中监听事件,EVM 的日志机制可以反过来“调用”用来监听事件的 javascript 回调函数。
contract ExampleContract
//一些状态变量
function foo(int256 value) returns (int256)
//改变状态
return value;
假设exampleContract就是ExampleContract的一个实例,一个前端使用web3.js,通过模拟函数的执行可以获得返回值:
var returnValue = exampleContract.foo.call(2);
console.log(returnValue);
但是一旦提交合约调用成为一个交易,则无法得到返回值
var returnValue = exampleContract.foo.sendTransaction(2,from: web3.eth.coinbase);
//交易的话,这里应该是一个交易哈希值
console.log(returnValue);
sendTransaction
函数的返回值总是创建交易的哈希。交易并不返回值给前端,这是因为交易没有马上被打包,还未上链。如果想获得一个返回值,那么应该使用事件的方式。
contract ExampleContract
event ReturnValue(address indexed from, int256 value);
function foo(int256 value) returns (int256)
//触发事件
ReturnValue(msg.sender, value);
return value;
前端获取返回值:
//调用事件
var returnValue = exampleContract.ReturnValue( from:web3.eth.coinbase);
//监听事件
exampleEvent.watch(function(err, result)
if (err)
console.log(err);
return;
console.log(result.args.value);
//其他业务
//exampleEvent.stopWatching();
)
//调用foo上链后,watch的回调会被触发,那么前端可以从foo获得返回值
exampleContract.foo.sendTransaction(2,from: web3.eth.coinbase);
异步的带数据的触发器
同理,前端应用可以采用监听事件进行回调的方式来实现异步操作
一种比较便宜的存储
在EVM里,事件被认为是日志(有LOG opcodes),数据可以被存储到日志,当事件被发送时,相应的日志被写到区块链中。根据这种特性,Logs被设计用来成为一种存储,它话费的燃料小于合约的storage,在EVM中Logs基本上每个字节会花费8Gas,而合约storage每32bytes话费20000Gas。
但是Logs不能被任何合约访问。
那如何用来做存储呢,假设场景:合约可以记录某个用户当前的余额,也可以记录每个用户的充值记录,但是可以在Logs记录来取代在合约里记录,减少花费。
contract CryptoExchange
event Deposit(uint256 indexed market, address indexed sender, uint256 amount, uint256 time);
function deposit(uint256 amount, uint256 market) returns (int256)
Deposit(market, msg.sender, amount, now);
cryptoExContract是web3实例化的CryptoExchange,在前端调用
var depositEvent = cryptoExContract.Deposit(sender:userAddress);
depositEvent.watch(function(err, result)
if (err)
console.log(err)
return
)
注意我们的事件参数sender
使用关键字indexed
修饰,表示索引,用于提高用户获取所有event的效率。
我们也可以从block0开始获取上链的事件
var depositEventAll = cryptoExContract.Deposit(
sender:userAddress,
fromBlock:0, toBlock:'latest'
);
depositEventAll.watch(function(err, result)
if (err)
console.log(err)
return
)
事件里的Indexed参数
一个事件最多三个indexed参数,在用户界面上可以使用 indexed 参数的特定值来进行过滤。
例如合约事件transfer:
event Transfer(address indexed from, address indexed to, uint256 amount);
假设应用监听事件,
1、监听from发送的事件
tokenContract.Transfer(
from:senderAddress
);
2、监听to接收的事件
tokenContract.Transfer(
to:receiverAddress
);
3、监特定from到特定to的事件
tokenContract.Transfer(
from:senderAddress,
to:receiverAddress
);
以上是关于区块链开发之Solidity编程基础合约事件的主要内容,如果未能解决你的问题,请参考以下文章