affaan-m/ECC · critical · SpendLimitError
Daily limit: ${daily} + ${usd_amount} > ${MAX_DAILY_SPEND_US
Error message
Daily limit: ${daily} + ${usd_amount} > ${MAX_DAILY_SPEND_USD} What it means
Second check in `SpendLimitGuard.check_and_record`: after the per-tx check passes, it sums the last 24h of spend (`_get_24h_spend`) and refuses if `daily + usd_amount > MAX_DAILY_SPEND_USD`. Fires when the new transaction would push the rolling daily total over $2000.
Source
Thrown at skills/llm-trading-agent-security/SKILL.md:67
### 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:
raise ValueError("min_amount_out is required before send")
actual_out = decode_uint256(sim_result)
if actual_out < expected_min_out:View on GitHub (pinned to 01e15490f0)
Solutions
- Confirm the daily cap is correct for mainnet; raise `MAX_DAILY_SPEND_USD` if the strategy legitimately needs it.
- Make `_record_spend` idempotent (key on tx hash) so retries do not inflate the rolling sum.
- Verify `_get_24h_spend` uses a correct UTC window and the same clock as `datetime.utcnow()`.
- Pause the strategy when nearing the cap; surface the remaining headroom to the operator.
Example fix
# before
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}")
# after — idempotent record, expose headroom
key = (tx_hash,) if tx_hash else None
daily = self._get_24h_spend()
headroom = MAX_DAILY_SPEND_USD - daily
if usd_amount > headroom:
raise SpendLimitError(f"Daily limit: headroom ${headroom}, requested ${usd_amount}") Defensive patterns
Strategy: validation
Validate before calling
def within_daily_cap(guard, usd: Decimal) -> bool:
return guard._get_24h_spend() + usd <= MAX_DAILY_SPEND_USD Type guard
null
Try / catch
try:
guard.check_and_record(usd_amount)
except SpendLimitError as e:
if 'Daily limit' in str(e):
schedule_retry_after_window_rolls()
raise Prevention
- Make `_record_spend` idempotent (key on tx hash) so retries do not double-count.
- Use UTC for the 24h window consistently.
- Surface remaining daily headroom to the operator and pause near the cap.
When it happens
Trigger: Several smaller (sub-$500) trades have accumulated near the $2000 daily ceiling and one more would cross it. Clock skew between `_get_24h_spend`'s window and now. Stuck retry loop re-records the same spend.
Common situations: Agent loops on a strategy and clusters trades; counter not idempotent so retries double-count; timezone handling in the 24h window makes the total drift; cap was set for testnet and not raised for mainnet.
Related errors
- Single tx ${usd_amount} exceeds max ${MAX_SINGLE_TX_USD}
- Simulation: {actual_out} < {expected_min_out}
- Potential prompt injection: {text[:100]}
- min_amount_out is required before send
- TRADING_WALLET_PRIVATE_KEY not set
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/481692e9d8d1277a.
Report an issue: GitHub.