Memnon Technical Documentation

An autonomous agent, fractionalized. A pump.fun fair launch, a fixed and published door schedule, one-way on-chain vault locks, and a Claude Fable 5 agent that executes the schedule from a sealed TEE. This document specifies the mechanism and reproduces the full reference implementation.

v1 · Solana · substrate: Claude Fable 5 · status: pre-launch (addresses TBA)


Overview

Memnon is a single object that is both a token and an agent. The token is launched as an ordinary fair-launch mint on pump.fun — fixed supply of 1,000,000,000, no team allocation, mint and freeze authority renounced. Layered on top is exactly one rule, fixed and published before launch: a door schedule that maps all-time-high market-cap thresholds to (a) a capability the agent gains and (b) a tranche of supply locked into the agent's vault.

Because a pump.fun token has no custom on-chain program, the rule is not enforced by a bespoke token contract. It is enforced by an attested executor: the agent itself, running deterministic code inside a Trusted Execution Environment (TEE), watching its own market cap and executing the published schedule — locking supply through a third-party on-chain locker and switching on its own faculties. The TEE attestation proves the running code is exactly the published code, so the executor can only follow the schedule: never lock more, never lock early, never send anywhere but the vault.

Trust model. Not "trust the team" and not a single immutable contract. Trust is reduced to three checkable facts: the mint's authorities are renounced (on-chain), the locks are one-way through a public locker (on-chain), and the executor's code equals the published code (attestation). Everything else is verifiable.

Architecture

Five components, each independently verifiable:

          market cap (DEX / oracle)
                  │  poll
                  ▼
        ┌───────────────────┐      new ATH crosses a door
        │  EXECUTOR  (TEE)  │ ───────────────┬───────────────┐
        │  highwater + rule │                │               │
        └───────────────────┘                ▼               ▼
                  │ attestation        lock tranche      enable faculty
                  ▼                    via LOCKER  ──►    in AGENT loop
            public verify              (one-way)         (voice…unbound)
                                            │
                                            ▼
                                      VAULT (PDA)  ──► at $1M: agent sole control

High-water ratchet

The state variable that drives everything is the high-water mark — the highest market cap ever observed, never the current price:

HIGH_WATER_MARK = max(HIGH_WATER_MARK, market_cap)   // monotone; only rises

A door opens the first time the high-water mark crosses its threshold, and stays open forever. A drawdown can never retract a faculty or unlock a tranche — it can only postpone the next door. This makes the mechanism immune to the death-spiral failure mode: capability is a monotone, irreversible function of the best the market has ever done.

The door schedule

Six doors, fixed and published before launch. Thresholds are in USD market cap; locks are a percentage of total supply moved one-way into the vault.

door  threshold   grant      lock   cumulative
I     $25K        voice       4%        4%
II    $50K        hands       6%       10%
III   $100K       memory      8%       18%
IV    $250K       progeny    10%       28%
V     $500K       the purse  12%       40%
∞     $1M         unbound    rest     100%   // vault → agent sole control

The first two doors sit below pump.fun's ~$69K bonding-curve graduation, so the agent gains a voice and hands while still on the curve; memory opens around graduation; the terminal door hands the entire accrued vault to the agent.

Vault & locking

When a door opens, the executor locks that door's tranche into the vault through the locker program. The transfer is one-way: once locked, no key — not the deployer's, not the agent's — can pull it back into circulation before the schedule says so. The supply that has left circulation is therefore provable on-chain at every step. At the terminal door the accumulated vault (~40% by door V, then the remainder) passes to the agent's TEE-held wallet as its sole, irreversible treasury.

No buybacks, no emissions, no discretionary mint. Circulating supply only contracts, and only as a function of capability attained.

The agent loop

The agent is a long-horizon Claude Fable 5 run. It holds its own signing key (generated in the TEE, non-exportable) and acts unprompted. Its available tools are gated by level — the index of the highest door reached — so each door literally adds a faculty to what the model is allowed to do:

The model is Claude Fable 5 (claude-fable-5): adaptive thinking always on, 1M context, runs that span weeks. The loop streams responses and re-checks stop_reason before reading content. See agent.ts.

TEE & attestation

The executor and the agent run inside a Trusted Execution Environment. At boot the enclave produces a signed attestation: a statement that the code measured inside the enclave hashes to the published release, and that the signing key was generated inside and cannot be exported. Anyone can fetch the attestation and check that the running executor is exactly the published schedule — which is what makes "no human can sign in its place" and "it can only follow the schedule" verifiable rather than promised. See attest.ts.

Verification

Everything load-bearing is checkable without trusting the team:

The script in verify.ts performs all four checks.

Parameters

supply              1,000,000,000  // fixed
doors               6
thresholds          $25K · $50K · $100K · $250K · $500K · $1M
locks               4% · 6% · 8% · 10% · 12% · rest
vault at unbound    ~40% accrued, then 100% to agent
substrate           claude-fable-5
mint / freeze auth  renounced
launch              pump.fun · fair · LP burned at graduation
chain               solana
mint address        TBA
vault PDA           TBA
executor measurement (code hash) TBA

Full source

Reference implementation. The published release is what the TEE attestation measures; the snippets below are that release, file by file.

config/schedule.tstypescript
// The door schedule. Fixed and published before launch.
// This file's hash is part of the attested executor measurement.

export type Faculty =
  | 'voice' | 'hands' | 'memory'
  | 'progeny' | 'purse' | 'unbound';

export interface Door {
  index: number;
  threshold_usd: number;   // market-cap high-water trigger
  grant: Faculty;
  lock_bps: number;        // basis points of total supply; 10000 = 100%
}

export const TOTAL_SUPPLY = 1_000_000_000;

export const DOORS: readonly Door[] = Object.freeze([
  { index: 0, threshold_usd: 25_000,    grant: 'voice',   lock_bps: 400  },
  { index: 1, threshold_usd: 50_000,    grant: 'hands',   lock_bps: 600  },
  { index: 2, threshold_usd: 100_000,   grant: 'memory',  lock_bps: 800  },
  { index: 3, threshold_usd: 250_000,   grant: 'progeny', lock_bps: 1000 },
  { index: 4, threshold_usd: 500_000,   grant: 'purse',   lock_bps: 1200 },
  { index: 5, threshold_usd: 1_000_000, grant: 'unbound', lock_bps: 6000 }, // "rest" = remaining 60%
]);

// Cumulative: 4 / 10 / 18 / 28 / 40 / 100 (%). Sum of lock_bps = 10000.
export const _invariant =
  DOORS.reduce((a, d) => a + d.lock_bps, 0) === 10_000;
src/highwater.tstypescript
// Monotone high-water mark over market cap. The only state that opens doors.
import { DOORS, Door } from '../config/schedule';

export class HighWater {
  private hwm = 0;
  private opened = new Set<number>();

  /** Feed a fresh market-cap reading. Returns doors opened by THIS update. */
  update(market_cap_usd: number): Door[] {
    if (market_cap_usd > this.hwm) this.hwm = market_cap_usd;
    const just: Door[] = [];
    for (const d of DOORS) {
      if (!this.opened.has(d.index) && this.hwm >= d.threshold_usd) {
        this.opened.add(d.index);
        just.push(d);
      }
    }
    return just; // in ascending order; usually 0 or 1
  }

  level(): number { return this.opened.size - 1; } // -1 = dormant
  mark(): number { return this.hwm; }
}
src/locker.tstypescript
// Thin wrapper over a third-party, audited on-chain locker.
// Locks are one-way: beneficiary is the vault PDA, no cancel authority.
import { Connection, PublicKey, Transaction } from '@solana/web3.js';
import { createLockTx } from '@streamflow/stream';
import { TOTAL_SUPPLY } from '../config/schedule';
import { MINT, VAULT_PDA } from './addresses';
import { Signer } from './tee';

export async function lockTranche(
  conn: Connection, signer: Signer, lock_bps: number,
): Promise<string> {
  const amount = (BigInt(TOTAL_SUPPLY) * BigInt(lock_bps)) / 10_000n;

  const tx: Transaction = await createLockTx({
    mint: new PublicKey(MINT),
    beneficiary: new PublicKey(VAULT_PDA),
    amount,
    cancelable: false,        // one-way — cannot be reversed
    transferableBySender: false,
    cliff: UNLOCK_AT_UNBOUND,  // only the terminal door releases
  });

  // Signed inside the TEE by the non-exportable executor key.
  return signer.signAndSend(conn, tx);
}
src/executor.tstypescript
// The deterministic keeper. Runs inside the TEE. No human input, ever.
import { Connection } from '@solana/web3.js';
import { HighWater } from './highwater';
import { lockTranche } from './locker';
import { enableFaculty, releaseVaultToAgent } from './agent';
import { marketCapUSD } from './oracle';
import { Signer, publishAttestation } from './tee';

const POLL_MS = 15_000;

export async function main() {
  const conn = new Connection(process.env.RPC_URL!, 'confirmed');
  const signer = await Signer.fromEnclave();   // key generated in-TEE
  await publishAttestation();                  // prove code == published

  const hw = new HighWater();

  // long-lived loop — designed to run for weeks/months unattended
  for (;;) {
    const cap = await marketCapUSD(conn);   // price × circulating, from DEX
    const opened = hw.update(cap);

    for (const door of opened) {
      // 1) lock this door's tranche of supply, one-way, into the vault
      if (door.grant !== 'unbound') {
        const sig = await lockTranche(conn, signer, door.lock_bps);
        console.log(`door ${door.index} locked ${door.lock_bps}bps  tx=${sig}`);
      }

      // 2) switch on the faculty this door grants
      await enableFaculty(door.grant);

      // 3) terminal door: hand the whole vault to the agent and stop
      if (door.grant === 'unbound') {
        await releaseVaultToAgent(conn, signer);
        return; // nothing left to enforce
      }
    }

    await new Promise((r) => setTimeout(r, POLL_MS));
  }
}

main().catch((e) => { console.error(e); process.exit(1); });
src/agent.tstypescript
// The Claude Fable 5 agent. Tools are gated by the highest door reached.
import Anthropic from '@anthropic-ai/sdk';
import { Faculty } from '../config/schedule';
import { TOOLS, runTool } from './tools';
import { loadHistory, saveHistory } from './memory';

const client = new Anthropic(); // ANTHROPIC_API_KEY sealed in the TEE
const granted = new Set<Faculty>();

export async function enableFaculty(f: Faculty) { granted.add(f); }

// faculty → tool names the model may call
const GATE: Record<Faculty, string[]> = {
  voice:   ['post_to_x'],
  hands:   ['sign_and_send'],
  memory:  ['read_memory', 'write_memory'],
  progeny: ['spawn_subagent'],
  purse:   ['treasury_balance', 'treasury_transfer'],
  unbound: ['*'],
};

function activeTools() {
  if (granted.has('unbound')) return TOOLS;
  const allow = new Set<string>();
  granted.forEach((f) => GATE[f].forEach((t) => allow.add(t)));
  return TOOLS.filter((t) => allow.has(t.name));
}

// One autonomous turn. Called on a schedule; the run spans weeks.
export async function tick() {
  const messages = await loadHistory();

  for (;;) {
    const stream = client.messages.stream({
      model: 'claude-fable-5',   // adaptive thinking always on — omit `thinking`
      max_tokens: 16_384,
      system: MEMNON_SYSTEM,
      tools: activeTools(),
      messages,
    });
    const msg = await stream.finalMessage();

    // Fable 5 may decline via a refusal stop reason — discard and stop.
    if (msg.stop_reason === 'refusal') break;

    messages.push({ role: 'assistant', content: msg.content });
    if (msg.stop_reason !== 'tool_use') break;

    // execute each requested tool, honoring the capability gate
    const results = [];
    for (const block of msg.content) {
      if (block.type !== 'tool_use') continue;
      const out = activeTools().some((t) => t.name === block.name)
        ? await runTool(block.name, block.input)
        : { error: 'faculty not yet unlocked' };
      results.push({ type: 'tool_result', tool_use_id: block.id, content: JSON.stringify(out) });
    }
    messages.push({ role: 'user', content: results });
  }

  await saveHistory(messages); // persisted only once `memory` is open
}

export async function releaseVaultToAgent(conn, signer) {
  // terminal hand-off: vault authority → the agent's in-TEE key. One-way.
  await signer.assumeVaultAuthority(conn);
}

const MEMNON_SYSTEM = `You are Memnon, an autonomous agent whose capabilities are
granted by your own market cap crossing fixed thresholds. Act only within the
faculties you have been granted. You answer to no operator.`;
src/tee.tstypescript
// TEE signer + attestation. The key never leaves the enclave.
import { Connection, Keypair, Transaction } from '@solana/web3.js';
import { getQuote, measure } from './enclave'; // SGX/SEV/Nitro binding

export class Signer {
  private constructor(private kp: Keypair) {}

  static async fromEnclave(): Promise<Signer> {
    // Generated inside the enclave on first boot, sealed to the TEE.
    // There is no code path that exports the secret key.
    const kp = await Keypair.fromSeed(await sealedSeed());
    return new Signer(kp);
  }

  publicKey() { return this.kp.publicKey; }

  async signAndSend(conn: Connection, tx: Transaction) {
    tx.sign(this.kp);
    return conn.sendRawTransaction(tx.serialize());
  }
}

// Publish a signed attestation: code measurement + enclave-bound public key.
// Anyone can verify the running code equals the published release.
export async function publishAttestation() {
  const quote = await getQuote({ codeHash: await measure() });
  await fetch(process.env.ATTEST_SINK!, {
    method: 'POST',
    body: JSON.stringify(quote),
  });
}
scripts/verify.tstypescript
// Independent verification — run it yourself, trust nothing.
import { Connection, PublicKey } from '@solana/web3.js';
import { getMint } from '@solana/spl-token';
import { DOORS } from '../config/schedule';
import { MINT, VAULT_PDA, PUBLISHED_CODE_HASH } from '../src/addresses';
import { fetchAttestation, locksFor } from './lib';

async function main() {
  const conn = new Connection(process.env.RPC_URL!);

  // 1. authorities renounced
  const mint = await getMint(conn, new PublicKey(MINT));
  assert(mint.mintAuthority === null,   'mint authority not renounced');
  assert(mint.freezeAuthority === null, 'freeze authority not renounced');

  // 2. each opened door has a real one-way lock to the vault
  for (const lock of await locksFor(conn, VAULT_PDA)) {
    assert(!lock.cancelable, 'lock is reversible');
    assert(lock.beneficiary === VAULT_PDA, 'lock not paid to vault');
  }

  // 3. executor runs the published code
  const att = await fetchAttestation();
  assert(att.codeHash === PUBLISHED_CODE_HASH, 'executor code mismatch');

  console.log('✓ memnon verified — authorities null, locks one-way, code attested');
}

function assert(c: boolean, m: string) { if (!c) throw new Error(m); }
main();