wevm / abitype

Strict TypeScript types for Ethereum ABIs
https://abitype.dev
MIT License
474 stars 39 forks source link

parseAbi cached inputs/outputs problem #247

Open brunomenezes opened 2 months ago

brunomenezes commented 2 months ago

Describe the bug

Context

I work on a web app that is a rollups explorer to support users who are developing with Cartesi technology. That said, I am working on a UI to support the developers in defining a JSON abi using the human-readable format that they can use to decode standard abi-encoded data through our App.

Expected

As a user defining my function signatures and structs, if I have a struct as a function return or input parameter and come to change it (e.g. types, param-name or remove a parameter), I expect the generated JSON ABI to reflect these changes.

What is actually happening

It does not consider the change in the struct. It only reflects the update if I change something in the function signature, but if I come back to the same signature, let's say the original function param is Baz baz. After changes to the struct, nothing happens, so changing to Baz baz2 will reflect the change immediately, but then coming back to Baz baz will reflect the old component definitions in the generated ABI.

Link to Minimal Reproducible Example

https://rollups-explorer-sepolia-git-feature-165-add-dec-dd1128-cartesi.vercel.app/specifications/new

Steps To Reproduce

I added a link to the running application.

  1. Copy the signatures below in the ABI Textarea input and check the accordions below, i.e. ABI Signatures and JSON ABI Generated.
  2. Modify the struct, e.g. change the parameter name from amount to price and check the JSON ABI Generated accordion; nothing will have changed there.
  3. Change the function balanceOf parameter name from baz to baz2, then check the accordion; it should now change.
  4. Last, roll back the function parameter name to baz and check the accordion. The outdated tuple definition should be back.

Input data example:

function balanceOf(Baz baz)
struct Baz {uint amount; string role;}

Package Version

1.0.5 (through Viem@2.17.4)

TypeScript Version

5.3.2

Check existing issues

Anything else?

After ruling out ui-libraries being responsible for any caching, I started looking into the parseAbi(). There is a seeded cache (Map()) that also adds information. However, it does not consider a change in the struct, so the cached data could be marked as stale and skipped to be overridden.

List of calls:

I believe these functions were not designed for prototyping and generating on-demand JSON abi through user input (my case) but rather statically defined in the application itself. So I have a couple of suggestions for a solution.

  1. In the uppermost layer, externalize a not-required Options object-like type for the parseAbi() just like parseAbiParameter. So, that becomes an opt-in situation that does not cause trouble for existing users. e.g. ts type Options = {noCache: boolean} that internally would bypass the caching as I notice some concern comments in the seeding for performance problems with increasing that map.
  2. Do not change the external API. Internally, recognise that important pieces of the cached data have changed and skip the cache read so it is overridden in the process. However, the nature of prototyping and generating on the fly may grow that cache Map.