2019-08-21 08:53:47 +03:00
|
|
|
_section: Events
|
|
|
|
|
|
|
|
Explain how topics and such work
|
2019-12-14 06:05:10 +03:00
|
|
|
|
|
|
|
_subsection: Solidity Topics
|
|
|
|
|
|
|
|
How to compute the topic...
|
2020-05-08 10:24:40 +03:00
|
|
|
|
|
|
|
_subsection: Logs and Filtering
|
|
|
|
|
|
|
|
Example hog logs are used.
|
|
|
|
|
|
|
|
Link to provider.getLogs and contract.on
|
|
|
|
|
|
|
|
_heading: Filters
|
|
|
|
|
|
|
|
Filter are used as a way to query ... efficient, explain bloom filters lightly
|
|
|
|
|
|
|
|
A filter may have up to 4 topic-sets, where each topic-set refers
|
|
|
|
to a condition that must match the log topic in that position (i.e. each
|
|
|
|
condition is ``AND``-ed together).
|
|
|
|
|
|
|
|
If a topic-set is ``null``, a log topic in that position is not filtered
|
|
|
|
at all and **any value** matches.
|
|
|
|
|
|
|
|
If a topic-set is a single topic, a log topic in that position must match
|
|
|
|
**that topic**.
|
|
|
|
|
|
|
|
If a topic-set is an array of topics, a log topic in that position must
|
|
|
|
match any **one** of topics (i.e. the topic in thie position are ``OR``-ed).
|
|
|
|
|
|
|
|
|
|
|
|
_table: Example Log Matching @style<full>
|
|
|
|
|
|
|
|
$TopicABaCD: **[** (topic[0] = A) **OR** (topic[0] = B) **]** **AND**
|
|
|
|
**[** (topic[1] = C) **OR** (topic[1] = D) **]**
|
|
|
|
|
|
|
|
| **Topic-Sets** | **Matching Logs** <<|
|
|
|
|
| [ A ] | topic[0] = A <<|
|
|
|
|
| [ A, null ] | ^ |
|
|
|
|
| [ null, B ] | topic[1] = B <<|
|
|
|
|
| [ null, [ B ] ] | ^ |
|
|
|
|
| [ null, [ B ], null ] | ^ |
|
|
|
|
| [ A, B ] | (topic[0] = A) **AND** (topic[1] = B) <<|
|
|
|
|
| [ A, [ B ] ] | ^ |
|
|
|
|
| [ A, [ B ], null ] | ^ |
|
|
|
|
| [ [ A, B ] ] | (topic[0] = A) **OR** (topic[0] = B) <<|
|
|
|
|
| [ [ A, B ], null ] | ^ |
|
|
|
|
| [ [ A, B ], [ C, D ] ] | $TopicABaCD <<|
|
|
|
|
|
|
|
|
|
|
|
|
_code: ERC-20 Transfer Filter Examples @lang<javascript>
|
|
|
|
|
|
|
|
// <hide>
|
|
|
|
const tokenAddress = ethers.constants.AddressZero;
|
|
|
|
const myAddress = ethers.constants.AddressZero;
|
|
|
|
const myOtherAddress = ethers.constants.AddressZero;
|
|
|
|
const id = ethers.utils.id;
|
|
|
|
const hexZeroPad = ethers.utils.hexZeroPad;
|
|
|
|
// </hide>
|
|
|
|
|
|
|
|
// Short example of manually creating filters for an ERC-20
|
|
|
|
// Transfer event.
|
|
|
|
//
|
|
|
|
// Most users should generally use the Contract API to
|
|
|
|
// compute filters, as it is much simpler, but this is
|
|
|
|
// provided as an illustration for those curious. See
|
|
|
|
// below for examples of the equivalent Contract API.
|
|
|
|
|
|
|
|
// ERC-20:
|
|
|
|
// Transfer(address indexed src, address indexed dst, uint val)
|
|
|
|
//
|
|
|
|
// -------------------^
|
|
|
|
// ----------------------------------------^
|
|
|
|
//
|
|
|
|
// Notice that only *src* and *dst* are *indexed*, so ONLY they
|
|
|
|
// qualify for filtering.
|
|
|
|
//
|
|
|
|
// Also, note that in Solidity an Event uses the first topic to
|
|
|
|
// identify the Event name; for Transfer this will be:
|
|
|
|
// id("Transfer(address,address,uint256)")
|
|
|
|
//
|
|
|
|
// Other Notes:
|
|
|
|
// - A topic must be 32 bytes; so shorter types must be padded
|
|
|
|
|
|
|
|
// List all token transfers *from* myAddress
|
|
|
|
filter = {
|
|
|
|
address: tokenAddress,
|
|
|
|
topics: [
|
|
|
|
id("Transfer(address,address,uint256)"),
|
|
|
|
hexZeroPad(myAddress, 32)
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
// List all token transfers *to* myAddress:
|
|
|
|
filter = {
|
|
|
|
address: tokenAddress,
|
|
|
|
topics: [
|
|
|
|
id("Transfer(address,address,uint256)"),
|
|
|
|
null,
|
|
|
|
hexZeroPad(myAddress, 32)
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
// List all token transfers *to* myAddress or myOtherAddress:
|
|
|
|
filter = {
|
|
|
|
address: tokenAddress,
|
|
|
|
topics: [
|
|
|
|
id("Transfer(address,address,uint256)"),
|
|
|
|
null,
|
|
|
|
[
|
|
|
|
hexZeroPad(myAddress, 32),
|
|
|
|
hexZeroPad(myOtherAddress, 32),
|
|
|
|
]
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
_null:
|
|
|
|
|
|
|
|
To simplify life, ..., explain here, the contract API
|
|
|
|
|
|
|
|
|
|
|
|
_code: ERC-20 Contract Filter Examples @lang<javascript>
|
|
|
|
|
|
|
|
// <hide>
|
|
|
|
const tokenAddress = "0x6B175474E89094C44Da98b954EedeAC495271d0F"; // DAI
|
|
|
|
const myAddress = "0x8ba1f109551bD432803012645Ac136ddd64DBA72";
|
|
|
|
const otherAddress = "0xEA517D5a070e6705Cc5467858681Ed953d285Eb9";
|
|
|
|
const provider = ethers.getDefaultProvider();
|
|
|
|
const Contract = ethers.Contract;
|
|
|
|
// </hide>
|
|
|
|
|
|
|
|
const abi = [
|
|
|
|
"event Transfer(address indexed src, address indexed dst, uint val)"
|
|
|
|
];
|
|
|
|
|
|
|
|
const contract = new Contract(tokenAddress, abi, provider);
|
|
|
|
|
|
|
|
// List all token transfers *from* myAddress
|
|
|
|
contract.filters.Transfer(myAddress)
|
|
|
|
//!
|
|
|
|
|
|
|
|
// List all token transfers *to* myAddress:
|
|
|
|
contract.filters.Transfer(null, myAddress)
|
|
|
|
//!
|
|
|
|
|
|
|
|
// List all token transfers *from* myAddress *to* otherAddress:
|
|
|
|
contract.filters.Transfer(myAddress, otherAddress)
|
|
|
|
//!
|
|
|
|
|
|
|
|
// List all token transfers *to* myAddress OR otherAddress:
|
|
|
|
contract.filters.Transfer(null, [ myAddress, otherAddress ])
|
|
|
|
//!
|
|
|
|
|
|
|
|
_heading: Other Things? TODO
|
|
|
|
|
|
|
|
Explain what happens to strings and bytes, how to filter and retain the value
|