import { type InterfaceAbi, type JsonRpcProvider } from 'ethers'; /** The revert shapes {@link decodeRevertData} distinguishes. */ export type IRevertKind = 'error-string' | 'panic' | 'custom' | 'unknown'; /** Result of decoding a raw revert blob with {@link decodeRevertData}. */ export interface IDecodedRevert { /** * `'error-string'` for `Error(string)` (a `require` message), `'panic'` for * compiler-inserted `Panic(uint256)`, `'custom'` when the selector matched a * corpus (or caller-supplied) custom error, `'unknown'` when nothing matched. */ kind: IRevertKind; /** The 4-byte selector (`0x` + 8 hex chars), always present — even for `'unknown'` so callers can 4byte-lookup it. */ selector: string; /** Error name (e.g. `'ERC20InsufficientBalance'`, `'Error'`, `'Panic'`). Absent for `'unknown'`. */ name?: string; /** Full error signature (e.g. `'ERC20InsufficientBalance(address,uint256,uint256)'`). Absent for `'unknown'`. */ signature?: string; /** * Decoded arguments in declaration order (`bigint` for integers, checksummed * strings for addresses). Absent when the selector matched but the argument * bytes were truncated or malformed — see {@link IDecodedRevert.reason}. */ args?: unknown[]; /** * Human-readable summary when one exists: the `Error(string)` message, the * named `Panic` code, or a note that the argument data was truncated. */ reason?: string; } /** * Decode a raw EVM revert blob into a named error with arguments. * * Pure and offline — no RPC calls, no network. Handles the three revert * shapes the EVM produces: * * 1. `Error(string)` (`0x08c379a0`) — a `require`/`revert` with a message. * 2. `Panic(uint256)` (`0x4e487b71`) — compiler-inserted checks, with the * numeric code translated to its documented meaning (overflow, division by * zero, …). * 3. Custom errors — matched against a built-in corpus of OpenZeppelin * ERC-6093 / SafeERC20 / ERC4626 / Ownable / Pausable errors, LayerZero V2 * OApp/OFT errors, and every `error` fragment in the vault ABIs the SDK * ships (tokenized vaults, SwapRouter, lending pools, …). Callers can * extend the corpus per call via `opts.extraAbis`, which take precedence. * * Truncated input degrades gracefully: when the 4-byte selector matches a * known error but the argument bytes are incomplete (e.g. an alert pipeline * clipped the hex), the result still carries `kind: 'custom'`, `name`, and * `signature`, with `args` omitted and `reason` explaining the truncation. * * @param data - The revert blob as a `0x`-prefixed hex string (the `data` * field of an ethers v6 `CALL_EXCEPTION`). Anything shorter than a 4-byte * selector, or not hex at all, yields `kind: 'unknown'`. * @param opts - Optional settings. * @param opts.extraAbis - Additional ABIs whose `error` fragments are checked * before the built-in corpus. * @returns The decoded revert. Never throws; unrecognized selectors return * `kind: 'unknown'` with the selector preserved so callers can look it up * via {@link lookupSelector}. * * @example * ```ts * const decoded = decodeRevertData('0xe450d38c…'); * // { * // kind: 'custom', * // selector: '0xe450d38c', * // name: 'ERC20InsufficientBalance', * // signature: 'ERC20InsufficientBalance(address,uint256,uint256)', * // args: ['0x9281…', 487711967n, 1261711967n], * // } * ``` */ export declare function decodeRevertData(data: string, opts?: { extraAbis?: InterfaceAbi[]; }): IDecodedRevert; /** Fields recovered from an ethers v6 error string by {@link extractRevertFromErrorText}. */ export interface IExtractedRevertContext { /** The revert blob from the top-level `data="0x…"` field, when present. */ revertData?: string; /** The failed operation from `action="…"` (e.g. `'estimateGas'`, `'call'`). */ action?: string; /** The ethers error code from `code=…` (e.g. `'CALL_EXCEPTION'`). */ code?: string; /** The embedded `transaction={ … }` fields that survived, when any did. */ tx?: { from?: string; to?: string; data?: string; }; } /** * Parse an ethers v6 error *string* and recover the machine-readable fields * embedded in it. * * ethers v6 serializes rich error objects into a single message of the shape * `… (action="estimateGas", data="0x…", reason=…, transaction={ "data": * "0x…", "from": "0x…", "to": "0x…" }, …, code=CALL_EXCEPTION, version=…)` — * exactly what error-alert pipelines end up carrying once the original error * object is stringified. This helper regex-extracts the revert `data`, the * `action`, the `code`, and the embedded transaction fields. * * Pure and offline. Tolerant of truncation: alert transports often cap * message length mid-hex, so every field is matched without requiring its * closing quote and the result simply omits whatever did not survive. * * @param text - The error text to parse (an ethers v6 `error.message`, or a * log/alert line that embeds one). * @returns The recovered fields; an empty object when nothing matched. Never * throws. * * @example * ```ts * const ctx = extractRevertFromErrorText(alertErrorLine); * if (ctx.revertData) console.log(decodeRevertData(ctx.revertData)); * ``` */ export declare function extractRevertFromErrorText(text: string): IExtractedRevertContext; /** * Look up candidate signatures for an unknown 4-byte selector against public * signature databases. * * Network helper — queries [openchain.xyz](https://openchain.xyz) first and * falls back to [4byte.directory](https://www.4byte.directory). Kept separate * from {@link decodeRevertData} so the core decode path stays offline. * Worst case 2 HTTPS requests. * * @param selector - The selector to look up. Longer hex (a full revert blob) * is accepted; only the first 4 bytes are used. * @returns Candidate signatures (e.g. `['ERC20InsufficientBalance(address,uint256,uint256)']`), * most-likely first. Empty when the input is not hex, no database knows the * selector, or both databases were unreachable. Never throws. * * @example * ```ts * const candidates = await lookupSelector('0xe450d38c'); * ``` */ export declare function lookupSelector(selector: string): Promise; /** Result of an {@link simulateCall} `eth_call` replay. */ export type ISimulateCallResult = { /** The call succeeded. */ ok: true; /** The raw return data of the call, `0x`-prefixed. */ returnData: string; } | { /** The call reverted or the node rejected it. */ ok: false; /** Fresh, untruncated revert blob when the node returned one. */ revertData?: string; /** {@link decodeRevertData} applied to `revertData`, when present. */ decoded?: IDecodedRevert; /** The underlying error message, for failures without revert data. */ errorMessage: string; }; /** * Replay a call via `eth_call` and decode the revert when it fails. * * The primary use is re-executing a transaction that failed at `estimateGas` * (so no transaction hash ever existed): the node returns the *full* revert * blob, which both confirms the failure still reproduces and recovers * untruncated revert data even when the original error text was clipped in * transit. Passing a historical `blockTag` replays against archival state * (requires an archive-capable RPC). * * Exactly 1 RPC call (`eth_call`). * * @param provider - A connected `JsonRpcProvider` for the target chain, e.g. * from `createProvider(rpcUrl, chainId)`. Note that some listed public RPCs * reject keyless `eth_call` — supply a working endpoint via the SDK's RPC * precedence (constructor `providers` map / `AUGUST_RPC_` env). * @param tx - The call to replay: `to` and `data` are required, `from` * matters whenever the target checks `msg.sender`. * @param blockTag - Optional block to execute against (`'latest'` by * default; a number or hex tag replays historical state). * @param opts - Optional settings forwarded to {@link decodeRevertData}. * @param opts.extraAbis - Additional ABIs checked before the built-in corpus * when decoding a revert. * @returns `{ ok: true, returnData }` on success; on failure `{ ok: false }` * with the fresh `revertData` and its decode when the node supplied one. * Never throws on revert — only on programmer error (e.g. no provider). * * @example * ```ts * const result = await simulateCall(provider, { * from: eoa, * to: vault, * data: calldata, * }); * if (!result.ok && result.decoded) console.log(result.decoded.signature); * ``` */ export declare function simulateCall(provider: JsonRpcProvider, tx: { from?: string; to: string; data: string; }, blockTag?: string | number, opts?: { extraAbis?: InterfaceAbi[]; }): Promise; /** Snapshot of a holder's token state returned by {@link readTokenState}. */ export interface ITokenState { /** Token symbol, when the contract implements `symbol()`. */ symbol?: string; /** Token decimals, when the contract implements `decimals()`. */ decimals?: number; /** The holder's raw balance in base units, when `balanceOf` resolved. */ balance?: bigint; /** Raw allowance from holder to `spender`, only probed when `spender` was given. */ allowance?: bigint; /** * Whether the holder is frozen/blacklisted by the token issuer, from the * first compliance getter the token implements (`isAccountFrozen` — Agora * AUSD, `isBlacklisted` — USDC-style, `isFrozen`). `undefined` when the * token exposes none of them — which is NOT evidence the holder is clear, * only that the token has no recognized compliance getter. */ frozen?: boolean; } /** * Read a bounded, fixed set of token-state probes for a holder — the exact * facts needed to explain a failed deposit/transfer: what the token is, what * the holder has, what the spender may pull, and whether the issuer froze the * holder. * * The probe set is deliberately fixed (no arbitrary calldata): `symbol()`, * `decimals()`, `balanceOf(holder)`, `allowance(holder, spender)` when a * spender is given, and the compliance getters tried in order — * `isAccountFrozen(address)` (Agora AUSD, selector `0xe816d97f`), * `isBlacklisted(address)` (USDC-style), `isFrozen(address)`. Probes the * token does not implement resolve to `undefined`; this function never * throws. * * Worst case 7 RPC calls (4 base probes + 3 compliance getters), batched by * the provider where supported. * * @param provider - A connected `JsonRpcProvider` for the token's chain. * @param token - The ERC-20 token contract address. * @param holder - The account whose balance/compliance state to read. * @param spender - Optional spender for the `allowance(holder, spender)` * probe (e.g. the vault a deposit approves). * @returns The token state with every unresolvable probe as `undefined`. * * @example * ```ts * const state = await readTokenState(provider, ausd, eoa, vault); * // { symbol: 'AUSD', decimals: 6, balance: 487711967n, allowance: 0n, frozen: false } * ``` */ export declare function readTokenState(provider: JsonRpcProvider, token: string, holder: string, spender?: string): Promise;