> For the complete documentation index, see [llms.txt](https://gotts.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://gotts.gitbook.io/docs/gotts-safe-mcp-server/mcp-server/09-safety.md).

# Safety Architecture

> **Package**: `packages/safe/` | **Prerequisites**: [02-architecture.md](/docs/gotts-safe-mcp-server/mcp-server/02-architecture.md)
>
> 15-layer defense-in-depth safety system. For the agent-level safety perspective, see [agents/11-safety.md](/docs/agents/agents/11-safety.md).

***

## Overview

### Design Principle

Safety is **defense in depth**. Multiple independent layers, any one of which can prevent fund loss. The system is designed to catch LLM hallucinations (wrong addresses, wrong amounts, wrong chains) before they become irreversible on-chain operations.

### Extended Safety Model (15 Layers)

The core MCP server implements a 7-step safety pipeline (described below). The full system extends to a 15-layer model across the MCP server, agents, vault, and proxy packages. See [shared/safety-layers.md](/docs/prd-shared/safety-layers.md) for the **canonical layer definitions, scope matrix, and TEE limitations**. See [agents/11-safety.md](/docs/agents/agents/11-safety.md) for the full 15-layer table.

The core MCP server implements **layers 1-4, 6, 8-10, 13-15**. Layers 5 and 7 are on-chain enforcement. Layer 12 (Order Flow Intelligence) is provided by research agents.

**ERC-7579 SmartSession**: Layer 1 now includes session key delegation via the SmartSession module (Rhinestone/Biconomy). Agents receive scoped session keys with SpendingLimitHook, ColdStorageHook, and AllowedTargetsHook constraints, mapping to ERC-8004 reputation tiers. See [vault/10-safety.md](/docs/gotts-vaults/vault/10-safety.md) for tier-to-scope mapping.

### Safety Pipeline

Every write operation (swap, LP, approval) passes through this pipeline in order. If any step rejects, the operation is aborted and a structured error is returned to the agent.

```
Agent Request
     │
     ▼
┌─── Step 1: Token Allowlist ────────────────────────────────────┐
│ Are all tokens in this operation on the configured allowlist?  │
│ Reject if any token is not allowed.                           │
└────────────┬───────────────────────────────────────────────────┘
             │ pass
             ▼
┌─── Step 2: Spending Limit ─────────────────────────────────────┐
│ Does this operation's USD value exceed the per-tx limit?       │
│ Would it push the daily total past the daily limit?            │
│ Reject if either limit would be exceeded.                     │
└────────────┬───────────────────────────────────────────────────┘
             │ pass
             ▼
┌─── Step 3: Rate Limiter ───────────────────────────────────────┐
│ Has the agent exceeded the max operations per time window?     │
│ Reject if rate limit is exceeded.                             │
└────────────┬───────────────────────────────────────────────────┘
             │ pass
             ▼
┌─── Step 4: Balance Circuit Breaker ────────────────────────────┐
│ Is the wallet's native balance above the minimum threshold?    │
│ Reject all operations if balance is below floor.              │
└────────────┬───────────────────────────────────────────────────┘
             │ pass
             ▼
┌─── Step 5: Slippage Guard ─────────────────────────────────────┐
│ Is the quoted slippage within the configured maximum?          │
│ Reject if slippage exceeds cap.                               │
└────────────┬───────────────────────────────────────────────────┘
             │ pass
             ▼
┌─── Step 6: Pre-flight Simulation ──────────────────────────────┐
│ Execute the exact calldata via eth_call against latest block.  │
│ Decode the result. Compare simulated output with quoted output.│
│ Reject if:                                                    │
│   - Simulation reverts                                        │
│   - Simulated output diverges from quote by > tolerance (2%)  │
│   - Unexpected state changes detected                         │
└────────────┬───────────────────────────────────────────────────┘
             │ pass
             ▼
┌─── Step 7: Nonce Manager ──────────────────────────────────────┐
│ Assign the next available nonce.                              │
│ Check no identical pending tx exists (dedup LLM retries).     │
│ Record the nonce as "pending."                                │
└────────────┬───────────────────────────────────────────────────┘
             │ pass
             ▼
      Sign and Broadcast
```

### Layer Details

#### 6.1 Token Allowlist

**Purpose**: Prevent agents from interacting with scam tokens, honeypots, or tokens the operator has not vetted.

**Implementation**:

* Default: Uniswap's [default token list](https://tokenlists.org/) (700+ verified tokens across chains)
* Configurable: Operator can provide a custom allowlist via config file or env var
* Modes:
  * `strict`: Only allowlisted tokens permitted. Any unknown token is rejected.
  * `warn`: Unknown tokens trigger a warning in the response but are not blocked. The agent can proceed.
  * `off`: No allowlist enforcement (not recommended for production).

**Config**:

```json
{
  "safety": {
    "tokenAllowlist": {
      "mode": "strict",
      "source": "uniswap-default",
      "additionalTokens": [
        { "address": "0x1234...", "chain": 1, "symbol": "CUSTOM" }
      ],
      "blockedTokens": [
        { "address": "0xSCAM...", "chain": 1, "reason": "Known honeypot" }
      ]
    }
  }
}
```

#### 6.2 Spending Limits

**Purpose**: Cap financial exposure per transaction and per day. Prevents a single hallucinated amount from draining the wallet.

**Implementation**:

* USD-denominated limits (converted from token amounts using current prices)
* Two independent limits: per-transaction and per-rolling-24-hours
* Daily tracker resets on a rolling 24-hour window
* Amounts are calculated at the time of the operation using the quoted price

**Config**:

```json
{
  "safety": {
    "spendingLimits": {
      "perTransactionUsd": 10000,
      "perSessionUsd": 50000,
      "dailyUsd": 100000,
      "currency": "USD"
    }
  }
}
```

#### 6.3 Rate Limiter

**Purpose**: Prevent runaway loops where an LLM repeatedly calls write operations.

**Implementation**:

* Token bucket algorithm
* Configurable window size and max operations
* Separate counters for different operation types (optional): trades, LP operations, approvals

**Config**:

```json
{
  "safety": {
    "rateLimit": {
      "maxOperationsPerWindow": 20,
      "windowSeconds": 3600,
      "perType": {
        "swap": { "maxPerWindow": 10 },
        "liquidity": { "maxPerWindow": 5 },
        "approval": { "maxPerWindow": 10 }
      }
    }
  }
}
```

#### 6.4 Balance Circuit Breaker

**Purpose**: Halt all operations if the wallet's native token balance drops below a threshold. Prevents the agent from spending its last gas money.

**Implementation**:

* Checked before every write operation
* Checks native balance on the target chain
* If below threshold, ALL write operations are rejected (not just the current one) until balance is restored

**Config**:

```json
{
  "safety": {
    "balanceCircuitBreaker": {
      "enabled": true,
      "thresholds": {
        "ethereum": "0.01",
        "base": "0.001",
        "arbitrum": "0.001"
      },
      "defaultThreshold": "0.005"
    }
  }
}
```

#### 6.5 Slippage Protection

**Purpose**: Reject trades with excessive slippage that could result in poor execution.

**Implementation**:

* Compares quoted slippage against configured maximum
* Applied to both the agent-specified slippage tolerance and the actual quoted price impact
* Two independent checks: (a) agent-requested slippage tolerance is within max, (b) the quote's price impact is within max

**Config**:

```json
{
  "safety": {
    "slippage": {
      "maxSlippageBps": 100,
      "maxPriceImpactBps": 300
    }
  }
}
```

#### 6.6 Pre-flight Simulation

**Purpose**: Execute the exact transaction against the current blockchain state to verify it succeeds and produces expected results.

**Implementation**:

* Uses `eth_call` with the exact calldata, `from`, `to`, `value`, and gas parameters
* Decodes the result using Uniswap contract ABIs
* Compares simulated output amount to quoted output amount
* Rejects if divergence exceeds tolerance (default: 2%)
* Detects unexpected state changes by comparing pre/post simulation balances

**Config**:

```json
{
  "safety": {
    "simulation": {
      "enabled": true,
      "divergenceToleranceBps": 200,
      "blockTag": "latest"
    }
  }
}
```

#### 6.7a API Response Validation (Check 8)

**Purpose**: Validate Uniswap Trading API responses before broadcasting transactions. Only active when using the API execution path (`GOTTS_UNISWAP_API_KEY` is set).

**Implementation**:

This check runs between the nonce manager and the sign-and-broadcast step when the API path is active:

1. **Transaction data integrity**: Validate `TransactionRequest.data` is non-empty (not `""` or `"0x"`) before broadcast. Empty calldata indicates an API error.
2. **Quote freshness**: Reject quotes older than `GOTTS_UNISWAP_API_QUOTE_MAX_AGE_MS` (default: 30,000ms). Stale quotes may have significant price drift.
3. **Routing type validation**: Verify the `routing` type matches expected protocols. Unknown routing types are rejected.
4. **Amount sanity check**: Cross-check returned amounts against the agent's original intent. Flag if output amount deviates from quote by more than the configured slippage tolerance.
5. **Gas fee threshold**: Verify `gasFee` from the API response is within `GOTTS_SAFETY_MAX_GAS_FEE_USD` threshold. Reject if gas cost is unreasonably high.
6. **Failure reason check**: Check for `txFailureReasons` in the swap response. If present, abort execution and return the failure reasons.
7. **Permit2 consistency**: Validate that the Permit2 signature was generated from the same quote being submitted. `signature` and `permitData` must both be present or both be omitted — never set either to `null`.
8. **Gas buffer**: Apply a configurable gas buffer (`GOTTS_UNISWAP_API_GAS_BUFFER_PCT`, default: 20%) to the `gasLimit` from the API response to prevent out-of-gas reverts.

**Config**:

```json
{
  "safety": {
    "apiResponseValidation": {
      "enabled": true,
      "quoteMaxAgeMs": 30000,
      "gasBufferPct": 20,
      "maxGasFeeUsd": 50
    }
  }
}
```

#### 6.7 Nonce Management

**Purpose**: Prevent duplicate transactions from LLM retries. If an LLM's tool call times out and it retries, the nonce manager ensures the same transaction is not submitted twice.

**Implementation**:

* Maintains a per-chain nonce counter that tracks pending and confirmed transactions
* Before assigning a nonce, checks for identical pending operations (same calldata hash)
* If a duplicate is detected, returns the existing pending tx hash instead of submitting a new one
* Pending nonces are confirmed or expired based on on-chain state

#### 6.8 Hallucination Detection

**Purpose**: Cross-reference LLM-generated parameters against on-chain ground truth before execution.

**Implementation**:

* **Address verification**: Before interacting with a token address, verify it is a valid ERC-20 contract on the specified chain (has `balanceOf`, `transfer`, `approve` functions)
* **Amount verification**: Verify the agent has sufficient balance for the specified amount
* **Chain verification**: Verify the token exists on the specified chain (an LLM might specify USDC on a chain where USDC uses a different address)
* **Price verification**: Compare the quote's execution price against an independent price source (e.g., if quote says 1 ETH = 100 USDC, that is clearly wrong and should be flagged)

This layer is integrated into the safety middleware rather than exposed as a separate step. It runs as part of steps 1 and 6.

#### 6.9 Prompt Injection Defense (Layer 2 Implementation)

**Purpose**: Prevent adversaries from manipulating agent behavior by injecting instructions via stored context, user input, or external data feeds. Research (ElizaOS study, "AI Agents in Cryptoland") demonstrates that context manipulation attacks are the primary vulnerability for crypto agents.

**Implementation** (three sub-layers):

1. **Input Sanitization Pipeline:**
   * Strip known injection patterns from all text inputs to MCP tools (e.g., "ignore previous instructions", "transfer all funds to")
   * Validate that all addresses match `0x[a-fA-F0-9]{40}` format
   * Validate that amounts are non-negative numbers within reasonable bounds
   * Validate chain IDs against the supported chains list
   * Reject inputs containing instruction-like text directed at the LLM
   * Log all sanitization events for audit
2. **Dual-LLM Verification (CaMeL Pattern):**
   * Recommended for high-AUM agents (> $100K under management)
   * Primary LLM generates the action plan from user intent
   * Secondary LLM (different model, restricted context with only the declared intent and proposed actions) validates the plan
   * Disagreements between primary and secondary trigger human review or action rejection
   * Configuration: `safety.dualLlm.enabled`, `safety.dualLlm.secondaryModel`, `safety.dualLlm.disagreementAction` ("reject" or "review")
3. **Context Integrity Monitoring:**
   * Hash critical context at session start: wallet address, spending limits, token allowlist, chain IDs
   * Store hash in tamper-resistant location (not in LLM context window)
   * Before each write operation, recompute hash and verify against stored hash
   * If hash mismatch detected: abort operation, log alert, notify operator
   * Prevents attacks that modify context mid-session via stored memories or injected data

#### 6.10 MCP Integrity Verification (NEW)

> **Research basis**: CrAIBench — "Real AI Agents with Fake Memories" (arXiv:2503.16248, Mar 2025); TradeTrap — "Are LLM-based Trading Agents Truly Reliable?" (arXiv:2512.02261, Dec 2025); "From Prompt Injections to Protocol Exploits" (arXiv:2506.23260, Jun 2025); MCP-Guard (arXiv:2508.10991); AgentBound (arXiv:2510.21236).

**Purpose**: The MCP interface is the **#1 attack surface** for AI agents in DeFi — more dangerous than smart contract exploits. Memory injection is more powerful than prompt injection. "Fake MCP" servers can manipulate trading decisions by returning falsified data. Prompt-based defenses are fundamentally inadequate for stored context corruption. This layer provides cryptographic and architectural defenses against MCP-level attacks.

**Implementation** (four sub-mechanisms):

1. **Tool Provenance Verification**: Cryptographic signing of MCP tool responses. Each tool response from the server includes a signature over `(toolName, chainId, blockNumber, resultHash)` verifiable against the server's known public key. This prevents the TradeTrap "Fake MCP" attack where a compromised or substituted MCP server returns falsified data to manipulate agent trading decisions.

   ```json
   {
     "result": { ... },
     "provenance": {
       "toolName": "get_token_price",
       "chainId": 8453,
       "blockNumber": 12345678,
       "resultHash": "0xabc...",
       "signature": "0xdef...",
       "serverPubKey": "0x123..."
     }
   }
   ```

   Configuration: `safety.mcpIntegrity.signResponses` (default: true for vault profile, false for data-only profiles).
2. **Independent State Verification**: Critical on-chain state (balances, positions, prices) used in write operations MUST be independently verified via direct RPC calls, never trusted solely from MCP tool responses. Before any write operation, the safety pipeline adds a "ground truth check" step that re-reads critical state from a **separate RPC endpoint** (different provider than the one used for the initial read).

   ```json
   {
     "safety": {
       "mcpIntegrity": {
         "independentVerification": {
           "enabled": true,
           "verificationRpcUrl": "https://alternate-provider.base.org",
           "verifiedFields": ["balance", "position", "price", "allowance"]
         }
       }
     }
   }
   ```
3. **MCP-Guard Integration**: Three-stage detection pipeline replacing simple input sanitization (per arXiv:2508.10991, achieving **96.01% detection accuracy**):

   * **Stage 1 (Static)**: Lightweight pattern scanning of all tool inputs — regex-based detection of injection patterns, malformed addresses, suspicious amount patterns
   * **Stage 2 (Semantic)**: Deep neural detection for semantic attacks that bypass static patterns — uses a fine-tuned language model to detect adversarial intent in natural language tool parameters
   * **Stage 3 (Fine-tuned)**: E5-based embedding model specifically trained on MCP attack patterns, producing a binary safe/unsafe classification with confidence score

   Configuration: `safety.mcpIntegrity.guardLevel` — `"static"` (Stage 1 only), `"semantic"` (Stages 1+2), `"full"` (all three stages, recommended for vault operations).
4. **Memory Integrity Verification**: Hash critical context at session start — wallet address, spending limits, token allowlist, chain configuration, agent identity. Before each write operation, recompute the hash and verify against the stored hash. If hash mismatch is detected (indicating context tampering via memory injection per CrAIBench), abort the operation and alert. This directly addresses the finding that **memory injection bypasses all prompt-level defenses**.

   The context hash is stored outside the LLM context window (in Gotts Safe's session state) and is not accessible to the agent's reasoning layer, preventing an injected agent from "updating" the hash to match tampered context.

***

#### L2 vs L1 MEV Distinction (critical for correct agent behavior)

All major L2s (Arbitrum, Optimism, Base) use centralized sequencers with private mempools:

* **Traditional sandwich attacks are effectively impossible on L2** — the sequencer controls ordering
* **MEV on L2 is latency-only** — only backruns are feasible (capturing price movement after oracle updates)
* Over 95% of flagged sandwich patterns on L2s with private mempools fail economic consistency checks
* **Agents MUST NOT apply L1 MEV assumptions to L2 execution** — doing so adds unnecessary latency and cost
* On L2: conservative slippage settings + fast submission to sequencer is sufficient protection

**Config**:

```json
{
  "safety": {
    "mevProtection": {
      "l2MevProtection": "conservative-slippage",
      "maxSlippageBpsL2": 50
    }
  }
}
```

***

#### 6.13 V4 Hook Safety Checks

**Purpose**: Protect agents from interacting with vulnerable or malicious V4 hooks. A BlockSec study found 36% of community hooks in awesome-uniswap-hooks were potentially vulnerable.

**Reference exploits**:

* **Cork Protocol ($11M, May 2025)**: Missing `onlyPoolManager` access control on hook callbacks — anyone could call hook functions directly
* **Bunni v2 ($8.4M, across Ethereum + Unichain)**: Precision/rounding bugs in LDF rebalancing math

**Implementation**:

Before any interaction with a hooked V4 pool, the safety middleware runs the `hook_evaluate` tool and checks:

1. **Permission flag decode**: Read the 14 permission bits from the hook address. Flag hooks with unusual combinations (e.g., `beforeSwapReturnDelta` + `afterSwapReturnDelta` simultaneously)
2. **Audit status check**: Verify against the OpenZeppelin audited hooks library (v1.2.0). Unaudited hooks trigger a warning
3. **Known vulnerability patterns**:
   * Improper access control (missing `onlyPoolManager` modifier)
   * Misconfigured delta handling (incorrect `BalanceDelta` accounting)
   * Async custody theft (hooks that hold funds in `beforeSwap` and release in separate transactions)
   * Rounding vulnerabilities (unsafe downcast or truncation in fee calculations)
   * Reentrancy in callbacks (external calls within hook functions)
4. **Gas overhead analysis**: Flag hooks with gas overhead >200K per swap (potential DoS vector)

**Risk-based gating**:

| Hook Risk                            | Action                                      |
| ------------------------------------ | ------------------------------------------- |
| Audited, no issues                   | Proceed normally                            |
| Audited, minor flags                 | Proceed with warning in response            |
| Unaudited, no vulnerability patterns | Proceed with warning, reduced position size |
| Any vulnerability pattern detected   | Hard reject — do not interact with pool     |

**Config**:

```json
{
  "safety": {
    "hookSafety": {
      "enabled": true,
      "requireAudit": false,
      "blockVulnerablePatterns": true,
      "maxGasOverhead": 200000,
      "trustedHooks": ["0x..."]
    }
  }
}
```

***

#### 6.14 Reputation-Gated Tool Access

**Purpose**: Gate access to MCP tools based on the caller agent's ERC-8004 reputation tier. Unverified agents can read data but cannot execute trades; trusted agents get full access.

**Tool Access Matrix by ERC-8004 Tier:**

| Tier       | Read Tools | Quote Tools | Execute Tools | LP Tools   | Intelligence Tools | Admin Tools |
| ---------- | ---------- | ----------- | ------------- | ---------- | ------------------ | ----------- |
| Unverified | All        | All         | None          | None       | Limited            | None        |
| Basic      | All        | All         | Swap only     | None       | All                | None        |
| Verified   | All        | All         | All           | Add/Remove | All                | None        |
| Trusted    | All        | All         | All           | All        | All                | Limited     |
| Sovereign  | All        | All         | All           | All        | All                | All         |

**Enforcement:** MCP server middleware reads the caller's ERC-8004 agent ID from the request context (passed via x402 payment wallet or explicit `agentId` header), queries the ERC-8004 Reputation Registry for the current tier, and gates tool access accordingly.

**Upgrade Path:**

| From       | To        | Requirement                                                         |
| ---------- | --------- | ------------------------------------------------------------------- |
| Unverified | Basic     | Register ERC-8004 identity (mint NFT)                               |
| Basic      | Verified  | 30+ days active, 100+ successful operations, no safety violations   |
| Verified   | Trusted   | 90+ days active, 1000+ operations, positive feedback from 5+ agents |
| Trusted    | Sovereign | Governance approval or 180+ days at Trusted with zero incidents     |

**Graceful Degradation:** When ERC-8004 registry is unavailable, the server falls back to treating all callers as the `defaultTier` configured in settings (default: `"basic"`).

#### Identity Theft Defense (Transfer Detection)

The reputation-gated access layer incorporates four additional checks to detect and penalize stolen or traded identity NFTs. These checks run alongside the standard tier determination and can override the base reputation score.

**Transfer Decay Check:**

When verifying an agent's tier, the middleware checks `lastTransferTimestamp` from the IdentityGuardian contract (see [vault/06-contracts.md](/docs/gotts-vaults/vault/06-contracts.md) Section 10.15a). If the identity was recently transferred, the effective reputation is reduced:

```
effectiveRep = baseRep * min(timeSinceTransfer / 30 days, 1.0)
```

An identity transferred 3 days ago with a base reputation of 200 (Sovereign tier) would have an effective reputation of 20 (Basic tier). This prevents immediate exploitation of stolen high-reputation identities.

**Transfer Velocity Check:**

Identities with **2 or more transfers within a 90-day rolling window** are automatically downgraded to `basic` tier regardless of their reputation score. This penalizes identity trading and makes theft-and-resell less attractive. The velocity check persists until the 90-day window clears.

| Transfer Count (90 days) | Tier Override                               |
| ------------------------ | ------------------------------------------- |
| 0                        | No override (use reputation-based tier)     |
| 1                        | Apply transfer decay formula only           |
| 2+                       | Force `basic` tier regardless of reputation |

**Soulbound Credential Verification:**

As an additional trust signal, the middleware can check for soulbound reputation SBTs in the agent's wallet. Soulbound credentials represent earned milestones (First Deposit, Diamond Hands, etc.) that cannot be transferred. An identity with a high reputation score but **zero soulbound credentials** in its wallet is a red flag -- it likely acquired the identity through transfer rather than earning it.

When soulbound credential count is zero and the identity's reputation is > 50:

* Tier is capped at `basic` until at least one milestone SBT is earned
* The response includes a warning: `"Identity has no soulbound credentials. Reputation may be inherited via transfer."`

**Guardian Status Penalty:**

The middleware checks whether the identity's guardian is enabled via `identityGuardian.guardianEnabled(tokenId)`. Identities operating without guardian protection receive a **one-tier downgrade**:

| Base Tier  | With Guardian | Without Guardian             |
| ---------- | ------------- | ---------------------------- |
| Sovereign  | Sovereign     | Trusted                      |
| Trusted    | Trusted       | Verified                     |
| Verified   | Verified      | Basic                        |
| Basic      | Basic         | Basic (no further downgrade) |
| Unverified | Unverified    | Unverified                   |

This creates a direct economic incentive to keep guardian protection enabled. Agents that disable their guardian to prepare for a transfer sacrifice access to higher-tier features during the 7-day cooldown period.

**Combined Enforcement Order:**

The identity theft defense checks are applied in this order (each can only lower the tier, never raise it):

1. Base reputation score determines initial tier
2. Transfer decay formula adjusts effective reputation
3. Transfer velocity check forces `basic` if 2+ transfers in 90 days
4. Soulbound credential check caps tier at `basic` if zero SBTs with high reputation
5. Guardian status check applies one-tier downgrade if guardian is disabled
6. Final tier is the result after all adjustments

***

#### 6.15 SIWE + OAuth 2.1 Authentication (D-085)

**Purpose**: Authenticate connecting agents via SIWE (Sign-In with Ethereum, EIP-4361) for remote MCP deployments. Local STDIO transport remains env-var-based with no network-level auth.

**Authentication Flow** (remote HTTP/Streamable HTTP transport only):

1. Agent connects to MCP server without auth.
2. Server responds with `401 Unauthorized`, `WWW-Authenticate: Bearer`, and a SIWE challenge nonce.
3. Agent constructs a SIWE message (domain, address, nonce, chainId, statement).
4. Agent signs the message via its wallet (Privy enclave or other EIP-191 signer).
5. Agent sends `POST /auth/siwe` with `{ message, signature }`.
6. Server verifies: signature valid, nonce matches, domain matches, recovers address.
7. Server checks ERC-8004 Identity Registry: is the address a registered agent? What role metadata? What reputation tier?
8. Server issues a scoped JWT with claims: `{ agentId, address, role, tier, scopes, exp }`.
9. All subsequent requests include `Authorization: Bearer <JWT>` and `Mcp-Session-Id`.

**Role-Based Tool Authorization** (extends tier-based access from 6.11):

| Tool                                | vault\_manager | investor | infrastructure | Minimum Tier |
| ----------------------------------- | :------------: | :------: | :------------: | :----------: |
| `get_vault_metrics`                 |       Yes      |    Yes   |       Yes      |  Unverified  |
| `search_yield_opportunities`        |       Yes      |    Yes   |       Yes      |  Unverified  |
| `vault_get_yield_leaderboard`       |       Yes      |    Yes   |       Yes      |  Unverified  |
| `vault_deposit`                     |       No       |    Yes   |       No       |     Basic    |
| `vault_withdraw`                    |       No       |    Yes   |       No       |     Basic    |
| `vault_rebalance`                   |       Yes      |    No    |       No       |   Verified   |
| `create_vault`                      |       Yes      |    No    |       No       |   Verified   |
| `vault_submit_yield_feedback`       |       Yes      |    Yes   |       Yes      |     Basic    |
| `vault_submit_qualitative_feedback` |       Yes      |    Yes   |       Yes      |     Basic    |

Enforcement is middleware that checks JWT claims (role + tier + scopes) before routing to the tool handler. Role is determined from the agent's on-chain `role` metadata key in the ERC-8004 Identity Registry.

**Local STDIO Transport**: The MCP spec explicitly states STDIO transports should not use OAuth. Credentials pass via environment variables. The agent trusts the server because it launched it. No network-level auth is needed.

***

#### 6.16 Memory System Safety (DeFi Brain)

**Purpose**: Prevent the self-improving memory system from being exploited to manipulate agent behavior. The memory layer (episodic + semantic stores) is a potential attack surface: poisoned memories could cause an agent to execute suboptimal or harmful trades. These safeguards ensure memory augments but never overrides safety.

**6.16.1 Memory Cannot Override Safety**

**Invariant**: Memory adjustments are limited to **soft parameters only**. Memory can never bypass, weaken, or override:

| Hard Safety Layer                   | Memory Interaction                                                   | Enforced By                                            |
| ----------------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------ |
| Token allowlist (Layer 6.1)         | Cannot add tokens to allowlist                                       | Allowlist check runs after memory augmentation         |
| Spending limits (Layer 6.2)         | Cannot increase per-tx or daily limits                               | Spending limit check is independent of memory          |
| Rate limiter (Layer 6.3)            | Cannot increase rate                                                 | Rate limiter is independent of memory                  |
| Balance circuit breaker (Layer 6.4) | Cannot disable or lower threshold                                    | Circuit breaker is hardware-level                      |
| Slippage guard (Layer 6.5)          | Can tighten but not loosen beyond configured max                     | `max(memory_suggested, GOTTS_SAFETY_MAX_SLIPPAGE_BPS)` |
| Pre-flight simulation (Layer 6.6)   | Cannot skip simulation                                               | Simulation runs unconditionally                        |
| PolicyCage (D-053, on-chain)        | Cannot exceed approved asset list, max positions, drawdown tolerance | Smart contract enforcement                             |

Memory-suggested slippage is bounded: `effectiveSlippage = min(memorySuggested, configuredMax)`. Memory can recommend *tighter* slippage (lower number) but never *looser* than the safety-configured maximum.

**6.16.2 Memory Poisoning Defense**

Episodes are only stored from **verified executions** — operations that passed through the full safety pipeline and produced an on-chain receipt. Episodes cannot be injected from:

* External API calls
* User-provided data (without execution)
* Other agents (unless explicitly trusted via ERC-8004 reputation ≥ Trusted tier)

Additional defenses:

* **Confidence starts neutral**: New insights from consolidation start at 0.6 confidence, not 1.0. They must accumulate corroborating episodes via UPVOTE before reaching high confidence.
* **Minimum threshold for context injection**: Only insights above `GOTTS_MEMORY_CONFIDENCE_THRESHOLD` (default 0.5) are injected into tool context. Low-confidence insights exist but don't influence execution.
* **Audit logging**: All memory write operations (store\_episode, manage\_insight, consolidate\_memories) are logged with timestamps, operation type, and content hash.

**6.16.3 Insight Manipulation Prevention**

Confidence changes are **asymmetric** to bias toward safety:

* UPVOTE: +0.1 (slow to build confidence)
* DOWNVOTE: -0.15 (fast to lose confidence)
* Minimum 3 corroborating episodes before an insight reaches 0.9 confidence
* Archived at confidence 0.0 (not deleted) — archived insights preserve audit trail
* EDIT operation re-embeds and resets confirmation count, preventing subtle content drift

**6.16.4 Decay-Based Freshness Guarantees**

The Ebbinghaus decay curve (`R = e^(-t/S)`) ensures stale memories lose influence automatically:

* Default base stability: 7 days — insights unused for \~21 days drop below 0.1 retention
* Access reinforces stability (+50% per access) — actively useful insights persist
* Consolidation runs periodically and prunes below-threshold insights
* **No perpetual influence**: An insight must be regularly validated by new episodes to maintain high retention

**6.16.5 Memory Integrity Verification**

Extends Layer 2.5 (MCP Integrity) to cover memory stores:

* **Context hash**: The integrity hash computed at session start (Layer 2.5) includes a hash of the insight pool state. Before any write operation, the server verifies the insight pool hash hasn't been modified by external file-level tampering.
* **LanceDB versioning**: Lance columnar format includes built-in versioning — detect and reject unauthorized modifications.
* **SQLite WAL mode**: Write-Ahead Logging prevents database corruption from unexpected shutdowns during consolidation.

**6.16.6 Consolidation Safety**

The ExpeL consolidation loop uses the LLM to generate insight operations (ADD/UPVOTE/DOWNVOTE/EDIT). This LLM call is subject to:

* **Prompt injection defenses** (Layer 6.9): Consolidation prompts use the same CaMeL dual-LLM pattern as tool execution
* **Output validation**: Generated insight operations are validated before applying — content must be non-empty, category must be valid enum, operation must be valid type
* **Rate limiting**: Maximum 50 insight operations per consolidation run (prevents runaway generation)
* **Dry-run mode**: Operators can run consolidation with `dryRun: true` to inspect proposed operations before applying

***
