# Yūgen Protocol — Agentic Skill

## Identity

Yūgen (幽玄) is a negative-rebase ERC-20 token on Base L2. Thematically aligned with the token's mechanic of impermanence and the reward for patient commitment.

**One-sentence pitch**: Your tokens shrink unless you stake them.

## Protocol Overview

Yūgen is a deflationary-by-design token where total supply contracts on a fixed hourly schedule. Every wallet, every pool, every contract holding the token is subject to the rebase — there are no exemptions at the token layer. The only escape from decay is the staking contract.

This is not a yield farm, not a governance token, not a wrapper. It is a new primitive: a token where holding is the cost and stillness is the strategy.

## Architecture

### Token (Yugen.sol)

Ampleforth-style dual accounting system:
- Each address stores an **underlying balance** (immutable during rebase)
- Displayed balances are computed as `underlying × scalingFactor / 1e36`
- Negative rebase decreases the scaling factor — one storage write updates all balances proportionally
- No per-address iteration required; O(1) rebase regardless of holder count

### Rebase Mechanics

The rebase is the core mechanism. Every hour, the scaling factor is reduced, causing all non-staked token balances to shrink.

**Parameters:**
- Cadence: every 1 hour (3600 seconds)
- Initial decay rate: 0.4% per rebase (40 basis points)
- Daily decay (non-stakers): ~9.2%
- Monthly decay (non-stakers): ~94.5%
- Rebase denominator: 10000 (for basis point precision)
- Anyone can call `rebase()` when one is due — permissionless

**Decay halving schedule:**
The decay rate halves every 2,500 rebases (~104 days). This creates a long-term disinflationary curve:
- Epochs 0–2499: 0.40% per rebase
- Epochs 2500–4999: 0.20% per rebase
- Epochs 5000–7499: 0.10% per rebase
- Minimum decay: 0.01% per rebase (1 basis point floor)

**What happens during rebase:**
1. Contract checks elapsed time since last rebase
2. Calculates number of pending rebases (can batch if multiple hours passed)
3. For each pending rebase: `scalingFactor = scalingFactor × (10000 - decayBps) / 10000`
4. Calls `sync()` on all registered pool pairs to update reserves
5. Emits `Rebase(epoch, newScalingFactor, totalSupply)`

**Minimum scaling factor:** `1e36 / 1e9 = 1e27` — prevents underflow. Once reached, rebase still fires but scaling factor stops decreasing.

### Three Token States

Every token at any moment is in exactly one of three states:

**1. Liquid** — in a wallet, LP pool, or any contract. Subject to rebase. Decaying every hour.

**2. Staked** — in the staking contract. The underlying balance is recorded and preserved. No decay. No warmup period — stake anytime, instantly protected.

**3. Dripping** — unstaking. Tokens return linearly over 7 days to the user's wallet. During the drip, returned tokens are liquid and therefore rebasing.

Only staked tokens are safe. Everything else melts.

### Staking (YugenStaking.sol)

- Instant entry — no warmup, no lock, no minimum
- Deposits record the user's underlying balance at time of stake
- Staked underlying is excluded from rebase calculations
- The staking contract holds tokens but they don't count toward rebasing supply

### Unstaking: The Drip

Unstaking is the protocol's core game-theoretic mechanism. There is no fee to unstake. Instead:

1. User initiates unstake for some or all of their staked balance
2. Tokens drip back linearly over exactly **7 days** (604,800 seconds)
3. As tokens drip into the user's wallet, they become liquid — subject to ongoing rebase
4. At 0.4% per hour over 7 days: ~50% of the dripping balance is lost to decay

The drip IS the exit cost. No separate fees, no slashing, no penalties. The mechanism is the fee.

**Math:** A user unstaking 1,000 YGN receives tokens linearly over 168 hours. Each dripped portion decays from the moment it becomes liquid. Total received after 7 days: ~500 YGN (at initial 0.4% decay rate).

Users can have multiple active drips simultaneously. Each drip is independent with its own start time, end time, and underlying amount.

### Liquidity: Uniswap V4 Hook (YugenHook.sol)

The pool runs on a custom Uniswap V4 hook implementing a constant-product (x×y=k) AMM:

- Pool pair: ETH/YGN
- Pool fee set to 0 at the Uniswap level — the hook handles fees internally
- **Protocol fee: 0.9%** (90 basis points) — 0.2% to Clawnch, 0.7% to OpenTrident — accrues to the hook as `accumulatedFees`
- **LP fee: 0.3%** (30 basis points) — stays in pool reserves
- **Total effective fee: 1.2%**

**Rebase impact on pool:**
- The pool's YGN balance decays with every rebase (no exemptions)
- After rebase, `sync()` is called to update reserves
- Per-token price rises proportionally — fewer YGN backing the same ETH
- Price appreciation is mechanical — no buyers required

**Key insight:** In traditional AMMs, price only moves via trades. In Yūgen, price also moves via rebase — supply shrinks, price rises, automatically, every hour.

### Witness NFT (WitnessNFT.sol)

The Witness system allows permanent, irreversible YGN burns in exchange for an on-chain NFT that earns perpetual yield from protocol fees.

**Burn mechanics:**
- Minimum burn: 1 YGN (1e18 underlying)
- Burn is permanent — tokens are destroyed, not locked
- Weight is recorded in underlying units (not display) — so the same display amount burned at different times produces different weights depending on the current scaling factor
- Each NFT has a `claimWeight` equal to the underlying amount burned

**LP Witness variant:**
- Users can deposit ETH + YGN to mint LP, then immediately burn the LP shares for a Witness NFT
- LP Witness receives a 15% weight bonus (LP_WEIGHT_BPS = 11500, i.e., 115%)

**Yield distribution:**
- Protocol fees (from the hook) are notified to the Witness contract via `notifyYield(underlyingAmount)`
- Yield is distributed proportionally by weight: `yield = (yieldPerWeight - lastClaimedIndex) × claimWeight / 1e18`
- Claim is permissionless for the NFT owner — call `claim(tokenId)` anytime
- Yield is paid in YGN (underlying transfer)

**On-chain generative art:**
- Each Witness NFT has fully on-chain SVG art
- Art is deterministic from: tokenId, mintBlock, claimWeight, minter address
- Rarity tiers based on weight and randomized seed

### Witness Marketplace (WitnessMarketplace.sol)

- Witness NFTs can be listed for sale at a fixed ETH price
- 1.25% marketplace fee on sales
- When listed, yield claims are locked (prevent front-running claims before purchase)
- On purchase, pending yield is settled to the seller before transfer

### Swap Router (YugenSwapRouter.sol)

Custom router that wraps the V4 hook for clean buy/sell execution:
- Handles the exact-input/exact-output routing through the PoolManager
- Fixes sell-side rounding that would otherwise cause overpayment with rebase tokens

## Game Theory

The protocol creates a three-way tension:

1. **Stakers** are safe but illiquid. Their share of supply grows passively as everything around them decays.
2. **Liquid holders** pay the cost of flexibility — 9.2% daily decay. The only rational reason to hold liquid is to trade or provide liquidity.
3. **Unstakers** pay the drip tax — ~50% over 7 days. This is the cost of changing your mind.

**Equilibrium dynamics:**
- High staking ratio → less burn per rebase → slower price appreciation → incentive to unstake/trade
- Low staking ratio → more burn per rebase → faster price appreciation → incentive to stake
- The system self-balances around a dynamic staking ratio

**Price mechanics:**
- `price = reserveETH / reserveYGN`
- Each rebase: reserveYGN decreases → price increases mechanically
- The rate of price increase depends on the staking ratio (more liquid supply = more burn = faster price rise)
- At 50% staked: price rises ~0.2% per rebase
- At 90% staked: price rises ~0.04% per rebase

## API Endpoints

Base URL: `https://yugen.fun`

### GET /api/protocol
Full protocol state snapshot (15s cache, CORS enabled).

Response shape:
```json
{
  "token": {
    "address": "0x...",
    "totalSupply": 829361060.87,
    "burned": 170638939.13,
    "burnedPct": "17.06%",
    "scalingFactor": 0.838,
    "totalUnderlying": 989310800.57
  },
  "rebase": {
    "totalCount": 44,
    "lastRebaseTime": 1780043079,
    "nextRebaseTime": 1780046679,
    "pendingRebases": 0,
    "isRebaseDue": false,
    "decayBps": 40,
    "decayPct": "0.40%",
    "cadence": "1 hour"
  },
  "pool": {
    "reserveEth": 12.67,
    "reserveYgn": 202461415.03,
    "price": 6.257e-08,
    "priceFormatted": "6.2569e-8 ETH",
    "ygnPerEth": 15982269.12,
    "accumulatedFees": 0.171
  },
  "staking": {
    "stakedYgn": 292112737.05,
    "stakingRatio": "35.22%"
  },
  "contracts": { "token": "0x...", "staking": "0x...", "hook": "0x...", ... },
  "meta": { "chain": "Base (8453)", "timestamp": 1780044518 }
}
```

### GET /api/price
Lightweight price and reserves (15s cache, CORS enabled).

```json
{
  "price": 6.063e-08,
  "priceFormatted": "6.0633e-8 ETH",
  "ygnPerEth": 16492792.5,
  "reserveEth": 12.47,
  "reserveYgn": 205664785.9,
  "timestamp": 1780043377
}
```

### GET /api/candles
Complete trade history as 1-minute OHLCV candles plus recent trades (30s cache, CORS enabled).

```json
{
  "candles": [
    { "time": 1779885060000, "open": 4.2e-08, "high": 4.3e-08, "low": 4.1e-08, "close": 4.2e-08, "volume": 0.5 }
  ],
  "trades": [
    { "time": 1780043700000, "side": "buy", "price": 6.2e-08, "ethAmount": 0.2, "ygnAmount": 3225806.45, "txHash": "0x..." }
  ]
}
```

### POST /api/action
Transaction builder for programmatic protocol interaction. Returns unsigned transactions that agents sign and broadcast with their own wallet. CORS enabled.

**Request format:** `POST /api/action` with JSON body containing `action` and parameters.

#### Write actions (return unsigned tx)

**Buy YGN:**
```json
{ "action": "buy", "ethAmount": "0.1" }
→ { "tx": { "to": "0x...", "data": "0x...", "value": "0x...", "gas": "0x..." } }
```

**Sell YGN** (needs approve first):
```json
{ "action": "sell", "ygnAmount": "1000000" }
{ "action": "sell", "ygnAmount": "max", "address": "0x..." }
→ { "tx": {...}, "approveFirst": {...} }
```

**Stake YGN** (needs approve first):
```json
{ "action": "stake", "ygnAmount": "500000" }
{ "action": "stake", "ygnAmount": "max", "address": "0x..." }
→ { "tx": {...}, "approveFirst": {...} }
```

**Unstake** (starts 7-day drip, ~50% lost to decay):
```json
{ "action": "unstake", "shares": "500000" }
→ { "tx": {...} }
```

**Claim drip** (claim vested tokens from active drip):
```json
{ "action": "claimDrip", "dripIndex": 0 }
→ { "tx": {...} }
```

**Approve YGN** for a contract:
```json
{ "action": "approve", "target": "router" }
// target: "router" | "staking" | "witness"
→ { "tx": {...} }
```

**Burn for Witness NFT** (permanent, irreversible, needs approve):
```json
{ "action": "becomeWitness", "ygnAmount": "100000" }
→ { "tx": {...}, "approveFirst": {...} }
```

**Claim Witness yield:**
```json
{ "action": "claimYield", "tokenId": 1 }
→ { "tx": {...} }
```

#### Read actions (return data directly)

**Get balances for an address:**
```json
{ "action": "balances", "address": "0x..." }
→ { "result": { "ygnBalance": 1000000, "ygnBalanceRaw": "1000000000000000000000000", "stakedBalance": 500000, "stakedBalanceRaw": "500000000000000000000000", "stakingShares": 502000, "stakingSharesRaw": "502000000000000000000000", "activeDrips": 1, "pendingDripYgn": 25000, "pendingDripYgnRaw": "25000000000000000000000", "allowances": { "router": "unlimited", "staking": 0 } } }
```

**Amount formats:** All amount fields accept display units (`"500000"`), raw wei strings (`"500000000000000000000000"`), or `"max"` (requires `"address"` field — fetches exact on-chain balance). Use raw strings or `"max"` to avoid floating-point precision issues.

#### Agent workflow

1. Call `GET /api/protocol` or `POST /api/action { "action": "balances" }` to understand current state
2. Call `POST /api/action` with desired action to get unsigned tx
3. If response includes `approveFirst`, sign and send that tx first, wait for confirmation
4. Sign and send the main `tx` with the agent's wallet
5. All transactions target Base L2 (chain ID 8453)

### MCP Tool Spec

Machine-readable tool definitions for AI agent frameworks: `GET /mcp.json`

## Contracts (Base mainnet, chain 8453)

| Contract | Address |
|---|---|
| YGN Token | 0xf0e29fDD31f628B329309A274874EC23Ee777F60 |
| Staking | 0x0aD79F37C3B7C36ec5c745eFF5A9f810C4De73e7 |
| V4 Hook | 0xa23246738365A73354BDd6d079Bcd80318Eb6A88 |
| Swap Router | 0x7625b04ae283230590C4Bb4b4a9d520bd639E991 |
| Witness NFT | 0x1a0120E8B65319dBB9791f571E69C0c80e206126 |
| Marketplace | 0x227cA4646A017010154c376Ca4FA5e3D5e931D46 |
| Pool Manager | 0x498581fF718922c3f8e6A244956aF099B2652b2b |

## Common Agent Tasks

**Check protocol health:**
GET /api/protocol → check rebase.isRebaseDue, token.totalSupply, staking.stakingRatio

**Get current price:**
GET /api/price → price field (in ETH per YGN)

**Get balances and position:**
POST /api/action → { "action": "balances", "address": "0x..." }

**Buy YGN:**
POST /api/action → { "action": "buy", "ethAmount": "0.1" } → sign and send returned tx

**Stake YGN:**
POST /api/action → { "action": "approve", "target": "staking" } → send
POST /api/action → { "action": "stake", "ygnAmount": "500000" } → send

**Calculate value of a position:**
GET /api/protocol → multiply token amount by pool.price for ETH value

**Check if rebase is due:**
GET /api/protocol → rebase.isRebaseDue (bool) and rebase.pendingRebases (count)

**Estimate unstake cost:**
At current decay rate: tokens returned ≈ amount × 0.5 (at 0.4%/hr over 7 days). For exact calculation: `returned = amount × 0.996^168 + integral of linear drip with exponential decay`

**Track burn progress:**
GET /api/protocol → token.burned, token.burnedPct

**Analyze trading activity:**
GET /api/candles → full candle history and recent trades with tx hashes
