Skip to content

AccessList based token balance override #3346

@MartinquaXD

Description

@MartinquaXD

Background

When a user requests a quote from the API we want to verify all quotes coming from solvers in order to avoid displaying prices that are too good to be true. For the quote verification simulation to work the trader address should have the required sell tokens. To provide a good UX where we show verified prices even if no wallet is connected or only one with insufficient sell token balance we already have some logic to figure out in which storage slot of a token contract the balances get stored. That information gets then used to override these storage slots to give the trader address the necessary fake token balance.
This currently uses a relatively simple but crude mechanism which is not able to detect the correct storage slots for somewhat unusual token implementations.

Details

In addition to our simple mechanism we should also implement a mechanism that utilizes access lists. The idea is relatively simple:

  1. use eth_createAccessList for the call sellToken.balanceOf(trader)
  2. this will return all the storage slots that will get read during the call
  3. use our current mechanism with all the storage slots from 2 to identify which storage slot holds the balances of our target trader

Advantages

That way we should be able to find the correct storage slots for all but very weird and exotic tokens (e.g. balances stored in multiple slots, balances stored in an unusual bit pattern, etc.) without requiring the storage slot to be at a range of previously investigated storage slots.

Downsides

While our current approach is able to find the position of the balances mapping(address => uint256) in the token contract the new approach will only be able to figure out where the balance value for a specific address will get stored.
For reference the storage inside a contract is basically a huge array and at which index (i.e. storage slot) values actually get stored depends on a few things. For a mapping commonly used for balances the storage slot of individual values is computed like this:owner_balance_storage_slot = keccak(mapping_storage_slot || owner_address). So specifically our current solution is able to find mapping_storage_slot which always constant for the same token contract and can be used to compute owner_balance_storage_slot with a given owner_address (for many token implementations).
The new approach is only able to find owner_balance_storage_slot but most likely for the vast majority of all token implementations. This also means that for the new approach we'd have to do 2 extra RPC calls for every token and owner pair.
Since RPC calls are pretty cheap this still seem like a good deal, though.

Acceptance criteria

new approach gets implemented
unit test for overriding balances with the new approach (1 for a token where current approach does not work and 1 for a token where currrent approach is sufficient)
new approach either gets used exclusively since it should be strictly more powerful than the current approach or only when the current approach doesn't work (if the added latencty is too problematic).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions