affaan-m/ECC · critical · SpendLimitError

Single tx ${usd_amount} exceeds max ${MAX_SINGLE_TX_USD}

Error message

Single tx ${usd_amount} exceeds max ${MAX_SINGLE_TX_USD}

What it means

`SpendLimitGuard.check_and_record` enforces a hard per-transaction USD cap (`MAX_SINGLE_TX_USD = Decimal('500')`). If `usd_amount > MAX_SINGLE_TX_USD` it raises `SpendLimitError(f"Single tx ${usd_amount} exceeds max ${MAX_SINGLE_TX_USD}")` before consulting the daily counter. Decimals are used (not float) to avoid rounding on money.

Source

Thrown at skills/llm-trading-agent-security/SKILL.md:63

```

Do not blindly inject token names, pair labels, webhooks, or social feeds into an execution-capable prompt.

### Hard spend limits

```python
from decimal import Decimal

MAX_SINGLE_TX_USD = Decimal("500")
MAX_DAILY_SPEND_USD = Decimal("2000")

class SpendLimitError(Exception):
    pass

class SpendLimitGuard:
    def check_and_record(self, usd_amount: Decimal) -> None:
        if usd_amount > MAX_SINGLE_TX_USD:
            raise SpendLimitError(f"Single tx ${usd_amount} exceeds max ${MAX_SINGLE_TX_USD}")

        daily = self._get_24h_spend()
        if daily + usd_amount > MAX_DAILY_SPEND_USD:
            raise SpendLimitError(f"Daily limit: ${daily} + ${usd_amount} > ${MAX_DAILY_SPEND_USD}")

        self._record_spend(usd_amount)
```

### Simulate before sending

```python
class SlippageError(Exception):
    pass

async def safe_execute(self, tx: dict, expected_min_out: int | None = None) -> str:
    sim_result = await self.w3.eth.call(tx)

    if expected_min_out is None:

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Confirm the cap should be raised — if so, update `MAX_SINGLE_TX_USD` and redeploy, keeping it as `Decimal`.
  2. Verify the USD conversion: oracle price, token decimals, and amount units (base units vs human units).
  3. If the trade is legitimate but large, split it across multiple sub-cap transactions (and let `check_and_record` track each).
  4. Make sure `usd_amount` is a `Decimal`, not `float` — float comparison on money is a defect.

Example fix

# before
if usd_amount > MAX_SINGLE_TX_USD:
    raise SpendLimitError(f"Single tx ${usd_amount} exceeds max ${MAX_SINGLE_TX_USD}")

# after — assert Decimal, contextual message
from decimal import Decimal, InvalidOperation
if not isinstance(usd_amount, Decimal):
    raise TypeError("usd_amount must be Decimal")
if usd_amount > MAX_SINGLE_TX_USD:
    raise SpendLimitError(
        f"Single tx ${usd_amount} exceeds max ${MAX_SINGLE_TX_USD}; "
        f"split into <=${MAX_SINGLE_TX_USD} chunks"
    )
Defensive patterns

Strategy: validation

Validate before calling

from decimal import Decimal
def within_single_cap(usd: Decimal) -> bool:
    return isinstance(usd, Decimal) and usd <= MAX_SINGLE_TX_USD

Type guard

from decimal import Decimal
import numbers
def is_usd_amount(x) -> bool:
    return isinstance(x, Decimal) and x > 0

Try / catch

try:
    guard.check_and_record(usd_amount)
except SpendLimitError as e:
    log.warning("single-tx cap hit: %s", e)
    split_or_abort(usd_amount)

Prevention

When it happens

Trigger: The agent constructs a swap/transfer whose USD value exceeds $500 (e.g. a large DEX trade, a bridge deposit). The guard runs before signing and aborts.

Common situations: Configured cap is too low for the intended strategy; user changed `MAX_SINGLE_TX_USD` in one place but not the other; price oracle returned a USD value inflated by a stale feed; agent miscalculated notional (decimals of the token).

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/ae037c0241120b59. Report an issue: GitHub.