# Ulysses omnichain - User Funds can get locked permanently via making a callout without deposit

MulticallRootRouter passes address(0) as settlement owner in no-deposit multicalls, so failed destination settlements can never be retried or redeemed, permanently locking user funds.

- Payout: Contest reward
- Severity: medium
- Program: Maia DAO Ecosystem
- Credited: zzebra83
- Disclosed: 2023-09-18
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-05-maia-findings/issues/377
- Library page: https://bugbountylibrary.com/r/c4%3A2023-05-maia%3AM-27
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** MulticallRootRouter anyExecute / _approveAndCallOut settlement owner
**Root cause:** In the no-deposit multicall paths (funcId 0x02/0x03), _approveAndCallOut is called with address(0) as the settlement owner instead of the user's virtual account, so the resulting settlement has no owner.
**Steps:**
1. User on source chain sends a no-deposit multicall (flag 0x01) with funcId 0x03 and OutputMultipleParams.
2. RootBranchBridgeExecutor.executeNoDeposit triggers MulticallRootRouter.anyExecute, which runs _multicall then _approveMultipleAndCallOut(address(0), ...).
3. Root port moves hTokens to destination branch and calls clearTokens; settlement is recorded with owner == address(0).
4. If the destination callout fails, anyFallback marks the settlement Failed.
5. User calls redeemSettlement(nonce): reverts SettlementRedeemUnavailable because depositOwner == address(0).
6. _retrySettlement also returns false since settlement.owner == address(0).
**How found:** Code review of anyExecute funcId 0x02/0x03 branches; author noticed the @audit comment questioning why address(0) is passed as owner to _approveAndCallOut, then traced redeemSettlement/_retrySettlement owner checks and wrote a Foundry PoC forcing a fallback.
**Exploitation:** No attacker profit; a user following the no-deposit multicall flow loses the global hTokens transferred to the root port if the destination settlement fails, since neither retry nor redeem is possible for a zero-owner settlement.
**Insight:** When a router forwards a settlement on behalf of a user, verify the settlement owner field is set to the actual caller/virtual account; zero-address owner is used as a sentinel for 'redeemed' and silently blocks retry/redeem paths.
