Tightly packing Ethereum event logs
Events on Ethereum are a emitted from contracts. It’s a great place to put data you want to query historical data for.
For example, ERC-20 tokens (like UCDC) use the
Transfer event to log when a token has been transferred. It consists of three arguments and is structured like this:
Transfer(address from, address to, uint256 amount).
This is how a sample
Transfer event looks like:
1 000000000000000000000000B42C838346Ce40aa3B22582A635c01D56C8C7943 (from) 2 000000000000000000000000728713b41fcEc5C071359Ecf2802Fa0B62bec5a8 (to) 3 0000000000000000000000000000000000000000000000000000000000000001 (amount)
As you can see, all arguments are padded with
0s to take up 32 bytes. Isn’t this a lot of useless space?
Even if you define an event with many small data types, it won’t be tightly packed.
This is how an event
TestEvent(uint8 someNumber, bool someBool) could look like:
1 000000000000000000000000000000000000000000000000000000000000000F (someNumber) 2 0000000000000000000000000000000000000000000000000000000000000001 (someBool)
Lots of unused space…
I don’t know…
Maybe it is because this data is only stored in transaction receipts and is therefore not so important?
Even if Solidity doesn’t automatically pack event arguments, we could always do it ourselves.
Imagine we have an event with four
We would have
Communities(uint64 communityId1, uint64 communityId2, uint64 communityId3, uint64 communityId4)
1 0000000000000000000000000000000000000000000000000000000000000000 (communityId1) // the min number 0 2 0000000000000000000000000000000000000000000000001111111111111111 (communityId2) 3 0000000000000000000000000000000000000000000000001234567890abcdef (communityId2) 4 000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF (communityId4) // the max number
Instead of these taking four 32-byte words, we could manually put them all into the same space.
1 000000000000000011111111111111111234567890abcdefFFFFFFFFFFFFFFFF (communityIds) // (communityId) (communityId2) (communityId3) (communityId4)
The problem with this is that it would be harder to parse.
Tools like Viem or Ethers would automatically parse the whole
communityIds hex as one giant number.
In Dune however, you could be able to parse it with this query:
Take a look at the event here: https://goerli.etherscan.io/address/0xf39011e462241b31bfc0018eb6913c8d6b87a3b1#events
It's a shame that Solidity doesn't automatically tightly pack event data. Doing it manually comes with trade-offs.
The best option in most cases is probably to stick with the default, don’t worry about the extra
0000s and not outsmart ourselves.