# Canceling a mint stake token can result in the execution fee being sent from the wrong vault

Canceling a mint order with native-token collateral refunds the execution fee from the LP vault instead of the portfolio vault, breaking LP accounting and blocking other users' orders.

- Payout: Contest reward
- Severity: high
- Program: Elfi Protocol
- Credited: Cosine
- Disclosed: 2024-05-09
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2024-05-elfi-protocol-judging/issues/86
- Library page: https://bugbountylibrary.com/r/sherlock%3A2024-05-elfi-protocol%3AH-21
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:sherlock sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** StakeFacet / MintProcess / GasProcess in elfi-perp-contracts
**Root cause:** validateAndDepositMintExecutionFee returns isExecutionFeeFromLpVault=true whenever isNativeToken and walletRequestTokenAmount >= executionFee, even when the deposit was routed to the portfolio vault as collateral (isCollateral=true). cancelMintStakeToken then uses that flag to pay the execution fee from the LP vault.
**Steps:**
1. Call `createMintStakeTokenRequest` with `params.isCollateral=true`, `params.isNativeToken=true`, `params.walletRequestTokenAmount >= params.executionFee` and non-zero `walletRequestTokenAmount`; deposit goes to portfolio vault via `AssetsProcess.depositToVault(..., DepositFrom.MINT_COLLATERAL, ...)`.
2. `MintProcess.validateAndDepositMintExecutionFee` returns `(walletRequestTokenAmount - executionFee, true)` because `isNativeToken && walletRequestTokenAmount >= executionFee`.
3. Before execution, call `cancelMintStakeToken(requestId, reasonCode)`.
4. `GasProcess.processExecutionFee` receives `mintRequest.isExecutionFeeFromLpVault == true` and pays `executionFee` from `getLpVaultAddress()` instead of `getPortfolioVaultAddress()`.
**How found:** Code review of the mint request lifecycle: noticed the `isExecutionFeeFromLpVault` flag is set purely from `isNativeToken && walletRequestTokenAmount >= executionFee` without checking `isCollateral`, then traced how `cancelMintStakeToken` consumes that flag to select the vault.
**Exploitation:** Attacker repeatedly creates and cancels native-token collateral mint orders, each cancellation draining the execution fee from the LP vault. The LP vault balance drops below the amount required by other users' pending orders, so those orders can never execute and cannot be cancelled because the system still assumes the original LP balance.
**Escalation:** Repeated cancellations accumulate LP vault shortfall, causing permanent denial of service for other users' mint/stake orders and locking their funds.
**Insight:** When a boolean flag is derived from one condition but later used to select a fund source, check every branch that sets the flag against the actual deposit destination; native-token fee deduction can silently flip the vault selection even when collateral routing sends funds elsewhere.
