import type { Provider } from "ethers"; import { getAddress, isAddress } from "ethers"; export const ERC1967_IMPLEMENTATION_SLOT = "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; export const ERC1967_ADMIN_SLOT = "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"; const getERC1967Address = async ( provider: Pick, proxyAddress: string, slot: string, label: string, ): Promise => { if (!isAddress(proxyAddress)) { throw new Error("Invalid proxy candidate address: " + proxyAddress); } const storage = await provider.getStorage(proxyAddress, slot); if (!/^0x[0-9a-fA-F]{64}$/.test(storage)) { throw new Error(`Invalid ERC1967 ${label} slot value for ${proxyAddress}`); } const storedAddress = "0x" + storage.slice(-40); if (storedAddress.toLowerCase() === "0x" + "00".repeat(20)) { return undefined; } return getAddress(storedAddress); }; export const getERC1967Implementation = async ( provider: Pick, proxyAddress: string, ): Promise => { return getERC1967Address( provider, proxyAddress, ERC1967_IMPLEMENTATION_SLOT, "implementation", ); }; export const getERC1967Admin = async ( provider: Pick, proxyAddress: string, ): Promise => { return getERC1967Address(provider, proxyAddress, ERC1967_ADMIN_SLOT, "admin"); };