datahaven-xyz/datahaven · error

ZeroFee

ZeroFee

Error message

ZeroFee

What it means

transfer_to_ethereum requires a strictly positive fee (fee > Zero::zero()). The fee is paid to T::FeeRecipient to compensate relayers; a zero fee would make relaying economically unviable and is therefore rejected with ZeroFee before any state changes.

Solutions

  1. Pass a fee greater than zero, at or above any configured minimum relayer fee.
  2. Update UI/scripts to require and validate a non-zero fee field before submission.
  3. Consult current relayer fee conventions to pick an acceptable fee value.

Example fix

// before
const fee = 0n;
await api.tx.datahavenNativeTransfer.transferToEthereum(recipient, amount, fee);
// after
const fee = await getMinRelayerFee(); // must be > 0
await api.tx.datahavenNativeTransfer.transferToEthereum(recipient, amount, fee);
Defensive patterns

Strategy: validation

Validate before calling

if (fee <= 0n) throw new Error('A positive relayer fee is required');

Type guard

const isValidFee = (fee) => typeof fee === 'bigint' && fee > 0n;

Try / catch

try {
  await transferToEthereum(recipient, amount, fee);
} catch (e) {
  if (String(e).includes('ZeroFee')) showFormError('Please set a non-zero relayer fee');
  else throw e;
}

Prevention

When it happens

Trigger: Calling transfer_to_ethereum with fee == 0, regardless of a valid amount and recipient.

Common situations: Frontends defaulting fee to 0 and not forcing the user to set a relayer fee; scripts omitting the fee parameter (defaulting to 0); protocol changes raising a minimum fee that old integrations don't honor.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of datahaven-xyz/datahaven@edcb13dbbc (2026-09-13). Data as JSON: /api/errors/0cf652acddda8e08. Report an issue: GitHub.

Appendix: source

Thrown at operator/pallets/datahaven-native-transfer/src/lib.rs:186

        /// - `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 message
            let message = Self::build_mint_message(token_id, recipient, amount, fee)?;
            T::OutboundQueue::validate(&message)
                .and_then(|ticket| T::OutboundQueue::deliver(ticket))
                .map_err(|_| Error::<T>::SendMessageFailed)?;

            Self::deposit_event(Event::TokensTransferredToEthereum {

View on GitHub (pinned to edcb13dbbc)