# Unspent gas fees are always refunded to the FeePayer() which leads to incorrect refunds if the FeeGranter() paid for the fees

MANTRA's FeeMarketDeductDecorator refunds unspent gas to FeePayer() instead of FeeGranter(), letting grantees drain a granter's granted funds.

- Payout: Audit contest
- Severity: high
- Program: MANTRA
- Found by: berndartmueller
- Disclosed: 2025-03-31
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2024-11-mantra-chain#h-02
- Library page: https://bugbountylibrary.com/r/c4%3A2024-11-mantra-chain%3AH-02
- Tags: area:web3 domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:go technique:source-review vuln:accounting-error vuln:business-logic

**Target:** Cosmos SDK fee market post-handler (x/xfeemarket/post/fee.go)
**Root cause:** PostHandle passes feeTx.FeePayer() to BurnFeeAndRefund, which refunds the tip/unspent fees to that address regardless of whether a FeeGranter actually paid.
**Steps:**
1. Set up a feegrant allowance from granter G to grantee P.
2. Submit a tx from P with a fee granter set to G and a tip.
3. PostHandle calls BurnFeeAndRefund with feePayer = P.
4. RefundTip sends the tip/unspent fees to P via SendCoinsFromModuleToAccount, not G.
5. Repeat to drain G's granted funds while P collects refunds.
**How found:** Code review of the fee market post-handler: noticed refund path uses FeePayer() without checking FeeGranter(), a mismatch with who actually paid.
**Exploitation:** A grantee repeatedly submits fee-granted transactions; each refund of unspent gas/tip accrues to the grantee rather than the granter, draining the granter's allowance over time.
**Insight:** In Cosmos SDK fee handling, always verify refund/rebate recipients against the actual payer (FeeGranter vs FeePayer); feegrant flows are a common source of misdirected refunds.

