# Cross-chain smart contract calls can revert but source chain tokens remain burnt and are not refunded

AxelarGateway.callContractWithToken burns source-chain tokens but has no refund path when the destination-chain contract call reverts, permanently losing user funds.

- Payout: Audit contest
- Severity: high
- Program: Axelar Network
- Credited: sseefried
- Disclosed: 2022-06-29
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-04-axelar-findings/issues/35
- Library page: https://bugbountylibrary.com/r/c4%3A2022-04-axelar%3AH-01
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** AxelarGateway cross-chain callContractWithToken / executeWithToken flow
**Root cause:** callContractWithToken burns tokens on the source chain but the protocol has no mechanism to detect a failed executeWithToken on the destination chain and re-mint/refund the user.
**Steps:**
1. Deploy TokenSwapper on destination chain with insufficient token B liquidity.
2. Call `AxelarGateway.callContractWithToken()` on source chain with token A amount; tokens burned at line 105.
3. Relay executes `executeWithToken` on destination; swap reverts due to insufficient token B.
4. Observe source-chain tokens remain burned with no refund; reducing token A amount makes the call succeed, confirming revert cause.
**How found:** Reasoned that smart contract calls commonly revert and that ERC20 semantics expect token return on failure; read callContractWithToken and found burn with no failure-handling path, then built a PoC using the repo's TokenSwapper to force a destination revert.
**Exploitation:** Any user initiating a cross-chain callWithToken to a destination contract that reverts (e.g. insufficient liquidity, logic failure) loses the burned source-chain tokens with no on-chain refund path.
**Insight:** For cross-chain token bridges, audit the failure/refund path of the destination execution, not just the happy path: force executeWithToken to revert (insufficient liquidity, reverting receiver) and check whether source-chain burned/minted tokens are recoverable.
