When PayFees instruction contains the exact fee amount quoted by query_weight_to_asset_fee, the swap in SwapFirstAssetTrader::buy_weight produces zero change. This zero-amount credit is unconditionally wrapped into an AssetsInHolding entry:
let unspent = AssetsInHolding::new_from_fungible_credit(id, Box::new(credit_change));
payment.subsume_assets(unspent);
This 0-amount entry propagates:
- buy_weight returns it as unspent → PayFees handler puts it in self.fees
- refund_surplus() moves leftover fees into self.holding
- post_process() calls drop_assets() because holding appears non-empty
- drop_assets() emits AssetsTrapped event containing Fungible(0)
- Fungibility::decode() rejects Fungible(0): "Fungible asset of zero amount is not allowed"
Fix: Guard buy_weight against 0-amount change, matching the existing pattern in refund_weight:
if credit_change.peek() > 0 {
let unspent = AssetsInHolding::new_from_fungible_credit(id, Box::new(credit_change));
payment.subsume_assets(unspent);
}
Discovered in: PR #10726, commit a2740c6