# Single sided liquidity can’t be used to lock LP tokens in the farm manager

Single-sided liquidity provision reverts because the internal re-invocation's sender is the contract, breaking the receiver==sender check that gates farm locking.

- Payout: Audit contest
- Severity: medium
- Program: MANTRA
- Credited: 0xAlix2
- Disclosed: 2025-03-31
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2024-11-mantra-dex#m-09
- Library page: https://bugbountylibrary.com/r/c4%3A2024-11-mantra-dex%3AM-09
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:medium tech:rust technique:source-review vuln:access-control vuln:business-logic

**Target:** CosmWasm pool-manager provide_liquidity command
**Root cause:** Single-sided provision recursively calls provide_liquidity from the contract itself, so info.sender equals the contract address and the receiver==sender authorization check for farm locking wrongly reverts.
**Steps:**
1. Call `provide_liquidity` on `o.whale.uluna` with a single asset (e.g. 1000 uwhale) and `unlocking_duration=86400`.
2. Contract swaps half, then re-invokes provide_liquidity internally with info.sender = contract address.
3. Receiver validation `ensure!(receiver == info.sender.to_string())` fails, returning `ContractError::Unauthorized`.
4. Observe single-sided deposit + farm lock cannot be done in one action.
**How found:** Code reading of the provide_liquidity flow (provide_liquidity -> swap -> rely -> provide_liquidity) revealed the internal call's sender is the contract, conflicting with the receiver==sender check; confirmed with an integration test expecting Unauthorized.
**Insight:** When a contract re-enters its own entrypoint after an internal swap, any sender==receiver authorization check will see the contract address as sender; audit recursive self-calls for auth checks that assume external callers.
