degenbot.exceptions =================== .. py:module:: degenbot.exceptions .. autoapi-nested-parse:: Exception classes for degenbot. ``degenbot.exceptions`` is the single documented import home for every FFI-raised exception. The FFI-raised types (the ``PoolRegistrationError`` fairly, the verifier errors) are **direct aliases** of the ``degenbot._ffi`` pyclasses — never Python subclasses: Rust raises the pyclass instances, so ``except`` / ``isinstance`` matching requires the exact same class object. The identity contract is pinned by ``tests/ffi/test_companion_alias_identity.py``. Submodules ---------- .. toctree:: :maxdepth: 1 /autoapi/degenbot/exceptions/arbitrage/index /autoapi/degenbot/exceptions/base/index /autoapi/degenbot/exceptions/infrastructure/index /autoapi/degenbot/exceptions/pool/index /autoapi/degenbot/exceptions/rpc/index /autoapi/degenbot/exceptions/verification/index Package Contents ---------------- .. py:class:: ArbCalculationError Bases: :py:obj:`ArbitrageError` Raised when an arbitrage calculation fails. .. py:class:: ArbitrageError Bases: :py:obj:`degenbot.exceptions.base.DegenbotError` Exception raised inside arbitrage helpers. .. py:class:: DirectionResolutionError Bases: :py:obj:`ArbitrageError` A discovered path's hop directions could not be resolved to a closed token cycle. The pathfinder contract guarantees every yielded path starts and ends at one of the requested boundary tokens ({WETH, native}), so a failure here is an invariant violation between the DB subgraph edges and the constructed pool objects (e.g. a pool built with different token0/token1 than the subgraph edge used) — a bug, not a skippable condition. .. py:class:: DuplicatePoolError(*, pool: str) Bases: :py:obj:`PathRejectedError` The same pool appears more than once in the path. A degenerate, non-executable cycle. V2/V3 pools are keyed by address; V4 pools by ``pool_id`` hex. ``pool`` is the duplicated pool's identity key. .. py:attribute:: pool .. py:class:: HopCountExceededError(*, hop_count: int, max_hops: int) Bases: :py:obj:`PathRejectedError` The path exceeds the configured maximum hop count. .. py:attribute:: hop_count .. py:attribute:: max_hops .. py:class:: HopCountInsufficientError(*, hop_count: int, min_hops: int) Bases: :py:obj:`PathRejectedError` The path is below the configured minimum hop count. .. py:attribute:: hop_count .. py:attribute:: min_hops .. py:class:: IncompatiblePoolInvariant Bases: :py:obj:`ArbitrageError` Raised when a pool's invariant type is not supported for. arbitrage path construction (e.g. Aerodrome stable pools). .. py:class:: InsufficientLiquidityError(*, liquidity: int, min_liquidity: int) Bases: :py:obj:`PathRejectedError` A pool's liquidity proxy is below the configured minimum. ``liquidity`` is the value returned by the caller-supplied ``liquidity_of`` extractor (the library does not encode pool-type-specific liquidity math). .. py:attribute:: liquidity .. py:attribute:: min_liquidity .. py:class:: InvalidForwardAmount Bases: :py:obj:`ArbitrageError` InvalidForwardAmount class. .. py:class:: InvalidSwapPathError Bases: :py:obj:`ArbitrageError` Raised in arbitrage helper constructors when the provided path is invalid. .. py:class:: NoLiquidity Bases: :py:obj:`ArbitrageError` Raised if a pool has no liquidity for the requested operation. .. py:class:: NoSolverSolution(message: str = 'Solver failed to converge on a solution.') Bases: :py:obj:`ArbitrageError` NoSolverSolution class. .. py:attribute:: message :value: 'Solver failed to converge on a solution.' .. py:class:: OptimizationError(message: str, *, iterations: int = 0, method: str | None = None) Bases: :py:obj:`ArbitrageError` Raised when a solver fails to find a profitable solution,. fails to converge, or receives invalid inputs. .. attribute:: message Human-readable error message explaining why optimization failed. :type: str .. attribute:: iterations Number of iterations completed before failure (if applicable). :type: int .. attribute:: method The solver method that was attempted (if applicable). :type: str | None .. py:attribute:: message .. py:attribute:: iterations :value: 0 .. py:attribute:: method :value: None .. py:class:: PathRejectedError Bases: :py:obj:`ArbitrageError` A path candidate was rejected by a path-composition policy predicate. Policy rejection is distinct from the Rust core's pool *admission* floor (``HookedPoolRejectedError`` / ``DynamicFeePoolRejectedError``, which subclass ``ValueError``). Policy rejects by deployment rule (token denylist/allowlist, hop-count, min-liquidity, duplicate-pool); admission rejects by correctness floor. Callers classify by type so the two hierarchies (``ArbitrageError`` vs ``ValueError``) stay separable. .. py:class:: RateOfExchangeBelowMinimum(rate: fractions.Fraction) Bases: :py:obj:`ArbitrageError` The rate of exchange for the path is below the minimum. .. py:attribute:: rate .. py:class:: TokenDenylistedError(*, token: str) Bases: :py:obj:`PathRejectedError` An intermediate or profit token is not permitted by the policy. Covers both denylist membership and allowlist absence. ``token`` is the checksummed offending token address. .. py:attribute:: token .. py:class:: Unprofitable Bases: :py:obj:`ArbitrageError` Unprofitable class. .. py:exception:: DegenbotError(*, message: str | None = None) Bases: :py:obj:`Exception` Base exception used as the parent class for all exceptions raised by this package. Calling code should catch `DegenbotError` and derived classes separately before general exceptions, e.g.: ``` try: degenbot.some_function() except SpecificDegenbotError: ... # handle a specific exception except DegenbotError: ... # handle non-specific degenbot exception except Exception: ... # handle exceptions raised by 3rd party dependencies or Python built-ins ``` An optional string-formatted message may be attached to the exception and retrieved by accessing the `.message` attribute. .. py:attribute:: message :type: str | None :value: None .. py:exception:: DegenbotTypeError(*, message: str | None = None) Bases: :py:obj:`DegenbotError` DegenbotTypeError error. .. py:exception:: DegenbotValueError(*, message: str | None = None) Bases: :py:obj:`DegenbotError` DegenbotValueError error. .. py:exception:: AnvilError(method: str, error: str) Bases: :py:obj:`degenbot.exceptions.base.DegenbotError` Raised on errors resulting from failed calls to Anvil via JSON-RPC. This exception is specifically for errors that occur when making RPC calls to an Anvil instance, such as invalid method calls, parameter errors, or other Anvil-specific failures. .. py:attribute:: method .. py:attribute:: error .. py:exception:: BackupExists(path: pathlib.Path) Bases: :py:obj:`degenbot.exceptions.base.DegenbotError` Raised by `degenbot database backup` if a file exists at the target path. .. py:attribute:: path .. py:exception:: Erc20TokenError(*, message: str | None = None) Bases: :py:obj:`degenbot.exceptions.base.DegenbotError` Exception raised inside ERC-20 token helpers. .. py:exception:: NoPriceOracle Bases: :py:obj:`Erc20TokenError` Raised when `.price` is called on a token without a price oracle. .. py:class:: AddressMismatch Bases: :py:obj:`LiquidityPoolError` The expected pool address does not match the provided address. .. py:class:: BrokenPool Bases: :py:obj:`LiquidityPoolError` BrokenPool class. .. py:class:: CurveError Bases: :py:obj:`degenbot.exceptions.base.DegenbotError` Base exception for Curve pool errors. .. py:class:: EVMRevertError(error: str | None = None) Bases: :py:obj:`degenbot.exceptions.base.DegenbotError` Raised when a simulated EVM contract operation would revert. .. py:attribute:: error :value: None .. py:class:: ExternalUpdateError Bases: :py:obj:`LiquidityPoolError` Raised when an external update does not pass sanity checks. .. py:class:: HookedPoolResult(amount_in: int, amount_out: int, hooks: set[degenbot.uniswap.v4_liquidity_pool.Hooks]) Bases: :py:obj:`PossibleInaccurateResult` Raised when a V4 pool has active hooks that may mutate the swap result. The pool's ``beforeSwap`` / ``afterSwap`` hooks can modify amounts or revert, so the pure-math result may differ from what the contract returns. The set of conflicting hooks is available on the ``hooks`` attribute. .. py:attribute:: hooks .. py:class:: IncompleteSwap(amount_in: int, amount_out: int) Bases: :py:obj:`LiquidityPoolError` Raised if a swap calculation would not consume the input or deliver the requested output. .. py:attribute:: amount_in .. py:attribute:: amount_out .. py:class:: InvalidSwapInputAmount Bases: :py:obj:`LiquidityPoolError` InvalidSwapInputAmount class. .. py:class:: InvalidUint256 Bases: :py:obj:`EVMRevertError` InvalidUint256 class. .. py:class:: LateUpdateError Bases: :py:obj:`LiquidityPoolError` Raised when an automatic update is attempted at a block prior to the last recorded update. .. py:class:: LiquidityMapWordMissing(word: int) Bases: :py:obj:`LiquidityPoolError` A word bitmap is not included in the liquidity map. .. py:attribute:: word .. py:class:: LiquidityPoolError Bases: :py:obj:`degenbot.exceptions.base.DegenbotError` Exception raised inside liquidity pool helpers. .. py:class:: MissingCurveData(pool_address: str, data_type: str, message: str) Bases: :py:obj:`CurveError` Raised when on-chain data is needed but no fetcher is available. .. py:attribute:: pool_address .. py:attribute:: data_type .. py:class:: NoPoolStateAvailable(block: degenbot.types.aliases.BlockNumber) Bases: :py:obj:`LiquidityPoolError` Raised when a previous pool state is not available. This can occur, e.g. if a pool was created in a block at or after a re-organization. .. py:class:: PoolCreationFailed Bases: :py:obj:`TrackerError` PoolCreationFailed class. .. py:class:: PoolNotAssociated(pool_address: str) Bases: :py:obj:`TrackerError` Raised by a pool tracker if a requested pool address is not associated with the DEX. .. py:class:: PossibleInaccurateResult(amount_in: int, amount_out: int, *, message: str) Bases: :py:obj:`LiquidityPoolError` Raised when a swap calculation may not match the on-chain result. The computed ``amount_in`` and ``amount_out`` are available on the exception so callers can inspect or use the approximate values after explicitly catching this exception. Subclasses add domain-specific context (hooks, stale rates, etc.). .. py:attribute:: amount_in .. py:attribute:: amount_out .. py:class:: StaleRateResult(amount_in: int, amount_out: int) Bases: :py:obj:`PossibleInaccurateResult` Raised when a Balancer ComposableStablePool's rate cache is stale. ComposableStablePools with time-varying rates (e.g. bb-a-* yield tokens) cache rates in ``_tokenRateCaches`` and refresh them before each swap via ``_beforeSwapJoinExit()``. Without a live ``BalancerRateProvider``, the pool uses construction-time rates that become stale as blocks pass. The computed amounts are available but may not match on-chain execution. .. py:class:: TrackerAlreadyInitialized Bases: :py:obj:`TrackerError` Raised by a pool tracker if a caller attempts to create from a known factory address. .. py:class:: TrackerError Bases: :py:obj:`degenbot.exceptions.base.DegenbotError` Exception raised inside pool tracker helpers. .. py:class:: UnknownPool(pool: degenbot.types.chain.ChecksummedAddress) Bases: :py:obj:`LiquidityPoolError` Raised when an update is provided for a pool not in the snapshot. Such updates can lead to inconsistent state because the pool state prior to the update is unknown. .. py:class:: UnknownPoolId(pool_id: bytes | str) Bases: :py:obj:`LiquidityPoolError` Raised when an update is provided for a pool ID not in the snapshot. Such updates can lead to inconsistent state because the pool state prior to the update is unknown. .. py:class:: ContractLogicError(message: str = '') Bases: :py:obj:`RpcError` An ``eth_call`` execution revert reported by the provider. The degenbot-owned equivalent of ``web3.exceptions.ContractLogicError``. Raised at the provider adapter seam (see :func:`degenbot.provider.alloy_errors.alloy_revert_error`) so probe sites catch one type regardless of backend. Constructed with a positional revert message (mirroring the web3 type's constructor) so call sites can write ``ContractLogicError("... reverted") `` and ``str(exc)`` returns that message. .. py:attribute:: message :value: None .. py:class:: RpcError Bases: :py:obj:`degenbot.exceptions.base.DegenbotError` Base for provider/RPC-layer failures. The degenbot-owned equivalent of ``web3.exceptions.Web3Exception``: the broad base a caller can catch to mean "an RPC call failed for some reason." Probe sites catch this instead of backend-specific native types, so they remain backend-agnostic. .. py:class:: TransactionNotFound Bases: :py:obj:`RpcError` A transaction hash the provider could not find. The degenbot-owned equivalent of ``web3.exceptions.TransactionNotFound``. Raised by the provider adapter seam when a receipt lookup misses.