๐งน Handling Cross-Chain Failures Gracefully
In single-chain flows, Supertransaction execution is atomic by defaultโeither all steps succeed or none do.
However, in cross-chain orchestration, there is no native atomicity guarantee. For example, a bridge transfer might succeed on the source chain, but fail on the destination chain due to unexpected conditions (e.g. protocol reverts, slippage, gas limits). In such cases, users may be left with partially executed operations and stranded tokens in intermediate smart accounts.
Cleanup transactions provide a partial solution to this limitation. By attaching a follow-up userOp to return leftover funds, developers can ensure users regain access to any unspent or unutilized tokens even after a failed orchestration.
This makes cleanup transactions a critical reliability feature for any multi-chain or multi-step workflow. They help preserve user trust, reduce support overhead, and ensure funds are never left behind due to unexpected cross-chain behavior.
โ๏ธ How It Works
- The SDK builds a
transfer
instruction constrained byruntimeNonceOf
. - Cleanup userOps stay in the mempool until all dependent instructions complete.
- Once constraints are met, the cleanup executes.
๐ For Fusion Orchestration
Learn how to set up Fusion Orhcestration
const quote = await meeClient.getFusionQuote({
trigger,
instructions,
cleanUps: [
{
chainId,
tokenAddress,
recipientAddress: eoa.address
}
],
feeToken: { chainId, address: tokenAddress }
});
- No
dependsOn
is neededโFusion batches into a single userOp.
๐ For EIP-7702 & Native SCA Orchestration
const quote = await meeClient.getQuote({
instructions,
cleanUps: [
{
chainId,
tokenAddress,
recipientAddress: eoa.address,
dependsOn: [userOp(2)],
amount: parseUnits("0.02", 6)
}
],
feeToken: { chainId, address: tokenAddress }
});
- Use
dependsOn
if cleanup must wait for specific instructions. - Otherwise, it defaults to the last executed instruction.
๐ธ Multi-Token Cleanup Example
cleanUps: [
{
tokenAddress: USDT,
dependsOn: [userOp(1)],
recipientAddress: eoa
},
{
tokenAddress: USDC,
dependsOn: [userOp(2)],
recipientAddress: eoa
}
];
Each cleanup executes independently after its dependency resolves.
๐ง Developer Tips
- Cleanup userOps always run last.
- Cleanup is skipped if the balance < 1 wei.
- In Fusion,
dependsOn
is almost never needed. - In Normal flows, specify
dependsOn
for non-sequential logic or multi-token flows.
These mechanics ensure seamless recovery even in the event of failure mid-orchestration.