# Where is my MOR? (diagnostic)

Source: https://nodedocs.mor.org/ai/where-is-my-mor

## Agent Instructions

- Non-browser fetches of page URLs on this site return clean Markdown (not the JS UI). Prefer `https://nodedocs.mor.org/llms-full.txt` for the full corpus, or `https://nodedocs.mor.org/llms.txt` for the index.
- Per-page Markdown is also at `<page-url>.md` (homepage: `https://nodedocs.mor.org/index.md`).
- Docs search MCP: `https://nodedocs.mor.org/mcp` (discovery: `https://nodedocs.mor.org/.well-known/mcp`).
- Never invent contract addresses, chain IDs, token addresses, or live bid/model counts. Cite Networks and tokens; link active.mor.org for live data.
- Never claim Morpheus runs inference — independent providers do. Opening a session escrows MOR; it does not spend it.

The vast majority of "my MOR is gone" reports are **not** lost MOR. Your MOR can only be in **three on-chain places**:

1. **Your wallet** — standard ERC-20 `balanceOf(you)` on the MOR token.
2. **Active session** — `openSession` moved your stake into the Inference Contract; `closedAt == 0`.
3. **`userStakesOnHold` queue** — day-lock of the **used stipend** after close; `releaseAt = startOfTheDay(min(closedAt, endsAt)) + 1 day`.

Walk this checklist top-to-bottom. The moment one matches, that is the answer.

## Bucket 1: Active session

If you recently opened a session in MorpheusUI or via `POST /blockchain/models/:id/session`, **the entire stake** is in the Inference Contract while `closedAt == 0`.

**Confirm:**

- `GET /blockchain/sessions/user?user=0x…` lists active sessions, or use the hosted [tech.mor.org/session.html](https://tech.mor.org/session.html) wallet checker.
- Your wallet's transactions on Base show the `openSession` call.

**Resolution:**

- **Wait** for natural expiration — your consumer node will submit `closeSession` ~1 minute after `endsAt` (if online). **Unused** stake returns in that txn; the **used stipend day-locks** until the next UTC day (Bucket 2).
- **Or close early** with `POST /blockchain/sessions/<sessionId>/close` — same split: unused immediate, used portion may go on-hold.

See [Sessions: stake, close, claim](/concepts/sessions-stake-close-recover) for the full lifecycle.

## Bucket 2: On-hold queue (used-stipend day-lock)

After a successful `closeSession`, the contract may park the **used stipend** in `userStakesOnHold[you]` with `releaseAt = startOfTheDay(min(closedAt, endsAt)) + 1 day`. This applies to **early close and same-day natural/late close** — not only early close. Until `releaseAt`, that slice is parked inside the contract — not lost, not in your wallet, not in any active session.

**Confirm:**

- `getUserStakesOnHold(yourAddress, iterations_)` on the Inference Contract — splits amounts into `hold_` (before `releaseAt`) vs `available_` (after).
- The hosted wallet checker at [tech.mor.org/session.html](https://tech.mor.org/session.html) shows this bucket explicitly.
- A direct Base RPC `eth_call` works too:
  ```bash
  DATA=$(cast calldata "getUserStakesOnHold(address,uint8)" 0xYOUR_WALLET 1)
  curl -sS https://mainnet.base.org -H 'Content-Type: application/json' \
    -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_call\",\"params\":[{\"to\":\"0x6aBE1d282f72B474E54527D93b979A4f64d3030a\",\"data\":\"$DATA\"},\"latest\"]}"
  ```

**Resolution:**

Use the proxy-router wallet endpoints to inspect the queue and claim rows whose `releaseAt` has passed:

```bash
curl -u 'admin:admin' \
  'http://localhost:8082/blockchain/stakes/onhold?iterations=20'
curl -u 'admin:admin' \
  -X POST 'http://localhost:8082/blockchain/stakes/withdraw' \
  -H 'Content-Type: application/json' \
  -d '{"iterations":20}'
```

To bypass the node, submit the on-chain call directly:

```bash
cast send 0x6aBE1d282f72B474E54527D93b979A4f64d3030a \
  "withdrawUserStakes(address,uint8)" 0xYOUR_WALLET 20 \
  --rpc-url https://mainnet.base.org \
  --private-key "$PRIVATE_KEY_OF_DELEGATEE"
```

The function selector is `0xa98a7c6b` if you're driving a non-Foundry tool. Or use MetaMask "Interact with contract" with the same ABI.

## Bucket 3: Stuck close (funding account or gas)

A session can sit "active" past `endsAt` because **`closeSession` is one transaction that has to succeed** — and it pays the provider from a **separate protocol funding account**, not from your stake. If that funding account is empty or has insufficient allowance to the Inference Contract, every close fails — yours included.

**Confirm:**

- `GET /blockchain/sessions/0x<sessionId>` shows `closedAt == 0` even though `endsAt` has passed.
- Failed `closeSession` transactions on Base from your consumer node's wallet.

**Common causes:**

- Provider payment pool empty or unapproved (operator-side issue).
- The wallet that submits `closeSession` has no ETH for gas.
- Your consumer node has been offline since `endsAt`.

**Resolution:**

- Wait for operators to top up the funding account (community Discord / mor.org status).
- Make sure your consumer node is online and has Base ETH on its operating wallet.
- If your node is up but the close still fails, check its logs — the failure reason is usually printed.

## Bucket 4: Wrong network

MorpheusUI and the proxy-router can be configured for either **BASE Mainnet (`8453`)** or **BASE Sepolia (`84532`)**. MOR balances are independent: mainnet MOR is at one address, testnet MOR at another. You may be querying the wrong contract.

**Confirm:**

- Check `ETH_NODE_CHAIN_ID` in your `.env` (or `CHAIN_ID` for the UI).
- Check the explorer URL the UI uses — `base.blockscout.com` (mainnet) vs `base-sepolia.blockscout.com` (testnet).
- Confirm `MOR_TOKEN_ADDRESS` matches [Networks and tokens](/get-started/networks-and-tokens).

**Resolution:** switch back to the right network. The MOR isn't gone — you're querying the wrong contract.

## Bucket 5: Wrong wallet address

MorpheusUI's mnemonic-recover only restores **tier-1 (index 0)** addresses. If your real wallet was a derived sub-account (e.g. MetaMask account #2), recovering by mnemonic gives you a different address with no funds.

**Confirm:** the lower-left address in MorpheusUI does **not** match your real ERC-20 wallet address.

**Resolution:** use **import private key** instead of mnemonic, or use a wallet that is the top-level address from this mnemonic.

## Bucket 6 (rare): Allowance mismatch

If you tried an action and the transaction reverted because you didn't have enough allowance, **no MOR moved** — but the action can look like it started.

**Confirm:**

- `GET /blockchain/allowance` against the Diamond contract.
- Failed transactions on the explorer.

**Resolution:** `POST /blockchain/approve?spender=&amount=...` and retry.

## What is *not* "lost MOR"

| Symptom | Reality |
|---------|---------|
| "Wallet balance dropped after opening a session." | Expected — stake is in the active session (Bucket 1). |
| "I closed (or let it expire) and only part came back." | Expected — unused returned; used stipend is in the on-hold queue (Bucket 2). Wait until after `releaseAt`, then `withdrawUserStakes`. |
| "I can't open another session with the same MOR today." | Expected — used stake is day-locked; size wallet float for gross daily stake. |
| "Session is past `endsAt` but still open." | Bucket 3 — close transaction hasn't succeeded yet. |
| "I see the contract holding tokens." | The Inference Contract holds tokens for **all users' active sessions and on-hold queues** combined. Not all of it is yours. |

## Truly lost MOR

In extremely rare cases — wrong-network transfer, sending to a non-Morpheus contract, etc. — MOR can actually be unrecoverable. **Always verify destination addresses** before sending.

## Related

- [Sessions: stake, close, claim](/concepts/sessions-stake-close-recover) — full lifecycle reference.
- [Why is my MOR locked in the contract?](/ai/why-locked-in-contract) — corrected lock-vs-unlock semantics.
- [Session states (open, close, claim)](/ai/session-states-open-close-recover) — deterministic state machine.
- Hosted wallet checker: [tech.mor.org/session.html](https://tech.mor.org/session.html).
