9

Using the Substrate blockchain framework, how can I convert between Substrate specific types and Rust primitive types and vice versa?

For example:

  • Convert a time (T::Moment) to a u64
  • Convert a u64 to a T::Balance

etc...

Original: https://stackoverflow.com/questions/56081117/how-do-you-convert-between-substrate-specific-types-and-rust-primitive-types

1 Answer 1

7

For most Substrate specific types like BlockNumber, Balance, Nonce, etc... we guarentee that these types use a u32 with the AtLeast32Bit trait.

From the trait BaseArithmetic, the following are implemented:

  • From: u8, u16, u32
  • TryFrom: u64, u128, usize
  • TryInto: u8, u16, u32, u64, u128, usize

Another trait is also provided to provide ergonomic infallible conversion when you don't care if the value saturates.

  • UniqueSaturatedInto: u8, u16, u32, u64, u128
  • UniqueSaturatedFrom: u64, u128

NOTE on SaturatedConversion

SaturatedConversion (saturated_into and saturated_from) should not be used unless you know what you're doing, you've thought and considered all options and your use-case implies that saturation is fundamentally correct. The only time I imagine this is the case is deep in runtime arithmetic where you are logically certain it will not overflow, but can't provide a proof because it would depend on consistent pre-existing state.

This means that working from u32 to Substrate specific types should be easy:

pub fn u32_to_balance(input: u32) -> T::Balance {
    input.into()
}

For larger types, you need to handle the case where the Balance type for a runtime is smaller than what is available:

pub fn u64_to_balance_option(input: u64) -> Option<T::Balance> {
    input.try_into().ok()
}

// Note the warning above about saturated conversions
pub fn u64_to_balance_saturated(input: u64) -> T::Balance {
    input.saturated_into()
}

When converting from T::Balance to a rust primitive, you need to also handle conversion between incompatible types:

pub fn balance_to_u64(input: T::Balance) -> Option<u64> {
    TryInto::<u64>::try_into(input).ok()
}

// Note the warning above about saturated conversions
pub fn balance_to_u64_saturated(input: T::Balance) -> u64 {
    input.saturated_into::<u64>()
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.