# Trust model

This page says what is fixed in code, what the protocol owner can change, and what you are trusting
the operators to do. The contracts are not upgradeable: there are no proxies, and none of them can be
replaced under a live launch.

## What nobody can do

- **Withdraw the liquidity.** The locker has no withdrawal function and no arbitrary call. The position
  and any dust are locked for good, for the owner too.
- **Mint or burn tokens**, or pause, tax or block transfers. The token is a plain fixed-supply ERC-20.
- **Change a launched pool's fee rates.** They are frozen at registration, with a hard 10% ceiling.
- **Change a token's name, symbol or metadata.**
- **Take from the escrow.** Only a recipient can claim its own balance.
- **Renounce ownership.** It is disabled on purpose, because fee sweeps and recovery depend on an
  owner existing. Ownership transfers in two steps.

## What the owner can do

| Power | Effect | Safeguard |
|---|---|---|
| Open or close launching, manage the whitelist | Controls new launches only | Existing tokens keep trading |
| Add or update launch configs, set the launch fee | Controls terms of new launches | `expectedEconomics` lets a creator refuse changed terms |
| Change protocol rate, creator bounds, conversion limit, protocol recipient | **Future** launches only (the launch fee follows the current recipient) | Live pools keep their frozen terms |
| Approve or revoke quote assets | New launches only | Existing pools keep trading |
| Reserve tickers | Blocks new launches of a symbol | A launch that holds it is unaffected |
| Change the fee sweep operator | Decides who may convert memecoin fees | Rotating it cannot redirect fees |
| Override a creator fee recipient | Redirects a launch's **creator tranche**, for any launch | **3-day** public notice, then a 3-day execution window. Emits `CreatorFeeRecipientChangeProposed` |
| Change the launch forwarder | A forwarder can attribute launches to any account | **48-hour** public notice |
| Disable the launch forwarder | Turns off `launchAndBuy` | Immediate, because it only removes trust. Plain launches continue |
| Rescue a pool's fees | Credits pending fees to the frozen recipients without converting | Goes to the normal recipients through the escrow, never to the owner |
| Set the bridge factory | Where future launches create their bridge wallet | Failure can never block a launch |

The recipient override exists so a creator who lost their key can be recovered, but it is not limited
to that case. A creator cannot veto it by moving the recipient: a matured proposal still executes. A
pending override appears in `GET /v1/tokens/:id` as `creatorFeeRecipientPending`, and a pending
forwarder change appears in `GET /v1/protocol` as `launchAndBuy.pending`.

## What the operators do

| Role | Can | Cannot |
|---|---|---|
| Fee sweep operator (keeper) | Decide when memecoin fees convert, and at what minimum | Send fees anywhere but the frozen recipients. Exceed the conversion's price-impact limit |
| Distributor owner | Publish epoch roots, manage exclusions | Reach the distributor's balance directly, or commit more than `unallocated` |

> [!WARNING]
> **Holder rewards trust the distributor owner.** A published Merkle root decides who is paid, and the
> contract cannot judge whether it is fair. The check is that anyone can rebuild the tree from public
> data and compare the root. See [Checking an epoch](/documentation/holder-rewards#checking-an-epoch).

## What Tartarus depends on

- **Uniswap V4.** Pools live on Uniswap's canonical deployment on Elysium.
- **Elysium.** Its sequencer, and its bridge to HyperEVM.
- **Tartarus services**, for fee sweeps, holder-reward publishing, the API and the RPC. If they stop,
  tokens keep trading and escrow balances stay claimable, but fees would stop reaching the escrow until
  someone sweeps them. Creators can always pay out quote fees themselves.

## Verifying this yourself

Read the current owner, wiring and policy directly from the chain:

```ts
await client.readContract({ address: FACTORY, abi: factoryAbi, functionName: "owner" });
await client.readContract({ address: HOOK, abi: hookAbi, functionName: "feeSweepOperator" });
await client.readContract({ address: FACTORY, abi: factoryAbi, functionName: "getLaunchFeePolicy", args: [token] });
await client.readContract({ address: FACTORY, abi: factoryAbi, functionName: "pendingCreatorFeeRecipient", args: [token] });
```