diff --git a/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json b/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json index da54f8ccec..191c2bb60b 100644 --- a/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json @@ -24,7 +24,7 @@ "arguments": [ "23,000000000" ], - "gasLimit": "9,000,000", + "gasLimit": "50,000,000", "gasPrice": "0" }, "expect": { diff --git a/contracts/feature-tests/basic-features/scenarios/storage_i64_bad.scen.json b/contracts/feature-tests/basic-features/scenarios/storage_i64_bad.scen.json index 6fb3ab0c59..dff181e2d0 100644 --- a/contracts/feature-tests/basic-features/scenarios/storage_i64_bad.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/storage_i64_bad.scen.json @@ -33,7 +33,7 @@ "expect": { "out": [], "status": "*", - "message": "str:storage decode error (key: i64): argument out of range", + "message": "str:storage decode error (key: i64): value too long", "logs": "*", "gas": "*", "refund": "*" diff --git a/contracts/feature-tests/basic-features/scenarios/storage_u64_bad.scen.json b/contracts/feature-tests/basic-features/scenarios/storage_u64_bad.scen.json index c7597fd010..e0ccba911e 100644 --- a/contracts/feature-tests/basic-features/scenarios/storage_u64_bad.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/storage_u64_bad.scen.json @@ -33,7 +33,7 @@ "expect": { "out": [], "status": "4", - "message": "str:storage decode error (key: u64): input too long", + "message": "str:storage decode error (key: u64): value too long", "logs": "*", "gas": "*", "refund": "*" diff --git a/framework/base/src/err_msg.rs b/framework/base/src/err_msg.rs index 361775d5f9..0c08099d90 100644 --- a/framework/base/src/err_msg.rs +++ b/framework/base/src/err_msg.rs @@ -16,6 +16,7 @@ pub const ARG_ASYNC_RETURN_WRONG_NUMBER: &str = "wrong number of arguments retur pub const ARG_CALLBACK_TOO_FEW: &str = "too few callback arguments provided"; pub const ARG_CALLBACK_TOO_MANY: &str = "too many callback arguments provided"; +pub const VALUE_TOO_LONG: &str = "value too long"; pub const ARG_OUT_OF_RANGE: &str = "argument out of range"; pub const ARG_BAD_LENGTH: &str = "argument has wrong length"; pub const ARG_BAD_LENGTH_32: &str = "argument has wrong length: 32 bytes expected"; diff --git a/framework/base/src/storage/storage_get.rs b/framework/base/src/storage/storage_get.rs index 85107896dd..153103452e 100644 --- a/framework/base/src/storage/storage_get.rs +++ b/framework/base/src/storage/storage_get.rs @@ -95,7 +95,6 @@ where .into_max_size_buffer_align_right(buffer, h) } - #[inline] fn into_i64(self, h: H) -> Result where H: DecodeErrorHandler, @@ -103,6 +102,13 @@ where self.to_managed_buffer().into_i64(h) } + fn into_u64(self, h: H) -> Result + where + H: DecodeErrorHandler, + { + self.to_managed_buffer().into_u64(h) + } + #[inline] fn supports_specialized_type() -> bool { T::type_eq::>() || T::type_eq::>() || T::type_eq::>() diff --git a/framework/base/src/storage/storage_set.rs b/framework/base/src/storage/storage_set.rs index a2f3c3b722..28284b9b7e 100644 --- a/framework/base/src/storage/storage_set.rs +++ b/framework/base/src/storage/storage_set.rs @@ -3,7 +3,7 @@ use unwrap_infallible::UnwrapInfallible; use crate::{ api::{ const_handles, use_raw_handle, ErrorApi, ManagedBufferApiImpl, ManagedTypeApi, - StorageWriteApi, StorageWriteApiImpl, + ManagedTypeApiImpl, StorageWriteApi, StorageWriteApiImpl, }, codec::*, contract_base::ExitCodecErrorHandler, @@ -47,6 +47,20 @@ where self.set_managed_buffer(&bytes.into()) } + fn set_u64(self, value: u64) { + let handle: A::ManagedBufferHandle = use_raw_handle(const_handles::MBUF_TEMPORARY_1); + A::managed_type_impl().mb_from_small_int_unsigned(handle.clone(), value as i64); + let managed_buffer = ManagedBuffer::from_handle(handle); + self.set_managed_buffer(&managed_buffer); + } + + fn set_i64(self, value: i64) { + let handle: A::ManagedBufferHandle = use_raw_handle(const_handles::MBUF_TEMPORARY_1); + A::managed_type_impl().mb_from_small_int_signed(handle.clone(), value); + let managed_buffer = ManagedBuffer::from_handle(handle); + self.set_managed_buffer(&managed_buffer); + } + #[inline] fn supports_specialized_type() -> bool { T::type_eq::>() || T::type_eq::>() || T::type_eq::>() diff --git a/framework/base/src/types/managed/basic/managed_buffer.rs b/framework/base/src/types/managed/basic/managed_buffer.rs index de2dc63bb8..e52ef628a7 100644 --- a/framework/base/src/types/managed/basic/managed_buffer.rs +++ b/framework/base/src/types/managed/basic/managed_buffer.rs @@ -2,7 +2,7 @@ use crate::{ abi::{TypeAbi, TypeAbiFrom, TypeName}, api::{ use_raw_handle, ErrorApiImpl, HandleConstraints, InvalidSliceError, ManagedBufferApiImpl, - ManagedTypeApi, StaticVarApiImpl, + ManagedTypeApi, ManagedTypeApiImpl, StaticVarApiImpl, }, codec::{ DecodeErrorHandler, Empty, EncodeErrorHandler, NestedDecode, NestedDecodeInput, @@ -313,23 +313,25 @@ impl ManagedBuffer { } /// Convenience method for quickly getting a top-decoded u64 from the managed buffer. - /// - /// TODO: remove this method once TopDecodeInput is implemented for ManagedBuffer reference. pub fn parse_as_u64(&self) -> Option { const U64_NUM_BYTES: usize = 8; let l = self.len(); if l > U64_NUM_BYTES { return None; } - let mut bytes = [0u8; U64_NUM_BYTES]; - if M::managed_type_impl() - .mb_load_slice(self.handle.clone(), 0, &mut bytes[U64_NUM_BYTES - l..]) - .is_err() - { - None - } else { - Some(u64::from_be_bytes(bytes)) + let value = M::managed_type_impl().mb_to_small_int_unsigned(self.handle.clone()); + Some(value as u64) + } + + /// Convenience method for quickly getting a top-decoded i64 from the managed buffer. + pub fn parse_as_i64(&self) -> Option { + const I64_NUM_BYTES: usize = 8; + let l = self.len(); + if l > I64_NUM_BYTES { + return None; } + let value = M::managed_type_impl().mb_to_small_int_signed(self.handle.clone()); + Some(value) } /// Produces a hex expression in another managed buffer, diff --git a/framework/base/src/types/managed/codec_util/managed_buffer_top_de_input.rs b/framework/base/src/types/managed/codec_util/managed_buffer_top_de_input.rs index fb091781a2..d4ee079723 100644 --- a/framework/base/src/types/managed/codec_util/managed_buffer_top_de_input.rs +++ b/framework/base/src/types/managed/codec_util/managed_buffer_top_de_input.rs @@ -1,8 +1,5 @@ use crate::{ - api::{ - const_handles, managed_types::BigIntApiImpl, use_raw_handle, ManagedTypeApi, - ManagedTypeApiImpl, - }, + api::ManagedTypeApi, codec::{ try_execute_then_cast, DecodeError, DecodeErrorHandler, TopDecodeInput, TryStaticCast, }, @@ -67,12 +64,21 @@ where where H: DecodeErrorHandler, { - let big_int_temp: M::BigIntHandle = use_raw_handle(const_handles::BIG_INT_TEMPORARY_1); - M::managed_type_impl().mb_to_big_int_signed(self.handle.clone(), big_int_temp.clone()); - if let Some(value) = M::managed_type_impl().bi_to_i64(big_int_temp) { + if let Some(value) = self.parse_as_i64() { + Ok(value) + } else { + Err(h.handle_error(err_msg::VALUE_TOO_LONG.into())) + } + } + + fn into_u64(self, h: H) -> Result + where + H: DecodeErrorHandler, + { + if let Some(value) = self.parse_as_u64() { Ok(value) } else { - Err(h.handle_error(err_msg::ARG_OUT_OF_RANGE.into())) + Err(h.handle_error(err_msg::VALUE_TOO_LONG.into())) } }