Skip to content

Instantly share code, notes, and snippets.

@banteg
Last active December 1, 2023 00:19
Show Gist options
  • Save banteg/0cee21909f7c1baedfa6c3d96ffe94f2 to your computer and use it in GitHub Desktop.
Save banteg/0cee21909f7c1baedfa6c3d96ffe94f2 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"id": "aff0db76-5a9a-4562-baf9-2f478413e918",
"metadata": {},
"source": [
"### diamond storage walkthrough by banteg\n",
"\n",
"hello and welcome. today we'll be reading this struct found in [zksync era](https://etherscan.io/address/0x32400084C286CF3E17e7B677ea9583e60a000324) by hand:\n",
" \n",
" struct DiamondStorage {\n",
" mapping(bytes4 => SelectorToFacet) selectorToFacet;\n",
" mapping(address => FacetToSelectors) facetToSelectors;\n",
" address[] facets;\n",
" bool isFrozen;\n",
" }\n",
" struct FacetToSelectors {\n",
" bytes4[] selectors;\n",
" uint16 facetPosition;\n",
" }\n",
" struct SelectorToFacet {\n",
" address facetAddress;\n",
" uint16 selectorPosition;\n",
" bool isFreezable;\n",
" }\n",
"\n",
"our plan is simple, read `facets` and then read `facetToSelectors` and get out. 20 minute adventure, right?"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "61df63bc-9196-4189-a05e-23bd50ad50ba",
"metadata": {
"execution": {
"iopub.execute_input": "2023-08-19T04:31:52.390544Z",
"iopub.status.busy": "2023-08-19T04:31:52.390018Z",
"iopub.status.idle": "2023-08-19T04:31:54.138566Z",
"shell.execute_reply": "2023-08-19T04:31:54.138189Z",
"shell.execute_reply.started": "2023-08-19T04:31:52.390501Z"
}
},
"outputs": [],
"source": [
"from functools import cache\n",
"from ape import chain, networks, Contract\n",
"from eth_utils import keccak\n",
"from hexbytes import HexBytes\n",
"from rich import print"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "0bcf568d-ca24-44dd-85c8-6ba1ea5510db",
"metadata": {
"execution": {
"iopub.execute_input": "2023-08-19T04:31:54.139446Z",
"iopub.status.busy": "2023-08-19T04:31:54.139091Z",
"iopub.status.idle": "2023-08-19T04:31:55.320975Z",
"shell.execute_reply": "2023-08-19T04:31:55.319992Z",
"shell.execute_reply.started": "2023-08-19T04:31:54.139435Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"INFO: Connecting to existing Erigon node at http://localhost:8545/[hidden].\n"
]
},
{
"data": {
"text/plain": [
"<geth chain_id=1>"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"networks.parse_network_choice(\":mainnet:geth\").__enter__()"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "ec7f227e-4eaa-4faf-b620-caff326bab66",
"metadata": {
"execution": {
"iopub.execute_input": "2023-08-19T04:31:55.324082Z",
"iopub.status.busy": "2023-08-19T04:31:55.323318Z",
"iopub.status.idle": "2023-08-19T04:31:55.329342Z",
"shell.execute_reply": "2023-08-19T04:31:55.328915Z",
"shell.execute_reply.started": "2023-08-19T04:31:55.324028Z"
}
},
"outputs": [],
"source": [
"address = \"0x32400084C286CF3E17e7B677ea9583e60a000324\"\n",
"\n",
"\n",
"def to_bytes(val: int, size=32) -> HexBytes:\n",
" return HexBytes(val.to_bytes(size, \"big\"))\n",
"\n",
"\n",
"def to_int(val: bytes) -> int:\n",
" return int.from_bytes(val, \"big\")\n",
"\n",
"\n",
"@cache\n",
"def get(address, slot) -> HexBytes:\n",
" return chain.provider.get_storage_at(address, slot)"
]
},
{
"cell_type": "markdown",
"id": "fe82f6f3-2bfc-4613-ad7f-68950a359575",
"metadata": {},
"source": [
"### the easy part: reading a mapping\n",
"\n",
"for a mapping `map` and a key `key`, then, the element `map[key]` is stored starting at `keccak256(key . p)`, where the dot means concatenation.\n",
"\n",
"we'll make a function that takes the list of keys to read and returns the computed positions of the keys, because in the mapping we'll read, the values are another lookup type."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "a326e0fe-f4b0-4217-bdd2-d3eed0ab7d80",
"metadata": {
"execution": {
"iopub.execute_input": "2023-08-19T04:31:55.331124Z",
"iopub.status.busy": "2023-08-19T04:31:55.330969Z",
"iopub.status.idle": "2023-08-19T04:31:55.334098Z",
"shell.execute_reply": "2023-08-19T04:31:55.333595Z",
"shell.execute_reply.started": "2023-08-19T04:31:55.331114Z"
}
},
"outputs": [],
"source": [
"def read_mapping(address, slot: bytes, keys: list[bytes]):\n",
" if isinstance(slot, int):\n",
" slot = to_bytes(slot)\n",
" result = []\n",
" for k in keys:\n",
" pos = keccak(k + slot)\n",
" result.append(\n",
" {\n",
" \"key\": k,\n",
" \"pos\": HexBytes(pos),\n",
" \"val\": get(address, pos),\n",
" }\n",
" )\n",
" return result"
]
},
{
"cell_type": "markdown",
"id": "ca620125-2024-4897-8e01-d00a882a6a5f",
"metadata": {},
"source": [
"### the hard part: reading a dynamic array\n",
"\n",
"if you ask a solidity dev, he'll tell you this:\n",
"\n",
"> Array data is located starting at `keccak256(p)` and it is laid out in the same way as statically-sized array data would:\n",
"> One element after the other, potentially sharing storage slots if the elements are not longer than 16 bytes.\n",
"> Dynamic arrays of dynamic arrays apply this rule recursively.\n",
"> The location of element `x[i][j]`, where the type of x is `uint24[][]`, is computed as follows\n",
"> (again, assuming x itself is stored at slot p): The slot is `keccak256(keccak256(p) + i) + floor(j / floor(256 / 24))`\n",
"> and the element can be obtained from the slot data v using `(v >> ((j % floor(256 / 24)) * 24)) & type(uint24).max`.\n",
"\n",
"you'll just roll your eyes and move on to a different problem. let's try to unpack this and come up with something more legible.\n",
"\n",
"the only thing written at `p` is the length of the array in items, not in words.\n",
"\n",
"the items themselves are stored starting at `keccak(p)`. they are written right to left when multiple items fit in a slot, but jump over to the next slot when an item doesn't fully fit. so, for example, each 20 byte address would occupy full 32 byte slots.\n",
"\n",
"with this knowledge let's try to come with a readable version."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "7aa43607-d39d-4518-876d-5ceca44ecc09",
"metadata": {
"execution": {
"iopub.execute_input": "2023-08-19T04:31:55.334984Z",
"iopub.status.busy": "2023-08-19T04:31:55.334866Z",
"iopub.status.idle": "2023-08-19T04:31:55.338256Z",
"shell.execute_reply": "2023-08-19T04:31:55.337767Z",
"shell.execute_reply.started": "2023-08-19T04:31:55.334974Z"
}
},
"outputs": [],
"source": [
"def read_array(address, pos, item_size=32):\n",
" # the main word contains the length of the array\n",
" array_len = to_int(get(address, pos))\n",
" # the array type[] is stored exactly like type[n], except that it starts at keccak256(p)\n",
" array_start = to_int(keccak(pos))\n",
" items_per_word = 32 // item_size\n",
" values = []\n",
"\n",
" for n in range(array_len):\n",
" word_pos = array_start + n // items_per_word\n",
" # items are written right to left\n",
" item_start = 32 - (n % items_per_word + 1) * item_size\n",
" word = get(address, word_pos)\n",
" ext = HexBytes(word)[item_start : item_start + item_size]\n",
" # print(f\"n={n} pos=..{word_pos % 1000} word={word} start={item_start} ext={ext}\")\n",
" values.append(ext)\n",
"\n",
" return values"
]
},
{
"cell_type": "markdown",
"id": "266d8863-ef87-4946-b814-6f617d3ffaf4",
"metadata": {},
"source": [
"### looking into the diamond\n",
"\n",
"now we need to carefully move though the levels of storage abstraction to extract the data we need."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "f19a349d-09ec-421d-bf58-d49b69158013",
"metadata": {
"execution": {
"iopub.execute_input": "2023-08-19T04:31:55.339248Z",
"iopub.status.busy": "2023-08-19T04:31:55.339078Z",
"iopub.status.idle": "2023-08-19T04:31:57.903892Z",
"shell.execute_reply": "2023-08-19T04:31:57.903498Z",
"shell.execute_reply.started": "2023-08-19T04:31:55.339237Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">{</span>\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'ExecutorFacet (0x9b1a10bdc4a40219544c835263b2ca3f3e689693)'</span>: <span style=\"font-weight: bold\">{</span>\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x0c4dd810'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'commitBlocks'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xce9dcf16'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'executeBlocks'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x7739cbe7'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'proveBlocks'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xa9a2d18a'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'revertBlocks'</span>\n",
" <span style=\"font-weight: bold\">}</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'MailboxFacet (0xa389bf185b301c8e20e79e3098e71399914035df)'</span>: <span style=\"font-weight: bold\">{</span>\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x6c0960f9'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'finalizeEthWithdrawal'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xb473318e'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'l2TransactionBaseCost'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x042901c7'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'proveL1ToL2TransactionStatus'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x263b7f8e'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'proveL2LogInclusion'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xe4948f43'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'proveL2MessageInclusion'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xeb672419'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'requestL2Transaction'</span>\n",
" <span style=\"font-weight: bold\">}</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'GovernanceFacet (0xf002dfbc52c250a2e14c148041adb8567a0b19bd)'</span>: <span style=\"font-weight: bold\">{</span>\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xe58bb639'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'acceptGovernor'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xed6d06c0'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'setAllowList'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x86cb9909'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'setL2BootloaderBytecodeHash'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x0707ac09'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'setL2DefaultAccountBytecodeHash'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xf235757f'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'setPendingGovernor'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x1cc5d103'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'setPorterAvailability'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xbe6f11cf'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'setPriorityTxMaxGasLimit'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x4623c91d'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'setValidator'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x5437988d'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'setVerifier'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x0b508883'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'setVerifierParams'</span>\n",
" <span style=\"font-weight: bold\">}</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'DiamondCutFacet (0xab458acbd8ff9b6cf7b8a029705a02f70dcdbf7d)'</span>: <span style=\"font-weight: bold\">{</span>\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x73fb9297'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'cancelUpgradeProposal'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x36d4eb84'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'executeUpgrade'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x27ae4c16'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'freezeDiamond'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x0551448c'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'proposeShadowUpgrade'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x8043760a'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'proposeTransparentUpgrade'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xbeda4b12'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'securityCouncilUpgradeApprove'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x17338945'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'unfreezeDiamond'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x587809c7'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'upgradeProposalHash'</span>\n",
" <span style=\"font-weight: bold\">}</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'GettersFacet (0x8c0f38f13526fcb379a80b87f4debdbcc9caecbd)'</span>: <span style=\"font-weight: bold\">{</span>\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xcdffacc6'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'facetAddress'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x52ef6b2c'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'facetAddresses'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xadfca15e'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'facetFunctionSelectors'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x7a0ed627'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'facets'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xa7cd63b7'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'getAllowList'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xfe10226d'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'getCurrentProposalId'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x79823c9a'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'getFirstUnprocessedPriorityTx'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x4fc07d75'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'getGovernor'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xd86970d8'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'getL2BootloaderBytecodeHash'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xfd791f3c'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'getL2DefaultAccountBytecodeHash'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x8665b150'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'getPendingGovernor'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x631f4bac'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'getPriorityQueueSize'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x0ec6b0b7'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'getPriorityTxMaxGasLimit'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x1b60e626'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'getProposedUpgradeHash'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xe39d3bff'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'getProposedUpgradeTimestamp'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x0ef240a0'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'getSecurityCouncil'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xfe26699e'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'getTotalBlocksCommitted'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x39607382'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'getTotalBlocksExecuted'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xaf6a2dcd'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'getTotalBlocksVerified'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xa1954fc5'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'getTotalPriorityTxs'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xa39980a0'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'getUpgradeProposalState'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x46657fe9'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'getVerifier'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x18e3a941'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'getVerifierParams'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x3db920ce'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'isApprovedBySecurityCouncil'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x29b98c67'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'isDiamondStorageFrozen'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xbd7c5412'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'isEthWithdrawalFinalized'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xc3bbd2d7'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'isFacetFreezable'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xe81e0ba1'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'isFunctionFreezable'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0xfacd743b'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'isValidator'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x9cd939e4'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'l2LogsRootHash'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x56142d7a'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'priorityQueueFrontOperation'</span>,\n",
" <span style=\"color: #008000; text-decoration-color: #008000\">'0x74f4d30d'</span>: <span style=\"color: #008000; text-decoration-color: #008000\">'storedBlockHash'</span>\n",
" <span style=\"font-weight: bold\">}</span>\n",
"<span style=\"font-weight: bold\">}</span>\n",
"</pre>\n"
],
"text/plain": [
"\u001b[1m{\u001b[0m\n",
" \u001b[32m'ExecutorFacet \u001b[0m\u001b[32m(\u001b[0m\u001b[32m0x9b1a10bdc4a40219544c835263b2ca3f3e689693\u001b[0m\u001b[32m)\u001b[0m\u001b[32m'\u001b[0m: \u001b[1m{\u001b[0m\n",
" \u001b[32m'0x0c4dd810'\u001b[0m: \u001b[32m'commitBlocks'\u001b[0m,\n",
" \u001b[32m'0xce9dcf16'\u001b[0m: \u001b[32m'executeBlocks'\u001b[0m,\n",
" \u001b[32m'0x7739cbe7'\u001b[0m: \u001b[32m'proveBlocks'\u001b[0m,\n",
" \u001b[32m'0xa9a2d18a'\u001b[0m: \u001b[32m'revertBlocks'\u001b[0m\n",
" \u001b[1m}\u001b[0m,\n",
" \u001b[32m'MailboxFacet \u001b[0m\u001b[32m(\u001b[0m\u001b[32m0xa389bf185b301c8e20e79e3098e71399914035df\u001b[0m\u001b[32m)\u001b[0m\u001b[32m'\u001b[0m: \u001b[1m{\u001b[0m\n",
" \u001b[32m'0x6c0960f9'\u001b[0m: \u001b[32m'finalizeEthWithdrawal'\u001b[0m,\n",
" \u001b[32m'0xb473318e'\u001b[0m: \u001b[32m'l2TransactionBaseCost'\u001b[0m,\n",
" \u001b[32m'0x042901c7'\u001b[0m: \u001b[32m'proveL1ToL2TransactionStatus'\u001b[0m,\n",
" \u001b[32m'0x263b7f8e'\u001b[0m: \u001b[32m'proveL2LogInclusion'\u001b[0m,\n",
" \u001b[32m'0xe4948f43'\u001b[0m: \u001b[32m'proveL2MessageInclusion'\u001b[0m,\n",
" \u001b[32m'0xeb672419'\u001b[0m: \u001b[32m'requestL2Transaction'\u001b[0m\n",
" \u001b[1m}\u001b[0m,\n",
" \u001b[32m'GovernanceFacet \u001b[0m\u001b[32m(\u001b[0m\u001b[32m0xf002dfbc52c250a2e14c148041adb8567a0b19bd\u001b[0m\u001b[32m)\u001b[0m\u001b[32m'\u001b[0m: \u001b[1m{\u001b[0m\n",
" \u001b[32m'0xe58bb639'\u001b[0m: \u001b[32m'acceptGovernor'\u001b[0m,\n",
" \u001b[32m'0xed6d06c0'\u001b[0m: \u001b[32m'setAllowList'\u001b[0m,\n",
" \u001b[32m'0x86cb9909'\u001b[0m: \u001b[32m'setL2BootloaderBytecodeHash'\u001b[0m,\n",
" \u001b[32m'0x0707ac09'\u001b[0m: \u001b[32m'setL2DefaultAccountBytecodeHash'\u001b[0m,\n",
" \u001b[32m'0xf235757f'\u001b[0m: \u001b[32m'setPendingGovernor'\u001b[0m,\n",
" \u001b[32m'0x1cc5d103'\u001b[0m: \u001b[32m'setPorterAvailability'\u001b[0m,\n",
" \u001b[32m'0xbe6f11cf'\u001b[0m: \u001b[32m'setPriorityTxMaxGasLimit'\u001b[0m,\n",
" \u001b[32m'0x4623c91d'\u001b[0m: \u001b[32m'setValidator'\u001b[0m,\n",
" \u001b[32m'0x5437988d'\u001b[0m: \u001b[32m'setVerifier'\u001b[0m,\n",
" \u001b[32m'0x0b508883'\u001b[0m: \u001b[32m'setVerifierParams'\u001b[0m\n",
" \u001b[1m}\u001b[0m,\n",
" \u001b[32m'DiamondCutFacet \u001b[0m\u001b[32m(\u001b[0m\u001b[32m0xab458acbd8ff9b6cf7b8a029705a02f70dcdbf7d\u001b[0m\u001b[32m)\u001b[0m\u001b[32m'\u001b[0m: \u001b[1m{\u001b[0m\n",
" \u001b[32m'0x73fb9297'\u001b[0m: \u001b[32m'cancelUpgradeProposal'\u001b[0m,\n",
" \u001b[32m'0x36d4eb84'\u001b[0m: \u001b[32m'executeUpgrade'\u001b[0m,\n",
" \u001b[32m'0x27ae4c16'\u001b[0m: \u001b[32m'freezeDiamond'\u001b[0m,\n",
" \u001b[32m'0x0551448c'\u001b[0m: \u001b[32m'proposeShadowUpgrade'\u001b[0m,\n",
" \u001b[32m'0x8043760a'\u001b[0m: \u001b[32m'proposeTransparentUpgrade'\u001b[0m,\n",
" \u001b[32m'0xbeda4b12'\u001b[0m: \u001b[32m'securityCouncilUpgradeApprove'\u001b[0m,\n",
" \u001b[32m'0x17338945'\u001b[0m: \u001b[32m'unfreezeDiamond'\u001b[0m,\n",
" \u001b[32m'0x587809c7'\u001b[0m: \u001b[32m'upgradeProposalHash'\u001b[0m\n",
" \u001b[1m}\u001b[0m,\n",
" \u001b[32m'GettersFacet \u001b[0m\u001b[32m(\u001b[0m\u001b[32m0x8c0f38f13526fcb379a80b87f4debdbcc9caecbd\u001b[0m\u001b[32m)\u001b[0m\u001b[32m'\u001b[0m: \u001b[1m{\u001b[0m\n",
" \u001b[32m'0xcdffacc6'\u001b[0m: \u001b[32m'facetAddress'\u001b[0m,\n",
" \u001b[32m'0x52ef6b2c'\u001b[0m: \u001b[32m'facetAddresses'\u001b[0m,\n",
" \u001b[32m'0xadfca15e'\u001b[0m: \u001b[32m'facetFunctionSelectors'\u001b[0m,\n",
" \u001b[32m'0x7a0ed627'\u001b[0m: \u001b[32m'facets'\u001b[0m,\n",
" \u001b[32m'0xa7cd63b7'\u001b[0m: \u001b[32m'getAllowList'\u001b[0m,\n",
" \u001b[32m'0xfe10226d'\u001b[0m: \u001b[32m'getCurrentProposalId'\u001b[0m,\n",
" \u001b[32m'0x79823c9a'\u001b[0m: \u001b[32m'getFirstUnprocessedPriorityTx'\u001b[0m,\n",
" \u001b[32m'0x4fc07d75'\u001b[0m: \u001b[32m'getGovernor'\u001b[0m,\n",
" \u001b[32m'0xd86970d8'\u001b[0m: \u001b[32m'getL2BootloaderBytecodeHash'\u001b[0m,\n",
" \u001b[32m'0xfd791f3c'\u001b[0m: \u001b[32m'getL2DefaultAccountBytecodeHash'\u001b[0m,\n",
" \u001b[32m'0x8665b150'\u001b[0m: \u001b[32m'getPendingGovernor'\u001b[0m,\n",
" \u001b[32m'0x631f4bac'\u001b[0m: \u001b[32m'getPriorityQueueSize'\u001b[0m,\n",
" \u001b[32m'0x0ec6b0b7'\u001b[0m: \u001b[32m'getPriorityTxMaxGasLimit'\u001b[0m,\n",
" \u001b[32m'0x1b60e626'\u001b[0m: \u001b[32m'getProposedUpgradeHash'\u001b[0m,\n",
" \u001b[32m'0xe39d3bff'\u001b[0m: \u001b[32m'getProposedUpgradeTimestamp'\u001b[0m,\n",
" \u001b[32m'0x0ef240a0'\u001b[0m: \u001b[32m'getSecurityCouncil'\u001b[0m,\n",
" \u001b[32m'0xfe26699e'\u001b[0m: \u001b[32m'getTotalBlocksCommitted'\u001b[0m,\n",
" \u001b[32m'0x39607382'\u001b[0m: \u001b[32m'getTotalBlocksExecuted'\u001b[0m,\n",
" \u001b[32m'0xaf6a2dcd'\u001b[0m: \u001b[32m'getTotalBlocksVerified'\u001b[0m,\n",
" \u001b[32m'0xa1954fc5'\u001b[0m: \u001b[32m'getTotalPriorityTxs'\u001b[0m,\n",
" \u001b[32m'0xa39980a0'\u001b[0m: \u001b[32m'getUpgradeProposalState'\u001b[0m,\n",
" \u001b[32m'0x46657fe9'\u001b[0m: \u001b[32m'getVerifier'\u001b[0m,\n",
" \u001b[32m'0x18e3a941'\u001b[0m: \u001b[32m'getVerifierParams'\u001b[0m,\n",
" \u001b[32m'0x3db920ce'\u001b[0m: \u001b[32m'isApprovedBySecurityCouncil'\u001b[0m,\n",
" \u001b[32m'0x29b98c67'\u001b[0m: \u001b[32m'isDiamondStorageFrozen'\u001b[0m,\n",
" \u001b[32m'0xbd7c5412'\u001b[0m: \u001b[32m'isEthWithdrawalFinalized'\u001b[0m,\n",
" \u001b[32m'0xc3bbd2d7'\u001b[0m: \u001b[32m'isFacetFreezable'\u001b[0m,\n",
" \u001b[32m'0xe81e0ba1'\u001b[0m: \u001b[32m'isFunctionFreezable'\u001b[0m,\n",
" \u001b[32m'0xfacd743b'\u001b[0m: \u001b[32m'isValidator'\u001b[0m,\n",
" \u001b[32m'0x9cd939e4'\u001b[0m: \u001b[32m'l2LogsRootHash'\u001b[0m,\n",
" \u001b[32m'0x56142d7a'\u001b[0m: \u001b[32m'priorityQueueFrontOperation'\u001b[0m,\n",
" \u001b[32m'0x74f4d30d'\u001b[0m: \u001b[32m'storedBlockHash'\u001b[0m\n",
" \u001b[1m}\u001b[0m\n",
"\u001b[1m}\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"diamond_storage = int(keccak(text=\"diamond.standard.diamond.storage\").hex(), 16) - 1\n",
"\n",
"# first we read addresses from the facets array at the offset 2\n",
"facets = read_array(address, diamond_storage + 2, item_size=20)\n",
"\n",
"# now we use them as the keys to read the facetToSelectors mapping\n",
"facet_keys = [to_bytes(to_int(x)) for x in facets]\n",
"\n",
"facet_to_selectors = read_mapping(address, diamond_storage + 1, facet_keys)\n",
"\n",
"selectors = {}\n",
"\n",
"# then we can read selectors for each facets from the FacetToSelectors.selectors\n",
"for item in facet_to_selectors:\n",
" key = item[\"key\"][-20:]\n",
" selectors[key] = read_array(address, item[\"pos\"], item_size=4)\n",
"\n",
"# now grab the abis of the contracts so we can show method names\n",
"contracts = {s: Contract(s) for s in selectors}\n",
"diamond = {\n",
" f'{contracts[s].contract_type.name} ({s.hex()})': {\n",
" f.hex(): contracts[s].contract_type.methods[f].name\n",
" for f in selectors[s] \n",
" }\n",
" for s in selectors\n",
"}\n",
"print(diamond)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment