I know there is a concept "ED", which means that if the account balance is below this value, it will be wiped out. I tried to figure out how it works. The `AccountData` is defined in the runtime while stored in the `frame-system` pallet. `try_mutate_exists` in the `frame_system` pallet used to mutate `AccountData`, but how and where does the substrate system wipe the account whose balance below ED? I find `OnKilledAccount` type in the `frame_system::Config`, but it's more like a callback after the account has been killed. 

```rs
impl<T: Config> StoredMap<T::AccountId, T::AccountData> for Pallet<T> {
    fn get(k: &T::AccountId) -> T::AccountData {
        Account::<T>::get(k).data
    }

    fn try_mutate_exists<R, E: From<DispatchError>>(
        k: &T::AccountId,
        f: impl FnOnce(&mut Option<T::AccountData>) -> Result<R, E>,
    ) -> Result<R, E> {
        let account = Account::<T>::get(k);
        let was_providing = is_providing(&account.data);
        let mut some_data = if was_providing {
            Some(account.data)
        } else {
            None
        };
        let result = f(&mut some_data)?;
        let is_providing = some_data.is_some();
        if !was_providing && is_providing {
            Self::inc_providers(k);
        } else if was_providing && !is_providing {
            match Self::dec_providers(k)? { // This may trigger account wipe
                DecRefStatus::Reaped => return Ok(result),
                DecRefStatus::Exists => {
                    // Update value as normal...
                }
            }
        } else if !was_providing && !is_providing {
            return Ok(result);
        }
        Account::<T>::mutate(k, |a| a.data = some_data.unwrap_or_default());
        Ok(result)
    }
}
```