Better handle potential transfer error in `send_user_message`
Think of a better way of handling potential error when a message with a value is sent from a program to user which doesn't make it to the mailbox.
In such cases we make an immediate transfer of the value from the source to the destination in the send_user_message. With the changes being introduced (eliminating minimum transfer requirement) this is no longer infallible but can fail in case the user's account has insufficient funds and the value itself doesn't exceed the existential deposit. In this case we consider the value as dust and invoke the dust handler manually:
CurrencyOf::<T>::transfer(&from, &to, value, ExistenceRequirement::AllowDeath)
.unwrap_or_else(|e| match e {
DispatchError::Token(TokenError::BelowMinimum) => {
<CurrencyOf<T> as fungible::Unbalanced<_>>::handle_dust(fungible::Dust(value));
}
_ => {
// Other errors are ruled out by the protocol guarantees.
unreachable!("Failed to transfer value: {:?}", e)
}
});
The implementation above might be risky in case we suddenly start having other legitimate errors due to underlying changes in Substrate which would lead to a panic.
Apart from that, doing the exhaustive match of the DispatchError is impractical due to the latter having lots of variants only a small fraction of which can happen in a transfer.
We can just in any case of user sending message (either it goes to mailbox or event) just deposit value using pallet-gear-bank and call its transfer_value method, which handles situations when beneficiary has lower than ED balance.