> ## Documentation Index
> Fetch the complete documentation index at: https://docs.darkmatter.rdytobash.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# Waterfall

> Waterfall — Dark Matter Protocol on Robinhood Chain.

# Reactor Deposit Waterfall

This is the protocol's most important payment structure: **exactly what happens to 1 ETH
the moment a player calls `injectMass(ref)`**. Every number below is a constant or a
verified line from `UltimateSingularityProtocol.sol`.

## The waterfall

```
injectMass{value: 1 ETH}(ref)
│
├── 5% (0.05 ETH) ──────────────▶ teamAddress
│       └── minus gas-sponsor skim (≤5% of this chunk → DarkMatterTreasury)
├── 5% (0.05 ETH) ──────────────▶ marketingAddress
├── 1% (0.01 ETH) ──────────────▶ StockDividendVault.deposit(user)   [stockDividendBps = 100]
├── 10% fee bucket (0.10 ETH):
│       ├── 10% of bucket (0.01 ETH) ──▶ founderPool  (FounderPass.receive)
│       └── 10% of bucket (0.01 ETH) ──▶ vipPool      (EventHorizonPool.creditDeposit)
│                └── 70% → weekly raffle pot / 30% → gravity dividend pot
├── 0% ─────────────────────────▶ DUST mint (no ETH leaves; see below)
└── remainder ──────────────────▶ stays in the reactor as YOUR yield curve position
                                  (+ buys radiation → auto-converts to Reactor Nodes)
```

## The code, verbatim

```solidity theme={null}
// UltimateSingularityProtocol.injectMass() — fee section
uint256 teamFee = _applyGasSponsorSkim((amount * 5) / 100); // skim → treasury first
teamAddress.transfer(teamFee);
marketingAddress.transfer((amount * 5) / 100);
_forwardStockDividend(msg.sender, amount);                  // 1% (stockDividendBps)
_forwardPoolCutFor(msg.sender, (amount * 10) / 100, amount); // 10% bucket, 10% per pool
_earnStardust(msg.sender, amount);                          // 500e18 DUST per ETH
```

Constants involved:

| Constant | Value | Meaning |
| - | - | - |
| `FEE_PERCENT` | 10 | Historical 10% fee bucket reference |
| `stockDividendBps` | 100 (1%) | Cut of gross deposit → StockDividendVault |
| `MAX_STOCK_DIVIDEND_BPS` | 500 (5%) | Hard cap on the dividend cut |
| `POOL_FEE_SHARE_BPS` | 1000 (10%) | Each pool's share **of the 10% bucket** = 1% of gross |
| `MAX_GAS_SPONSOR_BPS` | 500 (5%) | Cap on the skim taken from the team fee chunk |
| `stardustPerEth` | 500e18 | DUST minted per 1 ETH deposited |

## Worked example — 1 ETH deposit

Assume the gas-sponsor skim is set to 200 bps (2%) of the team chunk:

| Destination | Formula | Amount (1 ETH in) |
| - | - | - |
| Team (after skim) | `0.05 × (1 − 0.02)` | **0.049 ETH** |
| Gas-sponsor treasury (skim) | `0.05 × 0.02` | **0.001 ETH** |
| Marketing | `1 × 5%` | **0.05 ETH** |
| Stock dividend vault | `1 × 1%` | **0.01 ETH** |
| Founder Pass pool | `0.10 × 10%` | **0.01 ETH** |
| Event Horizon VIP pool | `0.10 × 10%` | **0.01 ETH** |
| **Stays in reactor (yield curve)** | remainder | **0.879 ETH** |
| DUST minted | `1 × 500e18` | **500 DUST** (boostable) |

**Effective deposit fee: 12.1% gross** (10% + 1% + 1% + 0.1% skim) with default wiring —
the rest starts working for the depositor immediately as Reactor Nodes.

## DUST earning — no ETH leaves

The DUST mint (`_earnStardust`) is a **side effect, not a fee**: it calls
`StardustWheel.earn(user, amount, "deposit")` which mints new DUST. Depositors get 500
DUST per ETH *in addition to* the waterfall above. Personal boosts and global Supernova
epochs multiply this (see [Stardust](casino/stardust.md)).

## The VIP pool auto-registration

When the 1% VIP cut arrives, the reactor calls — with the cut attached:

```solidity theme={null}
EventHorizonPool.creditDeposit(depositor, grossInjection)
```

The pool does three things in one call:

1. Pools the 1% fee into the **current week's pot** (70% raffle / 30% dividend).
2. Credits the depositor's `depositedThisWeek` with the **gross** injection — so a 0.05
   ETH deposit satisfies the 0.05 ETH weekly activity floor even though the pool only
   received 0.0005 ETH.
3. Auto-registers the depositor as a weekly member (weight = live NFT mass).

This is why no separate "registration" transaction exists for VIP weeks.

## NFT auto-invest — no double fee

DarkMatterNFT mints can auto-invest the buyer through `injectMassFor(user, ref)`. That
path forwards the stock dividend and earns DUST but **deliberately does not** forward
another Founder/VIP cut — the NFT mint already routed its explicit 40% protocol
allocation via `routeProtocolAllocation()`, and that allocation pays each pool 10%:

```
NFT mint (1 ETH example)
├── 40% (0.40 ETH) ──▶ routeProtocolAllocation()
│       ├── 10% (0.04) ──▶ founderPool
│       └── 10% (0.04) ──▶ vipPool
│       └── 80% (0.32) ──▶ stays in protocol reserve
└── 60% ──▶ auto-invested as injectMassFor (stock dividend + DUST apply)
```

## Compounding (`condenseMatter`) — a smaller waterfall

Compounding converts accumulated radiation into nodes and pays a **2% fee on the
compounded value**:

```solidity theme={null}
uint256 marketingFee = _applyGasSponsorSkim((ethValue * 2) / 100);
marketingAddress.call{value: marketingFee}("");   // after skim
_forwardPoolCutFor(msg.sender, marketingFee, ethValue);  // 10% of that → each pool
```

| Destination | Formula | Example: compounding 1 ETH of radiation (2% skim) |
| - | - | - |
| Treasury skim | `0.02 × 2%` | 0.0004 ETH |
| Marketing (after skim) | `0.02 − skim` | 0.0196 ETH |
| Each pool | `0.02 × 10%` | 0.002 ETH each |
| Net cost of compounding | sum of the above | **2.4% of compounded value** |

The nodes themselves are minted from the radiation (`radiationUsed / 1_080_000`) —
the fee is paid out of the radiation's ETH value, not out of the node count.
Compounding also counts toward the VIP weekly activity floor (credited as the gross
`ethValue`).

## Failure behavior — nothing is ever lost

Every forward in the waterfall is **fail-safe**:

| Forward | If it fails |
| - | - |
| Team / marketing transfers | Revert the deposit (required, plain `transfer`) |
| Stock dividend cut | Silently skipped — deposit continues, vault is one-shot-wired |
| Pool cuts | Try `creditDeposit(user, gross)` → fallback plain transfer → queue as `pendingPoolCredits` |
| DUST mint | Best-effort; failure never affects the deposit |

Queued pool credits are retried by **anyone** via `retryPoolCredits()` — permissionless
self-healing. The reactor's available balance view explicitly reserves queued credits:

```solidity theme={null}
uint256 reserved = pendingPoolCredits[founderPool] + pendingPoolCredits[vipPool];
uint256 balance = address(this).balance;
return balance > reserved ? balance - reserved : 0;
```

## The casino's own 1% <a id="casino-fee" />

Casino deposits (into `CrashVault`) run a parallel 1% fee at **ledger-credit time**
(`vault-sweep.js`), with the same half-dev / half-VIP split as the reactor's deposit
fee:

```
DEPOSIT_FEE_BPS = 100 (1%)
player chips   = custody − fee
dev share      = fee/2 (ceil)  → credited as chips to DEPOSIT_FEE_DEV_ADDRESS
VIP share      = fee − dev     → credited as chips to EventHorizonPool address
```

Because the fee is charged as **ledger claims against the same custody**, the vault
always custodies 100% of the assets — the fee rows are chips owned by the dev/VIP
addresses, which they withdraw through the same signature-gated flow as players.

Next: [Reactor Yield & Withdrawal Economics](reactor/yield-economics.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.