datahaven-xyz/datahaven · error
TransfersDisabled
TransfersDisabled
Error message
TransfersDisabled
What it means
The datahaven-native-transfer pallet rejects transfer_to_ethereum calls while the pallet is paused. Paused::<T> is a global kill-switch; when set, all outbound transfers to Ethereum are disabled to allow maintenance or incident response. The extrinsic fails with the TransfersDisabled dispatch error before any funds move.
Solutions
- Have the pallet admin invoke the unpause extrinsic (with appropriate governance/manager origin) once transfers are safe to resume.
- Before submitting, query Paused::<T> storage and surface a user-friendly 'bridge paused' state instead of letting the tx fail.
- Retry the transfer after the pause is lifted; funds were never debited.
Example fix
// before: submit blindly
api.tx.datahavenNativeTransfer.transferToEthereum(recipient, amount, fee).signAndSend(account);
// after
const paused = await api.query.datahavenNativeTransfer.paused();
if (paused.isTrue) throw new Error('Bridge transfers are paused');
await api.tx.datahavenNativeTransfer.transferToEthereum(recipient, amount, fee).signAndSend(account); Defensive patterns
Strategy: validation
Validate before calling
// check pause state before submitting
const paused = await api.query.datahavenNativeTransfer.paused();
if (paused.isTrue) throw new Error('Bridge transfers are currently paused'); Try / catch
try {
await api.tx.datahavenNativeTransfer.transferToEthereum(recipient, amount, fee).signAndSend(account);
} catch (e) {
if (String(e).includes('TransfersDisabled')) notifyUser('Bridge paused; try again later');
else throw e;
} Prevention
- Subscribe to the paused storage item and disable transfer UI when set.
- Surface maintenance windows in the app before accepting user inputs.
- Never assume funds were debited when this error returns.
When it happens
Trigger: Submitting transfer_to_ethereum (extrinsic at lib.rs:180 region) while Paused::<T>::get() is true — i.e., after the pause admin/manager has called the pallet's pause operation.
Common situations: DApps or users attempting outbound bridge transfers during an active security pause or scheduled maintenance window; integrations not checking pause state before building transactions.
Related errors
AI-assisted analysis of datahaven-xyz/datahaven@edcb13dbbc (2026-09-13).
Data as JSON: /api/errors/82519da307760ae5.
Report an issue: GitHub.
Appendix: source
Thrown at operator/pallets/datahaven-native-transfer/src/lib.rs:180
/// Locks the tokens in the vault and sends a message through Snowbridge
/// to mint the equivalent tokens on Ethereum.
///
/// Parameters:
/// - `origin`: The account initiating the transfer
/// - `recipient`: The Ethereum address to receive the tokens
/// - `amount`: The amount of tokens to transfer
/// - `fee`: The fee to incentivize relayers (in native tokens)
#[pallet::call_index(0)]
#[pallet::weight(T::WeightInfo::transfer_to_ethereum())]
pub fn transfer_to_ethereum(
origin: OriginFor<T>,
recipient: H160,
amount: BalanceOf<T>,
fee: BalanceOf<T>,
) -> DispatchResult {
let who = ensure_signed(origin)?;
ensure!(!Paused::<T>::get(), Error::<T>::TransfersDisabled);
// Get the token ID - fails if not registered
let token_id = T::NativeTokenId::get().ok_or(Error::<T>::TokenNotRegistered)?;
ensure!(amount > Zero::zero(), Error::<T>::InvalidAmount);
ensure!(fee > Zero::zero(), Error::<T>::ZeroFee);
ensure!(
recipient != H160::zero(),
Error::<T>::InvalidEthereumAddress
);
// Transfer fee to recipient
T::Currency::transfer(&who, &T::FeeRecipient::get(), fee, Preservation::Preserve)?;
// Lock tokens in the sovereign account
Self::lock_tokens(&who, amount)?;
// Build and send the messageView on GitHub (pinned to edcb13dbbc)