Skip to content

Commit

Permalink
Merge pull request multiversx#1889 from multiversx/mdec-fixes
Browse files Browse the repository at this point in the history
ManagedDecimal - 2 bug fixes
  • Loading branch information
andrei-marinica authored Dec 3, 2024
2 parents 2226062 + bf4bf77 commit 35acf8d
Show file tree
Hide file tree
Showing 14 changed files with 204 additions and 51 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
name: Contracts
uses: multiversx/mx-sc-actions/.github/workflows/contracts.yml@4ec1f927bd99ed90a816ded805daa75fd2040258
with:
rust-toolchain: stable
rust-toolchain: 1.82
path-to-sc-meta: framework/meta
mx-scenario-go-version: v2.1.0-alpha
coverage-args: --ignore-filename-regex='meta/src' --ignore-filename-regex='wasm-adapter' --ignore-filename-regex='benchmarks/' --ignore-filename-regex='tests/' --output ./coverage.md
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lldb-formatter-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
default: true
toolchain: stable
toolchain: 1.82

- name: Download vscode-lldb
uses: robinraju/[email protected]
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/plotter-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- name: Install rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
toolchain: 1.82
target: wasm32-unknown-unknown

- name: Run plotter tests
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/proxy-compare.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
default: true
toolchain: stable
toolchain: 1.82
target: wasm32-unknown-unknown

- name: Install prerequisites
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/template-test-current.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
default: true
toolchain: stable
toolchain: 1.82
target: wasm32-unknown-unknown

- name: Install prerequisites
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/template-test-released.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
default: true
toolchain: stable
toolchain: 1.82
target: wasm32-unknown-unknown

- name: Install prerequisites
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,21 @@
}
]
},
{
"name": "process_managed_decimal",
"mutability": "mutable",
"inputs": [
{
"name": "input",
"type": "ManagedDecimal<10>"
}
],
"outputs": [
{
"type": "ManagedDecimal<usize>"
}
]
},
{
"name": "esdt_local_role",
"mutability": "mutable",
Expand Down
13 changes: 13 additions & 0 deletions contracts/feature-tests/abi-tester/src/abi_proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,19 @@ where
.original_result()
}

pub fn process_managed_decimal<
Arg0: ProxyArg<ManagedDecimal<Env::Api, ConstDecimals<10>>>,
>(
self,
input: Arg0,
) -> TxTypedCall<Env, From, To, NotPayable, Gas, ManagedDecimal<Env::Api, usize>> {
self.wrapped_tx
.payment(NotPayable)
.raw_call("process_managed_decimal")
.argument(&input)
.original_result()
}

pub fn esdt_local_role(
self,
) -> TxTypedCall<Env, From, To, NotPayable, Gas, EsdtLocalRole> {
Expand Down
8 changes: 8 additions & 0 deletions contracts/feature-tests/abi-tester/src/abi_tester.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,14 @@ pub trait AbiTester {
(address, byte_array).into()
}

#[endpoint]
fn process_managed_decimal(
&self,
input: ManagedDecimal<Self::Api, ConstDecimals<10>>,
) -> ManagedDecimal<Self::Api, usize> {
input.into()
}

#[endpoint]
fn esdt_local_role(&self) -> EsdtLocalRole {
EsdtLocalRole::None
Expand Down
5 changes: 3 additions & 2 deletions contracts/feature-tests/abi-tester/wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@

// Init: 1
// Upgrade: 1
// Endpoints: 29
// Endpoints: 30
// Async Callback (empty): 1
// Total number of exported functions: 32
// Total number of exported functions: 33

#![no_std]

Expand All @@ -31,6 +31,7 @@ multiversx_sc_wasm_adapter::endpoints! {
optional_result => optional_result
address_vs_h256 => address_vs_h256
managed_address_vs_byte_array => managed_address_vs_byte_array
process_managed_decimal => process_managed_decimal
esdt_local_role => esdt_local_role
esdt_token_payment => esdt_token_payment
esdt_token_data => esdt_token_data
Expand Down
14 changes: 13 additions & 1 deletion framework/base/src/types/managed/wrapped/managed_decimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ impl<M: ManagedTypeApi, D: Decimals> ManagedDecimal<M, D> {
Ordering::Greater => {
let delta_decimals = from_num_decimals - scale_to_num_decimals;
let scaling_factor: &BigUint<M> = &delta_decimals.scaling_factor();
&self.data * scaling_factor
&self.data / scaling_factor
},
}
}
Expand Down Expand Up @@ -128,6 +128,14 @@ impl<M: ManagedTypeApi, const DECIMALS: NumDecimals> ManagedDecimal<M, ConstDeci
}
}

impl<M: ManagedTypeApi, const DECIMALS: NumDecimals>
From<ManagedDecimal<M, ConstDecimals<DECIMALS>>> for ManagedDecimal<M, NumDecimals>
{
fn from(value: ManagedDecimal<M, ConstDecimals<DECIMALS>>) -> Self {
value.into_var_decimals()
}
}

impl<M: ManagedTypeApi, const DECIMALS: NumDecimals> TopEncode
for ManagedDecimal<M, ConstDecimals<DECIMALS>>
{
Expand Down Expand Up @@ -252,6 +260,10 @@ impl<M: ManagedTypeApi> TypeAbi for ManagedDecimal<M, NumDecimals> {
TypeName::from("ManagedDecimal<usize>")
}

fn type_name_rust() -> TypeName {
TypeName::from("ManagedDecimal<$API, usize>")
}

fn is_variadic() -> bool {
false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ impl<M: ManagedTypeApi, D: Decimals> ManagedDecimalSigned<M, D> {
Ordering::Greater => {
let delta_decimals = from_num_decimals - scale_to_num_decimals;
let scaling_factor: &BigUint<M> = &delta_decimals.scaling_factor();
&self.data * &scaling_factor.value
&self.data / &scaling_factor.value
},
}
}
Expand Down
184 changes: 144 additions & 40 deletions framework/scenario/tests/managed_decimal_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use multiversx_sc::{
codec::test_util::{check_dep_encode_decode, check_top_encode_decode},
derive::{debug_const_managed_decimal, debug_managed_decimal},
types::{
BigFloat, BigInt, BigUint, ConstDecimals, ManagedDecimal, ManagedDecimalSigned, NumDecimals,
BigFloat, BigInt, BigUint, ConstDecimals, Decimals, ManagedDecimal, ManagedDecimalSigned,
NumDecimals,
},
};
use multiversx_sc_scenario::api::StaticApi;
Expand Down Expand Up @@ -38,33 +39,83 @@ pub fn test_managed_decimal() {
division,
ManagedDecimal::<StaticApi, ConstDecimals<2>>::from(BigUint::from(5u64))
);
}

fn assert_exact<D: Decimals>(dec: &ManagedDecimal<StaticApi, D>, raw_u64: u64, scale: usize) {
let raw_units = BigUint::from(raw_u64);
assert_eq!(dec.scale(), scale);
assert_eq!(dec.into_raw_units(), &raw_units);
assert_eq!(dec, &ManagedDecimal::from_raw_units(raw_units, scale));
}

let fixed_4: ManagedDecimal<StaticApi, NumDecimals> =
#[test]
pub fn test_managed_decimal_rescale_unchanged() {
let dec: ManagedDecimal<StaticApi, NumDecimals> =
ManagedDecimal::from_raw_units(BigUint::from(100u64), 2usize);
let fixed_5 = fixed_4.rescale(2usize);
assert_exact(&dec, 100u64, 2);
let rescaled = dec.rescale(2usize);
assert_exact(&rescaled, 100u64, 2);
assert_eq!(
fixed_5,
rescaled,
ManagedDecimal::from_raw_units(BigUint::from(100000000u64), 8usize)
);
}

let fixed_6: ManagedDecimal<StaticApi, ConstDecimals<2>> =
ManagedDecimal::from(BigUint::from(1500u64));
let fixed_7 = fixed_6.rescale(ConstDecimals::<8>);
#[test]
pub fn test_managed_decimal_rescale_up() {
let uint_value = 1500u64;
let dec: ManagedDecimal<StaticApi, ConstDecimals<2>> =
ManagedDecimal::from(BigUint::from(uint_value));
assert_exact(&dec, uint_value * 100, 2);
let rescaled = dec.rescale(ConstDecimals::<8>);
assert_exact(&rescaled, uint_value * 100000000, 8);
assert_eq!(
fixed_7,
ManagedDecimal::<StaticApi, ConstDecimals<8>>::from(BigUint::from(1500u64))
rescaled,
ManagedDecimal::<StaticApi, ConstDecimals<8>>::from(BigUint::from(uint_value))
);
}

let fixed_8: ManagedDecimal<StaticApi, NumDecimals> =
ManagedDecimal::from_raw_units(BigUint::from(5u64), 5usize);
let fixed_9 = fixed_8.rescale(ConstDecimals::<3>);
#[test]
pub fn test_managed_decimal_rescale_down_1() {
// 1234.0000000 -> 1234.
let uint_value = 1234u64;
let dec: ManagedDecimal<StaticApi, ConstDecimals<7>> =
ManagedDecimal::from(BigUint::from(uint_value));
assert_exact(&dec, uint_value * 10000000, 7);
let rescaled = dec.rescale(ConstDecimals::<3>);
assert_exact(&rescaled, uint_value * 1000, 3);
}

#[test]
pub fn test_managed_decimal_rescale_down_2() {
// 0.00009 -> 0.0000
let dec: ManagedDecimal<StaticApi, NumDecimals> =
ManagedDecimal::from_raw_units(BigUint::from(9u64), 5usize);
assert_exact(&dec, 9, 5);
let rescaled = dec.rescale(ConstDecimals::<4>);
assert_exact(&rescaled, 0, 4);
assert_eq!(
fixed_9,
ManagedDecimal::<StaticApi, ConstDecimals<3>>::const_decimals_from_raw(BigUint::from(
500u64
))
rescaled,
ManagedDecimal::<StaticApi, ConstDecimals<4>>::from(BigUint::zero())
);
}

#[test]
pub fn test_managed_decimal_rescale_down_3() {
// 1.00009 -> 1.0000
let dec: ManagedDecimal<StaticApi, NumDecimals> =
ManagedDecimal::from_raw_units(BigUint::from(100009u64), 5usize);
assert_exact(&dec, 100009, 5);
let rescaled = dec.rescale(ConstDecimals::<4>);
assert_exact(&rescaled, 10000, 4);
assert_eq!(
rescaled,
ManagedDecimal::<StaticApi, ConstDecimals<4>>::from(BigUint::from(1u64))
);
}

#[test]
pub fn test_managed_decimal_from_big_float() {
let float_1 = BigFloat::<StaticApi>::from_frac(3i64, 2i64);
let fixed_float_1 = ManagedDecimalSigned::<StaticApi, ConstDecimals<1>>::from_big_float(
&float_1,
Expand Down Expand Up @@ -166,6 +217,83 @@ pub fn test_addition_managed_decimal_signed() {
assert_eq!(addition_4.trunc(), BigInt::from(1i64));
}

fn assert_exact_signed<D: Decimals>(
dec: &ManagedDecimalSigned<StaticApi, D>,
raw_u64: i64,
scale: usize,
) {
let raw_units = BigInt::from(raw_u64);
assert_eq!(dec.scale(), scale);
assert_eq!(dec.into_raw_units(), &raw_units);
assert_eq!(dec, &ManagedDecimalSigned::from_raw_units(raw_units, scale));
}

#[test]
pub fn test_managed_decimal_signed_rescale_unchanged() {
let dec: ManagedDecimalSigned<StaticApi, NumDecimals> =
ManagedDecimalSigned::from_raw_units(BigInt::from(100), 2usize);
assert_exact_signed(&dec, 100, 2);
let rescaled = dec.rescale(2usize);
assert_exact_signed(&rescaled, 100, 2);
assert_eq!(
rescaled,
ManagedDecimalSigned::from_raw_units(BigInt::from(100000000), 8usize)
);
}

#[test]
pub fn test_managed_decimal_signed_rescale_up() {
let uint_value = -1500i64;
let dec: ManagedDecimalSigned<StaticApi, ConstDecimals<2>> =
ManagedDecimalSigned::from(BigInt::from(uint_value));
assert_exact_signed(&dec, uint_value * 100, 2);
let rescaled = dec.rescale(ConstDecimals::<8>);
assert_exact_signed(&rescaled, uint_value * 100000000, 8);
assert_eq!(
rescaled,
ManagedDecimalSigned::<StaticApi, ConstDecimals<8>>::from(BigInt::from(uint_value))
);
}

#[test]
pub fn test_managed_decimal_signed_rescale_down_1() {
// -1234.0000000 -> -1234.
let uint_value = -1234;
let dec: ManagedDecimalSigned<StaticApi, ConstDecimals<7>> =
ManagedDecimalSigned::from(BigInt::from(uint_value));
assert_exact_signed(&dec, uint_value * 10000000, 7);
let rescaled = dec.rescale(ConstDecimals::<3>);
assert_exact_signed(&rescaled, uint_value * 1000, 3);
}

#[test]
pub fn test_managed_decimal_signed_rescale_down_2() {
// 0.00009 -> 0.0000
let dec: ManagedDecimalSigned<StaticApi, NumDecimals> =
ManagedDecimalSigned::from_raw_units(BigInt::from(-9), 5usize);
assert_exact_signed(&dec, -9, 5);
let rescaled = dec.rescale(ConstDecimals::<4>);
assert_exact_signed(&rescaled, 0, 4);
assert_eq!(
rescaled,
ManagedDecimalSigned::<StaticApi, ConstDecimals<4>>::from(BigInt::zero())
);
}

#[test]
pub fn test_managed_decimal_signed_rescale_down_3() {
// -1.00009 -> -1.0000
let dec: ManagedDecimalSigned<StaticApi, NumDecimals> =
ManagedDecimalSigned::from_raw_units(BigInt::from(-100009), 5usize);
assert_exact_signed(&dec, -100009, 5);
let rescaled = dec.rescale(ConstDecimals::<4>);
assert_exact_signed(&rescaled, -10000, 4);
assert_eq!(
rescaled,
ManagedDecimalSigned::<StaticApi, ConstDecimals<4>>::from(BigInt::from(-1))
);
}

#[test]
pub fn test_substraction_managed_decimal_signed() {
let fixed_1 = ManagedDecimalSigned::<StaticApi, ConstDecimals<2>>::from(BigInt::from(1i64));
Expand Down Expand Up @@ -260,30 +388,6 @@ pub fn test_devision_managed_decimal_signed() {

#[test]
pub fn test_rescale_managed_decimal_signed() {
let fixed_1: ManagedDecimalSigned<StaticApi, NumDecimals> =
ManagedDecimalSigned::from_raw_units(BigInt::from(-10000i64), 2usize);

let fixed_2 = fixed_1.rescale(3usize);
assert_eq!(
fixed_2,
ManagedDecimalSigned::from_raw_units(BigInt::from(-100000000i64), 6usize)
);

let fixed_3: ManagedDecimalSigned<StaticApi, ConstDecimals<2>> =
ManagedDecimalSigned::from(BigInt::from(-1500i64));
let fixed_4 = fixed_3.rescale(ConstDecimals::<8>);
assert_eq!(fixed_4.into_raw_units(), &BigInt::from(-150000000000i64));

let fixed_5: ManagedDecimalSigned<StaticApi, NumDecimals> =
ManagedDecimalSigned::from_raw_units(BigInt::from(-5i64), 5usize);
let fixed_6 = fixed_5.rescale(ConstDecimals::<3>);
assert_eq!(
fixed_6,
ManagedDecimalSigned::<StaticApi, ConstDecimals<3>>::const_decimals_from_raw(BigInt::from(
-500i64
))
);

let float_1 = BigFloat::<StaticApi>::from_frac(-3i64, 2i64);
let fixed_float_1 = ManagedDecimalSigned::<StaticApi, ConstDecimals<1>>::from_big_float(
&float_1,
Expand Down
Loading

0 comments on commit 35acf8d

Please sign in to comment.