mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
c3d6f19e12
Changed the name of the variable because the RTD displays it in green (like the data type or the syntax of the word function), apparently, this is due to the formatting of the RTD text. https://docs.soliditylang.org/en/latest/contracts.html#events
135 lines
4.7 KiB
ReStructuredText
135 lines
4.7 KiB
ReStructuredText
.. index:: ! event
|
|
|
|
.. _events:
|
|
|
|
******
|
|
Events
|
|
******
|
|
|
|
Solidity events give an abstraction on top of the EVM's logging functionality.
|
|
Applications can subscribe and listen to these events through the RPC interface of an Ethereum client.
|
|
|
|
Events are inheritable members of contracts. When you call them, they cause the
|
|
arguments to be stored in the transaction's log - a special data structure
|
|
in the blockchain. These logs are associated with the address of the contract,
|
|
are incorporated into the blockchain, and stay there as long as a block is
|
|
accessible (forever as of now, but this might
|
|
change with Serenity). The Log and its event data is not accessible from within
|
|
contracts (not even from the contract that created them).
|
|
|
|
It is possible to request a Merkle proof for logs, so if
|
|
an external entity supplies a contract with such a proof, it can check
|
|
that the log actually exists inside the blockchain. You have to supply block headers
|
|
because the contract can only see the last 256 block hashes.
|
|
|
|
You can add the attribute ``indexed`` to up to three parameters which adds them
|
|
to a special data structure known as :ref:`"topics" <abi_events>` instead of
|
|
the data part of the log. If you use arrays (including ``string`` and ``bytes``)
|
|
as indexed arguments, its Keccak-256 hash is stored as a topic instead, this is
|
|
because a topic can only hold a single word (32 bytes).
|
|
|
|
All parameters without the ``indexed`` attribute are :ref:`ABI-encoded <ABI>`
|
|
into the data part of the log.
|
|
|
|
Topics allow you to search for events, for example when filtering a sequence of
|
|
blocks for certain events. You can also filter events by the address of the
|
|
contract that emitted the event.
|
|
|
|
For example, the code below uses the web3.js ``subscribe("logs")``
|
|
`method <https://web3js.readthedocs.io/en/1.0/web3-eth-subscribe.html#subscribe-logs>`_ to filter
|
|
logs that match a topic with a certain address value:
|
|
|
|
.. code-block:: javascript
|
|
|
|
var options = {
|
|
fromBlock: 0,
|
|
address: web3.eth.defaultAccount,
|
|
topics: ["0x0000000000000000000000000000000000000000000000000000000000000000", null, null]
|
|
};
|
|
web3.eth.subscribe('logs', options, function (error, result) {
|
|
if (!error)
|
|
console.log(result);
|
|
})
|
|
.on("data", function (log) {
|
|
console.log(log);
|
|
})
|
|
.on("changed", function (log) {
|
|
});
|
|
|
|
|
|
The hash of the signature of the event is one of the topics, except if you
|
|
declared the event with the ``anonymous`` specifier. This means that it is
|
|
not possible to filter for specific anonymous events by name, you can
|
|
only filter by the contract address. The advantage of anonymous events
|
|
is that they are cheaper to deploy and call.
|
|
|
|
::
|
|
|
|
// SPDX-License-Identifier: GPL-3.0
|
|
pragma solidity >=0.4.21 <0.9.0;
|
|
|
|
contract ClientReceipt {
|
|
event Deposit(
|
|
address indexed _from,
|
|
bytes32 indexed _id,
|
|
uint _value
|
|
);
|
|
|
|
function deposit(bytes32 _id) public payable {
|
|
// Events are emitted using `emit`, followed by
|
|
// the name of the event and the arguments
|
|
// (if any) in parentheses. Any such invocation
|
|
// (even deeply nested) can be detected from
|
|
// the JavaScript API by filtering for `Deposit`.
|
|
emit Deposit(msg.sender, _id, msg.value);
|
|
}
|
|
}
|
|
|
|
The use in the JavaScript API is as follows:
|
|
|
|
::
|
|
|
|
var abi = /* abi as generated by the compiler */;
|
|
var ClientReceipt = web3.eth.contract(abi);
|
|
var clientReceipt = ClientReceipt.at("0x1234...ab67" /* address */);
|
|
|
|
var depositEvent = clientReceipt.Deposit();
|
|
|
|
// watch for changes
|
|
depositEvent.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 depositEvent = clientReceipt.Deposit(function(error, result) {
|
|
if (!error)
|
|
console.log(result);
|
|
});
|
|
|
|
The output of the above looks like the following (trimmed):
|
|
|
|
.. code-block:: json
|
|
|
|
{
|
|
"returnValues": {
|
|
"_from": "0x1111…FFFFCCCC",
|
|
"_id": "0x50…sd5adb20",
|
|
"_value": "0x420042"
|
|
},
|
|
"raw": {
|
|
"data": "0x7f…91385",
|
|
"topics": ["0xfd4…b4ead7", "0x7f…1a91385"]
|
|
}
|
|
}
|
|
|
|
Additional Resources for Understanding Events
|
|
==============================================
|
|
|
|
- `Javascript documentation <https://github.com/ethereum/web3.js/blob/1.x/docs/web3-eth-contract.rst#events>`_
|
|
- `Example usage of events <https://github.com/ethchange/smart-exchange/blob/master/lib/contracts/SmartExchange.sol>`_
|
|
- `How to access them in js <https://github.com/ethchange/smart-exchange/blob/master/lib/exchange_transactions.js>`_
|