-
Notifications
You must be signed in to change notification settings - Fork 482
Description
Currently emitting ink! events is very costly with respect to Wasm file sizes.
The Wasm file size bloat primarily stems from the fact that upon emitting an event we first create an event instances that we immediately encode.
The creation process under Wasm is very costly if an event instance has a large memory footprint.
In the ERC-20 example contract we have several events with a structure like:
#[ink(event)]
pub struct Transferred {
from: Option<AccountId>,
to: Option<AccountId>,
amount: Balance,
}Where AccountId is 256 bit and Balance is 128 bit wide. This means that even in packed form the Transferred struct has a memory footprint of at least 642 bits. Creating instances of this type in Wasm is extremely costly since Wasm has to use the shadow stack for big types like these. What we should do instead is to use references where possible, however:
#[ink(event)]
pub struct Transferred<'a> {
from: Option<&'a AccountId>,
to: Option<&'a AccountId>,
amount: &'a Balance,
}Is currently not an allowed event definition since we require ink! events to be scale::Encode and scale::Decode where the latter requires Self: 'static which is not true for the event definition with references.
Maybe we could drop the latter trait bound since we do not really require events to be decodable - that's just a nice-to-have feature.
Note though that the reference-based event definition still has a memory footprint of at least 98 bits which still requires Wasm to use the shadow stack.
OR we may be able to emit event without constructing an event instance in the first place by creating intelligent constructors that work with EncodeLike<T> for each event field instead of T so it is possible to feed references instead.
This potential solution would probably yield the best results since we won't be required to create short-lived instances of potentially big types.