import { type Address, type Hex, type PublicClient, toHex } from "viem"; /** * Discovered storage-slot indices for a single ERC20 token. Slot indices are * the small-integer base index used in the contract's `mapping(address => * uint256) balances` / `mapping(address => mapping(address => uint256)) * allowances` declaration. They are owner-/spender-agnostic — the concrete * storage slot is then derived cryptographically. * * Cache and reuse these across calls: they don't change for a deployed token. */ export type Erc20SlotHints = { /** Slot index for the `balances` mapping (base storage slot). */ balanceSlotIndex?: bigint; /** Slot index for the `allowance` mapping (outer base storage slot). */ allowanceSlotIndex?: bigint; }; export type SlotHints = Record; export type FetchSlotHintsOptions = { /** When `true`, do not probe for the balance slot. */ skipBalance?: boolean; /** When `true`, do not probe for the allowance slot. */ skipAllowance?: boolean; /** Spender for allowance probing. Defaults to the Permit2 address. */ allowanceSpender?: Address; /** Max sequential base slot to scan (0..N). Defaults to 20. */ maxSequentialSlot?: number; /** Extra non-sequential slot indices to try (e.g. known anomalies). */ extraSlotCandidates?: bigint[]; }; /** * Compute the storage slot of `balances[owner]` in a Solidity-style * `mapping(address => uint256)` at base slot `slotIndex`. */ export declare function computeBalanceSlot(owner: Address, slotIndex: bigint): Hex; /** * Compute the storage slot of `allowance[owner][spender]` in a Solidity-style * `mapping(address => mapping(address => uint256))` at base slot `slotIndex`. */ export declare function computeAllowanceSlot(owner: Address, spender: Address, slotIndex: bigint): Hex; /** * Probe a single ERC20 token to discover its `balances` and `allowance` slot * indices, by overriding sequential base-slot candidates and reading the * value back. * * Strategy is intentionally simpler than `eth_createAccessList`-based * discovery: most ERC20 layouts (OpenZeppelin, Solady, custom) use a small * integer base slot. Sequential probing from 0 hits the answer in 1–3 RPC * calls; access-list discovery costs an `eth_createAccessList` + per-candidate * probe and isn't supported by all proxies. * * Results are cached module-scope by `chainId:token` (slot indices are * owner-/spender-agnostic and immutable for a deployed token), so subsequent * calls for the same token short-circuit to a Map lookup. * * @example * ```ts * const hints = await fetchErc20SlotHints(client, token, { * allowanceSpender: permit2Address, * }) * // → { balanceSlotIndex: 0n, allowanceSlotIndex: 1n } * ``` */ export declare function fetchErc20SlotHints(client: PublicClient, token: Address, options?: FetchSlotHintsOptions): Promise; /** * Convenience batch wrapper for `fetchErc20SlotHints` over many tokens. * Caller-side parallelism is preserved (one `Promise.all` over the inputs); * the per-token cache means repeats are free. */ export declare function fetchErc20SlotHintsBatch(client: PublicClient, tokens: Address[], options?: FetchSlotHintsOptions): Promise; /** * Helper for callers who want to pre-seed the slot-hints cache from their own * persistence layer (e.g. localStorage). */ export declare function primeSlotHintsCache(chainId: number, hints: Record): void; /** Helper used by deriveStateOverrides to look up a hint without re-probing. */ export declare function getCachedSlotHints(chainId: number, token: Address): Erc20SlotHints | undefined; export { toHex }; //# sourceMappingURL=slotHints.d.ts.map