Skip to content

Commit 90f481f

Browse files
Update event docs for pallet-revive and multi ABI support (#482)
* Refactor event docs for `pallet-revive` and multi ABI support * Update "all" ABI docs * typo Co-authored-by: Michael Müller <mich@elmueller.net> * typo Co-authored-by: Michael Müller <mich@elmueller.net> --------- Co-authored-by: Michael Müller <mich@elmueller.net>
1 parent 38ff0d6 commit 90f481f

File tree

2 files changed

+74
-38
lines changed

2 files changed

+74
-38
lines changed

docs/basics/abi/all.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ for both calling conventions. This means:
4040
then the `default` attribute annotation is unnecessary.
4141
- Call builders and [contract references][contract-refs] are generated for
4242
both ink! and Solidity ABI calling conventions.
43+
- Both an ink! and Solidity ABI encoded event are emitted for each call to
44+
`Self::env().emit_event()` or `self.env().emit_event()`.
4345

4446
:::note
4547
Your contract sizes will get larger if you support both the ink! and Solidity ABI.

docs/basics/events.md

Lines changed: 72 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,12 @@ pub struct Transferred {
8282
amount: u128,
8383
}
8484
```
85-
> Note that generics are [not currently supported](https://github.com/use-ink/ink/issues/2044)
86-
> , so the concrete types of `Environment`
87-
> specific types such as `AccountId` must match up with the types used in the contract.
85+
86+
:::note
87+
Generics are [not currently supported](https://github.com/use-ink/ink/issues/2044),
88+
so the concrete types of `Environment` specific types such as `AccountId`
89+
must match up with the types used in the contract.
90+
:::
8891

8992
This definition can exist within a contract definition module (inline events), in a different
9093
module in the same crate or even in a different crate to be shared by multiple contracts.
@@ -98,37 +101,48 @@ using the new `event` attribute macro directly will behave exactly the same.
98101

99102
### Topics
100103

101-
When an event is emitted, 0 or more topics can be associated with it. The event is then indexed
102-
together with other events with the same topic value.
104+
When an event is emitted, up to 4 topics (including the signature topic, if any) can be associated with it.
105+
The event is then indexed together with other events with the same topic value.
103106

104107
An event's fields can be annotated with `#[ink(topic)]` (see example), which will result in a
105108
topic derived from the value of that field being emitted together with the event.
106109

107-
Topics are by default a 32 byte array (`[u8; 32]`), although this is configurable on the
108-
Polkadot SDK runtime level. If the SCALE encoded bytes of a field value are `<= 32`, then the
109-
encoded bytes are used directly as the topic value.
110+
Topics are a 32 byte array (`[u8; 32]`), and the topic value is encoded as follows:
110111

111-
For example, in the common case of indexing a field of type `AccountId`, where the default
112-
`AccountId` type is 32 bytes in length, the topic value will be the encoded account id itself. This
113-
makes it easy to filter for all events which have a topic of a specific `AccountId`.
112+
- If the SCALE encoded bytes of a field value are `<= 32`,
113+
then the encoded bytes are used directly as the topic value.
114+
If necessary, the topic value is padded on the right side with zero-bytes such that its length is 32 bytes.
115+
- For example, in the common case of indexing a field of type `AccountId`, where the default
116+
`AccountId` type is 32 bytes in length, the topic value will be the encoded account id itself.
117+
This makes it easy to filter for all events which have a topic of a specific `AccountId`.
118+
- If the size of the SCALE encoded bytes of the field value exceeds 32,
119+
then the encoded bytes are hashed using the `Blake2x256` hash function.
114120

115-
If however the size of the encoded bytes of the value of a field exceeds 32, then the encoded
116-
bytes will be hashed using the `Blake2x256` hasher.
121+
:::note
122+
The topic encoding specification above only applies to native/ink! ABI encoded events.
117123

118-
> Topics are a native concept in the Polkadot SDK, and can be queried via [`EventTopics`](https://docs.rs/frame-system/latest/frame_system/pallet/storage_types/struct.EventTopics.html)
124+
For Solidity ABI encoded events, topics (and event data) are encoded according to the
125+
[Solidity ABI specification for events][sol-abi-events] and [indexed event parameters][sol-abi-topics].
126+
:::
119127

120-
How to choose which fields to make topics? A good rule of thumb is to ask yourself if somebody
121-
might want to search for this topic. For this reason the `amount` in the example `Transferred` event
122-
above was not made indexable ‒ there will most probably be a lot of different events with differing
123-
amounts each.
128+
[sol-abi-events]: https://docs.soliditylang.org/en/latest/abi-spec.html#events
129+
[sol-abi-topics]: https://docs.soliditylang.org/en/latest/abi-spec.html#encoding-of-indexed-event-parameters
124130

125-
#### Signature Topic
131+
:::note
132+
Topics are a native concept in the Polkadot SDK, and can be queried via [`EventTopics`](https://docs.rs/frame-system/latest/frame_system/pallet/storage_types/struct.EventTopics.html)
133+
:::
126134

127-
By default all events have a signature topic. This allows indexing of all events of the same
128-
type, emitted by different contracts. The `#[ink::event]` macro generates a signature topic at
129-
compile time by hashing the name of the event concatenated with the *names of the types* of the all
130-
the field
131-
names:
135+
### How to choose which fields to make topics?
136+
A good rule of thumb is to ask yourself if somebody might want to search for this topic.
137+
For this reason the `amount` in the example `Transferred` event above was not made indexable ‒
138+
there will most probably be a lot of different events with differing amounts each.
139+
140+
### Signature Topic
141+
142+
By default all events have a signature topic.
143+
This allows indexing of all events of the same type, emitted by different contracts.
144+
The `#[ink::event]` macro generates a signature topic at compile time by
145+
hashing the name of the event concatenated with the *names of the types* of all the fields:
132146
```
133147
blake2b("Event(field1_type,field2_type)")`
134148
```
@@ -137,18 +151,25 @@ So for our `Transferred` example it will be:
137151
blake2b("Transferred(Option<AccountId>,Option<AccountId>,u128)")`
138152
```
139153

154+
:::note
155+
The signature topic computation specification above only applies to native/ink! ABI encoded events.
156+
157+
For Solidity ABI encoded events, the signature topic is computed as the event signature
158+
according to the [Solidity ABI specification for events][sol-abi-events].
159+
:::
160+
140161
:::caution
141162
Important caveat: because the *name* of the field type is used, refactoring an event
142-
definition to use a type alias or a fully qualified type will change the signature topic, even
143-
though the underlying type is the same. Two otherwise identical definitions of an event with the
144-
same name and same field types but different field type names will have different signature
145-
topics.
163+
definition to use a type alias or a fully qualified type will change the signature topic,
164+
even though the underlying type is the same.
165+
Two otherwise identical definitions of an event with the same name and same field types
166+
but different field type names will have different signature topics.
146167
:::
147168

148169
When decoding events emitted from a contract, signature topics are now required to determine which
149170
type of event to decode into.
150171

151-
#### Anonymous Events
172+
### Anonymous Events
152173

153174
Events annotated with `anonymous` will not have a signature topic generated and published with the
154175
event.
@@ -179,10 +200,11 @@ may be desirable for some contracts, and would be a small gas cost optimization
179200

180201
However, when interacting with the contract from a client, no signature topic means that another
181202
way is required to determine the type of the event to be decoded into (i.e. how do we know it is
182-
a `Transferred` event, not an `Approval` event. One way would be to try decoding for each type
183-
of event defined in the metadata of the contract until one succeeds. If calling a specific
184-
`message`, it may be known up front what type of event that message will raise, so the client
185-
code could just decode into that event directly.
203+
a `Transferred` event, not an `Approval` event.
204+
One way would be to try decoding for each type of event defined in the metadata of the contract
205+
until one succeeds.
206+
If calling a specific `message`, it may be known up front what type of event that message will raise,
207+
so the client code could just decode into that event directly.
186208

187209
## Emitting Events in a Constructor
188210

@@ -224,12 +246,24 @@ pub fn transfer(&mut self, to: AccountId, amount: Balance) -> Result {
224246
}
225247
```
226248

249+
:::note
250+
In ["all" ABI mode][abi-all], both an ink! and Solidity ABI encoded event are emitted
251+
for each call to `Self::env().emit_event()` or `self.env().emit_event()`.
252+
253+
To emit a single event for a specific ABI, 2 additional ABI-specific utilities are provided
254+
in "all" ABI mode:
255+
- `emit_event_ink`: emits a single ink! ABI encoded event.
256+
- `emit_event_sol`: emits a single Solidity ABI encoded event.
257+
:::
258+
259+
[abi-all]: ./abi/all.md
260+
227261
## Cost of using Events
228262

229263
When using events and topics, developers should be mindful of the costs associated.
230264

231-
Firstly: if optimizing for contract size, using events will increase the size of the final code size. So
232-
minimizing or eliminating event usage where necessary will reduce contract size. The same can be
233-
said for the execution (aka gas) costs when using events. We recommend considering the cost of
234-
events when using them, and measuring the code size and gas costs with different usage patterns
235-
when optimizing.
265+
Firstly: if optimizing for contract size, using events will increase the size of the final code size.
266+
So minimizing or eliminating event usage where necessary will reduce contract size.
267+
The same can be said for the execution (aka gas) costs when using events.
268+
We recommend considering the cost of events when using them,
269+
and measuring the code size and gas costs with different usage patterns when optimizing.

0 commit comments

Comments
 (0)