datahaven-xyz/datahaven · error · Error
InvalidTokenTransferFees
InvalidTokenTransferFees
Error message
InvalidTokenTransferFees
What it means
The system pallet's `set_token_transfer_fees` extrinsic throws `Error::InvalidTokenTransferFees` when fee validation fails: `create_asset_xcm` and `transfer_asset_xcm` must be non-zero, and `register_token` must be greater than `meth(100)` (100 units, intentionally expensive to deter token-registration spam). Fees that are zero or too cheap are rejected before dispatching the SetTokenTransferFees command to Ethereum.
Solutions
- Pass non-zero values for create_asset_xcm and transfer_asset_xcm.
- Ensure register_token is denominated correctly and exceeds meth(100); recompute from the fee policy before dispatching.
- Convert units explicitly (e.g. multiply decimals) in the proposal script to avoid denomination mistakes.
Example fix
// before let register_token = U256::from(100); // way below meth(100) minimum System::set_token_transfer_fees(origin, U256::one(), U256::one(), register_token)?; // after let one_hundred = meth(100); // e.g. 100 * 10^18 assert!(create_asset_xcm > 0 && transfer_asset_xcm > 0 && register_token > one_hundred); System::set_token_transfer_fees(origin, create_asset_xcm, transfer_asset_xcm, register_token)?;
Defensive patterns
Strategy: validation
Validate before calling
if (createAssetXcm === 0n || transferAssetXcm === 0n || registerToken <= meth(100)) throw new Error('fees fail policy'); Type guard
function feesSatisfyPolicy(c, t, r) { return c > 0n && t > 0n && r > meth(100); } Try / catch
try { await api.tx.system.setTokenTransferFees(c, t, r).signAndSend(root); } catch (e) { if (String(e).includes('InvalidTokenTransferFees')) { recalcFees(); } else { throw e; } } Prevention
- Centralize fee computation in one denomination-aware helper
- Never hardcode 0 for XCM fees
- Recompute register_token floor whenever unit conventions change
- Simulate the extrinsic before on-chain dispatch
When it happens
Trigger: Calling `set_token_transfer_fees(origin, create_asset_xcm, transfer_asset_xcm, register_token)` with root origin where either XCM fee is 0, or `register_token <= meth(100)` (i.e. at most 100 ETH-equivalent in the configured unit).
Common situations: Governance proposals setting fees in the wrong denomination (e.g. wei vs whole units) making register_token far below the 100-unit floor; typos passing 0 for an XCM fee; scripts copying fees from another chain with different units.
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/7e8d4c7850d54b73.
Report an issue: GitHub.
Appendix: source
Thrown at operator/pallets/system/src/lib.rs:374
/// - `origin`: Must be root
/// - `create_asset_xcm`: The XCM execution cost for creating a new asset class on AssetHub,
/// in DOT
/// - `transfer_asset_xcm`: The XCM execution cost for performing a reserve transfer on
/// AssetHub, in DOT
/// - `register_token`: The Ether fee for registering a new token, to discourage spamming
#[pallet::call_index(9)]
#[pallet::weight((T::WeightInfo::set_token_transfer_fees(), DispatchClass::Operational))]
pub fn set_token_transfer_fees(
origin: OriginFor<T>,
create_asset_xcm: u128,
transfer_asset_xcm: u128,
register_token: U256,
) -> DispatchResult {
ensure_root(origin)?;
// Basic validation of new costs. Particularly for token registration, we want to ensure
// its relatively expensive to discourage spamming. Like at least 100 USD.
ensure!(
create_asset_xcm > 0 && transfer_asset_xcm > 0 && register_token > meth(100),
Error::<T>::InvalidTokenTransferFees
);
let command = Command::SetTokenTransferFees {
create_asset_xcm,
transfer_asset_xcm,
register_token,
};
Self::send(PRIMARY_GOVERNANCE_CHANNEL, command, PaysFee::<T>::No)?;
Self::deposit_event(Event::<T>::SetTokenTransferFees {
create_asset_xcm,
transfer_asset_xcm,
register_token,
});
Ok(())
}View on GitHub (pinned to edcb13dbbc)