ERC-7571: Shadow Events

The ability to generate custom instrumentation/shadow logs is something that people already do today, as @wjmelements, @miohtama and @charliemarketplace mentioned. Platforms like Shadow, Ghostlogs, and others will make that more accessible than it is today, which is good. While people might disagree on methods (or timing), I don’t think many would argue against enabling smaller teams/devs to do something/have capabilities that generally larger, more experienced, and resourced teams had.

In its current form, this ERC aims to enshrine a format for others to follow. It would be beneficial to generalize the proposal more so it can address different use cases, decoupling it from an ideology that some might object to. It would also be worth removing the name of a private company from the format. You could better achieve the desired benefits for the community by incorporating some of the suggestions above.

Sidenote: as @charliemarketplace mentioned, Shadow logs also suffer from some of the problems you mentioned with Transfer spoofing. this will now be cheaper and possibly harder to figure out from the code.

edited later: On the topic of further generalizing – a thread by highbyte mentioned an old idea/proposal he made that is relevant and can be an inspiration on this subject.

1 Like

Working on a small dashboard to look at the data around this.

early analysis indicates that event logs account for approximately 4-6% of the total gas consumption on average, but we could however save around ~100-500k USD daily ( depending on gas price )

Though the daily gas usage varies, the percentage of gas used by logs has remained within a narrow band, signifying that event logs have a predictable and relatively small impact on the overall gas consumption within the network This could imply a stable transaction pattern or efficient use of logs in the network’s operations

PS: I have employed a preliminary and straightforward method to analyze the data presented. While this approach may lack sophistication, it serves as an initial framework for understanding the trends. I invite the community to review the methodology first and build upon it.


While I understand how useful it is to track events and logs not specified in the source code directly (and frankly tracing is still a bit cumbersome for many people), in my opinion a better and more flexible approach seems to just debug trace and analyse using a modded node as well as define events outside of the core smart contract logic.

Therefore it is foreseeable one would still need to debug trace anyways for any events not defined by the developer team, which wouldn’t really solve the problem in many cases.

(Sidenote: also not a fan of naming core primitives after private companies especially given the proposers are very much biased in this direction)

I think the general concept of having additional computation run in an modified, off-chain execution environment is useful. However, this ERC currently seems more like a request for a language feature rather than proposing standards around off-chain computation. I think it could be more useful as an ERC if it instead specified a standardized model for off-chain computation and left changes to language front-ends to individual languages. I think a useful, standardized model for off-chain computation would look something like follows:

  • embedded as metadata in the init- or runtime code (initcode is better from a resource perspective since it does not need to be stored in the state)
  • represented by a series of tuples (hook_pc, bytecode) in the metadata.
  • each time the node hits a hook_pc in the runtime code, it switches to “off-chain” mode and executes the pointed-to bytecode, finally switching out of “off-chain” mode and jumping back to the original pc.
  • define “off-chain” (as opposed to on-chain) computation. off-chain computation would essentially be bytecode which runs in a sandboxed environment where local changes to memory, stack and storage all revert at the end of the hook. an additional nice-to-have for off-chain mode would be for LOG opcodes to be allowed even in staticcalls.
  • a method for specifying that a node enable off-chain mode. this is an opt-in mode for clients to implement. because off-chain mode is sandboxed, it can run off-chain mode alongside its regular execution (subject only to resource requirements).
  • (potentially) a separate RPC method like eth_getOffchainLogs which would fetch logs generated in offchain mode

This would have the following benefits:

  1. Clear and front-end agnostic implementation for compilers. Languages could introduce taint analysis to decide which blocks of code to push into offchain hooks, or otherwise provide whatever features they want in the front-end which enable this feature. As a side note, from the perspective of language implementation, you don’t need conditional compilation blocks to get an efficient implementation here – a powerful enough optimizer can move all code which is not used on-chain into off-chain blocks. No new compiler modes need to be introduced! This is an important security consideration.
  2. Source-code and tooling agnostic. This method doesn’t depend on having source code available or any special tooling (besides a node shipping with this feature) to recover the “off-chain” behavior. So long as you have the initcode, you can recover the off-chain behavior!
  3. Can be run alongside regular execution. As a kind of corollary of the above property (the encoding is entirely embedded in bytecode) and the fact that it runs in sandbox mode: anybody running a node with the appropriate extensions can recover the off-chain computations. This is important so that both users and app developers do not need to rely on a centralized indexer. They can - for convenience or cost reasons! But they do not need to.
  4. Safe. The way that the off-chain computation is designed prevents any semantic differences between running in “off-chain” and “on-chain” mode, which prevents a large class of correctness mistakes (that is, developers test their code in off-chain mode for debugging convenience but deploy in on-chain mode) before they even happen. Another way of thinking about this is from the tooling perspective - this method results in only a single bytecode artifact. It’s hard to run the wrong bytecode when you only have one bytecode to run!