Storage hooks

Track value changes to specific variables in contract storage

Simple variables and mapping values

To hook on a variable, you provide its name/path as defined in source code. For example, for Wrapped Ether, you could hook on balanceOf or allowance (or name, symbol, decimals, but they won't be very interesting!).

If you want to track a specific value within a mapping, hook on the mapping and then filter on the key in the callback.

Using slither to construct paths

For complex cases where variables are nested, you can used slither-read-storage to generate the layouts and construct the paths required for storage hooks:

slither-read-storage 0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8 --json storage_layout.json --etherscan-apikey *your etherscan api key*

Open storage_layout.json, which contains a description of each storage variable. Input the slither name field to the Variable path input on sim.

Example 1: Simple variables

If the type doesn't involves a struct, all you need to do is provide us the top level variable names for instance liquidity or feeGrowthGlobal0X128 in the case of UniswapV3Pool.

{
    ...
    "liquidity": {
        "name": "liquidity",
        "type_string": "uint128",
        "slot": 4,
        "size": 128,
        "offset": 0,
        "value": null,
        "elems": {}
    },
    ...
      "feeGrowthGlobal0X128": {
        "name": "feeGrowthGlobal0X128",
        "type_string": "uint256",
        "slot": 1,
        "size": 256,
        "offset": 0,
        "value": null,
        "elems": {}
    },
    ...
}

Example 2: Structs

In the case of structs, you need to give us the full path. protocolFees has two members, so you would need to define either protocolFees.token0 or protocolFees.token1, depending on which variable you want to hook on.

{
  ...
    "protocolFees": {
        "name": "protocolFees",
        "type_string": "UniswapV3Pool.ProtocolFees",
        "slot": 3,
        "size": 256,
        "offset": 0,
        "value": null,
        "elems": {
            "token0": {
                "name": "protocolFees.token0",
                "type_string": "uint128",
                "slot": 3,
                "size": 128,
                "offset": 0,
                "value": null,
                "elems": {}
            },
            "token1": {
                "name": "protocolFees.token1",
                "type_string": "uint128",
                "slot": 3,
                "size": 128,
                "offset": 128,
                "value": null,
                "elems": {}
            }
        }
    },
  ...
}

If you want to hook on both, add one storage hook for each.