# Message channels can be blocked resulting in DoS

User-supplied gasLimit of 1 in addLocalToken forces lzReceive out-of-gas on root chain, blocking the LayerZero channel and DoS'ing all cross-chain messaging.

- Payout: Contest reward
- Severity: medium
- Program: Maia DAO
- Credited: LokiThe5th
- Disclosed: 2023-11-29
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2023-09-maia-findings/issues/399
- Library page: https://bugbountylibrary.com/r/c4%3A2023-09-maia%3AM-09
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:dos vuln:misconfiguration

**Target:** LayerZero cross-chain messaging via BranchBridgeAgent/RootBridgeAgent lzReceive
**Root cause:** BridgeAgent accepts arbitrary user-supplied gasParams without validating a minimum gasLimit for the destination lzReceive call; combined with a non-blocking lzReceive pattern and no forceResumeReceive implementation, a too-low gasLimit reverts the endpoint call and blocks the channel.
**Steps:**
1. Deploy ERC20 on branch chain (e.g. Polygon/Avalanche) and call `CoreBranchRouter.addLocalToken(token, GasParams(1, 0))` with gasLimit=1.
2. BranchBridgeAgent.callOutSystem forwards poisoned _gParams to `_performCall`, which calls `ILayerZeroEndpoint.send` with `abi.encodePacked(uint16(2), gasLimit, remoteBranchExecutionGas, rootBridgeAgentAddress)`.
3. On root chain, Endpoint's receivePayload try/catch calls `RootBridgeAgent.lzReceive` with gasLimit=1, reverting OutOfGas; Endpoint stores payload and marks channel blocked.
4. Subsequent messages to same chain revert with `LayerZero: in message blocking` even with valid gas (e.g. GasParams(2_000_000,0)).
5. Channel only clears via manual `Endpoint.retryPayload()` paid by protocol; no `forceResumeReceive` implemented.
**How found:** Code review of gas parameter flow from CoreBranchRouter through BridgeAgent to LayerZero Endpoint, cross-referenced with LayerZero best-practice docs warning that UA must enforce gas estimates on-chain; noticed getFeeEstimate exists but is never used for validation, and ILayerZeroUserApplicationConfig not implemented.
**Exploitation:** Attacker initiates a cheap high-payload call from a low-gas L2 (Polygon zkEVM/Optimism) with gasLimit=1, forcing the root-chain lzReceive to revert and blocking the src->root channel; protocol must pay Arbitrum gas to retryPayload, and attacker can re-block cheaply after each unblock.
**Escalation:** Repeat griefing after each retryPayload to keep channel permanently unusable from that source chain at low cost.
**Insight:** When a protocol passes user-controlled gas limits into a cross-chain messaging layer, check whether the destination lzReceive can be forced to revert — a single cheap low-gas call can wedge the entire channel because LayerZero blocks subsequent messages until retryPayload/forceResumeReceive.
