{"record":{"id":"481692e9d8d1277a","repo":"affaan-m/ECC","slug":"daily-limit-daily-usd-amount-max-dail","errorCode":null,"errorMessage":"Daily limit: ${daily} + ${usd_amount} > ${MAX_DAILY_SPEND_USD}","messagePattern":"Daily limit: (.+?) \\+ (.+?) > (.+?)","errorType":"exception","errorClass":"SpendLimitError","httpStatus":null,"severity":"critical","filePath":"skills/llm-trading-agent-security/SKILL.md","lineNumber":67,"sourceCode":"### Hard spend limits\n\n```python\nfrom decimal import Decimal\n\nMAX_SINGLE_TX_USD = Decimal(\"500\")\nMAX_DAILY_SPEND_USD = Decimal(\"2000\")\n\nclass SpendLimitError(Exception):\n    pass\n\nclass SpendLimitGuard:\n    def check_and_record(self, usd_amount: Decimal) -> None:\n        if usd_amount > MAX_SINGLE_TX_USD:\n            raise SpendLimitError(f\"Single tx ${usd_amount} exceeds max ${MAX_SINGLE_TX_USD}\")\n\n        daily = self._get_24h_spend()\n        if daily + usd_amount > MAX_DAILY_SPEND_USD:\n            raise SpendLimitError(f\"Daily limit: ${daily} + ${usd_amount} > ${MAX_DAILY_SPEND_USD}\")\n\n        self._record_spend(usd_amount)\n```\n\n### Simulate before sending\n\n```python\nclass SlippageError(Exception):\n    pass\n\nasync def safe_execute(self, tx: dict, expected_min_out: int | None = None) -> str:\n    sim_result = await self.w3.eth.call(tx)\n\n    if expected_min_out is None:\n        raise ValueError(\"min_amount_out is required before send\")\n\n    actual_out = decode_uint256(sim_result)\n    if actual_out < expected_min_out:","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/skills/llm-trading-agent-security/SKILL.md#L49-L85","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\ndaily = self._get_24h_spend()\nif daily + usd_amount > MAX_DAILY_SPEND_USD:\n    raise SpendLimitError(f\"Daily limit: ${daily} + ${usd_amount} > ${MAX_DAILY_SPEND_USD}\")\n\n# after — idempotent record, expose headroom\nkey = (tx_hash,) if tx_hash else None\ndaily = self._get_24h_spend()\nheadroom = MAX_DAILY_SPEND_USD - daily\nif usd_amount > headroom:\n    raise SpendLimitError(f\"Daily limit: headroom ${headroom}, requested ${usd_amount}\")","handlingStrategy":"validation","validationCode":"def within_daily_cap(guard, usd: Decimal) -> bool:\n    return guard._get_24h_spend() + usd <= MAX_DAILY_SPEND_USD","typeGuard":"null","tryCatchPattern":"try:\n    guard.check_and_record(usd_amount)\nexcept SpendLimitError as e:\n    if 'Daily limit' in str(e):\n        schedule_retry_after_window_rolls()\n    raise","preventionTips":["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."],"tags":["web3","trading","spend-limits","security","agents"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}