A receiver revert can stop a cross-chain swap’s destination delivery. With an EVM cross-chain message, the destination transaction first transfers the output token to the receiver, then calls its cfReceive function; if that call reverts, EVM atomicity rolls back the token transfer too. The swap may have succeeded on the source and in the swap protocol while the receiver gets nothing.
What exactly reverts?
In a cross-chain message (CCM), the receiver contract must implement cfReceive(uint32,bytes,bytes,address,uint256). The call includes the source chain and address, your message bytes, the output token address and amount. For native tokens, the amount is also sent as msg.value; for ERC-20s, the vault transfers tokens before calling the receiver.
That order makes receiver design a security issue as well as a delivery issue. Since the tokens have already arrived when cfReceive runs, a public function that trusts its arguments could be called by someone else with fabricated details. Restrict calls to the vault, or make the receiver’s logic verify that the expected funds actually arrived.
A plain token transfer to a contract is a different path: it does not call cfReceive. For example, the protocol documents that an Ethereum native-asset transfer can fail when a contract’s receive logic needs more than 8,000 gas. Don’t assume that a contract that accepts one kind of transfer can handle a CCM call, or vice versa.
How does the failure affect delivery?
The destination transaction is atomic: if cfReceive reverts, its earlier token transfer is rolled back. The EVM’s REVERT rule also rolls back state changes and logs from that execution. A successful swap on the source side therefore does not prove that the destination contract received tokens.
Before broadcast, the protocol simulates the transaction. If that simulation detects a revert, or the receiver does not implement the required interface, the transaction may not be broadcast. The signed payload can still be available for manual broadcast, but changing its gas settings cannot change the receiver address, message or call data. If the receiver logic itself always reverts, more gas will not repair it.
How much gas should you budget?
Set gas_budget to cover the receiver’s logic, then add a margin. Estimate with eth_estimateGas using the expected message and the vault as from; subtract the 21,000 base gas used in the protocol’s example, then apply your margin. The EVM CCM specification gives 10% as an example and caps the EVM destination gas limit at 10 million.
For example, say the call estimates at 210,000 gas including the base amount. Subtract 21,000 to get 189,000; with a 10% margin, set a budget of about 208,000. This is a starting point, not a guarantee: state changes, external calls and Arbitrum’s variable L1 inclusion costs can change execution needs. On Arbitrum, include those L1 costs in the estimate and refresh it when L1 gas prices move.
If you use Chainflip, include the CCM gas deduction and broadcast charges in your net-output comparison; Chainflip fees affect how much output remains after funding delivery. The protocol estimates the destination transaction cost from the requested budget and deducts it from the swap output; its public EVM CCM specification recommends allowing for unpredictable gas use and says unused gas is not refunded.
What should you choose or check before swapping?
Choose a CCM route when the destination contract needs to act on the received asset in the same transaction, and when you can test that exact call. A direct wallet payout avoids receiver-call failure modes, but it cannot execute your contract logic. For a receiver you control, catch failures from optional downstream calls where possible, so a failed integration does not revert the whole delivery.
Before sending, simulate the exact message and receiver state, confirm the interface and vault authorization, and check that the budget fits under the cap. If a delivery fails, inspect the destination transaction or broadcast status first: a gas shortfall may allow manual rebroadcast with more gas, while a logic revert needs a corrected receiver or a different destination. Ethereum or Arbitrum explorers can confirm whether execution reverted.
Questions to check after a failed delivery
Does a reverted destination call undo the swap?
No. The destination transaction’s token transfer is rolled back with the receiver call, but that does not automatically undo the already completed source-side deposit or swap. Check the protocol’s swap status and the destination broadcast status separately; they describe different stages of the route.
Can I fix a receiver revert by adding gas?
Only if the failure was caused by insufficient gas. A signed payload may be rebroadcast with higher gas settings, but its encoded receiver, message and call data stay fixed. If the contract rejects the caller, fails a condition or cannot handle the message, correct the receiver logic before trying another swap.
Should my receiver catch every external-call failure?
Catch failures from optional downstream actions when delivery should succeed without them. If the action is essential—for example, a required swap into another asset—silently catching its failure can leave funds in an unexpected state. Make that choice explicit in the contract and test both success and revert paths.
Where do I confirm what happened?
Use the destination chain’s explorer to inspect the transaction receipt and execution status, then compare its transaction hash and timing with the protocol’s swap or broadcast status. A reverted receipt means that execution did not preserve the token transfer; a missing destination transaction may indicate the protocol did not broadcast it.
- Test the receiver with the exact message and vault caller.
- Estimate gas, add a margin and include Arbitrum L1 costs where relevant.
- Check the destination receipt and swap status separately after failure.