# MCDEX Insufficient Validation Bugfix Review

MCDEX Broker.batchTrade trusted a caller-supplied liquidity pool contract, letting an attacker pass arbitrary source/destination addresses and drain any user's ETH balance.

- Payout: $50,000
- Severity: critical
- Program: MCDEX
- Credited: Lucash-dev
- Disclosed: 2021-07-12
- Write-up quality: 7/10
- Original: https://immunefi.com/blog/bug-fix-reviews/mcdex-insufficient-validation-bugfix-review/
- Library page: https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-mcdex-insufficient-validation-bugfix-review
- Tags: domain:web3 impact:funds-loss kind:bounty platform:blog platform:immunefi sev:critical tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** Broker.sol batchTrade() on MCDEX layer-2 perpetual exchange
**Root cause:** batchTrade() delegated all input validation to a caller-supplied liquidity pool contract address, so an arbitrary no-op contract bypassed validation entirely. The gas reimbursement logic then transferred funds between attacker-chosen source and destination addresses.
**Steps:**
1. Deploy a malicious liquidity pool contract whose brokerTrade() is a NOOP returning without validation.
2. Craft an order struct with trader=victim, relayer=attacker, liquidityPool=malicious contract, brokerFeeLimit=1 ether.
3. Compress the order with arbitrary zero-filled signature data (signatures are never validated).
4. Call `broker.batchTrade([compressed], ["0"], ["1000000000000000000"])` to trigger gas reimbursement of 1 ether from victim to attacker.
5. Verify victim balance drops to 0 and attacker receives the full amount.
**How found:** Researcher observed that batchTrade() outsourced validation to an externally supplied liquidity pool address, meaning the trust boundary was attacker-controlled; hypothesized a no-op contract would skip all checks and let arbitrary source/destination addresses reach the reimbursement transfer.
**Exploitation:** Attacker needs no capital: deploy a no-op liquidity pool, submit a batchTrade with the victim as trader/source and attacker as relayer/destination, and the broker's gas reimbursement transfers the victim's entire deposited balance to the attacker.
**Insight:** When a contract delegates validation to an address passed in by the caller, that address is attacker-controlled—look for any downstream value transfer that uses other caller-supplied fields (source/destination) as the real exploit primitive.
