diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e7490734f..e116a990d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,9 +12,11 @@ and this project adheres to - cosmwasm-std: Add iterators for `Coins` ([#1806]). - cosmwasm-std: Make `abs_diff` const for `Uint{256,512}` and `Int{64,128,256,512}`. It is now const for all integer types. +- cosmwasm-std: Implement `TryFrom` for `Decimal` ([#1832]) [#1799]: https://github.com/CosmWasm/cosmwasm/pull/1799 [#1806]: https://github.com/CosmWasm/cosmwasm/pull/1806 +[#1832]: https://github.com/CosmWasm/cosmwasm/pull/1832 ### Changed diff --git a/packages/std/src/math/decimal.rs b/packages/std/src/math/decimal.rs index 108b76b2e2..b8de3e90bc 100644 --- a/packages/std/src/math/decimal.rs +++ b/packages/std/src/math/decimal.rs @@ -11,7 +11,7 @@ use crate::errors::{ CheckedFromRatioError, CheckedMultiplyRatioError, DivideByZeroError, OverflowError, OverflowOperation, RoundUpOverflowError, StdError, }; -use crate::forward_ref_partial_eq; +use crate::{forward_ref_partial_eq, Decimal256}; use super::Fraction; use super::Isqrt; @@ -498,6 +498,18 @@ impl Fraction for Decimal { } } +impl TryFrom for Decimal { + type Error = DecimalRangeExceeded; + + fn try_from(value: Decimal256) -> Result { + value + .atomics() + .try_into() + .map(Decimal) + .map_err(|_| DecimalRangeExceeded) + } +} + impl FromStr for Decimal { type Err = StdError; @@ -817,6 +829,22 @@ mod tests { assert_eq!(value.0, Decimal::DECIMAL_FRACTIONAL / Uint128::from(80u8)); } + #[test] + fn decimal_from_decimal256_works() { + let too_big = Decimal256::new(Uint256::from(Uint128::MAX) + Uint256::one()); + assert_eq!(Decimal::try_from(too_big), Err(DecimalRangeExceeded)); + + let just_right = Decimal256::new(Uint256::from(Uint128::MAX)); + assert_eq!(Decimal::try_from(just_right), Ok(Decimal::MAX)); + + assert_eq!(Decimal::try_from(Decimal256::zero()), Ok(Decimal::zero())); + assert_eq!(Decimal::try_from(Decimal256::one()), Ok(Decimal::one())); + assert_eq!( + Decimal::try_from(Decimal256::percent(50)), + Ok(Decimal::percent(50)) + ); + } + #[test] fn decimal_from_atomics_works() { let one = Decimal::one();