A tool that allows you to inspect deployed EIP-2535 Diamond proxy contracts from your command line.
Inspector Facet was inspired by Louper.dev (GitHub).
Inspector Facet uses side information about facet ABIs to match the selectors that a Diamond proxy is serving to human-understandable information about the facets and the functions.
We support side information obtained from:
Inspector Facet can build a complete audit log of all Diamond-related operations on an EIP2535 proxy
contract. Use this functionality with the --timeline argument.
Inspector Facet is written in Python 3 and is distributed using PyPI: https://pypi.org/project/inspector-facet/
To install Inspector Facet, run:
pip install inspector-facetinspector-facet --helpTo use Inspector Facet:
The following command produces human-readable output:
inspector-facet \
--network <brownie network name for blockchain> \
--address <address of diamond contract> \
--project <path to brownie project> \
--format humanThe following command produces JSON output and can be used to inspect a Diamond contract programatically (e.g. as part of a CI/CD pipeline):
inspector-facet \
--network <brownie network name for blockchain> \
--address <address of diamond contract> \
--project <path to brownie project> \
--format jsonThe following command produces human-readable output:
inspector-facet \
--network <brownie network name for blockchain> \
--address <address of diamond contract> \
--project <path to foundry project> \
--foundry \
--format humanThe following command produces JSON output and can be used to inspect a Diamond contract programatically (e.g. as part of a CI/CD pipeline):
inspector-facet \
--network <brownie network name for blockchain> \
--address <address of diamond contract> \
--project <path to foundry project> \
--foundry \
--format jsoninspector-facet \
--network <brownie network name for blockchain> \
--address <address of diamond contract> \
--project <path to foundry project> \
--hardhat \
--format humanThe following command produces JSON output and can be used to inspect a Diamond contract programatically (e.g. as part of a CI/CD pipeline):
inspector-facet \
--network <brownie network name for blockchain> \
--address <address of diamond contract> \
--project <path to foundry project> \
--hardhat \
--format jsonThe --build-dir command allows you to specify the name of the build directory in your brownie or
foundry project in case you aren't using the standard directories (build/ for brownie and out/ for foundry).
To build an audit log, you will need to crawl DiamondCut events from the blockchain. You can do this using moonworm.
First, you will need to install moonworm:
pip install moonwormThis should be done in a separate Python environment from inspector-facet because brownie pins its dependencies
and doesn't play nice with other libraries (GitHub issue).
Once moonworm is installed, you can find the deployment block for your contract:
moonworm find-deployment -w <JSON RPC URL for blockchain node> -c <contract address> -t 0.5Save the output of this command as START_BLOCK.
Then crawl the DiamondCut event data:
moonworm watch \
-i inspector_facet/abis/DiamondCutFacetABI.json \
-w <JSON RPC URL for blockchain node> \
-c <contract address> \
--start $START_BLOCK \
--end <current block number> \
--only-events \
-o <output filename> \
--min-blocks-batch 1000 \
--max-blocks-batch 1000000If you are crawling data from a POA chain (like Polygon), add --poa to the command above.
Then, invoke inspector-facet as:
inspector-facet \
--crawldata <output filename> \
--project <path to brownie project (should contain build artifacts in build/contracts)> \
--format human \
--timelineInternally, Inspector Facet uses brownie to work with any
Ethereum-based blockchain. When you use inspector-facet, even with a hardhat project, inspector-facet
will still use brownie to interact with any blockchain.
Any inspector-facet command that calls out to a blockchain will take a -n/--network argument. The value
of this argument must be the name of a brownie network configured in your Python environment.
brownie is a dependency of inspector-facet and is automatically installed when you install inspector-facet.
To see a list of available brownie networks, activate the Python environment in which you installed
inspector-facet and run:
brownie networks listThe output will look like this (truncated for brevity):
$ brownie networks list
Brownie v1.17.2 - Python development framework for Ethereum
The following networks are declared:
Ethereum
├─Mainnet (Infura): mainnet
├─Ropsten (Infura): ropsten
├─Rinkeby (Infura): rinkeby
├─Goerli (Infura): goerli
└─Kovan (Infura): kovan
Ethereum Classic
├─Mainnet: etc
└─Kotti: kotti
Arbitrum
└─Mainnet: arbitrum-main
...
To view the details for any particular network, use:
brownie networks modify $NETWORKFor example:
$ brownie networks modify mainnet
$ brownie networks modify mainnet
Brownie v1.17.2 - Python development framework for Ethereum
SUCCESS: Network 'Mainnet (Infura)' has been modified
└─Mainnet (Infura)
├─id: mainnet
├─chainid: 1
├─explorer: https://api.etherscan.io/api
├─host: https://mainnet.infura.io/v3/$WEB3_INFURA_PROJECT_ID
└─multicall2: 0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696
If you want to connect to this network, using Infura, all you have to do is set your WEB3_INFURA_PROJECT_ID
environment variable (get this information from your project dashboard on Infura) and set --network mainnet
when you invoke inspector-facet.
For networks which have publicly available nodes, it's even more straightforward:
$ brownie networks modify etc
Brownie v1.17.2 - Python development framework for Ethereum
SUCCESS: Network 'Mainnet' has been modified
└─Mainnet
├─id: etc
├─chainid: 61
├─explorer: https://blockscout.com/etc/mainnet/api
└─host: https://www.ethercluster.com/etc
You don't need any additional environment variables.
To add your own network, use the brownie networks add command.
The signature for this command is:
brownie networks add <label> <network-name> chainid=<chain ID for network> host=<JSON RPC endpoint> explorer=<API URL for blockchain explorer>
The <label> is purely for organizational purposes and can be set to whatever string you want.
For example, if you wanted to add the public Polygon RPC service as a network, you would do:
brownie networks add Polygon matic chainid=137 host=https://polygon-rpc.com explorer=https://api.polygonscan.com/apiYou can get help in any of the following ways:
- File an issue
- Ask for help on Moonstream Discord
