LLM交易代理安全 是做什么的?
自主交易代理面临比普通LLM应用更严苛的威胁模型:一次提示注入或错误的工具调用路径可能直接导致资产损失。
何时使用
- 构建能够签名并发送交易的AI代理
- 审计交易机器人或链上执行助手
- 为代理设计钱包密钥管理方案
- 为LLM赋予订单下达、资产交换或金库操作的权限
工作原理
对防御进行分层。单一检查是不够的。应将提示卫生、支出策略、模拟、执行限制和钱包隔离视为独立的安全控制措施。
示例
将提示注入视为财务攻击
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"潜在的提示注入: {text[:100]}")
return text
不要盲目地将代币名称、配对标签、网络钩子或社交信息源注入到具有执行能力的提示中。
硬性支出限制
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"单笔交易 ${usd_amount} 超过最大值 ${MAX_SINGLE_TX_USD}")
daily = self._get_24h_spend()
if daily + usd_amount > MAX_DAILY_SPEND_USD:
raise SpendLimitError(f"每日限制: ${daily} + ${usd_amount} > ${MAX_DAILY_SPEND_USD}")
self._record_spend(usd_amount)
发送前模拟
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")
actual_out = decode_uint256(sim_result)
if actual_out < expected_min_out:
raise SlippageError(f"模拟结果: {actual_out} < {expected_min_out}")
signed = self.account.sign_transaction(tx)
return await self.w3.eth.send_raw_transaction(signed.raw_transaction)
断路器
class TradingCircuitBreaker:
MAX_CONSECUTIVE_LOSSES = 3
MAX_HOURLY_LOSS_PCT = 0.05
def check(self, portfolio_value: float) -> None:
if self.consecutive_losses >= self.MAX_CONSECUTIVE_LOSSES:
self.halt("连续亏损次数过多")
if self.hour_start_value <= 0:
self.halt("hour_start_value 无效")
return
hourly_pnl = (portfolio_value - self.hour_start_value) / self.hour_start_value
if hourly_pnl < -self.MAX_HOURLY_LOSS_PCT:
self.halt(f"小时损益 {hourly_pnl:.1%} 低于阈值")
钱包隔离
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 未设置")
account = Account.from_key(private_key)
使用专用热钱包,仅存放当前会话所需的资金。切勿让代理访问主金库钱包。
MEV与截止时间保护
import time
PRIVATE_RPC = "https://rpc.flashbots.net"
MAX_SLIPPAGE_BPS = {"stable": 10, "volatile": 50}
deadline = int(time.time()) + 60
预部署检查清单
- 外部数据在进入LLM上下文之前已进行消毒处理
- 支出限制独立于模型输出强制执行
- 交易在发送前已模拟
min_amount_out为必填项- 断路器在出现回撤或无效状态时停止交易
- 密钥来自环境变量或密钥管理器,绝不来自代码或日志
- 在适当情况下使用私有内存池或受保护的路由
- 滑点和截止时间根据具体策略设置
- 所有代理决策(不仅是成功发送)均记录审计日志