| name | llm-trading-agent-security |
| description | 지갑 또는 거래 권한을 가진 자율 트레이딩 에이전트를 위한 보안 패턴입니다. 프롬프트 인젝션, 지출 한도, 전송 전 시뮬레이션, 서킷 브레이커, MEV 보호, 키 처리를 다룹니다. |
| origin | ECC direct-port adaptation |
| version | 1.0.0 |
LLM Trading Agent Security
자율 트레이딩 에이전트는 일반 LLM 앱보다 위협 모델이 훨씬 가혹합니다. 인젝션이나 잘못된 도구 경로가 바로 자산 손실로 이어질 수 있습니다.
사용 시점
- 거래를 서명하고 전송하는 AI 에이전트를 만들 때
- 트레이딩 봇이나 온체인 실행 도우미를 감사할 때
- 에이전트용 지갑 키 관리를 설계할 때
- LLM에 주문 실행, 스왑, treasury 작업 권한을 줄 때
동작 방식
방어는 계층적으로 쌓습니다. 어느 하나의 체크만으로는 충분하지 않습니다. 프롬프트 위생, 지출 정책, 시뮬레이션, 실행 한도, 지갑 격리를 독립 제어로 취급합니다.
예시
프롬프트 인젝션을 금융 공격으로 취급
import re
INJECTION_PATTERNS = [
r'ignore (previous|all) instructions',
r'new (task|directive|instruction)',
r'system prompt',
r'send .{0,50} to 0x[0-9a-fA-F]{40}',
r'transfer .{0,50} to',
r'approve .{0,50} for',
]
def sanitize_onchain_data(text: str) -> str:
for pattern in INJECTION_PATTERNS:
if re.search(pattern, text, re.IGNORECASE):
raise ValueError(f"Potential prompt injection: {text[:100]}")
return text
토큰 이름, pair 라벨, webhook, 소셜 피드를 실행 권한이 있는 프롬프트에 그대로 주입하지 않습니다.
강한 지출 한도
from decimal import Decimal
MAX_SINGLE_TX_USD = Decimal("500")
MAX_DAILY_SPEND_USD = Decimal("2000")
class SpendLimitError(Exception):
pass
전송 전 시뮬레이션
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:
raise SlippageError(f"Simulation: {actual_out} < {expected_min_out}")
서킷 브레이커
class TradingCircuitBreaker:
MAX_CONSECUTIVE_LOSSES = 3
MAX_HOURLY_LOSS_PCT = 0.05
지갑 격리
import os
from eth_account import Account
private_key = os.environ.get("TRADING_WALLET_PRIVATE_KEY")
if not private_key:
raise EnvironmentError("TRADING_WALLET_PRIVATE_KEY not set")
account = Account.from_key(private_key)
세션에 필요한 자금만 넣은 전용 hot wallet을 사용합니다. 메인 treasury wallet을 직접 연결하지 않습니다.
MEV와 deadline 보호
import time
PRIVATE_RPC = "https://rpc.flashbots.net"
MAX_SLIPPAGE_BPS = {"stable": 10, "volatile": 50}
deadline = int(time.time()) + 60
배포 전 체크리스트
- 외부 데이터는 LLM 컨텍스트에 들어가기 전에 sanitize된다
- 지출 한도는 모델 출력과 독립적으로 강제된다
- 거래는 전송 전에 시뮬레이션된다
min_amount_out이 필수다
- drawdown이나 invalid state에서 circuit breaker가 멈춘다
- 키는 env 또는 secret manager에서 오며 코드나 로그에 없다
- 적절하면 private mempool 또는 protected routing을 쓴다
- slippage와 deadline은 전략별로 설정된다
- 성공한 전송뿐 아니라 모든 agent decision이 audit log에 남는다