# monsterion — program configs & parameters

A single reference for every tunable constant baked into the on-chain Anchor
programs (`/programs`) and mirrored in the UI (`src/lib/protocol.ts`). The UI reads
from `protocol.ts` so dashboards can never drift from the contracts; the values
below are the source of truth as currently deployed.

**Toolchain:** Anchor `0.31.1` · Solana/Agave `4.0.2` · all 8 programs deployed to
**devnet**. Basis-point denominator `BPS_DENOMINATOR = 10_000` (so `10_000 bps = 1.0×`).

---

## 1. Badge multipliers (staking_vault)

Your badge tier is the highest one unlocked by the **staked TOKEN amount**. It sets
the badge component of your reward weight. Thresholds and multipliers are hardcoded
on-chain (`programs/staking_vault/src/lib.rs::badge`).

| Tier | Min stake (TOKEN) | On-chain `MULT_BPS` | Multiplier | Glyph |
| --- | ---: | ---: | ---: | :---: |
| _(none)_ | < 10,000 | 10,000 | 1× (no badge) | — |
| **Bronze** | 10,000 | 10,000 | **1×** | ◔ |
| **Silver** | 50,000 | 20,000 | **2×** | ◑ |
| **Gold** | 250,000 | 40,000 | **4×** | ◕ |
| **Diamond** | 1,000,000 | 80,000 | **8×** | ● |

- Tier is recomputed on every `stake` / `unstake` from the new staked total
  (`badge_tier_for`).
- An amount below 10,000 earns no badge and a 1× badge component.

---

## 2. Duration (lock) multipliers (staking_vault)

Locking your stake for a fixed term boosts the lock component of your weight. Locks
can only be **extended, never shortened**, and locked stake **cannot be unstaked
before expiry** (`StillLocked`). Enforced on-chain by the `Clock` sysvar
(`programs/staking_vault/src/lib.rs::lock`).

| Lock | Duration | On-chain threshold | `MULT_BPS` | Multiplier |
| --- | --- | --- | ---: | ---: |
| No lock | 0 | — | 10,000 | **1×** |
| 30 days | 30 d | `30·24·60·60 s` | 15,000 | **1.5×** |
| 90 days | 90 d | `90·24·60·60 s` | 25,000 | **2.5×** |
| 180 days | 180 d | `180·24·60·60 s` | 40,000 | **4×** |
| **5 years** (diamond hands) | 1,825 d | `5·365·24·60·60 s` | 100,000 | **10×** |

- The applied tier is the **largest threshold ≤ the lock duration** (`lock_multiplier`).
- 5-year is a selectable fixed tier; "365-day years" → `FIVE_YEARS = 157,680,000 s`.

---

## 3. Weight & reward formulas

**Stake weight** (`compute_weight`, exact on-chain integer math):

```
weight = staked × (badge_bps / 10_000) × (lock_bps / 10_000)
       = staked × badgeMultiplier × lockMultiplier
```

Maximum boost = Diamond (8×) × 5-year lock (10×) = **80×**.
Example: 1,000,000 staked, Diamond, 5-year lock → weight `80,000,000`.

**Reward accrual** (reward_distributor — MasterChef accumulator):

```
reward_index += harvested × INDEX_SCALE / total_weight      // on each epoch
pending        = weight × reward_index / INDEX_SCALE − reward_debt
```

- `INDEX_SCALE = 1_000_000_000_000` (1e12) — must match in both staking_vault and
  reward_distributor.
- `total_weight` is read on-chain from `StakingState` (never caller-supplied).
- Rewards are **pull-based**: a staker signs + pays gas to `claim_reward`; the payout
  is a real SPL transfer of the reserve asset (PYUSD) from the pool ATA.
- **Entry checkpoint (Phase 5.1):** on any weight change, `reward_debt` is adjusted by
  `Δweight × reward_index / INDEX_SCALE`, so a position only earns on index growth
  *after* its weight is established (no retroactive claims).

UI mirror: `stakeWeight()` and `userReward(harvested, weight, totalWeight)` in
`protocol.ts`.

---

## 4. Flywheel fee split (fee_router)

The flagship split is **hardcoded** and compile-time asserted to sum to 10,000 bps
(`programs/fee_router/src/lib.rs`). It can never be changed and there is no admin path.

| Leg | bps | % | Destination |
| --- | ---: | ---: | --- |
| Reserve | 7,000 | **70%** | swap → PYUSD → Kamino → realized yield → stakers |
| Liquidity | 1,500 | **15%** | locked DAMM v2 liquidity |
| Keeper | 1,500 | **15%** | permissionless keepers / automation |

---

## 4b. Fee-Share Launch (fee_share_pool)

The simplest launch type — same Meteora DBC launch, but **all trading fees flow into
one pool** and stakers claim a proportional share on a biweekly cadence. Distinct
from the flywheel: no swap, no PYUSD/Kamino/JupSOL — the **raw fee/quote token** is
distributed as-is.

| Parameter | Value | Note |
| --- | ---: | --- |
| Default trading fee | **1%** (`100 bps`) | on the DBC/DAMM pool |
| Treasury cut | **20%** (`treasury_bps = 2000`) | configurable per launch, hard-capped ≤ **50%** |
| Staker share | **80%** | the remainder of each harvest |
| Harvest cadence | **~14 days** | `HARVEST_INTERVAL`; permissionless, gated `HarvestTooSoon` |
| Share math | `weight = stake × lockMultiplier` | flat pro-rata **× optional lock boost**, no badge tiers |
| Payout token | raw fee / quote token | no swap |
| Claim | pull-based | staker pays gas; `reward_index` accumulator + entry checkpoint |

**Flow:** `harvest()` (keeper, biweekly-gated) reads the `intake` balance on-chain
(no caller-supplied amount), sends `treasury_bps` to the pinned treasury, moves the
rest to the `reward_vault`, and advances `reward_index += stakerAmount × INDEX_SCALE
/ total_weight`. `claim()` pays `weight × reward_index / INDEX_SCALE − reward_debt`.
The optional lock boost reuses the same lock tiers as §2 (1 / 1.5 / 2.5 / 4 / 10×).
Principal (staked tokens) is never touched by the reward path.

---

## 5. Fee modules (module_registry / creator_fee_module)

Presets selectable at launch. Each split must sum to 10,000 bps; once initialized
`immutable = true`, the split can never change, and only the recorded `creator` may
call `update_split` on a mutable module. `send_*_share` destinations are pinned to
the recipients recorded at init (keeper share pays the caller).

| ID | Module | Creator | Reserve | Liquidity | Keeper | Burn |
| --- | --- | ---: | ---: | ---: | ---: | ---: |
| A | Creator Cashflow | 80% | — | 10% | 10% | — |
| **B** | **PYUSD Flywheel** ⭐ | — | **70%** | **15%** | **15%** | — |
| C | Balanced Creator + Reserve | 40% | 40% | 10% | 10% | — |
| D | Burn + Liquidity | 10% | — | 40% | 10% | 40% |
| E | Custom Immutable Split | 50% | 25% | 15% | 10% | — |

`CreatorFeeModule` fields: `launch`, `token_mint`, `creator`, `reserve_dest`,
`liquidity_dest`, the five bps, `immutable`, `bump`.

---

## 6. Reserve adapters (treasury_vault)

Per-pair `ReserveConfig` holds the reserve value trustlessly. **Principal is
monotonic and never distributed** — only realized yield above principal is harvestable.

```
harvestable_yield = max(current_value − principal_deposited, 0)
```

| `adapter_kind` | Name | Reserve held as | `current_value` source |
| ---: | --- | --- | --- |
| 0 | **NativeLst** | the LST (e.g. JupSOL) | `shares × pool_rate` — `sync_value_from_lst` reads the SPL/Sanctum stake pool at verified offsets (pool_mint@162, total_lamports@258, pool_token_supply@266) |
| 1 | **Lending** | cToken in a lending market | `cToken × reserve_rate` — `sync_value_from_lender` reads the Kamino KLend `Reserve`; rate uses a `Fraction` with **60 fractional bits** (`÷ 2^60`) |

- `yield_source` is pinned at init; a sync only accepts the bound pool + matching mint
  (`WrongStakePool` / `WrongMint`), and the adapter kind is enforced (`WrongAdapter`).
- `ReserveConfig` fields: `launch`, `reserve_mint`, `yield_source`, `adapter_kind`,
  `principal_deposited`, `current_value`, `bump`.

---

## 7. Launch packages (launchpad_factory)

One-time setup fee paid in SOL via a real lamport transfer (`collect_setup_fee`,
once per launch, `setup_fee_paid` guard).

| Package | Price (SOL) | Recommended module | Includes |
| --- | ---: | --- | --- |
| Basic | 1 | creator-cashflow | token + DBC launch, simple fee module, basic dashboard |
| **Flywheel** ⭐ | 10 | pyusd-flywheel | DBC launch, PYUSD reserve, Kamino, staking/badges, 70/15/15 |
| Pro | 5 | custom-immutable | custom split, page, badges, locked-liquidity strategy |
| Custom | 20 | custom-immutable | everything in Pro + bespoke audited module + DAMM v2 migration |

**Token immutability (Phase 5):** `create_launch` mints the full supply to the
creator, writes Metaplex metadata with `is_mutable = false`, then **revokes the mint
authority and freeze authority** → fixed supply, unfreezable, immutable metadata.
`CreateLaunchParams` includes `decimals: u8`.

---

## 8. Keeper bounties (bounded)

Automation is permissionless; bounties come from the 15% keeper allocation and are
capped so volume can't overpay keepers.

| Action | Rule | Cap |
| --- | --- | ---: |
| `claimFees()` | 0.25% of claimed fees | $20 |
| `swapToPYUSD()` | 0.25% of swapped amount | $20 |
| `depositToKamino()` | fixed bounty | $1 |
| `harvestYield()` | 1% of harvested yield | $10 |

---

## 9. Deployed program IDs (devnet)

| Program | Program ID |
| --- | --- |
| launchpad_factory | `7ReSRA67nDQHWG6QwTYt7fuWiLDxkRFYhva5J6v8Rn3e` |
| module_registry | `BC6fB3tUmTnb7Z5dupwSHZQ48z3BVcsUT8b2xYokYtxq` |
| creator_fee_module | `5i8TqsYCf2UWe3uzBfQ5RRqqpKF5qogBWvzc13rVsNvA` |
| fee_router | `3WQHWhJMhw9Mc6au3Ecu8APifekbyKo83mT87Hu7FW6B` |
| treasury_vault | `6CxDQWrGN8J9Crj419xBekdD1RQjkpaxuchHPhJJm5UD` |
| staking_vault | `APJeeF4cWiQMRzvVE6Jw8ysRLtRo3etauD5kAmXjWWRs` |
| reward_distributor | `4tN2ka4ropHr6AUzidnFU8Tejgo3VyfqByciDjxNugnW` |
| liquidity_module | `DMr6v6UUDV6SoWScLLVmKmhi1ohut2MrL5Z98JTRnzNx` |
| fee_share_pool | `FZxqMX5SKpWyTGMJNy63DCqX1Rdm1RVV5kAeEomjXcX8` |

### PDA seeds

| Seed | Program | Keyed by |
| --- | --- | --- |
| `b"launch"` | launchpad_factory | mint |
| `b"module_registry"` | module_registry | — (singleton) |
| `b"fee_module"` | creator_fee_module | launch |
| `b"router_config"` | fee_router | pyusd mint |
| `b"reserve"` | treasury_vault | launch |
| `b"stake"` | staking_vault | launch + owner |
| `b"staking_state"` | staking_vault | launch |
| `b"stake_vault"` | staking_vault | — (vault authority) |
| `b"reward_pool"` | reward_distributor | launch |
| `b"liquidity"` | liquidity_module | launch |
| `b"share_pool"` | fee_share_pool | launch |
| `b"share_pos"` | fee_share_pool | pool + owner |
| `b"staked"` / `b"intake"` / `b"rewards"` | fee_share_pool | launch (vault token accounts) |

---

## 10. External integrations (pinned mainnet IDs)

CPIs and rate reads target these exact programs/accounts (validated on-chain).

| Integration | ID |
| --- | --- |
| SPL Stake Pool program | `SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy` |
| Sanctum SPL-multi program | `SPMBzsVUuoHA4Jm6KunbsotaahvVikZs1JyTW6iJvbn` |
| JupSOL mint | `jupSoLaHXQiZZTSfEWMTRRgpnyFm8f6sZdosWBjx93v` |
| JupSOL stake pool | `8VpRhuxa7sUUepdY3kQiTmX9rS5vx4WgaXiAnXq4KCtr` |
| Kamino KLend program | `KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD` |
| Kamino main market | `7u3HeHxYDLhnCoErrtycNokbQYbWGzLs6JSDqGAv5PfF` |
| Meteora DBC program | `dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN` |
| Meteora DAMM v2 (cp-amm) | `cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG` |
| Jupiter swap API | `https://api.jup.ag/swap/v2` |

**Hand-rolled CPI discriminators** (anchor `sha256("global:<name>")[..8]`):

| CPI | Disc | Accts |
| --- | --- | ---: |
| DBC `claim_trading_fee` | `[8,236,89,49,152,125,177,81]` | 14 |
| DBC `initialize_virtual_pool_with_spl_token` | `[140,85,215,176,102,54,104,79]` | 16 |
| cp-amm `claim_position_fee` | `[180,38,154,17,133,33,162,211]` | 15 |
| cp-amm `add_liquidity` | `[181,157,89,67,143,182,52,72]` | 14 |
| cp-amm `permanent_lock_position` | `[165,176,125,6,231,171,186,213]` | 6 |

---

## 11. Tokens & swap policy

| Token | Mainnet mint | Notes |
| --- | --- | --- |
| PYUSD | `2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo` | **Token-2022**; devnet/testnet: `CXk2AMBfi3TwaEL2468s6zP8xq9NxTXjp9gjMgzeUynM` |
| USDC | `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v` | allowed swap input |
| USDT | `Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB` | allowed swap input |
| WSOL | `So11111111111111111111111111111111111111112` | allowed swap input |

- **Allowed swap inputs:** WSOL, USDC, USDT. **Only swap output:** PYUSD.
- Token-2022 program: `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`.

**$IONS:** symbol `ꙮ $IONS`, total supply `1,000,000,000`, status _not launched_.

---

## 12. Trustless invariants

**Hardcoded (cannot change):** fee split · PYUSD-only output · swap-route output ·
Kamino market · liquidity pool · reward distributor · staking token mint · creator
wallet/module.

**Forbidden by design (no instruction exists):** arbitrary transfers · arbitrary
swaps · admin withdrawals · changing recipient wallets · changing split percentages ·
sending PYUSD to a team wallet · unlocking liquidity.

> Rewards are variable and not guaranteed; principal is never distributed; users never
> deposit PYUSD (the reserve is protocol-owned). See `protocol.ts::COPY` for the full
> compliance wording surfaced in the UI.
