- Your wallet — standard ERC-20
balanceOf(you)on the MOR token. - Active session —
openSessionmoved your stake into the Inference Contract;closedAt == 0. userStakesOnHoldqueue — early-close timelock;releaseAt = startOfTheDay(closedAt) + 1 day.
Bucket 1: Active session
If you recently opened a session in MorpheusUI or viaPOST /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 wallet checker.- Your wallet’s transactions on Base show the
openSessioncall.
- Wait for natural expiration — your consumer node will submit
closeSession~1 minute afterendsAtand your full stake will land back in your wallet inside the same transaction (no extra step). - Or close early with
POST /blockchain/sessions/<sessionId>/close. The contract may park a slice inuserStakesOnHold(see Bucket 2); the rest comes back immediately.
Bucket 2: On-hold queue (early close timelock)
If you closed a session before its scheduledendsAt, the contract may have pushed a slice of your stake to userStakesOnHold[you] with releaseAt = startOfTheDay(closedAt) + 1 day. Effectively this means after the end of the next full UTC day from your close. Until then, 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 intohold_(beforereleaseAt) vsavailable_(after).- The hosted wallet checker at tech.mor.org/session.html shows this bucket explicitly.
- A direct Base RPC
eth_callworks too:
releaseAt, call withdrawUserStakes on the Diamond contract. There is no HTTP route on the proxy-router for this — you submit the on-chain call yourself:
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” pastendsAt 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>showsclosedAt == 0even thoughendsAthas passed.- Failed
closeSessiontransactions on Base from your consumer node’s wallet.
- Provider payment pool empty or unapproved (operator-side issue).
- The wallet that submits
closeSessionhas no ETH for gas. - Your consumer node has been offline since
endsAt.
- 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_IDin your.env(orCHAIN_IDfor the UI). - Check the explorer URL the UI uses —
base.blockscout.com(mainnet) vsbase-sepolia.blockscout.com(testnet). - Confirm
MOR_TOKEN_ADDRESSmatches Networks and tokens.
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/allowanceagainst the Diamond contract.- Failed transactions on the explorer.
POST /blockchain/approve?spender=<DiamondContract>&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 early and only part came back.” | Expected — the rest is in the on-hold queue (Bucket 2). Wait until after the next full UTC day, then withdrawUserStakes. |
”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 — full lifecycle reference.
- Why is my MOR locked in the contract? — corrected lock-vs-unlock semantics.
- Session states (open, close, claim) — deterministic state machine.
- Hosted wallet checker: tech.mor.org/session.html.

