From 0f08f80cf48fb5fa9db4a1514c49f77409e0d8d5 Mon Sep 17 00:00:00 2001 From: hal3e Date: Mon, 19 Feb 2024 14:04:42 +0100 Subject: [PATCH 01/30] feat!: new encoding --- packages/fuels/Forc.toml | 3 +++ .../fuels/tests/types/contracts/type_inside_enum/src/main.sw | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/fuels/Forc.toml b/packages/fuels/Forc.toml index 525eb44489..707dd5c4df 100644 --- a/packages/fuels/Forc.toml +++ b/packages/fuels/Forc.toml @@ -104,3 +104,6 @@ members = [ 'tests/types/scripts/script_u256', 'tests/types/scripts/script_vectors', ] + +[patch.'https://github.com/fuellabs/sway'] +std = { git = "https://github.com/fuellabs/sway", branch = "xunilrj/encoding-contract-call" } diff --git a/packages/fuels/tests/types/contracts/type_inside_enum/src/main.sw b/packages/fuels/tests/types/contracts/type_inside_enum/src/main.sw index 019109c243..3f6a0978f1 100644 --- a/packages/fuels/tests/types/contracts/type_inside_enum/src/main.sw +++ b/packages/fuels/tests/types/contracts/type_inside_enum/src/main.sw @@ -3,7 +3,7 @@ contract; #[allow(dead_code)] enum SomeEnum { SomeStr: str[4], - SomeArr: [u64; 7], + SomeArr: [u64; 2], } #[allow(dead_code)] From b04d73d57ba611a7360f51a51de54bc25025a6d2 Mon Sep 17 00:00:00 2001 From: hal3e Date: Mon, 26 Feb 2024 10:18:03 +0100 Subject: [PATCH 02/30] Work in progress --- packages/fuels/tests/contracts.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/fuels/tests/contracts.rs b/packages/fuels/tests/contracts.rs index 231b26b362..9a27ecfaca 100644 --- a/packages/fuels/tests/contracts.rs +++ b/packages/fuels/tests/contracts.rs @@ -28,6 +28,7 @@ async fn test_multiple_args() -> Result<()> { // Make sure we can call the contract with multiple arguments let contract_methods = contract_instance.methods(); let response = contract_methods.get(5, 6).call().await?; + dbg!(&response); assert_eq!(response.value, 11); From bc3f94e736db7de789ab21c3d194e6e300296656 Mon Sep 17 00:00:00 2001 From: hal3e Date: Thu, 7 Mar 2024 13:12:40 +0100 Subject: [PATCH 03/30] update sway --- .../tests/contracts/lib_contract/src/main.sw | 16 ---------------- .../tests/predicates/signatures/src/main.sw | 3 ++- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/packages/fuels/tests/contracts/lib_contract/src/main.sw b/packages/fuels/tests/contracts/lib_contract/src/main.sw index ae4cf896e4..bedcd0610f 100644 --- a/packages/fuels/tests/contracts/lib_contract/src/main.sw +++ b/packages/fuels/tests/contracts/lib_contract/src/main.sw @@ -2,22 +2,6 @@ contract; use lib_contract::LibContract; -impl AbiEncode for str[21] { - fn abi_encode(self, ref mut buffer: Buffer) { - let s = from_str_array(self); - - let len = s.len(); - let ptr = s.as_ptr(); - - let mut i = 0; - while i < len { - let byte = ptr.add::(i).read::(); - buffer.push(byte); - i += 1; - } - } -} - impl LibContract for Contract { fn increment(value: u64) -> u64 { value + 1 diff --git a/packages/fuels/tests/predicates/signatures/src/main.sw b/packages/fuels/tests/predicates/signatures/src/main.sw index fc7fbb1910..c9a29fbcdc 100644 --- a/packages/fuels/tests/predicates/signatures/src/main.sw +++ b/packages/fuels/tests/predicates/signatures/src/main.sw @@ -5,10 +5,11 @@ use std::{b512::B512, constants::ZERO_B256, ecr::ec_recover_address, inputs::inp fn extract_public_key_and_match(signature: B512, expected_public_key: b256) -> u64 { if let Result::Ok(pub_key_sig) = ec_recover_address(signature, ZERO_B256) { - if pub_key_sig.value == expected_public_key { + if pub_key_sig == Address::from(expected_public_key) { return 1; } } + 0 } From 0ef792d9141102c5642387fbef63cf237802ce83 Mon Sep 17 00:00:00 2001 From: hal3e Date: Sat, 9 Mar 2024 11:24:31 +0100 Subject: [PATCH 04/30] encoder - scripts --- packages/fuels-core/src/codec/abi_decoder.rs | 26 +--- .../experimental_bounded_decoder.rs | 51 ++----- packages/fuels-core/src/codec/abi_encoder.rs | 13 +- .../experimental_bounded_encoder.rs | 136 ++++++++++++++++++ packages/fuels-core/src/codec/logs.rs | 29 +--- packages/fuels-core/src/types.rs | 14 +- packages/fuels-core/src/types/param_types.rs | 4 + .../fuels-core/src/types/unresolved_bytes.rs | 1 + packages/fuels-programs/src/contract.rs | 4 + packages/fuels-programs/src/receipt_parser.rs | 5 + packages/fuels/Forc.toml | 2 +- packages/fuels/tests/scripts.rs | 3 + packages/fuels/tests/types_contracts.rs | 1 + packages/fuels/tests/types_scripts.rs | 27 +++- 14 files changed, 209 insertions(+), 107 deletions(-) create mode 100644 packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs diff --git a/packages/fuels-core/src/codec/abi_decoder.rs b/packages/fuels-core/src/codec/abi_decoder.rs index 27f171b857..00664d8cca 100644 --- a/packages/fuels-core/src/codec/abi_decoder.rs +++ b/packages/fuels-core/src/codec/abi_decoder.rs @@ -1,13 +1,13 @@ -mod bounded_decoder; #[cfg(experimental)] +mod bounded_decoder; +#[cfg(not(experimental))] mod experimental_bounded_decoder; #[cfg(experimental)] -use crate::codec::abi_decoder::experimental_bounded_decoder::ExperimentalBoundedDecoder; -use crate::{ - codec::abi_decoder::bounded_decoder::BoundedDecoder, - types::{errors::Result, param_types::ParamType, Token}, -}; +use crate::codec::abi_decoder::bounded_decoder::BoundedDecoder; +#[cfg(not(experimental))] +use crate::codec::abi_decoder::experimental_bounded_decoder::BoundedDecoder; +use crate::types::{errors::Result, param_types::ParamType, Token}; #[derive(Debug, Clone, Copy)] pub struct DecoderConfig { @@ -81,20 +81,6 @@ impl ABIDecoder { pub fn decode_multiple(&self, param_types: &[ParamType], bytes: &[u8]) -> Result> { BoundedDecoder::new(self.config).decode_multiple(param_types, bytes) } - - #[cfg(experimental)] - pub fn experimental_decode(&self, param_type: &ParamType, bytes: &[u8]) -> Result { - ExperimentalBoundedDecoder::new(self.config).decode(param_type, bytes) - } - - #[cfg(experimental)] - pub fn experimental_decode_multiple( - &self, - param_types: &[ParamType], - bytes: &[u8], - ) -> Result> { - ExperimentalBoundedDecoder::new(self.config).decode_multiple(param_types, bytes) - } } #[cfg(test)] diff --git a/packages/fuels-core/src/codec/abi_decoder/experimental_bounded_decoder.rs b/packages/fuels-core/src/codec/abi_decoder/experimental_bounded_decoder.rs index 5876b387f4..e2d382785e 100644 --- a/packages/fuels-core/src/codec/abi_decoder/experimental_bounded_decoder.rs +++ b/packages/fuels-core/src/codec/abi_decoder/experimental_bounded_decoder.rs @@ -1,7 +1,10 @@ use std::{iter::repeat, str}; use crate::{ - codec::DecoderConfig, + codec::{ + utils::{CodecDirection, CounterWithLimit}, + DecoderConfig, + }, constants::WORD_SIZE, types::{ enum_variants::EnumVariants, @@ -13,7 +16,7 @@ use crate::{ /// Is used to decode bytes into `Token`s from which types implementing `Tokenizable` can be /// instantiated. Implements decoding limits to control resource usage. -pub(crate) struct ExperimentalBoundedDecoder { +pub(crate) struct BoundedDecoder { depth_tracker: CounterWithLimit, token_tracker: CounterWithLimit, } @@ -28,10 +31,12 @@ const B256_BYTES_SIZE: usize = 4 * WORD_SIZE; const LENGTH_BYTES_SIZE: usize = WORD_SIZE; const DISCRIMINANT_BYTES_SIZE: usize = WORD_SIZE; -impl ExperimentalBoundedDecoder { +impl BoundedDecoder { pub(crate) fn new(config: DecoderConfig) -> Self { - let depth_tracker = CounterWithLimit::new(config.max_depth, "depth"); - let token_tracker = CounterWithLimit::new(config.max_tokens, "token"); + let depth_tracker = + CounterWithLimit::new(config.max_depth, "depth", CodecDirection::Decoding); + let token_tracker = + CounterWithLimit::new(config.max_tokens, "token", CodecDirection::Decoding); Self { depth_tracker, token_tracker, @@ -295,40 +300,6 @@ struct Decoded { bytes_read: usize, } -struct CounterWithLimit { - count: usize, - max: usize, - name: String, -} - -impl CounterWithLimit { - fn new(max: usize, name: impl Into) -> Self { - Self { - count: 0, - max, - name: name.into(), - } - } - - fn increase(&mut self) -> Result<()> { - self.count += 1; - if self.count > self.max { - return Err(error!( - Codec, - "{} limit `{}` reached while decoding. Try increasing it", self.name, self.max - )); - } - - Ok(()) - } - - fn decrease(&mut self) { - if self.count > 0 { - self.count -= 1; - } - } -} - fn peek_u8(bytes: &[u8]) -> Result { let slice = peek_fixed::(bytes)?; Ok(u8::from_be_bytes(*slice)) @@ -373,7 +344,7 @@ fn peek_discriminant(bytes: &[u8]) -> Result { } fn peek(data: &[u8], len: usize) -> Result<&[u8]> { - (len <= data.len()).then_some(&data[..len]).ok_or(error!( + (len <= data.len()).then(|| &data[..len]).ok_or(error!( Codec, "tried to read `{len}` bytes but only had `{}` remaining!", data.len() diff --git a/packages/fuels-core/src/codec/abi_encoder.rs b/packages/fuels-core/src/codec/abi_encoder.rs index 86a93b6244..9115e34f71 100644 --- a/packages/fuels-core/src/codec/abi_encoder.rs +++ b/packages/fuels-core/src/codec/abi_encoder.rs @@ -1,10 +1,15 @@ +#[cfg(experimental)] mod bounded_encoder; +#[cfg(not(experimental))] +mod experimental_bounded_encoder; + use std::default::Default; -use crate::{ - codec::abi_encoder::bounded_encoder::BoundedEncoder, - types::{errors::Result, unresolved_bytes::UnresolvedBytes, Token}, -}; +#[cfg(experimental)] +use crate::codec::abi_encoder::bounded_encoder::BoundedEncoder; +#[cfg(not(experimental))] +use crate::codec::abi_encoder::experimental_bounded_encoder::BoundedEncoder; +use crate::types::{errors::Result, unresolved_bytes::UnresolvedBytes, Token}; #[derive(Debug, Clone, Copy)] pub struct EncoderConfig { diff --git a/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs b/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs new file mode 100644 index 0000000000..104470ef37 --- /dev/null +++ b/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs @@ -0,0 +1,136 @@ +use crate::{ + codec::{ + utils::{CodecDirection, CounterWithLimit}, + EncoderConfig, + }, + types::{ + errors::Result, + unresolved_bytes::{Data, UnresolvedBytes}, + EnumSelector, StaticStringToken, Token, U256, + }, +}; + +pub(crate) struct BoundedEncoder { + depth_tracker: CounterWithLimit, + token_tracker: CounterWithLimit, +} + +impl BoundedEncoder { + pub(crate) fn new(config: EncoderConfig) -> Self { + let depth_tracker = + CounterWithLimit::new(config.max_depth, "depth", CodecDirection::Encoding); + let token_tracker = + CounterWithLimit::new(config.max_tokens, "token", CodecDirection::Encoding); + Self { + depth_tracker, + token_tracker, + } + } + + /// Encodes `Token`s in `args` following the ABI specs defined + /// [here](https://github.com/FuelLabs/fuel-specs/blob/master/specs/protocol/abi.md) + pub fn encode(&mut self, args: &[Token]) -> Result { + let data = vec![Data::Inline(self.encode_tokens(args)?)]; + + Ok(UnresolvedBytes::new(data)) + } + + fn encode_tokens(&mut self, tokens: &[Token]) -> Result> { + let mut data = vec![]; + + for token in tokens.iter() { + let new_data = self.encode_token(token)?; + data.extend(new_data); + } + + Ok(data) + } + + fn run_w_depth_tracking( + &mut self, + encoder: impl FnOnce(&mut Self) -> Result>, + ) -> Result> { + self.depth_tracker.increase()?; + let res = encoder(self); + self.depth_tracker.decrease(); + + res + } + + fn encode_token(&mut self, arg: &Token) -> Result> { + self.token_tracker.increase()?; + let encoded_token = match arg { + Token::Unit => vec![], + Token::Bool(arg_bool) => vec![u8::from(*arg_bool)], + Token::U8(arg_u8) => vec![*arg_u8], + Token::U16(arg_u16) => arg_u16.to_be_bytes().to_vec(), + // Token::U32(arg_u32) => arg_u32.to_be_bytes().to_vec(), + Token::U32(arg_u32) => (*arg_u32 as u64).to_be_bytes().to_vec(), + Token::U64(arg_u64) => arg_u64.to_be_bytes().to_vec(), + Token::U128(arg_u128) => arg_u128.to_be_bytes().to_vec(), + Token::U256(arg_u256) => Self::encode_u256(*arg_u256), + Token::B256(arg_bits256) => arg_bits256.to_vec(), + Token::Bytes(data) => Self::encode_bytes(data.to_vec())?, + Token::String(string) => Self::encode_bytes(string.clone().into_bytes())?, + Token::RawSlice(data) => data.clone(), + Token::StringArray(arg_string) => Self::encode_string_array(arg_string)?, + Token::StringSlice(arg_string) => Self::encode_string_slice(arg_string)?, + Token::Tuple(arg_tuple) => { + self.run_w_depth_tracking(|ctx| ctx.encode_tokens(arg_tuple))? + } + Token::Array(arg_array) => { + self.run_w_depth_tracking(|ctx| ctx.encode_tokens(arg_array))? + } + Token::Vector(data) => self.run_w_depth_tracking(|ctx| ctx.encode_vector(data))?, + Token::Struct(arg_struct) => { + self.run_w_depth_tracking(|ctx| ctx.encode_tokens(arg_struct))? + } + Token::Enum(arg_enum) => self.run_w_depth_tracking(|ctx| ctx.encode_enum(arg_enum))?, + }; + + Ok(encoded_token) + } + + fn encode_u256(arg_u256: U256) -> Vec { + let mut bytes = [0u8; 32]; + arg_u256.to_big_endian(&mut bytes); + + bytes.to_vec() + } + + fn encode_bytes(data: Vec) -> Result> { + let len = data.len(); + + Ok([Self::encode_length(len as u64), data].concat()) + } + + fn encode_string_array(arg_string: &StaticStringToken) -> Result> { + Ok(arg_string.get_encodable_str()?.as_bytes().to_vec()) + } + + fn encode_string_slice(arg_string: &StaticStringToken) -> Result> { + Ok(arg_string.get_encodable_str()?.as_bytes().to_vec()) + } + + fn encode_vector(&mut self, data: &[Token]) -> Result> { + let encoded_data = self.encode_tokens(data)?; + + Ok([Self::encode_length(data.len() as u64), encoded_data].concat()) + } + + fn encode_enum(&mut self, selector: &EnumSelector) -> Result> { + let (discriminant, token_within_enum, _) = selector; + let encoded_discriminant = Self::encode_discriminant(*discriminant); + let encoded_token = self.encode_token(token_within_enum)?; + + Ok([encoded_discriminant, encoded_token].concat()) + } + + fn encode_length(len: u64) -> Vec { + len.to_be_bytes().to_vec() + } + + fn encode_discriminant(discriminant: u64) -> Vec { + discriminant.to_be_bytes().to_vec() + } +} diff --git a/packages/fuels-core/src/codec/logs.rs b/packages/fuels-core/src/codec/logs.rs index 23ac108931..3596a5c710 100644 --- a/packages/fuels-core/src/codec/logs.rs +++ b/packages/fuels-core/src/codec/logs.rs @@ -7,8 +7,6 @@ use std::{ use fuel_tx::{ContractId, Receipt}; -#[cfg(not(experimental))] -use crate::types::param_types::ParamType; use crate::{ codec::{ABIDecoder, DecoderConfig}, traits::{Parameterize, Tokenizable}, @@ -33,31 +31,11 @@ impl LogFormatter { decoder_config: DecoderConfig, bytes: &[u8], ) -> Result { - #[cfg(not(experimental))] - let token = { - Self::can_decode_log_with_type::()?; - ABIDecoder::new(decoder_config).decode(&T::param_type(), bytes)? - }; - - #[cfg(experimental)] - let token = ABIDecoder::new(decoder_config).experimental_decode(&T::param_type(), bytes)?; + let token = ABIDecoder::new(decoder_config).decode(&T::param_type(), bytes)?; Ok(format!("{:?}", T::from_token(token)?)) } - #[cfg(not(experimental))] - fn can_decode_log_with_type() -> Result<()> { - match T::param_type() { - // String slices cannot be decoded from logs as they are encoded as ptr, len - // TODO: Once https://github.com/FuelLabs/sway/issues/5110 is resolved we can remove this - ParamType::StringSlice => Err(error!( - Codec, - "string slices cannot be decoded from logs. Convert the slice to `str[N]` with `__to_str_array`" - )), - _ => Ok(()), - } - } - pub fn can_handle_type(&self) -> bool { TypeId::of::() == self.type_id } @@ -195,11 +173,6 @@ impl LogDecoder { .extract_log_id_and_data() .filter_map(|(log_id, bytes)| { target_ids.contains(&log_id).then(|| { - #[cfg(experimental)] - let token = ABIDecoder::new(self.decoder_config) - .experimental_decode(&T::param_type(), &bytes)?; - - #[cfg(not(experimental))] let token = ABIDecoder::new(self.decoder_config).decode(&T::param_type(), &bytes)?; diff --git a/packages/fuels-core/src/types.rs b/packages/fuels-core/src/types.rs index 0bd9b91250..4ace7d9929 100644 --- a/packages/fuels-core/src/types.rs +++ b/packages/fuels-core/src/types.rs @@ -75,24 +75,24 @@ pub enum Token { // Used for unit type variants in Enum. An "empty" enum is not represented as Enum, // because this way we can have both unit and non-unit type variants. Unit, + Bool(bool), U8(u8), U16(u16), U32(u32), U64(u64), U128(u128), U256(U256), - Bool(bool), B256([u8; 32]), + Bytes(Vec), + String(String), + RawSlice(Vec), + StringArray(StaticStringToken), + StringSlice(StaticStringToken), + Tuple(Vec), Array(Vec), Vector(Vec), - StringSlice(StaticStringToken), - StringArray(StaticStringToken), Struct(Vec), Enum(Box), - Tuple(Vec), - RawSlice(Vec), - Bytes(Vec), - String(String), } impl fmt::Display for Token { diff --git a/packages/fuels-core/src/types/param_types.rs b/packages/fuels-core/src/types/param_types.rs index f436140e05..32f68d360b 100644 --- a/packages/fuels-core/src/types/param_types.rs +++ b/packages/fuels-core/src/types/param_types.rs @@ -52,6 +52,7 @@ impl ParamType { // Depending on the type, the returned value will be stored // either in `Return` or `ReturnData`. pub fn get_return_location(&self) -> ReturnLocation { + #[cfg(experimental)] match self { Self::Unit | Self::U8 | Self::U16 | Self::U32 | Self::U64 | Self::Bool => { ReturnLocation::Return @@ -59,6 +60,9 @@ impl ParamType { _ => ReturnLocation::ReturnData, } + + #[cfg(not(experimental))] + ReturnLocation::ReturnData } /// Given a [ParamType], return the number of elements of that [ParamType] that can fit in diff --git a/packages/fuels-core/src/types/unresolved_bytes.rs b/packages/fuels-core/src/types/unresolved_bytes.rs index 02198f98b7..40ff4bdc1f 100644 --- a/packages/fuels-core/src/types/unresolved_bytes.rs +++ b/packages/fuels-core/src/types/unresolved_bytes.rs @@ -9,6 +9,7 @@ pub enum Data { Dynamic(Vec), } impl Data { + #[cfg(experimental)] pub(crate) fn size_in_bytes(&self) -> usize { match self { Data::Inline(data) => data.len(), diff --git a/packages/fuels-programs/src/contract.rs b/packages/fuels-programs/src/contract.rs index 883f9f7535..6050cf72df 100644 --- a/packages/fuels-programs/src/contract.rs +++ b/packages/fuels-programs/src/contract.rs @@ -725,7 +725,10 @@ pub fn method_hash( let tx_policies = TxPolicies::default(); let call_parameters = CallParameters::default(); + #[cfg(experimental)] let compute_custom_input_offset = should_compute_custom_input_offset(args); + #[cfg(not(experimental))] + let compute_custom_input_offset = true; let unresolved_bytes = ABIEncoder::new(encoder_config).encode(args); let contract_call = ContractCall { @@ -755,6 +758,7 @@ pub fn method_hash( // If the data passed into the contract method is an integer or a // boolean, then the data itself should be passed. Otherwise, it // should simply pass a pointer to the data in memory. +#[cfg(experimental)] fn should_compute_custom_input_offset(args: &[Token]) -> bool { args.len() > 1 || args.iter().any(|t| { diff --git a/packages/fuels-programs/src/receipt_parser.rs b/packages/fuels-programs/src/receipt_parser.rs index 1c68d02b7d..c43f6b85cd 100644 --- a/packages/fuels-programs/src/receipt_parser.rs +++ b/packages/fuels-programs/src/receipt_parser.rs @@ -43,6 +43,7 @@ impl ReceiptParser { // During a script execution, the script's contract id is the **null** contract id .unwrap_or_else(ContractId::zeroed); + #[cfg(experimental)] output_param.validate_is_decodable(self.decoder.config.max_depth)?; let data = self @@ -64,7 +65,11 @@ impl ReceiptParser { output_param: &ParamType, contract_id: &ContractId, ) -> Option> { + #[cfg(experimental)] let extra_receipts_needed = output_param.is_extra_receipt_needed(true); + #[cfg(not(experimental))] + let extra_receipts_needed = false; + match output_param.get_return_location() { ReturnLocation::ReturnData if extra_receipts_needed && matches!(output_param, ParamType::Enum { .. }) => diff --git a/packages/fuels/Forc.toml b/packages/fuels/Forc.toml index 707dd5c4df..315a10cef4 100644 --- a/packages/fuels/Forc.toml +++ b/packages/fuels/Forc.toml @@ -106,4 +106,4 @@ members = [ ] [patch.'https://github.com/fuellabs/sway'] -std = { git = "https://github.com/fuellabs/sway", branch = "xunilrj/encoding-contract-call" } +std = { git = "https://github.com/fuellabs/sway", branch = "xunilrj/fix-new-encoding-abi" } diff --git a/packages/fuels/tests/scripts.rs b/packages/fuels/tests/scripts.rs index d95bf67e88..7941babe80 100644 --- a/packages/fuels/tests/scripts.rs +++ b/packages/fuels/tests/scripts.rs @@ -97,6 +97,8 @@ async fn test_basic_script_with_tx_policies() -> Result<()> { } #[tokio::test] +// Remove this test once the new encoding lands as the max_input will be irrelevant +// for direct script calls as all script_data is `inline` async fn test_script_call_with_non_default_max_input() -> Result<()> { use fuels::{ test_helpers::ChainConfig, @@ -144,6 +146,7 @@ async fn test_script_call_with_non_default_max_input() -> Result<()> { let result = script_instance.main(a, b).call().await?; assert_eq!(result.value, "heyoo"); + Ok(()) } diff --git a/packages/fuels/tests/types_contracts.rs b/packages/fuels/tests/types_contracts.rs index 0e83147caa..17d191e02f 100644 --- a/packages/fuels/tests/types_contracts.rs +++ b/packages/fuels/tests/types_contracts.rs @@ -33,6 +33,7 @@ async fn test_methods_typeless_argument() -> Result<()> { .await?; assert_eq!(response.value, 63); + Ok(()) } diff --git a/packages/fuels/tests/types_scripts.rs b/packages/fuels/tests/types_scripts.rs index 9bc436bff0..b1e04a6547 100644 --- a/packages/fuels/tests/types_scripts.rs +++ b/packages/fuels/tests/types_scripts.rs @@ -21,10 +21,12 @@ async fn main_function_generic_arguments() -> Result<()> { twix: bam_comp, mars: 1000, }; + let result = script_instance .main(bim.clone(), bam.clone()) .call() .await?; + let expected = ( GenericSnack { twix: GenericBimbam { @@ -34,7 +36,9 @@ async fn main_function_generic_arguments() -> Result<()> { }, GenericBimbam { val: 255_u8 }, ); + assert_eq!(result.value, expected); + Ok(()) } @@ -52,14 +56,23 @@ async fn main_function_option_result() -> Result<()> { wallet = "wallet" ) ); + { + let result = script_instance.main(Some(42), None).call().await?; + + assert_eq!(result.value, Ok(Some(true))); + } + { + let result = script_instance.main(Some(987), None).call().await?; + + assert_eq!(result.value, Ok(None)); + } + { + let expected_error = Err(TestError::ZimZam("error".try_into().unwrap())); + let result = script_instance.main(None, Some(987)).call().await?; + + assert_eq!(result.value, expected_error); + } - let result = script_instance.main(Some(42), None).call().await?; - assert_eq!(result.value, Ok(Some(true))); - let result = script_instance.main(Some(987), None).call().await?; - assert_eq!(result.value, Ok(None)); - let expected_error = Err(TestError::ZimZam("error".try_into().unwrap())); - let result = script_instance.main(None, Some(987)).call().await?; - assert_eq!(result.value, expected_error); Ok(()) } From b01d6226fd73357696c17a580e6e8e08731a2560 Mon Sep 17 00:00:00 2001 From: hal3e Date: Mon, 11 Mar 2024 10:54:48 +0100 Subject: [PATCH 05/30] move token to its module --- packages/fuels-core/src/codec/logs.rs | 16 ++++ packages/fuels-core/src/types.rs | 91 +------------------ packages/fuels-core/src/types/token.rs | 90 ++++++++++++++++++ packages/fuels/tests/contracts.rs | 1 - .../contracts/type_inside_enum/src/main.sw | 2 +- packages/fuels/tests/types_contracts.rs | 2 +- 6 files changed, 110 insertions(+), 92 deletions(-) create mode 100644 packages/fuels-core/src/types/token.rs diff --git a/packages/fuels-core/src/codec/logs.rs b/packages/fuels-core/src/codec/logs.rs index 3596a5c710..3a028afed6 100644 --- a/packages/fuels-core/src/codec/logs.rs +++ b/packages/fuels-core/src/codec/logs.rs @@ -31,11 +31,27 @@ impl LogFormatter { decoder_config: DecoderConfig, bytes: &[u8], ) -> Result { + #[cfg(experimental)] + Self::can_decode_log_with_type::()?; + let token = ABIDecoder::new(decoder_config).decode(&T::param_type(), bytes)?; Ok(format!("{:?}", T::from_token(token)?)) } + #[cfg(experimental)] + fn can_decode_log_with_type() -> Result<()> { + match T::param_type() { + // String slices cannot be decoded from logs as they are encoded as ptr, len + // TODO: Once https://github.com/FuelLabs/sway/issues/5110 is resolved we can remove this + ParamType::StringSlice => Err(error!( + Codec, + "string slices cannot be decoded from logs. Convert the slice to `str[N]` with `__to_str_array`" + )), + _ => Ok(()), + } + } + pub fn can_handle_type(&self) -> bool { TypeId::of::() == self.type_id } diff --git a/packages/fuels-core/src/types.rs b/packages/fuels-core/src/types.rs index 4ace7d9929..48f7720e90 100644 --- a/packages/fuels-core/src/types.rs +++ b/packages/fuels-core/src/types.rs @@ -1,22 +1,17 @@ -use std::fmt; - use fuel_types::bytes::padded_len; pub use fuel_types::{ Address, AssetId, Bytes32, Bytes4, Bytes64, Bytes8, ChainId, ContractId, MessageId, Nonce, Salt, Word, }; -pub use crate::types::{core::*, wrappers::*}; -use crate::types::{ - enum_variants::EnumVariants, - errors::{error, Error, Result}, -}; +pub use crate::types::{core::*, token::*, wrappers::*}; pub mod bech32; mod core; pub mod enum_variants; pub mod errors; pub mod param_types; +mod token; pub mod transaction_builders; pub mod tx_status; pub mod unresolved_bytes; @@ -24,88 +19,6 @@ mod wrappers; pub type ByteArray = [u8; 8]; pub type Selector = ByteArray; -pub type EnumSelector = (u64, Token, EnumVariants); - -#[derive(Debug, Clone, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)] -pub struct StaticStringToken { - data: String, - expected_len: Option, -} - -impl StaticStringToken { - pub fn new(data: String, expected_len: Option) -> Self { - StaticStringToken { data, expected_len } - } - - fn validate(&self) -> Result<()> { - if !self.data.is_ascii() { - return Err(error!(Codec, "string data can only have ascii values")); - } - - if let Some(expected_len) = self.expected_len { - if self.data.len() != expected_len { - return Err(error!( - Codec, - "string data has len {}, but the expected len is {}", - self.data.len(), - expected_len - )); - } - } - - Ok(()) - } - - pub fn get_encodable_str(&self) -> Result<&str> { - self.validate()?; - Ok(self.data.as_str()) - } -} - -impl TryFrom for String { - type Error = Error; - fn try_from(string_token: StaticStringToken) -> Result { - string_token.validate()?; - Ok(string_token.data) - } -} - -#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] -pub enum Token { - // Used for unit type variants in Enum. An "empty" enum is not represented as Enum, - // because this way we can have both unit and non-unit type variants. - Unit, - Bool(bool), - U8(u8), - U16(u16), - U32(u32), - U64(u64), - U128(u128), - U256(U256), - B256([u8; 32]), - Bytes(Vec), - String(String), - RawSlice(Vec), - StringArray(StaticStringToken), - StringSlice(StaticStringToken), - Tuple(Vec), - Array(Vec), - Vector(Vec), - Struct(Vec), - Enum(Box), -} - -impl fmt::Display for Token { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{self:?}") - } -} - -impl Default for Token { - fn default() -> Self { - Token::U8(0) - } -} /// Converts a u16 to a right aligned array of 8 bytes. pub fn pad_u16(value: u16) -> ByteArray { diff --git a/packages/fuels-core/src/types/token.rs b/packages/fuels-core/src/types/token.rs new file mode 100644 index 0000000000..7d0840bc3a --- /dev/null +++ b/packages/fuels-core/src/types/token.rs @@ -0,0 +1,90 @@ +use std::fmt; + +use crate::types::{ + core::U256, + enum_variants::EnumVariants, + errors::{error, Error, Result}, +}; + +pub type EnumSelector = (u64, Token, EnumVariants); + +#[derive(Debug, Clone, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)] +pub struct StaticStringToken { + data: String, + expected_len: Option, +} + +impl StaticStringToken { + pub fn new(data: String, expected_len: Option) -> Self { + StaticStringToken { data, expected_len } + } + + fn validate(&self) -> Result<()> { + if !self.data.is_ascii() { + return Err(error!(Codec, "string data can only have ascii values")); + } + + if let Some(expected_len) = self.expected_len { + if self.data.len() != expected_len { + return Err(error!( + Codec, + "string data has len {}, but the expected len is {}", + self.data.len(), + expected_len + )); + } + } + + Ok(()) + } + + pub fn get_encodable_str(&self) -> Result<&str> { + self.validate()?; + Ok(self.data.as_str()) + } +} + +impl TryFrom for String { + type Error = Error; + fn try_from(string_token: StaticStringToken) -> Result { + string_token.validate()?; + Ok(string_token.data) + } +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub enum Token { + // Used for unit type variants in Enum. An "empty" enum is not represented as Enum, + // because this way we can have both unit and non-unit type variants. + Unit, + Bool(bool), + U8(u8), + U16(u16), + U32(u32), + U64(u64), + U128(u128), + U256(U256), + B256([u8; 32]), + Bytes(Vec), + String(String), + RawSlice(Vec), + StringArray(StaticStringToken), + StringSlice(StaticStringToken), + Tuple(Vec), + Array(Vec), + Vector(Vec), + Struct(Vec), + Enum(Box), +} + +impl fmt::Display for Token { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{self:?}") + } +} + +impl Default for Token { + fn default() -> Self { + Token::U8(0) + } +} diff --git a/packages/fuels/tests/contracts.rs b/packages/fuels/tests/contracts.rs index a6946a347a..0bec35fee2 100644 --- a/packages/fuels/tests/contracts.rs +++ b/packages/fuels/tests/contracts.rs @@ -22,7 +22,6 @@ async fn test_multiple_args() -> Result<()> { // Make sure we can call the contract with multiple arguments let contract_methods = contract_instance.methods(); let response = contract_methods.get(5, 6).call().await?; - dbg!(&response); assert_eq!(response.value, 11); diff --git a/packages/fuels/tests/types/contracts/type_inside_enum/src/main.sw b/packages/fuels/tests/types/contracts/type_inside_enum/src/main.sw index 3f6a0978f1..d9430cd347 100644 --- a/packages/fuels/tests/types/contracts/type_inside_enum/src/main.sw +++ b/packages/fuels/tests/types/contracts/type_inside_enum/src/main.sw @@ -3,7 +3,7 @@ contract; #[allow(dead_code)] enum SomeEnum { SomeStr: str[4], - SomeArr: [u64; 2], + SomeArr: [u64; 4], } #[allow(dead_code)] diff --git a/packages/fuels/tests/types_contracts.rs b/packages/fuels/tests/types_contracts.rs index 17d191e02f..3486c0c37a 100644 --- a/packages/fuels/tests/types_contracts.rs +++ b/packages/fuels/tests/types_contracts.rs @@ -757,7 +757,7 @@ async fn type_inside_enum() -> Result<()> { assert_eq!(response.value, enum_string); // Array inside enum - let enum_array = SomeEnum::SomeArr([1, 2, 3, 4, 5, 6, 7]); + let enum_array = SomeEnum::SomeArr([1, 2, 3, 4]); let response = contract_methods .arr_inside_enum(enum_array.clone()) .call() From 991f641ef8182f2b22de5dda7006d8492f921e73 Mon Sep 17 00:00:00 2001 From: hal3e Date: Mon, 11 Mar 2024 13:40:17 +0100 Subject: [PATCH 06/30] add correct u32 encoding --- .../src/codec/abi_encoder/experimental_bounded_encoder.rs | 3 +-- packages/fuels/Forc.toml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs b/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs index 104470ef37..0d18f4a3c1 100644 --- a/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs +++ b/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs @@ -64,8 +64,7 @@ impl BoundedEncoder { Token::Bool(arg_bool) => vec![u8::from(*arg_bool)], Token::U8(arg_u8) => vec![*arg_u8], Token::U16(arg_u16) => arg_u16.to_be_bytes().to_vec(), - // Token::U32(arg_u32) => arg_u32.to_be_bytes().to_vec(), - Token::U32(arg_u32) => (*arg_u32 as u64).to_be_bytes().to_vec(), + Token::U32(arg_u32) => arg_u32.to_be_bytes().to_vec(), Token::U64(arg_u64) => arg_u64.to_be_bytes().to_vec(), Token::U128(arg_u128) => arg_u128.to_be_bytes().to_vec(), Token::U256(arg_u256) => Self::encode_u256(*arg_u256), diff --git a/packages/fuels/Forc.toml b/packages/fuels/Forc.toml index 315a10cef4..501e388ee4 100644 --- a/packages/fuels/Forc.toml +++ b/packages/fuels/Forc.toml @@ -106,4 +106,4 @@ members = [ ] [patch.'https://github.com/fuellabs/sway'] -std = { git = "https://github.com/fuellabs/sway", branch = "xunilrj/fix-new-encoding-abi" } +std = { git = "https://github.com/fuellabs/sway", branch = "xunilrj/fix-decode-for-u16-u32" } From 012a42ffd4e2d57ac68356ff0c56be882c62aeae Mon Sep 17 00:00:00 2001 From: hal3e Date: Mon, 11 Mar 2024 22:15:27 +0100 Subject: [PATCH 07/30] Work in progress --- packages/fuels-core/src/codec/abi_encoder.rs | 19 +++- .../experimental_bounded_encoder.rs | 2 +- .../fuels-core/src/codec/function_selector.rs | 19 +++- packages/fuels-core/src/types.rs | 3 + packages/fuels-programs/src/call_utils.rs | 98 ++++++++++++++++++- packages/fuels-programs/src/contract.rs | 1 + .../tests/types/contracts/bytes/src/main.sw | 1 + packages/fuels/tests/types_contracts.rs | 1 + 8 files changed, 140 insertions(+), 4 deletions(-) diff --git a/packages/fuels-core/src/codec/abi_encoder.rs b/packages/fuels-core/src/codec/abi_encoder.rs index 9115e34f71..98eba9fc47 100644 --- a/packages/fuels-core/src/codec/abi_encoder.rs +++ b/packages/fuels-core/src/codec/abi_encoder.rs @@ -58,11 +58,11 @@ mod tests { use std::slice; use itertools::chain; + #[cfg(experimental)] use sha2::{Digest, Sha256}; use super::*; use crate::{ - codec::first_four_bytes_of_sha256_hash, constants::WORD_SIZE, types::{ enum_variants::EnumVariants, errors::Error, param_types::ParamType, StaticStringToken, @@ -70,10 +70,14 @@ mod tests { }, }; + #[cfg(experimental)] + use crate::codec::first_four_bytes_of_sha256_hash; + const VEC_METADATA_SIZE: usize = 3 * WORD_SIZE; const DISCRIMINANT_SIZE: usize = WORD_SIZE; #[test] + #[cfg(experimental)] fn encode_function_signature() { let fn_signature = "entry_one(u64)"; @@ -85,6 +89,7 @@ mod tests { } #[test] + #[cfg(experimental)] fn encode_function_with_u32_type() -> Result<()> { // @todo eventually we must update the json abi examples in here. // They're in the old format. @@ -122,6 +127,7 @@ mod tests { } #[test] + #[cfg(experimental)] fn encode_function_with_u32_type_multiple_args() -> Result<()> { // let json_abi = // r#" @@ -158,6 +164,7 @@ mod tests { } #[test] + #[cfg(experimental)] fn encode_function_with_u64_type() -> Result<()> { // let json_abi = // r#" @@ -192,6 +199,7 @@ mod tests { } #[test] + #[cfg(experimental)] fn encode_function_with_bool_type() -> Result<()> { // let json_abi = // r#" @@ -226,6 +234,7 @@ mod tests { } #[test] + #[cfg(experimental)] fn encode_function_with_two_different_type() -> Result<()> { // let json_abi = // r#" @@ -265,6 +274,7 @@ mod tests { } #[test] + #[cfg(experimental)] fn encode_function_with_bits256_type() -> Result<()> { // let json_abi = // r#" @@ -309,6 +319,7 @@ mod tests { } #[test] + #[cfg(experimental)] fn encode_function_with_array_type() -> Result<()> { // let json_abi = // r#" @@ -350,6 +361,7 @@ mod tests { } #[test] + #[cfg(experimental)] fn encode_function_with_string_array_type() -> Result<()> { // let json_abi = // r#" @@ -389,6 +401,7 @@ mod tests { } #[test] + #[cfg(experimental)] fn encode_function_with_string_slice_type() -> Result<()> { // let json_abi = // r#" @@ -431,6 +444,7 @@ mod tests { } #[test] + #[cfg(experimental)] fn encode_function_with_struct() -> Result<()> { // let json_abi = // r#" @@ -480,6 +494,7 @@ mod tests { } #[test] + #[cfg(experimental)] fn encode_function_with_enum() -> Result<()> { // let json_abi = // r#" @@ -624,6 +639,7 @@ mod tests { } #[test] + #[cfg(experimental)] fn encode_function_with_nested_structs() -> Result<()> { // let json_abi = // r#" @@ -679,6 +695,7 @@ mod tests { } #[test] + #[cfg(experimental)] fn encode_comprehensive_function() -> Result<()> { // let json_abi = // r#" diff --git a/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs b/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs index 0d18f4a3c1..7646e3661b 100644 --- a/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs +++ b/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs @@ -108,7 +108,7 @@ impl BoundedEncoder { } fn encode_string_slice(arg_string: &StaticStringToken) -> Result> { - Ok(arg_string.get_encodable_str()?.as_bytes().to_vec()) + Self::encode_bytes(arg_string.get_encodable_str()?.as_bytes().to_vec()) } fn encode_vector(&mut self, data: &[Token]) -> Result> { diff --git a/packages/fuels-core/src/codec/function_selector.rs b/packages/fuels-core/src/codec/function_selector.rs index 4877ac15eb..a80fad1616 100644 --- a/packages/fuels-core/src/codec/function_selector.rs +++ b/packages/fuels-core/src/codec/function_selector.rs @@ -1,7 +1,11 @@ +#[cfg(experimental)] use sha2::{Digest, Sha256}; -use crate::types::{param_types::ParamType, ByteArray}; +use crate::types::param_types::ParamType; +#[cfg(experimental)] +use crate::types::ByteArray; +#[cfg(experimental)] /// Given a function name and its inputs will return a ByteArray representing /// the function selector as specified in the Fuel specs. pub fn resolve_fn_selector(name: &str, inputs: &[ParamType]) -> ByteArray { @@ -10,16 +14,27 @@ pub fn resolve_fn_selector(name: &str, inputs: &[ParamType]) -> ByteArray { first_four_bytes_of_sha256_hash(&fn_signature) } +#[cfg(not(experimental))] +pub fn resolve_fn_selector(name: &str, _inputs: &[ParamType]) -> Vec { + let bytes = name.as_bytes().to_vec(); + let len = bytes.len() as u64; + + [len.to_be_bytes().to_vec(), bytes].concat() +} + +#[cfg(experimental)] fn resolve_fn_signature(name: &str, inputs: &[ParamType]) -> String { let fn_args = resolve_args(inputs); format!("{name}({fn_args})") } +#[cfg(experimental)] fn resolve_args(arg: &[ParamType]) -> String { arg.iter().map(resolve_arg).collect::>().join(",") } +#[cfg(experimental)] fn resolve_arg(arg: &ParamType) -> String { match &arg { ParamType::U8 => "u8".to_owned(), @@ -79,6 +94,7 @@ fn resolve_arg(arg: &ParamType) -> String { } } +#[cfg(experimental)] /// Hashes an encoded function selector using SHA256 and returns the first 4 bytes. /// The function selector has to have been already encoded following the ABI specs defined /// [here](https://github.com/FuelLabs/fuel-specs/blob/1be31f70c757d8390f74b9e1b3beb096620553eb/specs/protocol/abi.md) @@ -116,6 +132,7 @@ macro_rules! calldata { pub use calldata; +#[cfg(experimental)] #[cfg(test)] mod tests { use super::*; diff --git a/packages/fuels-core/src/types.rs b/packages/fuels-core/src/types.rs index 48f7720e90..7009d43b4e 100644 --- a/packages/fuels-core/src/types.rs +++ b/packages/fuels-core/src/types.rs @@ -18,7 +18,10 @@ pub mod unresolved_bytes; mod wrappers; pub type ByteArray = [u8; 8]; +#[cfg(experimental)] pub type Selector = ByteArray; +#[cfg(not(experimental))] +pub type Selector = Vec; /// Converts a u16 to a right aligned array of 8 bytes. pub fn pad_u16(value: u16) -> ByteArray { diff --git a/packages/fuels-programs/src/call_utils.rs b/packages/fuels-programs/src/call_utils.rs index fbe9f54878..f0026d7581 100644 --- a/packages/fuels-programs/src/call_utils.rs +++ b/packages/fuels-programs/src/call_utils.rs @@ -5,8 +5,9 @@ use fuel_asm::{op, RegId}; use fuel_tx::{AssetId, Bytes32, ContractId, Output, PanicReason, Receipt, TxPointer, UtxoId}; use fuel_types::{Address, Word}; use fuels_accounts::Account; +#[cfg(experimental)] +use fuels_core::constants::WORD_SIZE; use fuels_core::{ - constants::WORD_SIZE, error, offsets::call_script_data_offset, types::{ @@ -244,6 +245,7 @@ pub(crate) fn get_instructions( }) } +#[cfg(experimental)] /// Returns script data, consisting of the following items in the given order: /// 1. Amount to be forwarded `(1 * `[`WORD_SIZE`]`)` /// 2. Asset ID to be forwarded ([`AssetId::LEN`]) @@ -323,6 +325,91 @@ pub(crate) fn build_script_data_from_contract_calls( Ok((script_data, param_offsets)) } +#[cfg(not(experimental))] +/// Returns script data, consisting of the following items in the given order: +/// 1. Amount to be forwarded `(1 * `[`WORD_SIZE`]`)` +/// 2. Asset ID to be forwarded ([`AssetId::LEN`]) +/// 3. Gas to be forwarded `(1 * `[`WORD_SIZE`]`)` - Optional +/// 4. Contract ID ([`ContractId::LEN`]); +/// 5. Function selector `(1 * `[`WORD_SIZE`]`)` +/// 6. Calldata offset (optional) `(1 * `[`WORD_SIZE`]`)` +/// 7. Encoded arguments (optional) (variable length) +pub(crate) fn build_script_data_from_contract_calls( + calls: &[ContractCall], + data_offset: usize, +) -> Result<(Vec, Vec)> { + use fuel_types::bytes::WORD_SIZE; + + let mut script_data = vec![]; + let mut param_offsets = vec![]; + + // The data for each call is ordered into segments + let mut segment_offset = data_offset; + + for call in calls { + let gas_forwarded = call.call_parameters.gas_forwarded(); + + script_data.extend(call.call_parameters.amount().to_be_bytes()); + script_data.extend(call.call_parameters.asset_id().iter()); + + let gas_forwarded_size = gas_forwarded + .map(|gf| { + script_data.extend((gf as Word).to_be_bytes()); + + WORD_SIZE + }) + .unwrap_or_default(); + + script_data.extend(call.contract_id.hash().as_ref()); + + let call_param_offsets = CallOpcodeParamsOffset { + amount_offset: segment_offset, + asset_id_offset: segment_offset + WORD_SIZE, + gas_forwarded_offset: gas_forwarded.map(|_| segment_offset + WORD_SIZE + AssetId::LEN), + call_data_offset: segment_offset + WORD_SIZE + AssetId::LEN + gas_forwarded_size, + }; + + let encoded_selector_offset = + call_param_offsets.call_data_offset + ContractId::LEN + WORD_SIZE + WORD_SIZE; + + script_data.extend((encoded_selector_offset as u64).to_be_bytes()); + + param_offsets.push(call_param_offsets); + + // If the method call takes custom inputs or has more than + // one argument, we need to calculate the `call_data_offset`, + // which points to where the data for the custom types start in the + // transaction. If it doesn't take any custom inputs, this isn't necessary. + // Custom inputs are stored after the previously added parameters, + // including custom_input_offset + let custom_input_offset = segment_offset + + WORD_SIZE // amount size + + AssetId::LEN + + gas_forwarded_size + + ContractId::LEN + + WORD_SIZE + + WORD_SIZE + + call.encoded_selector.len(); + + script_data.extend((custom_input_offset as u64).to_be_bytes()); + script_data.extend(call.encoded_selector.clone()); + + let bytes = call + .encoded_args + .as_ref() + .map(|ub| ub.resolve(custom_input_offset as Word)) + .map_err(|e| error!(Codec, "cannot encode contract call arguments: {e}"))?; + + script_data.extend(bytes); + + // the data segment that holds the parameters for the next call + // begins at the original offset + the data we added so far + segment_offset = data_offset + script_data.len(); + } + + Ok((script_data, param_offsets)) +} + /// Returns the VM instructions for calling a contract method /// We use the [`Opcode`] to call a contract: [`CALL`](Opcode::CALL) /// pointing at the following registers: @@ -589,6 +676,7 @@ pub fn new_variable_outputs(num: usize) -> Vec { mod test { use std::slice; + use fuel_types::bytes::WORD_SIZE; use fuels_accounts::wallet::WalletUnlocked; use fuels_core::{ codec::ABIEncoder, @@ -604,12 +692,17 @@ mod test { use super::*; use crate::contract::CallParameters; + #[cfg(not(experimental))] + impl ContractCall { pub fn new_with_random_id() -> Self { ContractCall { contract_id: random_bech32_contract_id(), encoded_args: Ok(Default::default()), + #[cfg(experimental)] encoded_selector: [0; 8], + #[cfg(not(experimental))] + encoded_selector: [0; 8].to_vec(), call_parameters: Default::default(), compute_custom_input_offset: false, variable_outputs: vec![], @@ -658,7 +751,10 @@ mod test { let calls: Vec = (0..NUM_CALLS) .map(|i| ContractCall { contract_id: contract_ids[i].clone(), + #[cfg(experimental)] encoded_selector: selectors[i], + #[cfg(not(experimental))] + encoded_selector: selectors[i].to_vec(), encoded_args: Ok(args[i].clone()), call_parameters: CallParameters::new(i as u64, asset_ids[i], i as u64), compute_custom_input_offset: i == 1, diff --git a/packages/fuels-programs/src/contract.rs b/packages/fuels-programs/src/contract.rs index 6050cf72df..f258f08867 100644 --- a/packages/fuels-programs/src/contract.rs +++ b/packages/fuels-programs/src/contract.rs @@ -925,6 +925,7 @@ impl MultiContractCallHandler { } else { provider.send_transaction_and_await_commit(tx).await? }; + let receipts = tx_status.take_receipts_checked(Some(&self.log_decoder))?; self.get_response(receipts) diff --git a/packages/fuels/tests/types/contracts/bytes/src/main.sw b/packages/fuels/tests/types/contracts/bytes/src/main.sw index 84ff054e93..f1d859132d 100644 --- a/packages/fuels/tests/types/contracts/bytes/src/main.sw +++ b/packages/fuels/tests/types/contracts/bytes/src/main.sw @@ -68,6 +68,7 @@ impl MyContract for Contract { } fn return_bytes(len: u8) -> Bytes { + log(len); let mut bytes = Bytes::new(); let mut i: u8 = 0; while i < len { diff --git a/packages/fuels/tests/types_contracts.rs b/packages/fuels/tests/types_contracts.rs index 3486c0c37a..ae11c3e387 100644 --- a/packages/fuels/tests/types_contracts.rs +++ b/packages/fuels/tests/types_contracts.rs @@ -93,6 +93,7 @@ async fn call_with_structs() -> Result<()> { let response = contract_methods.increment_counter(10).call().await?; assert_eq!(52, response.value); + Ok(()) } From ba21451660c22ac6c64d3bc2abf9235d19a6e446 Mon Sep 17 00:00:00 2001 From: hal3e Date: Tue, 12 Mar 2024 15:16:23 +0100 Subject: [PATCH 08/30] fix contract call --- .../experimental_bounded_encoder.rs | 2 +- packages/fuels-programs/src/call_utils.rs | 40 ++--- packages/fuels/Forc.toml | 2 +- packages/fuels/tests/contracts.rs | 12 +- packages/fuels/tests/types_contracts.rs | 152 +++++++++++------- 5 files changed, 121 insertions(+), 87 deletions(-) diff --git a/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs b/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs index 7646e3661b..7bcf75a4e0 100644 --- a/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs +++ b/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs @@ -71,7 +71,7 @@ impl BoundedEncoder { Token::B256(arg_bits256) => arg_bits256.to_vec(), Token::Bytes(data) => Self::encode_bytes(data.to_vec())?, Token::String(string) => Self::encode_bytes(string.clone().into_bytes())?, - Token::RawSlice(data) => data.clone(), + Token::RawSlice(data) => Self::encode_bytes(data.clone())?, Token::StringArray(arg_string) => Self::encode_string_array(arg_string)?, Token::StringSlice(arg_string) => Self::encode_string_slice(arg_string)?, Token::Tuple(arg_tuple) => { diff --git a/packages/fuels-programs/src/call_utils.rs b/packages/fuels-programs/src/call_utils.rs index f0026d7581..30df9cc0ee 100644 --- a/packages/fuels-programs/src/call_utils.rs +++ b/packages/fuels-programs/src/call_utils.rs @@ -331,9 +331,10 @@ pub(crate) fn build_script_data_from_contract_calls( /// 2. Asset ID to be forwarded ([`AssetId::LEN`]) /// 3. Gas to be forwarded `(1 * `[`WORD_SIZE`]`)` - Optional /// 4. Contract ID ([`ContractId::LEN`]); -/// 5. Function selector `(1 * `[`WORD_SIZE`]`)` +/// 5. Function selector offset `(1 * `[`WORD_SIZE`]`)` /// 6. Calldata offset (optional) `(1 * `[`WORD_SIZE`]`)` -/// 7. Encoded arguments (optional) (variable length) +/// 7. Encoded function selector +/// 8. Encoded arguments pub(crate) fn build_script_data_from_contract_calls( calls: &[ContractCall], data_offset: usize, @@ -360,8 +361,6 @@ pub(crate) fn build_script_data_from_contract_calls( }) .unwrap_or_default(); - script_data.extend(call.contract_id.hash().as_ref()); - let call_param_offsets = CallOpcodeParamsOffset { amount_offset: segment_offset, asset_id_offset: segment_offset + WORD_SIZE, @@ -372,27 +371,9 @@ pub(crate) fn build_script_data_from_contract_calls( let encoded_selector_offset = call_param_offsets.call_data_offset + ContractId::LEN + WORD_SIZE + WORD_SIZE; - script_data.extend((encoded_selector_offset as u64).to_be_bytes()); - param_offsets.push(call_param_offsets); - // If the method call takes custom inputs or has more than - // one argument, we need to calculate the `call_data_offset`, - // which points to where the data for the custom types start in the - // transaction. If it doesn't take any custom inputs, this isn't necessary. - // Custom inputs are stored after the previously added parameters, - // including custom_input_offset - let custom_input_offset = segment_offset - + WORD_SIZE // amount size - + AssetId::LEN - + gas_forwarded_size - + ContractId::LEN - + WORD_SIZE - + WORD_SIZE - + call.encoded_selector.len(); - - script_data.extend((custom_input_offset as u64).to_be_bytes()); - script_data.extend(call.encoded_selector.clone()); + let custom_input_offset = encoded_selector_offset + call.encoded_selector.len(); let bytes = call .encoded_args @@ -400,6 +381,10 @@ pub(crate) fn build_script_data_from_contract_calls( .map(|ub| ub.resolve(custom_input_offset as Word)) .map_err(|e| error!(Codec, "cannot encode contract call arguments: {e}"))?; + script_data.extend(call.contract_id.hash().as_ref()); + script_data.extend((encoded_selector_offset as Word).to_be_bytes()); + script_data.extend((custom_input_offset as Word).to_be_bytes()); + script_data.extend(call.encoded_selector.clone()); script_data.extend(bytes); // the data segment that holds the parameters for the next call @@ -423,7 +408,7 @@ pub(crate) fn build_script_data_from_contract_calls( /// non-reserved register. pub(crate) fn get_single_call_instructions( offsets: &CallOpcodeParamsOffset, - output_param_type: &ParamType, + _output_param_type: &ParamType, ) -> Result> { let call_data_offset = offsets .call_data_offset @@ -441,6 +426,7 @@ pub(crate) fn get_single_call_instructions( let mut instructions = [ op::movi(0x10, call_data_offset), op::movi(0x11, amount_offset), + #[cfg(experimental)] op::lw(0x11, 0x11, 0), op::movi(0x12, asset_id_offset), ] @@ -454,6 +440,7 @@ pub(crate) fn get_single_call_instructions( instructions.extend(&[ op::movi(0x13, gas_forwarded_offset), + #[cfg(experimental)] op::lw(0x13, 0x13, 0), op::call(0x10, 0x11, 0x12, 0x13), ]); @@ -462,12 +449,14 @@ pub(crate) fn get_single_call_instructions( None => instructions.push(op::call(0x10, 0x11, 0x12, RegId::CGAS)), }; - instructions.extend(extract_heap_data(output_param_type)?); + #[cfg(experimental)] + instructions.extend(extract_heap_data(_output_param_type)?); #[allow(clippy::iter_cloned_collect)] Ok(instructions.into_iter().collect::>()) } +#[cfg(experimental)] fn extract_heap_data(param_type: &ParamType) -> Result> { match param_type { ParamType::Enum { variants, .. } => { @@ -503,6 +492,7 @@ fn extract_heap_data(param_type: &ParamType) -> Result Result<()> { let tolerance = 0.2; let expected_min_gas_price = 0; // This is the default `min_gas_price` from `ConsensusParameters` - let expected_gas_used = 949; - let expected_metered_bytes_size = 792; - let expected_total_fee = 898; + let expected_gas_used = 960; + let expected_metered_bytes_size = 832; + let expected_total_fee = 914; let estimated_transaction_cost = contract_instance .methods() @@ -1224,6 +1227,7 @@ async fn multi_call_from_calls_with_different_account_types() -> Result<()> { } #[tokio::test] +#[cfg(experimental)] // TODO: @hal3e add other example with new the new call function async fn low_level_call() -> Result<()> { use fuels::types::SizedAsciiString; diff --git a/packages/fuels/tests/types_contracts.rs b/packages/fuels/tests/types_contracts.rs index ae11c3e387..f23e556fc0 100644 --- a/packages/fuels/tests/types_contracts.rs +++ b/packages/fuels/tests/types_contracts.rs @@ -1802,6 +1802,7 @@ async fn test_base_type_in_vec_output() -> Result<()> { Ok(()) } + #[tokio::test] async fn test_composite_types_in_vec_output() -> Result<()> { setup_program_test!( @@ -1871,6 +1872,7 @@ async fn test_composite_types_in_vec_output() -> Result<()> { Ok(()) } +#[cfg(experimental)] #[tokio::test] async fn test_nested_vector_methods_fail() -> Result<()> { // This is just an E2E test of the method `ParamType::contains_nested_heap_types`, hence it's @@ -2071,78 +2073,116 @@ async fn test_heap_type_in_enums() -> Result<()> { ); let contract_methods = contract_instance.methods(); - let resp = contract_methods.returns_bytes_result(true).call().await?; - let expected = Ok(Bytes(vec![1, 1, 1, 1])); - assert_eq!(resp.value, expected); + { + let resp = contract_methods.returns_bytes_result(true).call().await?; + let expected = Ok(Bytes(vec![1, 1, 1, 1])); - let resp = contract_methods.returns_bytes_result(false).call().await?; - let expected = Err(TestError::Something([255u8, 255u8, 255u8, 255u8, 255u8])); - assert_eq!(resp.value, expected); + assert_eq!(resp.value, expected); + } + { + let resp = contract_methods.returns_bytes_result(false).call().await?; + let expected = Err(TestError::Something([255u8, 255u8, 255u8, 255u8, 255u8])); - let resp = contract_methods.returns_vec_result(true).call().await?; - let expected = Ok(vec![2, 2, 2, 2, 2]); - assert_eq!(resp.value, expected); + assert_eq!(resp.value, expected); + } + { + let resp = contract_methods.returns_vec_result(true).call().await?; + let expected = Ok(vec![2, 2, 2, 2, 2]); - let resp = contract_methods.returns_vec_result(false).call().await?; - let expected = Err(TestError::Else(7777)); - assert_eq!(resp.value, expected); + assert_eq!(resp.value, expected); + } + { + let resp = contract_methods.returns_vec_result(false).call().await?; + let expected = Err(TestError::Else(7777)); - let resp = contract_methods.returns_string_result(true).call().await?; - let expected = Ok("Hello World".to_string()); - assert_eq!(resp.value, expected); + assert_eq!(resp.value, expected); + } + { + let resp = contract_methods.returns_string_result(true).call().await?; + let expected = Ok("Hello World".to_string()); - let resp = contract_methods.returns_string_result(false).call().await?; - let expected = Err(TestError::Else(3333)); - assert_eq!(resp.value, expected); + assert_eq!(resp.value, expected); + } + { + let resp = contract_methods.returns_string_result(false).call().await?; + let expected = Err(TestError::Else(3333)); - let resp = contract_methods.returns_str_result(true).call().await?; - let expected = Ok("Hello World".try_into()?); - assert_eq!(resp.value, expected); + assert_eq!(resp.value, expected); + } + { + let resp = contract_methods.returns_str_result(true).call().await?; + let expected = Ok("Hello World".try_into()?); - let resp = contract_methods.returns_string_result(false).call().await?; - let expected = Err(TestError::Else(3333)); - assert_eq!(resp.value, expected); + assert_eq!(resp.value, expected); + } + { + let resp = contract_methods.returns_string_result(false).call().await?; + let expected = Err(TestError::Else(3333)); - let resp = contract_methods.returns_bytes_option(true).call().await?; - let expected = Some(Bytes(vec![1, 1, 1, 1])); - assert_eq!(resp.value, expected); + assert_eq!(resp.value, expected); + } + { + let resp = contract_methods.returns_bytes_option(true).call().await?; + let expected = Some(Bytes(vec![1, 1, 1, 1])); - let resp = contract_methods.returns_bytes_option(false).call().await?; - assert!(resp.value.is_none()); + assert_eq!(resp.value, expected); + } + { + let resp = contract_methods.returns_bytes_option(false).call().await?; - let resp = contract_methods.returns_vec_option(true).call().await?; - let expected = Some(vec![2, 2, 2, 2, 2]); - assert_eq!(resp.value, expected); + assert!(resp.value.is_none()); + } + { + let resp = contract_methods.returns_vec_option(true).call().await?; + let expected = Some(vec![2, 2, 2, 2, 2]); - let resp = contract_methods.returns_vec_option(false).call().await?; - assert!(resp.value.is_none()); + assert_eq!(resp.value, expected); + } + { + let resp = contract_methods.returns_vec_option(false).call().await?; - let resp = contract_methods.returns_string_option(true).call().await?; - let expected = Some("Hello World".to_string()); - assert_eq!(resp.value, expected); + assert!(resp.value.is_none()); + } + { + let resp = contract_methods.returns_string_option(true).call().await?; + let expected = Some("Hello World".to_string()); - let resp = contract_methods.returns_string_option(false).call().await?; - assert!(resp.value.is_none()); + assert_eq!(resp.value, expected); + } + { + let resp = contract_methods.returns_string_option(false).call().await?; - let resp = contract_methods.returns_str_option(true).call().await?; - let expected = Some("Hello World".try_into()?); - assert_eq!(resp.value, expected); + assert!(resp.value.is_none()); + } + { + let resp = contract_methods.returns_str_option(true).call().await?; + let expected = Some("Hello World".try_into()?); - let resp = contract_methods.returns_string_option(false).call().await?; - assert!(resp.value.is_none()); + assert_eq!(resp.value, expected); + } + { + let resp = contract_methods.returns_string_option(false).call().await?; - // If the LW(RET) instruction was not executed only conditionally, then the FuelVM would OOM. - let _ = contract_methods - .would_raise_a_memory_overflow() - .call() - .await?; + assert!(resp.value.is_none()); + } + + #[cfg(experimental)] + { + // If the LW(RET) instruction was not executed only conditionally, then the FuelVM would OOM. + let _ = contract_methods + .would_raise_a_memory_overflow() + .call() + .await?; + + let resp = contract_methods + .returns_a_heap_type_too_deep() + .call() + .await + .expect_err("should fail because it has a deeply nested heap type"); + let expected = "codec: enums currently support only one level deep heap types".to_string(); + + assert_eq!(resp.to_string(), expected); + } - let resp = contract_methods - .returns_a_heap_type_too_deep() - .call() - .await - .expect_err("should fail because it has a deeply nested heap type"); - let expected = "codec: enums currently support only one level deep heap types".to_string(); - assert_eq!(resp.to_string(), expected); Ok(()) } From 21f37b4c03293ee914c83bedae106c5d9f96ee5b Mon Sep 17 00:00:00 2001 From: hal3e Date: Tue, 12 Mar 2024 17:46:49 +0100 Subject: [PATCH 09/30] wip --- .../fuels/tests/types/predicates/predicate_vector/src/main.sw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fuels/tests/types/predicates/predicate_vector/src/main.sw b/packages/fuels/tests/types/predicates/predicate_vector/src/main.sw index d23cd2200d..8664900b44 100644 --- a/packages/fuels/tests/types/predicates/predicate_vector/src/main.sw +++ b/packages/fuels/tests/types/predicates/predicate_vector/src/main.sw @@ -2,5 +2,5 @@ predicate; fn main(a: u32, b: u64, c: Vec) -> bool { let number: u64 = c.get(2).unwrap(); - number == (b + a.as_u64()) + number == (b + a.as_u64()) } From f88f1b279c85fda7fbf10a3d4a3a2f68643f174d Mon Sep 17 00:00:00 2001 From: hal3e Date: Tue, 12 Mar 2024 17:52:07 +0100 Subject: [PATCH 10/30] wip --- packages/fuels/Forc.toml | 2 +- packages/fuels/tests/predicates.rs | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/fuels/Forc.toml b/packages/fuels/Forc.toml index 7381878a75..f88436feba 100644 --- a/packages/fuels/Forc.toml +++ b/packages/fuels/Forc.toml @@ -106,4 +106,4 @@ members = [ ] [patch.'https://github.com/fuellabs/sway'] -std = { git = "https://github.com/fuellabs/sway", branch = "xunilrj/source-id-optional-when-auto-impl" } +std = { git = "https://github.com/fuellabs/sway", branch = "xunilrj/fix-predicate-entry" } diff --git a/packages/fuels/tests/predicates.rs b/packages/fuels/tests/predicates.rs index e417ae471c..d192c31c27 100644 --- a/packages/fuels/tests/predicates.rs +++ b/packages/fuels/tests/predicates.rs @@ -796,9 +796,16 @@ async fn predicate_can_access_manually_added_witnesses() -> Result<()> { .build(&provider) .await?; + #[cfg(experimental)] let witness = ABIEncoder::default() .encode(&[64u8.into_token()])? .resolve(0); + + #[cfg(not(experimental))] + let witness = ABIEncoder::default() + .encode(&[64u64.into_token()])? // u64 because this is VM memory + .resolve(0); + let witness2 = ABIEncoder::default() .encode(&[4096u64.into_token()])? .resolve(0); @@ -868,9 +875,16 @@ async fn tx_id_not_changed_after_adding_witnesses() -> Result<()> { let tx_id = tx.id(provider.chain_id()); + #[cfg(experimental)] let witness = ABIEncoder::default() .encode(&[64u8.into_token()])? .resolve(0); + + #[cfg(not(experimental))] + let witness = ABIEncoder::default() + .encode(&[64u64.into_token()])? // u64 because this is VM memory + .resolve(0); + let witness2 = ABIEncoder::default() .encode(&[4096u64.into_token()])? .resolve(0); From c3d362efb60b001af75b6cc49f30e0e1e0078c2c Mon Sep 17 00:00:00 2001 From: hal3e Date: Thu, 14 Mar 2024 16:26:06 +0100 Subject: [PATCH 11/30] fix or exclude tests --- packages/fuels-core/src/codec/abi_encoder.rs | 12 ++++++---- .../experimental_bounded_encoder.rs | 4 ++-- .../fuels-core/src/codec/function_selector.rs | 4 +++- .../fuels-core/src/types/unresolved_bytes.rs | 1 - packages/fuels-programs/src/call_utils.rs | 22 +++++++++---------- packages/fuels/Forc.toml | 2 +- packages/fuels/tests/bindings.rs | 19 ++++++++++++++-- packages/fuels/tests/contracts.rs | 4 ++-- packages/fuels/tests/from_token.rs | 6 ++++- packages/fuels/tests/logs.rs | 2 +- packages/fuels/tests/providers.rs | 3 +++ 11 files changed, 52 insertions(+), 27 deletions(-) diff --git a/packages/fuels-core/src/codec/abi_encoder.rs b/packages/fuels-core/src/codec/abi_encoder.rs index 9a2f4601dd..5c3a3affac 100644 --- a/packages/fuels-core/src/codec/abi_encoder.rs +++ b/packages/fuels-core/src/codec/abi_encoder.rs @@ -1,14 +1,13 @@ -#[cfg(experimental)] mod bounded_encoder; #[cfg(not(experimental))] mod experimental_bounded_encoder; use std::default::Default; -#[cfg(experimental)] use crate::codec::abi_encoder::bounded_encoder::BoundedEncoder; + #[cfg(not(experimental))] -use crate::codec::abi_encoder::experimental_bounded_encoder::BoundedEncoder; +use crate::codec::abi_encoder::experimental_bounded_encoder::ExperimentalBoundedEncoder; use crate::types::{errors::Result, unresolved_bytes::UnresolvedBytes, Token}; #[derive(Debug, Clone, Copy)] @@ -49,7 +48,12 @@ impl ABIEncoder { /// Encodes `Token`s in `args` following the ABI specs defined /// [here](https://github.com/FuelLabs/fuel-specs/blob/master/specs/protocol/abi.md) pub fn encode(&self, args: &[Token]) -> Result { - BoundedEncoder::new(self.config, false).encode(args) + #[cfg(experimental)] + let res = BoundedEncoder::new(self.config, false).encode(args); + #[cfg(not(experimental))] + let res = ExperimentalBoundedEncoder::new(self.config, false).encode(args); + + res } } diff --git a/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs b/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs index 7e39e267c2..0fc33ce7ee 100644 --- a/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs +++ b/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs @@ -10,12 +10,12 @@ use crate::{ }, }; -pub(crate) struct BoundedEncoder { +pub(crate) struct ExperimentalBoundedEncoder { depth_tracker: CounterWithLimit, token_tracker: CounterWithLimit, } -impl BoundedEncoder { +impl ExperimentalBoundedEncoder { pub(crate) fn new(config: EncoderConfig, _unused: bool) -> Self { let depth_tracker = CounterWithLimit::new(config.max_depth, "depth", CodecDirection::Encoding); diff --git a/packages/fuels-core/src/codec/function_selector.rs b/packages/fuels-core/src/codec/function_selector.rs index 5bf78ab527..dcb01a1416 100644 --- a/packages/fuels-core/src/codec/function_selector.rs +++ b/packages/fuels-core/src/codec/function_selector.rs @@ -1,7 +1,9 @@ #[cfg(experimental)] use sha2::{Digest, Sha256}; -use crate::types::param_types::{NamedParamType, ParamType}; +#[cfg(experimental)] +use crate::types::param_types::NamedParamType; +use crate::types::param_types::ParamType; #[cfg(experimental)] use crate::types::ByteArray; diff --git a/packages/fuels-core/src/types/unresolved_bytes.rs b/packages/fuels-core/src/types/unresolved_bytes.rs index 40ff4bdc1f..02198f98b7 100644 --- a/packages/fuels-core/src/types/unresolved_bytes.rs +++ b/packages/fuels-core/src/types/unresolved_bytes.rs @@ -9,7 +9,6 @@ pub enum Data { Dynamic(Vec), } impl Data { - #[cfg(experimental)] pub(crate) fn size_in_bytes(&self) -> usize { match self { Data::Inline(data) => data.len(), diff --git a/packages/fuels-programs/src/call_utils.rs b/packages/fuels-programs/src/call_utils.rs index 54daf3581c..b72c966016 100644 --- a/packages/fuels-programs/src/call_utils.rs +++ b/packages/fuels-programs/src/call_utils.rs @@ -332,8 +332,8 @@ pub(crate) fn build_script_data_from_contract_calls( /// 3. Gas to be forwarded `(1 * `[`WORD_SIZE`]`)` - Optional /// 4. Contract ID ([`ContractId::LEN`]); /// 5. Function selector offset `(1 * `[`WORD_SIZE`]`)` -/// 6. Calldata offset (optional) `(1 * `[`WORD_SIZE`]`)` -/// 7. Encoded function selector +/// 6. Calldata offset `(1 * `[`WORD_SIZE`]`)` +/// 7. Encoded function selector - method name /// 8. Encoded arguments pub(crate) fn build_script_data_from_contract_calls( calls: &[ContractCall], @@ -350,10 +350,10 @@ pub(crate) fn build_script_data_from_contract_calls( for call in calls { let gas_forwarded = call.call_parameters.gas_forwarded(); - script_data.extend(call.call_parameters.amount().to_be_bytes()); - script_data.extend(call.call_parameters.asset_id().iter()); + script_data.extend(call.call_parameters.amount().to_be_bytes()); // 1. Amount + script_data.extend(call.call_parameters.asset_id().iter()); // 2. Asset ID - let gas_forwarded_size = gas_forwarded + let gas_forwarded_size = gas_forwarded // 3. Gas to be forwarded - Optional .map(|gf| { script_data.extend((gf as Word).to_be_bytes()); @@ -381,11 +381,11 @@ pub(crate) fn build_script_data_from_contract_calls( .map(|ub| ub.resolve(custom_input_offset as Word)) .map_err(|e| error!(Codec, "cannot encode contract call arguments: {e}"))?; - script_data.extend(call.contract_id.hash().as_ref()); - script_data.extend((encoded_selector_offset as Word).to_be_bytes()); - script_data.extend((custom_input_offset as Word).to_be_bytes()); - script_data.extend(call.encoded_selector.clone()); - script_data.extend(bytes); + script_data.extend(call.contract_id.hash().as_ref()); // 4. Contract ID + script_data.extend((encoded_selector_offset as Word).to_be_bytes()); // 5. Fun. selector offset + script_data.extend((custom_input_offset as Word).to_be_bytes()); // 6. Calldata offset + script_data.extend(call.encoded_selector.clone()); // 7. Encoded function selector + script_data.extend(bytes); // 8. Encoded arguments // the data segment that holds the parameters for the next call // begins at the original offset + the data we added so far @@ -426,7 +426,6 @@ pub(crate) fn get_single_call_instructions( let mut instructions = [ op::movi(0x10, call_data_offset), op::movi(0x11, amount_offset), - #[cfg(experimental)] op::lw(0x11, 0x11, 0), op::movi(0x12, asset_id_offset), ] @@ -440,7 +439,6 @@ pub(crate) fn get_single_call_instructions( instructions.extend(&[ op::movi(0x13, gas_forwarded_offset), - #[cfg(experimental)] op::lw(0x13, 0x13, 0), op::call(0x10, 0x11, 0x12, 0x13), ]); diff --git a/packages/fuels/Forc.toml b/packages/fuels/Forc.toml index f88436feba..5833f01046 100644 --- a/packages/fuels/Forc.toml +++ b/packages/fuels/Forc.toml @@ -106,4 +106,4 @@ members = [ ] [patch.'https://github.com/fuellabs/sway'] -std = { git = "https://github.com/fuellabs/sway", branch = "xunilrj/fix-predicate-entry" } +std = { git = "https://github.com/fuellabs/sway", branch = "xunilrj/remove-method-name-log" } diff --git a/packages/fuels/tests/bindings.rs b/packages/fuels/tests/bindings.rs index 872364a45f..227a726d83 100644 --- a/packages/fuels/tests/bindings.rs +++ b/packages/fuels/tests/bindings.rs @@ -1,10 +1,14 @@ -use std::{slice, str::FromStr}; +#[cfg(experimental)] +use std::slice; +use std::str::FromStr; +use fuels::prelude::*; +#[cfg(experimental)] use fuels::{ core::{codec::ABIEncoder, traits::Tokenizable}, - prelude::*, types::{Bits256, EvmAddress}, }; +#[cfg(experimental)] use sha2::{Digest, Sha256}; pub fn null_contract_id() -> Bech32ContractId { @@ -13,6 +17,7 @@ pub fn null_contract_id() -> Bech32ContractId { .unwrap() } +#[cfg(experimental)] #[tokio::test] async fn compile_bindings_from_contract_file() { // Generates the bindings from an ABI definition in a JSON file @@ -44,6 +49,7 @@ async fn compile_bindings_from_contract_file() { assert_eq!("000000005f68ee3d000000000000002a", encoded); } +#[cfg(experimental)] #[tokio::test] async fn compile_bindings_from_inline_contract() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -104,6 +110,7 @@ async fn compile_bindings_from_inline_contract() -> Result<()> { Ok(()) } +#[cfg(experimental)] #[tokio::test] async fn compile_bindings_array_input() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -181,6 +188,7 @@ async fn compile_bindings_array_input() -> Result<()> { Ok(()) } +#[cfg(experimental)] #[tokio::test] async fn compile_bindings_bool_array_input() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -255,6 +263,7 @@ async fn compile_bindings_bool_array_input() -> Result<()> { Ok(()) } +#[cfg(experimental)] #[tokio::test] async fn compile_bindings_string_input() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -325,6 +334,7 @@ async fn compile_bindings_string_input() -> Result<()> { Ok(()) } +#[cfg(experimental)] #[tokio::test] async fn compile_bindings_b256_input() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -396,6 +406,7 @@ async fn compile_bindings_b256_input() -> Result<()> { Ok(()) } +#[cfg(experimental)] #[tokio::test] async fn compile_bindings_evm_address_input() -> Result<()> { abigen!(Contract( @@ -466,6 +477,7 @@ async fn compile_bindings_evm_address_input() -> Result<()> { Ok(()) } +#[cfg(experimental)] #[tokio::test] async fn compile_bindings_struct_input() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -568,6 +580,7 @@ async fn compile_bindings_struct_input() -> Result<()> { Ok(()) } +#[cfg(experimental)] #[tokio::test] async fn compile_bindings_nested_struct_input() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -676,6 +689,7 @@ async fn compile_bindings_nested_struct_input() -> Result<()> { Ok(()) } +#[cfg(experimental)] #[tokio::test] async fn compile_bindings_enum_input() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -763,6 +777,7 @@ async fn compile_bindings_enum_input() -> Result<()> { Ok(()) } +#[cfg(experimental)] #[tokio::test] async fn shared_types() -> Result<()> { setup_program_test!( diff --git a/packages/fuels/tests/contracts.rs b/packages/fuels/tests/contracts.rs index 107ee755da..d17bc980df 100644 --- a/packages/fuels/tests/contracts.rs +++ b/packages/fuels/tests/contracts.rs @@ -1707,7 +1707,7 @@ async fn test_arguments_with_gas_forwarded() -> Result<()> { let response = contract_instance .methods() .get_single(x) - .call_params(CallParameters::default().with_gas_forwarded(1024))? + .call_params(CallParameters::default().with_gas_forwarded(4096))? .call() .await?; @@ -1717,7 +1717,7 @@ async fn test_arguments_with_gas_forwarded() -> Result<()> { contract_instance_2 .methods() .u32_vec(vec_input.clone()) - .call_params(CallParameters::default().with_gas_forwarded(1024))? + .call_params(CallParameters::default().with_gas_forwarded(4096))? .call() .await?; } diff --git a/packages/fuels/tests/from_token.rs b/packages/fuels/tests/from_token.rs index 663453e59b..b17d35bf2f 100644 --- a/packages/fuels/tests/from_token.rs +++ b/packages/fuels/tests/from_token.rs @@ -1,6 +1,8 @@ use std::str::FromStr; -use fuels::{core::traits::Tokenizable, prelude::*, types::Token}; +use fuels::prelude::*; +#[cfg(experimental)] +use fuels::{core::traits::Tokenizable, types::Token}; pub fn null_contract_id() -> Bech32ContractId { // a bech32 contract address that decodes to [0u8;32] @@ -8,6 +10,7 @@ pub fn null_contract_id() -> Bech32ContractId { .unwrap() } +#[cfg(experimental)] #[tokio::test] async fn create_struct_from_decoded_tokens() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -102,6 +105,7 @@ async fn create_struct_from_decoded_tokens() -> Result<()> { Ok(()) } +#[cfg(experimental)] #[tokio::test] async fn create_nested_struct_from_decoded_tokens() -> Result<()> { // Generates the bindings from the an ABI definition inline. diff --git a/packages/fuels/tests/logs.rs b/packages/fuels/tests/logs.rs index 746e9b96bc..4ededc1a05 100644 --- a/packages/fuels/tests/logs.rs +++ b/packages/fuels/tests/logs.rs @@ -1453,7 +1453,7 @@ async fn can_configure_decoder_for_script_log_decoding() -> Result<()> { // String slices cannot be decoded from logs as they are encoded as ptr, len // TODO: Once https://github.com/FuelLabs/sway/issues/5110 is resolved we can remove this #[tokio::test] -#[cfg(not(experimental))] +#[cfg(experimental)] async fn string_slice_log() -> Result<()> { setup_program_test!( Wallets("wallet"), diff --git a/packages/fuels/tests/providers.rs b/packages/fuels/tests/providers.rs index 06307452ba..2f7a0cd378 100644 --- a/packages/fuels/tests/providers.rs +++ b/packages/fuels/tests/providers.rs @@ -323,7 +323,10 @@ async fn test_gas_forwarded_defaults_to_tx_limit() -> Result<()> { ); // The gas used by the script to call a contract and forward remaining gas limit. + #[cfg(experimental)] let gas_used_by_script = 360; + #[cfg(not(experimental))] + let gas_used_by_script = 864; let gas_limit = 225_883; let response = contract_instance .methods() From 3f2313312ef1e3e1f7d63beffb869ebeb87c7feb Mon Sep 17 00:00:00 2001 From: hal3e Date: Tue, 19 Mar 2024 16:23:07 +0100 Subject: [PATCH 12/30] fix tests --- examples/contracts/src/lib.rs | 15 +- examples/debugging/src/lib.rs | 21 +- packages/fuels-core/src/codec.rs | 3 + packages/fuels-core/src/codec/abi_decoder.rs | 181 +++++++----- .../codec/abi_decoder/decode_as_debug_str.rs | 163 +++++++++++ packages/fuels-core/src/codec/abi_encoder.rs | 265 +++++++++++------- packages/fuels-programs/src/call_utils.rs | 21 +- packages/fuels-programs/src/receipt_parser.rs | 7 + packages/fuels/Forc.toml | 2 +- packages/fuels/tests/providers.rs | 2 +- 10 files changed, 504 insertions(+), 176 deletions(-) diff --git a/examples/contracts/src/lib.rs b/examples/contracts/src/lib.rs index 1e1b7d8e23..5b65d98572 100644 --- a/examples/contracts/src/lib.rs +++ b/examples/contracts/src/lib.rs @@ -107,7 +107,12 @@ mod tests { .await?; // ANCHOR_END: contract_call_cost_estimation - assert_eq!(transaction_cost.gas_used, 791); + #[cfg(experimental)] + let expected_gas = 791; + #[cfg(not(experimental))] + let expected_gas = 2086; + + assert_eq!(transaction_cost.gas_used, expected_gas); Ok(()) } @@ -602,7 +607,12 @@ mod tests { .await?; // ANCHOR_END: multi_call_cost_estimation - assert_eq!(transaction_cost.gas_used, 1162); + #[cfg(experimental)] + let expected_gas = 1162; + #[cfg(not(experimental))] + let expected_gas = 3511; + + assert_eq!(transaction_cost.gas_used, expected_gas); Ok(()) } @@ -676,6 +686,7 @@ mod tests { Ok(()) } + #[cfg(experimental)] #[tokio::test] async fn low_level_call_example() -> Result<()> { use fuels::{ diff --git a/examples/debugging/src/lib.rs b/examples/debugging/src/lib.rs index bae1cceca6..a2700ebefd 100644 --- a/examples/debugging/src/lib.rs +++ b/examples/debugging/src/lib.rs @@ -3,17 +3,19 @@ mod tests { use std::collections::HashMap; use fuel_abi_types::abi::program::ProgramABI; + #[cfg(experimental)] + use fuels::core::codec::{calldata, fn_selector}; use fuels::{ - core::{ - codec::{calldata, fn_selector, resolve_fn_selector, ABIDecoder}, - traits::Parameterize, - }, + core::codec::ABIDecoder, macros::abigen, types::{errors::Result, param_types::ParamType, SizedAsciiString}, }; + #[cfg(experimental)] #[test] fn get_a_fn_selector() { + use fuels::core::{codec::resolve_fn_selector, traits::Parameterize}; + // ANCHOR: example_fn_selector // fn some_fn_name(arg1: Vec, arg2: u8) let fn_name = "some_fn_name"; @@ -25,8 +27,11 @@ mod tests { // ANCHOR_END: example_fn_selector } + #[cfg(experimental)] #[test] fn a_fn_selector_from_json_abi() -> Result<()> { + use fuels::core::codec::resolve_fn_selector; + let json_abi_file = "../../packages/fuels/tests/contracts/contract_test/out/debug/contract_test-abi.json"; let abi_file_contents = std::fs::read_to_string(json_abi_file)?; @@ -60,6 +65,7 @@ mod tests { Ok(()) } + #[cfg(experimental)] #[test] fn test_macros() -> Result<()> { let function_selector = fn_selector!(initialize_counter(u64)); @@ -161,9 +167,14 @@ mod tests { let expected_u8 = 1; + #[cfg(experimental)] + let data = [0, 0, 0, 0, 0, 0, 0, 1]; + #[cfg(not(experimental))] + let data = [1]; + assert_eq!( format!("{expected_u8}"), - decoder.decode_as_debug_str(¶m_type, &[0, 0, 0, 0, 0, 0, 0, 1])? + decoder.decode_as_debug_str(¶m_type, &data)? ); } diff --git a/packages/fuels-core/src/codec.rs b/packages/fuels-core/src/codec.rs index 58583b3547..09bc586e38 100644 --- a/packages/fuels-core/src/codec.rs +++ b/packages/fuels-core/src/codec.rs @@ -34,7 +34,10 @@ mod tests { #[test] fn can_convert_bytes_into_tuple() -> Result<()> { + #[cfg(experimental)] let tuple_in_bytes: Vec = vec![0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2]; + #[cfg(not(experimental))] + let tuple_in_bytes: Vec = vec![0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2]; let the_tuple: (u64, u32) = try_from_bytes(&tuple_in_bytes, DecoderConfig::default())?; diff --git a/packages/fuels-core/src/codec/abi_decoder.rs b/packages/fuels-core/src/codec/abi_decoder.rs index b2001b5f8d..8f8b587860 100644 --- a/packages/fuels-core/src/codec/abi_decoder.rs +++ b/packages/fuels-core/src/codec/abi_decoder.rs @@ -129,7 +129,10 @@ mod tests { #[test] fn decode_int() -> Result<()> { - let data = [0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff]; + #[cfg(experimental)] + let data = [0, 0, 0, 0, 255, 255, 255, 255]; + #[cfg(not(experimental))] + let data = [255, 255, 255, 255]; let decoded = ABIDecoder::default().decode(&ParamType::U32, &data)?; @@ -148,16 +151,28 @@ mod tests { ParamType::U128, ParamType::U256, ]; + + #[cfg(experimental)] + let data = [ + 0, 0, 0, 0, 255, 255, 255, 255, // u32 + 255, // u8 + 0, 0, 0, 0, 0, 0, 255, 255, // u16 + 255, 255, 255, 255, 255, 255, 255, 255, // u64 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // u128 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // u256 + ]; + #[cfg(not(experimental))] let data = [ - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, // u32 - 0xff, // u8 - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, // u16 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // u64 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, // u128 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, // u256 + 255, 255, 255, 255, // u32 + 255, // u8 + 255, 255, // u16 + 255, 255, 255, 255, 255, 255, 255, 255, // u64 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // u128 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // u256 ]; let decoded = ABIDecoder::default().decode_multiple(&types, &data)?; @@ -178,7 +193,7 @@ mod tests { #[test] fn decode_bool() -> Result<()> { let types = vec![ParamType::Bool, ParamType::Bool]; - let data = [0x01, 0x0]; + let data = [1, 0]; let decoded = ABIDecoder::default().decode_multiple(&types, &data)?; @@ -192,9 +207,8 @@ mod tests { #[test] fn decode_b256() -> Result<()> { let data = [ - 0xd5, 0x57, 0x9c, 0x46, 0xdf, 0xcc, 0x7f, 0x18, 0x20, 0x70, 0x13, 0xe6, 0x5b, 0x44, - 0xe4, 0xcb, 0x4e, 0x2c, 0x22, 0x98, 0xf4, 0xac, 0x45, 0x7b, 0xa8, 0xf8, 0x27, 0x43, - 0xf3, 0x1e, 0x93, 0xb, + 213, 87, 156, 70, 223, 204, 127, 24, 32, 112, 19, 230, 91, 68, 228, 203, 78, 44, 34, + 152, 244, 172, 69, 123, 168, 248, 39, 67, 243, 30, 147, 11, ]; let decoded = ABIDecoder::default().decode(&ParamType::B256, &data)?; @@ -207,11 +221,17 @@ mod tests { #[test] fn decode_string_array() -> Result<()> { let types = vec![ParamType::StringArray(23), ParamType::StringArray(5)]; + #[cfg(experimental)] let data = [ - 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, // This is - 0x61, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x73, // a full s - 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x00, // entence - 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x00, 0x00, 0x00, // Hello + 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, + 116, 101, 110, 99, 101, //This is a full sentence + 72, 101, 108, 108, 111, // Hello + ]; + #[cfg(not(experimental))] + let data = [ + 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, + 116, 101, 110, 99, 101, //This is a full sentence + 72, 101, 108, 108, 111, // Hello ]; let decoded = ABIDecoder::default().decode_multiple(&types, &data)?; @@ -232,10 +252,16 @@ mod tests { #[test] fn decode_string_slice() -> Result<()> { let types = vec![ParamType::StringSlice]; + #[cfg(experimental)] + let data = [ + 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, + 116, 101, 110, 99, 101, //This is a full sentence + ]; + #[cfg(not(experimental))] let data = [ - 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, // This is - 0x61, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x73, // a full s - 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, // entence + 0, 0, 0, 0, 0, 0, 0, 23, // [length] + 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, + 116, 101, 110, 99, 101, //This is a full sentence ]; let decoded = ABIDecoder::default().decode_multiple(&types, &data)?; @@ -252,9 +278,8 @@ mod tests { #[test] fn decode_array() -> Result<()> { - // Create a parameter type for u8[2]. let types = vec![ParamType::Array(Box::new(ParamType::U8), 2)]; - let data = [0xff, 0x2a]; + let data = [255, 42]; let decoded = ABIDecoder::default().decode_multiple(&types, &data)?; @@ -271,9 +296,11 @@ mod tests { // bar: bool, // } - let data = [ - 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - ]; + #[cfg(experimental)] + let data = [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]; + #[cfg(not(experimental))] + let data = [1, 1]; + let param_type = ParamType::Struct { name: "".to_string(), fields: to_named(&[ParamType::U8, ParamType::Bool]), @@ -291,10 +318,14 @@ mod tests { #[test] fn decode_bytes() -> Result<()> { - let data = [0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05]; + #[cfg(experimental)] + let data = [255, 0, 1, 2, 3, 4, 5]; + #[cfg(not(experimental))] + let data = [0, 0, 0, 0, 0, 0, 0, 7, 255, 0, 1, 2, 3, 4, 5]; + let decoded = ABIDecoder::default().decode(&ParamType::Bytes, &data)?; - let expected = Token::Bytes(data.to_vec()); + let expected = Token::Bytes([255, 0, 1, 2, 3, 4, 5].to_vec()); assert_eq!(decoded, expected); @@ -317,9 +348,10 @@ mod tests { }]; // "0" discriminant and 42 enum value - let data = [ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2a, - ]; + #[cfg(experimental)] + let data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42]; + #[cfg(not(experimental))] + let data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42]; let decoded = ABIDecoder::default().decode_multiple(&types, &data)?; @@ -329,6 +361,7 @@ mod tests { Ok(()) } + #[cfg(experimental)] #[test] fn decoder_will_skip_enum_padding_and_decode_next_arg() -> Result<()> { // struct MyStruct { @@ -413,10 +446,12 @@ mod tests { generics: vec![], }; + #[cfg(experimental)] let data = [ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0, 0, 0, 0, 0, 0, 0, 10, 1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, ]; + #[cfg(not(experimental))] + let data = [0, 10, 1, 1, 2]; let decoded = ABIDecoder::default().decode(&nested_struct, &data)?; @@ -470,20 +505,24 @@ mod tests { let types = [nested_struct, u8_arr, b256]; + #[cfg(experimental)] + let bytes = [ + 0, 0, 0, 0, 0, 0, 0, 10, // u16 + 1, 0, 0, 0, 0, 0, 0, 0, // bool + 1, 2, // array[u8;2] + 1, 2, // array[u8;2] + 213, 87, 156, 70, 223, 204, 127, 24, 32, 112, 19, 230, 91, 68, 228, 203, 78, 44, 34, + 152, 244, 172, 69, 123, 168, 248, 39, 67, 243, 30, 147, 11, // b256 + ]; + + #[cfg(not(experimental))] let bytes = [ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, // u16 - 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // bool - 0x1, 0x2, // array[u8] - 0x1, 0x2, // array[u8] - 0xd5, 0x57, 0x9c, 0x46, 0xdf, 0xcc, 0x7f, 0x18, // b256 start - 0x20, 0x70, 0x13, 0xe6, 0x5b, 0x44, 0xe4, 0xcb, // - 0x4e, 0x2c, 0x22, 0x98, 0xf4, 0xac, 0x45, 0x7b, // - 0xa8, 0xf8, 0x27, 0x43, 0xf3, 0x1e, 0x93, - 0xb, // b256 end - // 0x66, 0x6f, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, // "foo" - // 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, // - // 0x61, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x73, // - // 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, // + 0, 10, // u16 + 1, // bool + 1, 2, // array[u8;2] + 1, 2, // array[u8;2] + 213, 87, 156, 70, 223, 204, 127, 24, 32, 112, 19, 230, 91, 68, 228, 203, 78, 44, 34, + 152, 244, 172, 69, 123, 168, 248, 39, 67, 243, 30, 147, 11, // b256 ]; let decoded = ABIDecoder::default().decode_multiple(&types, &bytes)?; @@ -500,9 +539,8 @@ mod tests { let u8_arr = Token::Array(vec![Token::U8(1), Token::U8(2)]); let b256 = Token::B256([ - 0xd5, 0x57, 0x9c, 0x46, 0xdf, 0xcc, 0x7f, 0x18, 0x20, 0x70, 0x13, 0xe6, 0x5b, 0x44, - 0xe4, 0xcb, 0x4e, 0x2c, 0x22, 0x98, 0xf4, 0xac, 0x45, 0x7b, 0xa8, 0xf8, 0x27, 0x43, - 0xf3, 0x1e, 0x93, 0xb, + 213, 87, 156, 70, 223, 204, 127, 24, 32, 112, 19, 230, 91, 68, 228, 203, 78, 44, 34, + 152, 244, 172, 69, 123, 168, 248, 39, 67, 243, 30, 147, 11, ]); let expected: Vec = vec![foo, u8_arr, b256]; @@ -512,6 +550,7 @@ mod tests { Ok(()) } + #[cfg(experimental)] #[test] fn units_in_structs_are_decoded_as_one_word() -> Result<()> { let data = [ @@ -531,6 +570,7 @@ mod tests { Ok(()) } + #[cfg(experimental)] #[test] fn enums_with_all_unit_variants_are_decoded_from_one_word() -> Result<()> { let data = [0, 0, 0, 0, 0, 0, 0, 1]; @@ -553,7 +593,7 @@ mod tests { #[test] fn out_of_bounds_discriminant_is_detected() -> Result<()> { let data = [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2]; - let types = to_named(&[ParamType::U32]); + let types = to_named(&[ParamType::U64]); let enum_variants = EnumVariants::new(types)?; let enum_type = ParamType::Enum { name: "".to_string(), @@ -642,12 +682,13 @@ mod tests { } #[test] - pub fn capacity_maloc() { + pub fn capacity_malloc() { let param_type = Array(Box::new(U8), usize::MAX); let result = ABIDecoder::default().decode(¶m_type, &[]); assert!(matches!(result, Err(Error::Codec(_)))); } + #[cfg(experimental)] #[test] fn decoding_enum_with_more_than_one_heap_type_variant_fails() -> Result<()> { let mut param_types = vec![ @@ -687,6 +728,7 @@ mod tests { Ok(()) } + #[cfg(experimental)] #[test] fn enums_w_too_deeply_nested_heap_types_not_allowed() { let variants = to_named(&[ @@ -772,28 +814,39 @@ mod tests { max_tokens: 3, ..Default::default() }; + { + let data = [0; 3 * WORD_SIZE]; + let inner_param_types = vec![ParamType::U64; 3]; + for param_type in [ + ParamType::Struct { + name: "".to_string(), + fields: to_named(&inner_param_types), + generics: vec![], + }, + ParamType::Tuple(inner_param_types.clone()), + ParamType::Array(Box::new(ParamType::U64), 3), + ] { + assert_decoding_failed_w_data( + config, + ¶m_type, + "token limit `3` reached while decoding. Try increasing it", + &data, + ); + } + } + { + let data = [0, 0, 0, 0, 0, 0, 0, 3, 1, 2, 3]; - let data = [0; 3 * WORD_SIZE]; - let inner_param_types = vec![ParamType::U8; 3]; - for param_type in [ - ParamType::Struct { - name: "".to_string(), - fields: to_named(&inner_param_types), - generics: vec![], - }, - ParamType::Tuple(inner_param_types.clone()), - ParamType::Array(Box::new(ParamType::U8), 3), - ParamType::Vector(Box::new(ParamType::U8)), - ] { assert_decoding_failed_w_data( config, - ¶m_type, + &ParamType::Vector(Box::new(ParamType::U8)), "token limit `3` reached while decoding. Try increasing it", &data, ); } } + #[cfg(experimental)] #[test] fn vectors_of_zst_are_not_supported() { let param_type = ParamType::Vector(Box::new(ParamType::StringArray(0))); diff --git a/packages/fuels-core/src/codec/abi_decoder/decode_as_debug_str.rs b/packages/fuels-core/src/codec/abi_decoder/decode_as_debug_str.rs index 15c4d9e9c3..60ca568dfc 100644 --- a/packages/fuels-core/src/codec/abi_decoder/decode_as_debug_str.rs +++ b/packages/fuels-core/src/codec/abi_decoder/decode_as_debug_str.rs @@ -104,6 +104,7 @@ mod tests { }, }; + #[cfg(experimental)] #[test] fn param_type_decode_debug() -> Result<()> { let decoder = ABIDecoder::default(); @@ -259,4 +260,166 @@ mod tests { Ok(()) } + + #[cfg(not(experimental))] + #[test] + fn param_type_decode_debug() -> Result<()> { + let decoder = ABIDecoder::default(); + { + assert_eq!( + format!("{:?}", true), + decoder.decode_as_debug_str(&bool::param_type(), &[1])? + ); + + assert_eq!( + format!("{:?}", 128u8), + decoder.decode_as_debug_str(&u8::param_type(), &[128])? + ); + + assert_eq!( + format!("{:?}", 256u16), + decoder.decode_as_debug_str(&u16::param_type(), &[1, 0])? + ); + + assert_eq!( + format!("{:?}", 512u32), + decoder.decode_as_debug_str(&u32::param_type(), &[0, 0, 2, 0])? + ); + + assert_eq!( + format!("{:?}", 1024u64), + decoder.decode_as_debug_str(&u64::param_type(), &[0, 0, 0, 0, 0, 0, 4, 0])? + ); + + assert_eq!( + format!("{:?}", 1024u128), + decoder.decode_as_debug_str( + &u128::param_type(), + &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0] + )? + ); + + assert_eq!( + format!("{:?}", U256::from(2048)), + decoder.decode_as_debug_str( + &U256::param_type(), + &[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 8, 0 + ] + )? + ); + } + { + let bytes = [ + 239, 134, 175, 169, 105, 108, 240, 220, 99, 133, 226, 196, 7, 166, 225, 89, 161, + 16, 60, 239, 183, 226, 174, 6, 54, 251, 51, 211, 203, 42, 158, 74, + ]; + let bits256 = Bits256(bytes); + + assert_eq!( + format!("{bits256:?}"), + decoder.decode_as_debug_str( + &Bits256::param_type(), + &[ + 239, 134, 175, 169, 105, 108, 240, 220, 99, 133, 226, 196, 7, 166, 225, 89, + 161, 16, 60, 239, 183, 226, 174, 6, 54, 251, 51, 211, 203, 42, 158, 74 + ] + )? + ); + + assert_eq!( + format!("{:?}", Bytes(bytes.to_vec())), + decoder.decode_as_debug_str( + &Bytes::param_type(), + &[ + 0, 0, 0, 0, 0, 0, 0, 32, 239, 134, 175, 169, 105, 108, 240, 220, 99, 133, + 226, 196, 7, 166, 225, 89, 161, 16, 60, 239, 183, 226, 174, 6, 54, 251, 51, + 211, 203, 42, 158, 74 + ] + )? + ); + + assert_eq!( + format!("{:?}", RawSlice(bytes.to_vec())), + decoder.decode_as_debug_str( + &RawSlice::param_type(), + &[ + 0, 0, 0, 0, 0, 0, 0, 32, 239, 134, 175, 169, 105, 108, 240, 220, 99, 133, + 226, 196, 7, 166, 225, 89, 161, 16, 60, 239, 183, 226, 174, 6, 54, 251, 51, + 211, 203, 42, 158, 74 + ] + )? + ); + + assert_eq!( + format!("{:?}", EvmAddress::from(bits256)), + decoder.decode_as_debug_str( + &EvmAddress::param_type(), + &[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 166, 225, 89, 161, 16, 60, 239, 183, + 226, 174, 6, 54, 251, 51, 211, 203, 42, 158, 74 + ] + )? + ); + } + { + assert_eq!( + format!("{:?}", AsciiString::new("Fuel".to_string())?), + decoder.decode_as_debug_str( + &AsciiString::param_type(), + &[0, 0, 0, 0, 0, 0, 0, 4, 70, 117, 101, 108] + )? + ); + + assert_eq!( + format!("{:?}", SizedAsciiString::<4>::new("Fuel".to_string())?), + decoder.decode_as_debug_str( + &SizedAsciiString::<4>::param_type(), + &[70, 117, 101, 108, 0, 0, 0, 0] + )? + ); + + assert_eq!( + format!("{}", "Fuel"), + decoder.decode_as_debug_str( + &String::param_type(), + &[0, 0, 0, 0, 0, 0, 0, 4, 70, 117, 101, 108] + )? + ); + } + { + assert_eq!( + format!("{:?}", (1, 2)), + decoder.decode_as_debug_str(&<(u8, u8)>::param_type(), &[1, 2])? + ); + + assert_eq!( + format!("{:?}", [3, 4]), + decoder.decode_as_debug_str( + &<[u64; 2]>::param_type(), + &[0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4] + )? + ); + } + { + assert_eq!( + format!("{:?}", Some(42)), + decoder.decode_as_debug_str( + &>::param_type(), + &[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 42] + )? + ); + + assert_eq!( + format!("{:?}", Err::(42u64)), + decoder.decode_as_debug_str( + &>::param_type(), + &[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 42] + )? + ); + } + + Ok(()) + } } diff --git a/packages/fuels-core/src/codec/abi_encoder.rs b/packages/fuels-core/src/codec/abi_encoder.rs index 5c3a3affac..33a1e84e97 100644 --- a/packages/fuels-core/src/codec/abi_encoder.rs +++ b/packages/fuels-core/src/codec/abi_encoder.rs @@ -78,13 +78,15 @@ impl ConfigurablesEncoder { mod tests { use std::slice; + #[cfg(experimental)] use itertools::chain; #[cfg(experimental)] use sha2::{Digest, Sha256}; use super::*; + #[cfg(experimental)] + use crate::constants::WORD_SIZE; use crate::{ - constants::WORD_SIZE, to_named, types::{ errors::Error, @@ -96,7 +98,9 @@ mod tests { #[cfg(experimental)] use crate::codec::first_four_bytes_of_sha256_hash; + #[cfg(experimental)] const VEC_METADATA_SIZE: usize = 3 * WORD_SIZE; + #[cfg(experimental)] const DISCRIMINANT_SIZE: usize = WORD_SIZE; #[test] @@ -566,6 +570,7 @@ mod tests { } // The encoding follows the ABI specs defined [here](https://github.com/FuelLabs/fuel-specs/blob/master/specs/protocol/abi.md) + #[cfg(experimental)] #[test] fn enums_are_sized_to_fit_the_biggest_variant() -> Result<()> { // Our enum has two variants: B256, and U64. So the enum will set aside @@ -646,20 +651,28 @@ mod tests { let top_level_enum_token = Token::Enum(Box::new((0, struct_a_token, top_level_enum_variants))); - let encoded = ABIEncoder::default() + let result = ABIEncoder::default() .encode(slice::from_ref(&top_level_enum_token))? .resolve(0); - let correct_encoding: Vec = [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // TopLevelEnum::v1 discriminant - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // DeeperEnum::v2 discriminant - b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', // str[10] - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // DeeperEnum padding - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x44, // StructA.some_number - ] - .into(); + #[cfg(experimental)] + let expected = [ + 0, 0, 0, 0, 0, 0, 0, 0, // TopLevelEnum::v1 discriminant + 0, 0, 0, 0, 0, 0, 0, 1, // DeeperEnum::v2 discriminant + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, // str[10] + 0, 0, 0, 0, 0, 0, // DeeperEnum padding + 0, 0, 0, 0, 0, 0, 44, 68, // StructA.some_number + ]; + #[cfg(not(experimental))] + let expected = [ + 0, 0, 0, 0, 0, 0, 0, 0, // TopLevelEnum::v1 discriminant + 0, 0, 0, 0, 0, 0, 0, 1, // DeeperEnum::v2 discriminant + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, // str[10] + 0, 0, 44, 68, // StructA.some_number + ]; + + assert_eq!(result, expected); - assert_eq!(hex::encode(correct_encoding), hex::encode(encoded)); Ok(()) } @@ -828,9 +841,11 @@ mod tests { .resolve(0); assert_eq!(actual, expected); + Ok(()) } + #[cfg(experimental)] #[test] fn units_in_composite_types_are_encoded_in_one_word() -> Result<()> { let expected = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5]; @@ -843,6 +858,7 @@ mod tests { Ok(()) } + #[cfg(experimental)] #[test] fn enums_with_units_are_correctly_padded() -> Result<()> { let discriminant = vec![0, 0, 0, 0, 0, 0, 0, 1]; @@ -860,6 +876,7 @@ mod tests { Ok(()) } + #[cfg(experimental)] #[test] fn vector_has_ptr_cap_len_and_then_data() -> Result<()> { // arrange @@ -884,6 +901,7 @@ mod tests { Ok(()) } + #[cfg(experimental)] #[test] fn data_from_two_vectors_aggregated_at_the_end() -> Result<()> { // arrange @@ -920,7 +938,7 @@ mod tests { } #[test] - fn a_vec_in_an_enum() -> Result<()> { + fn vec_in_enum() -> Result<()> { // arrange let offset = 40; let types = to_named(&[ParamType::B256, ParamType::Vector(Box::new(ParamType::U64))]); @@ -934,26 +952,34 @@ mod tests { .resolve(offset as u64); // assert - let discriminant = vec![0, 0, 0, 0, 0, 0, 0, 1]; - - const PADDING: usize = std::mem::size_of::<[u8; 32]>() - VEC_METADATA_SIZE; - - let vec1_ptr = ((DISCRIMINANT_SIZE + PADDING + VEC_METADATA_SIZE + offset) as u64) - .to_be_bytes() - .to_vec(); - let vec1_cap = [0, 0, 0, 0, 0, 0, 0, 1]; - let vec1_len = [0, 0, 0, 0, 0, 0, 0, 1]; - let vec1_data = [0, 0, 0, 0, 0, 0, 0, 5]; - - let expected = chain!( - discriminant, - vec![0; PADDING], - vec1_ptr, - vec1_cap, - vec1_len, - vec1_data - ) - .collect::>(); + #[cfg(experimental)] + let expected = { + let discriminant = vec![0, 0, 0, 0, 0, 0, 0, 1]; + + const PADDING: usize = std::mem::size_of::<[u8; 32]>() - VEC_METADATA_SIZE; + + let vec1_ptr = ((DISCRIMINANT_SIZE + PADDING + VEC_METADATA_SIZE + offset) as u64) + .to_be_bytes() + .to_vec(); + let vec1_cap = [0, 0, 0, 0, 0, 0, 0, 1]; + let vec1_len = [0, 0, 0, 0, 0, 0, 0, 1]; + let vec1_data = [0, 0, 0, 0, 0, 0, 0, 5]; + + chain!( + discriminant, + vec![0; PADDING], + vec1_ptr, + vec1_cap, + vec1_len, + vec1_data + ) + .collect::>() + }; + #[cfg(not(experimental))] + let expected = [ + 0, 0, 0, 0, 0, 0, 0, 1, // enum dicsriminant + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5, // vec[len, u64] + ]; assert_eq!(result, expected); @@ -961,7 +987,7 @@ mod tests { } #[test] - fn an_enum_in_a_vec() -> Result<()> { + fn enum_in_vec() -> Result<()> { // arrange let offset = 40; let types = to_named(&[ParamType::B256, ParamType::U8]); @@ -977,15 +1003,24 @@ mod tests { .resolve(offset as u64); // assert - const PADDING: usize = std::mem::size_of::<[u8; 32]>() - WORD_SIZE; + #[cfg(experimental)] + let expected = { + const PADDING: usize = std::mem::size_of::<[u8; 32]>() - WORD_SIZE; - let vec1_ptr = ((VEC_METADATA_SIZE + offset) as u64).to_be_bytes().to_vec(); - let vec1_cap = [0, 0, 0, 0, 0, 0, 0, 1]; - let vec1_len = [0, 0, 0, 0, 0, 0, 0, 1]; - let discriminant = 1u64.to_be_bytes(); - let vec1_data = chain!(discriminant, [0; PADDING], 8u64.to_be_bytes()).collect::>(); + let vec1_ptr = ((VEC_METADATA_SIZE + offset) as u64).to_be_bytes().to_vec(); + let vec1_cap = [0, 0, 0, 0, 0, 0, 0, 1]; + let vec1_len = [0, 0, 0, 0, 0, 0, 0, 1]; + let discriminant = 1u64.to_be_bytes(); + let vec1_data = + chain!(discriminant, [0; PADDING], 8u64.to_be_bytes()).collect::>(); - let expected = chain!(vec1_ptr, vec1_cap, vec1_len, vec1_data).collect::>(); + chain!(vec1_ptr, vec1_cap, vec1_len, vec1_data).collect::>() + }; + #[cfg(not(experimental))] + let expected = [ + 0, 0, 0, 0, 0, 0, 0, 1, // vec len + 0, 0, 0, 0, 0, 0, 0, 1, 8, // enum discriminant and u8 value + ]; assert_eq!(result, expected); @@ -993,7 +1028,7 @@ mod tests { } #[test] - fn a_vec_in_a_struct() -> Result<()> { + fn vec_in_struct() -> Result<()> { // arrange let offset = 40; let token = Token::Struct(vec![Token::Vector(vec![Token::U64(5)]), Token::U8(9)]); @@ -1004,15 +1039,22 @@ mod tests { .resolve(offset as u64); // assert - let vec1_ptr = ((VEC_METADATA_SIZE + WORD_SIZE + offset) as u64) - .to_be_bytes() - .to_vec(); - let vec1_cap = [0, 0, 0, 0, 0, 0, 0, 1]; - let vec1_len = [0, 0, 0, 0, 0, 0, 0, 1]; - let vec1_data = [0, 0, 0, 0, 0, 0, 0, 5]; - - let expected = - chain!(vec1_ptr, vec1_cap, vec1_len, [9], [0; 7], vec1_data).collect::>(); + #[cfg(experimental)] + let expected = { + let vec1_ptr = ((VEC_METADATA_SIZE + WORD_SIZE + offset) as u64) + .to_be_bytes() + .to_vec(); + let vec1_cap = [0, 0, 0, 0, 0, 0, 0, 1]; + let vec1_len = [0, 0, 0, 0, 0, 0, 0, 1]; + let vec1_data = [0, 0, 0, 0, 0, 0, 0, 5]; + + chain!(vec1_ptr, vec1_cap, vec1_len, [9], [0; 7], vec1_data).collect::>() + }; + #[cfg(not(experimental))] + let expected = [ + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5, // vec[len, u64] + 9, // u8 + ]; assert_eq!(result, expected); @@ -1020,7 +1062,7 @@ mod tests { } #[test] - fn a_vec_in_a_vec() -> Result<()> { + fn vec_in_vec() -> Result<()> { // arrange let offset = 40; let token = Token::Vector(vec![Token::Vector(vec![Token::U8(5), Token::U8(6)])]); @@ -1031,21 +1073,29 @@ mod tests { .resolve(offset as u64); // assert - let vec1_data_offset = (VEC_METADATA_SIZE + offset) as u64; - let vec1_ptr = vec1_data_offset.to_be_bytes().to_vec(); - let vec1_cap = [0, 0, 0, 0, 0, 0, 0, 1]; - let vec1_len = [0, 0, 0, 0, 0, 0, 0, 1]; - - let vec2_ptr = (vec1_data_offset + VEC_METADATA_SIZE as u64) - .to_be_bytes() - .to_vec(); - let vec2_cap = [0, 0, 0, 0, 0, 0, 0, 2]; - let vec2_len = [0, 0, 0, 0, 0, 0, 0, 2]; - let vec2_data = [5, 6]; - - let vec1_data = chain!(vec2_ptr, vec2_cap, vec2_len, vec2_data).collect::>(); - - let expected = chain!(vec1_ptr, vec1_cap, vec1_len, vec1_data).collect::>(); + #[cfg(experimental)] + let expected = { + let vec1_data_offset = (VEC_METADATA_SIZE + offset) as u64; + let vec1_ptr = vec1_data_offset.to_be_bytes().to_vec(); + let vec1_cap = [0, 0, 0, 0, 0, 0, 0, 1]; + let vec1_len = [0, 0, 0, 0, 0, 0, 0, 1]; + + let vec2_ptr = (vec1_data_offset + VEC_METADATA_SIZE as u64) + .to_be_bytes() + .to_vec(); + let vec2_cap = [0, 0, 0, 0, 0, 0, 0, 2]; + let vec2_len = [0, 0, 0, 0, 0, 0, 0, 2]; + let vec2_data = [5, 6]; + + let vec1_data = chain!(vec2_ptr, vec2_cap, vec2_len, vec2_data).collect::>(); + + chain!(vec1_ptr, vec1_cap, vec1_len, vec1_data).collect::>() + }; + #[cfg(not(experimental))] + let expected = [ + 0, 0, 0, 0, 0, 0, 0, 1, // vec1 len + 0, 0, 0, 0, 0, 0, 0, 2, 5, 6, // vec2 [len, u8, u8] + ]; assert_eq!(result, expected); @@ -1059,17 +1109,22 @@ mod tests { let offset = 40; // act - let encoded_bytes = ABIEncoder::default().encode(&[token])?.resolve(offset); + let result = ABIEncoder::default().encode(&[token])?.resolve(offset); // assert - let ptr = [0, 0, 0, 0, 0, 0, 0, 64]; - let cap = [0, 0, 0, 0, 0, 0, 0, 8]; - let len = [0, 0, 0, 0, 0, 0, 0, 3]; - let data = [1, 2, 3, 0, 0, 0, 0, 0]; + #[cfg(experimental)] + let expected = { + let ptr = [0, 0, 0, 0, 0, 0, 0, 64]; + let cap = [0, 0, 0, 0, 0, 0, 0, 8]; + let len = [0, 0, 0, 0, 0, 0, 0, 3]; + let data = [1, 2, 3, 0, 0, 0, 0, 0]; - let expected_encoded_bytes = [ptr, cap, len, data].concat(); + [ptr, cap, len, data].concat() + }; + #[cfg(not(experimental))] + let expected = [0, 0, 0, 0, 0, 0, 0, 3, 1, 2, 3]; // bytes[len, u8, u8, u8] - assert_eq!(expected_encoded_bytes, encoded_bytes); + assert_eq!(result, expected); Ok(()) } @@ -1081,17 +1136,22 @@ mod tests { let offset = 40; // act - let encoded_bytes = ABIEncoder::default().encode(&[token])?.resolve(offset); + let result = ABIEncoder::default().encode(&[token])?.resolve(offset); // assert - let ptr = [0, 0, 0, 0, 0, 0, 0, 56].to_vec(); - let len = [0, 0, 0, 0, 0, 0, 0, 3].to_vec(); - let data = [1, 2, 3].to_vec(); - let padding = [0, 0, 0, 0, 0].to_vec(); + #[cfg(experimental)] + let expected = { + let ptr = [0, 0, 0, 0, 0, 0, 0, 56].to_vec(); + let len = [0, 0, 0, 0, 0, 0, 0, 3].to_vec(); + let data = [1, 2, 3].to_vec(); + let padding = [0, 0, 0, 0, 0].to_vec(); - let expected_encoded_bytes = [ptr, len, data, padding].concat(); + [ptr, len, data, padding].concat() + }; + #[cfg(not(experimental))] + let expected = [0, 0, 0, 0, 0, 0, 0, 3, 1, 2, 3]; // raw_slice[len, u8, u8, u8] - assert_eq!(expected_encoded_bytes, encoded_bytes); + assert_eq!(result, expected); Ok(()) } @@ -1104,34 +1164,49 @@ mod tests { let offset = 40; // act - let encoded_std_string = ABIEncoder::default().encode(&[token])?.resolve(offset); + let result = ABIEncoder::default().encode(&[token])?.resolve(offset); // assert - let ptr = [0, 0, 0, 0, 0, 0, 0, 64]; - let cap = [0, 0, 0, 0, 0, 0, 0, 8]; - let len = [0, 0, 0, 0, 0, 0, 0, 5]; - let data = [0x54, 0x68, 0x69, 0x73, 0x20, 0, 0, 0]; + #[cfg(experimental)] + let expected = { + let ptr = [0, 0, 0, 0, 0, 0, 0, 64]; + let cap = [0, 0, 0, 0, 0, 0, 0, 8]; + let len = [0, 0, 0, 0, 0, 0, 0, 5]; + let data = [0x54, 0x68, 0x69, 0x73, 0x20, 0, 0, 0]; - let expected_encoded_std_string = [ptr, cap, len, data].concat(); + [ptr, cap, len, data].concat() + }; + #[cfg(not(experimental))] + let expected = [0, 0, 0, 0, 0, 0, 0, 5, 84, 104, 105, 115, 32]; // string[len, data] - assert_eq!(expected_encoded_std_string, encoded_std_string); + assert_eq!(result, expected); Ok(()) } #[test] fn encoding_large_unsigned_integers() -> Result<()> { - let token = Token::U128(u128::MAX); - let expected_encoding = [255; 16]; - let result = ABIEncoder::default().encode(&[token])?.resolve(0); - assert_eq!(result, expected_encoding); - let token = Token::U256(U256::MAX); - let expected_encoding = [255; 32]; - let result = ABIEncoder::default().encode(&[token])?.resolve(0); - assert_eq!(result, expected_encoding); + { + let token = Token::U128(u128::MAX); + let expected_encoding = [255; 16]; + + let result = ABIEncoder::default().encode(&[token])?.resolve(0); + + assert_eq!(result, expected_encoding); + } + { + let token = Token::U256(U256::MAX); + let expected_encoding = [255; 32]; + + let result = ABIEncoder::default().encode(&[token])?.resolve(0); + + assert_eq!(result, expected_encoding); + } + Ok(()) } + #[cfg(experimental)] #[test] fn capacity_overflow_is_caught() -> Result<()> { let token = Token::Enum(Box::new(( diff --git a/packages/fuels-programs/src/call_utils.rs b/packages/fuels-programs/src/call_utils.rs index 4c419f0c79..a95b13795a 100644 --- a/packages/fuels-programs/src/call_utils.rs +++ b/packages/fuels-programs/src/call_utils.rs @@ -664,17 +664,16 @@ pub fn new_variable_outputs(num: usize) -> Vec { mod test { use std::slice; + #[cfg(experimental)] use fuel_types::bytes::WORD_SIZE; use fuels_accounts::wallet::WalletUnlocked; - use fuels_core::{ - codec::ABIEncoder, - types::{ - bech32::Bech32ContractId, - coin::{Coin, CoinStatus}, - coin_type::CoinType, - Token, - }, + use fuels_core::types::{ + bech32::Bech32ContractId, + coin::{Coin, CoinStatus}, + coin_type::CoinType, }; + #[cfg(experimental)] + use fuels_core::{codec::ABIEncoder, types::Token}; use rand::Rng; use super::*; @@ -710,6 +709,7 @@ mod test { Bech32ContractId::new("fuel", rand::thread_rng().gen::<[u8; 32]>()) } + #[cfg(experimental)] #[tokio::test] async fn test_script_data() { // Arrange @@ -1037,8 +1037,10 @@ mod test { const BASE_INSTRUCTION_COUNT: usize = 5; // 2 instructions (movi and lw) added in get_single_call_instructions when gas_offset is set const GAS_OFFSET_INSTRUCTION_COUNT: usize = 2; + #[cfg(experimental)] // 4 instructions (lw, lw, muli, retd) added by extract_data_receipt const EXTRACT_DATA_RECEIPT_INSTRUCTION_COUNT: usize = 4; + #[cfg(experimental)] // 4 instructions (movi, lw, jnef, retd) added by extract_heap_data const EXTRACT_HEAP_DATA_INSTRUCTION_COUNT: usize = 4; @@ -1060,6 +1062,7 @@ mod test { ); } + #[cfg(experimental)] #[test] fn test_with_heap_type() { let output_params = vec![ @@ -1079,6 +1082,7 @@ mod test { } } + #[cfg(experimental)] #[test] fn test_with_gas_offset_and_heap_type() { let mut call = ContractCall::new_with_random_id(); @@ -1095,6 +1099,7 @@ mod test { ); } + #[cfg(experimental)] #[test] fn test_with_enum_with_heap_and_non_heap_variant() { let variant_sets = vec![ diff --git a/packages/fuels-programs/src/receipt_parser.rs b/packages/fuels-programs/src/receipt_parser.rs index c43f6b85cd..a7c70ff514 100644 --- a/packages/fuels-programs/src/receipt_parser.rs +++ b/packages/fuels-programs/src/receipt_parser.rs @@ -324,7 +324,13 @@ mod tests { let contract_id = target_contract(); let mut receipts = expected_receipts.clone(); + #[cfg(experimental)] receipts.push(get_return_receipt(contract_id, RECEIPT_VAL)); + #[cfg(not(experimental))] // all data is returned as RETD + receipts.push(get_return_data_receipt( + contract_id, + &RECEIPT_VAL.to_be_bytes(), + )); let mut parser = ReceiptParser::new(&receipts, Default::default()); let token = parser @@ -337,6 +343,7 @@ mod tests { Ok(()) } + #[cfg(experimental)] #[tokio::test] async fn receipt_parser_extract_return_data_heap() -> Result<()> { let expected_receipts = get_relevant_receipts(); diff --git a/packages/fuels/Forc.toml b/packages/fuels/Forc.toml index 5833f01046..56f6d19e9a 100644 --- a/packages/fuels/Forc.toml +++ b/packages/fuels/Forc.toml @@ -106,4 +106,4 @@ members = [ ] [patch.'https://github.com/fuellabs/sway'] -std = { git = "https://github.com/fuellabs/sway", branch = "xunilrj/remove-method-name-log" } +std = { git = "https://github.com/fuellabs/sway", branch = "xunilrj/new-encoding-fixes" } diff --git a/packages/fuels/tests/providers.rs b/packages/fuels/tests/providers.rs index 17587d83b6..a61f1fcbfa 100644 --- a/packages/fuels/tests/providers.rs +++ b/packages/fuels/tests/providers.rs @@ -326,7 +326,7 @@ async fn test_gas_forwarded_defaults_to_tx_limit() -> Result<()> { #[cfg(experimental)] let gas_used_by_script = 360; #[cfg(not(experimental))] - let gas_used_by_script = 864; + let gas_used_by_script = 876; let gas_limit = 225_883; let response = contract_instance .methods() From 558ee65c6d18755deebf53a5dd17035667861dd9 Mon Sep 17 00:00:00 2001 From: hal3e Date: Thu, 21 Mar 2024 11:43:34 +0100 Subject: [PATCH 13/30] add script heap_types test --- packages/fuels-core/src/types/core/bytes.rs | 4 +- packages/fuels/Forc.toml | 1 + .../types/scripts/script_heap_types/Forc.toml | 5 +++ .../scripts/script_heap_types/src/main.sw | 37 +++++++++++++++++++ packages/fuels/tests/types_scripts.rs | 33 +++++++++++++++++ 5 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 packages/fuels/tests/types/scripts/script_heap_types/Forc.toml create mode 100644 packages/fuels/tests/types/scripts/script_heap_types/src/main.sw diff --git a/packages/fuels-core/src/types/core/bytes.rs b/packages/fuels-core/src/types/core/bytes.rs index 02e6dc6519..2164cbab89 100644 --- a/packages/fuels-core/src/types/core/bytes.rs +++ b/packages/fuels-core/src/types/core/bytes.rs @@ -19,8 +19,8 @@ impl Bytes { } impl From for Vec { - fn from(raw_slice: Bytes) -> Vec { - raw_slice.0 + fn from(bytes: Bytes) -> Vec { + bytes.0 } } diff --git a/packages/fuels/Forc.toml b/packages/fuels/Forc.toml index 56f6d19e9a..68142ee7e4 100644 --- a/packages/fuels/Forc.toml +++ b/packages/fuels/Forc.toml @@ -95,6 +95,7 @@ members = [ 'tests/types/scripts/options_results', 'tests/types/scripts/script_bytes', 'tests/types/scripts/script_generics', + 'tests/types/scripts/script_heap_types', #TODO: Decide what to do with this test project once # https://github.com/FuelLabs/sway/issues/5145 is resolved # 'tests/types/scripts/script_raw_slice', diff --git a/packages/fuels/tests/types/scripts/script_heap_types/Forc.toml b/packages/fuels/tests/types/scripts/script_heap_types/Forc.toml new file mode 100644 index 0000000000..3c4d838276 --- /dev/null +++ b/packages/fuels/tests/types/scripts/script_heap_types/Forc.toml @@ -0,0 +1,5 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "script_heap_types" diff --git a/packages/fuels/tests/types/scripts/script_heap_types/src/main.sw b/packages/fuels/tests/types/scripts/script_heap_types/src/main.sw new file mode 100644 index 0000000000..83f5f4763e --- /dev/null +++ b/packages/fuels/tests/types/scripts/script_heap_types/src/main.sw @@ -0,0 +1,37 @@ +script; + +use std::bytes::Bytes; +use std::string::String; + +#[allow(dead_code)] +struct StructGenerics { + one: T, + two: K, + three: U +} + +#[allow(dead_code)] +enum EnumGeneric { + One: H, + Two: I, +} + + +fn main() -> EnumGeneric>>, String> { + let mut some_vec = Vec::new(); + some_vec.push(2u8); + some_vec.push(4u8); + some_vec.push(8u8); + + let struct_generics = StructGenerics { + one: Bytes::from(some_vec), + two: String::from_ascii_str("fuel"), + three: some_vec + }; + + let mut enum_vec = Vec::new(); + enum_vec.push(struct_generics); + enum_vec.push(struct_generics); + + EnumGeneric::One(enum_vec) +} diff --git a/packages/fuels/tests/types_scripts.rs b/packages/fuels/tests/types_scripts.rs index b1e04a6547..beb6060bcf 100644 --- a/packages/fuels/tests/types_scripts.rs +++ b/packages/fuels/tests/types_scripts.rs @@ -322,3 +322,36 @@ async fn script_handles_std_string() -> Result<()> { Ok(()) } + +#[cfg(not(experimental))] +#[tokio::test] +async fn nested_heap_types() -> Result<()> { + setup_program_test!( + Wallets("wallet"), + Abigen(Script( + name = "MyScript", + project = "packages/fuels/tests/types/scripts/script_heap_types", + )), + LoadScript( + name = "script_instance", + script = "MyScript", + wallet = "wallet" + ) + ); + + let arr = [2u8, 4, 8]; + let struct_generics = StructGenerics { + one: Bytes(arr.to_vec()), + two: String::from("fuel"), + three: arr.to_vec(), + }; + + let enum_vec = [struct_generics.clone(), struct_generics].to_vec(); + let expected = EnumGeneric::One(enum_vec); + + let result = script_instance.main().call().await?; + + assert_eq!(result.value, expected); + + Ok(()) +} From c0f401bd1a40318de75b190f11a35c086426f0da Mon Sep 17 00:00:00 2001 From: hal3e Date: Thu, 21 Mar 2024 11:43:48 +0100 Subject: [PATCH 14/30] add contract heap_types test --- packages/fuels/Forc.toml | 1 + .../types/contracts/heap_types/Forc.toml | 5 +++ .../types/contracts/heap_types/src/main.sw | 42 +++++++++++++++++ packages/fuels/tests/types_contracts.rs | 45 +++++++++++++++++-- 4 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 packages/fuels/tests/types/contracts/heap_types/Forc.toml create mode 100644 packages/fuels/tests/types/contracts/heap_types/src/main.sw diff --git a/packages/fuels/Forc.toml b/packages/fuels/Forc.toml index 68142ee7e4..81a728a60d 100644 --- a/packages/fuels/Forc.toml +++ b/packages/fuels/Forc.toml @@ -62,6 +62,7 @@ members = [ 'tests/types/contracts/evm_address', 'tests/types/contracts/generics', 'tests/types/contracts/heap_type_in_enums', + 'tests/types/contracts/heap_types', 'tests/types/contracts/identity', 'tests/types/contracts/native_types', 'tests/types/contracts/nested_structs', diff --git a/packages/fuels/tests/types/contracts/heap_types/Forc.toml b/packages/fuels/tests/types/contracts/heap_types/Forc.toml new file mode 100644 index 0000000000..df2dc22cd2 --- /dev/null +++ b/packages/fuels/tests/types/contracts/heap_types/Forc.toml @@ -0,0 +1,5 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "heap_types" diff --git a/packages/fuels/tests/types/contracts/heap_types/src/main.sw b/packages/fuels/tests/types/contracts/heap_types/src/main.sw new file mode 100644 index 0000000000..e8550552d0 --- /dev/null +++ b/packages/fuels/tests/types/contracts/heap_types/src/main.sw @@ -0,0 +1,42 @@ +contract; + +use std::bytes::Bytes; +use std::string::String; + +#[allow(dead_code)] +struct StructGenerics { + one: T, + two: K, + three: U +} + +#[allow(dead_code)] +enum EnumGeneric { + One: H, + Two: I, +} + +abi HeapTypesContract { + fn nested_heap_types() -> EnumGeneric>, String>; +} + +impl HeapTypesContract for Contract { + fn nested_heap_types() -> EnumGeneric>, String> { + let mut some_vec = Vec::new(); + some_vec.push(2u8); + some_vec.push(4u8); + some_vec.push(8u8); + + let struct_generics = StructGenerics { + one: Bytes::from(some_vec), + two: String::from_ascii_str("fuel"), + three: some_vec.as_raw_slice() + }; + + let mut enum_vec = Vec::new(); + enum_vec.push(struct_generics); + enum_vec.push(struct_generics); + + EnumGeneric::One(enum_vec) + } +} diff --git a/packages/fuels/tests/types_contracts.rs b/packages/fuels/tests/types_contracts.rs index 449b98fe48..ac4553499e 100644 --- a/packages/fuels/tests/types_contracts.rs +++ b/packages/fuels/tests/types_contracts.rs @@ -1959,8 +1959,8 @@ async fn test_bytes_as_input() -> Result<()> { #[tokio::test] async fn test_contract_raw_slice() -> Result<()> { - let wallet = launch_provider_and_get_wallet().await?; setup_program_test!( + Wallets("wallet"), Abigen(Contract( name = "RawSliceContract", project = "packages/fuels/tests/types/contracts/raw_slice" @@ -2004,8 +2004,8 @@ async fn test_contract_raw_slice() -> Result<()> { #[tokio::test] async fn test_contract_returning_string_slice() -> Result<()> { - let wallet = launch_provider_and_get_wallet().await?; setup_program_test!( + Wallets("wallet"), Abigen(Contract( name = "StringSliceContract", project = "packages/fuels/tests/types/contracts/string_slice" @@ -2029,8 +2029,8 @@ async fn test_contract_returning_string_slice() -> Result<()> { #[tokio::test] async fn test_contract_std_lib_string() -> Result<()> { - let wallet = launch_provider_and_get_wallet().await?; setup_program_test!( + Wallets("wallet"), Abigen(Contract( name = "StdLibString", project = "packages/fuels/tests/types/contracts/std_lib_string" @@ -2059,8 +2059,8 @@ async fn test_contract_std_lib_string() -> Result<()> { #[tokio::test] async fn test_heap_type_in_enums() -> Result<()> { - let wallet = launch_provider_and_get_wallet().await?; setup_program_test!( + Wallets("wallet"), Abigen(Contract( name = "HeapTypeInEnum", project = "packages/fuels/tests/types/contracts/heap_type_in_enums" @@ -2186,3 +2186,40 @@ async fn test_heap_type_in_enums() -> Result<()> { Ok(()) } + +#[cfg(not(experimental))] +#[tokio::test] +async fn nested_heap_types() -> Result<()> { + setup_program_test!( + Wallets("wallet"), + Abigen(Contract( + name = "HeapTypeInEnum", + project = "packages/fuels/tests/types/contracts/heap_types" + )), + Deploy( + name = "contract_instance", + contract = "HeapTypeInEnum", + wallet = "wallet" + ), + ); + + let arr = [2u8, 4, 8]; + let struct_generics = StructGenerics { + one: Bytes(arr.to_vec()), + two: String::from("fuel"), + three: RawSlice(arr.to_vec()), + }; + + let enum_vec = [struct_generics.clone(), struct_generics].to_vec(); + let expected = EnumGeneric::One(enum_vec); + + let result = contract_instance + .methods() + .nested_heap_types() + .call() + .await?; + + assert_eq!(result.value, expected); + + Ok(()) +} From 92ac876733a791e1fc12cd864f485a4a7a96ea30 Mon Sep 17 00:00:00 2001 From: hal3e Date: Thu, 21 Mar 2024 15:20:27 +0100 Subject: [PATCH 15/30] refactor --- examples/types/src/lib.rs | 6 +- packages/fuels-core/src/codec/abi_encoder.rs | 12 ++-- packages/fuels-programs/src/call_utils.rs | 68 +++++++++----------- packages/fuels/tests/contracts.rs | 1 - 4 files changed, 42 insertions(+), 45 deletions(-) diff --git a/examples/types/src/lib.rs b/examples/types/src/lib.rs index 322395e4d2..2fcf447453 100644 --- a/examples/types/src/lib.rs +++ b/examples/types/src/lib.rs @@ -4,8 +4,10 @@ mod tests { #[cfg(feature = "fuel-core-lib")] use fuels::prelude::Config; - use fuels::prelude::Result; - use fuels::types::{Bits256, EvmAddress, Identity}; + use fuels::{ + prelude::Result, + types::{Bits256, EvmAddress, Identity}, + }; #[tokio::test] async fn bytes32() -> Result<()> { diff --git a/packages/fuels-core/src/codec/abi_encoder.rs b/packages/fuels-core/src/codec/abi_encoder.rs index 33a1e84e97..cb2b576cae 100644 --- a/packages/fuels-core/src/codec/abi_encoder.rs +++ b/packages/fuels-core/src/codec/abi_encoder.rs @@ -4,11 +4,12 @@ mod experimental_bounded_encoder; use std::default::Default; -use crate::codec::abi_encoder::bounded_encoder::BoundedEncoder; - #[cfg(not(experimental))] use crate::codec::abi_encoder::experimental_bounded_encoder::ExperimentalBoundedEncoder; -use crate::types::{errors::Result, unresolved_bytes::UnresolvedBytes, Token}; +use crate::{ + codec::abi_encoder::bounded_encoder::BoundedEncoder, + types::{errors::Result, unresolved_bytes::UnresolvedBytes, Token}, +}; #[derive(Debug, Clone, Copy)] pub struct EncoderConfig { @@ -85,6 +86,8 @@ mod tests { use super::*; #[cfg(experimental)] + use crate::codec::first_four_bytes_of_sha256_hash; + #[cfg(experimental)] use crate::constants::WORD_SIZE; use crate::{ to_named, @@ -95,9 +98,6 @@ mod tests { }, }; - #[cfg(experimental)] - use crate::codec::first_four_bytes_of_sha256_hash; - #[cfg(experimental)] const VEC_METADATA_SIZE: usize = 3 * WORD_SIZE; #[cfg(experimental)] diff --git a/packages/fuels-programs/src/call_utils.rs b/packages/fuels-programs/src/call_utils.rs index a95b13795a..d3e13daaf5 100644 --- a/packages/fuels-programs/src/call_utils.rs +++ b/packages/fuels-programs/src/call_utils.rs @@ -329,12 +329,12 @@ pub(crate) fn build_script_data_from_contract_calls( /// Returns script data, consisting of the following items in the given order: /// 1. Amount to be forwarded `(1 * `[`WORD_SIZE`]`)` /// 2. Asset ID to be forwarded ([`AssetId::LEN`]) -/// 3. Gas to be forwarded `(1 * `[`WORD_SIZE`]`)` - Optional -/// 4. Contract ID ([`ContractId::LEN`]); -/// 5. Function selector offset `(1 * `[`WORD_SIZE`]`)` -/// 6. Calldata offset `(1 * `[`WORD_SIZE`]`)` -/// 7. Encoded function selector - method name -/// 8. Encoded arguments +/// 3. Contract ID ([`ContractId::LEN`]); +/// 4. Function selector offset `(1 * `[`WORD_SIZE`]`)` +/// 5. Calldata offset `(1 * `[`WORD_SIZE`]`)` +/// 6. Encoded function selector - method name +/// 7. Encoded arguments +/// 8. Gas to be forwarded `(1 * `[`WORD_SIZE`]`)` - Optional pub(crate) fn build_script_data_from_contract_calls( calls: &[ContractCall], data_offset: usize, @@ -348,44 +348,40 @@ pub(crate) fn build_script_data_from_contract_calls( let mut segment_offset = data_offset; for call in calls { - let gas_forwarded = call.call_parameters.gas_forwarded(); + let amount_offset = segment_offset; + let asset_id_offset = amount_offset + WORD_SIZE; + let call_data_offset = asset_id_offset + AssetId::LEN; + let encoded_selector_offset = call_data_offset + ContractId::LEN + 2 * WORD_SIZE; + let encoded_args_offset = encoded_selector_offset + call.encoded_selector.len(); script_data.extend(call.call_parameters.amount().to_be_bytes()); // 1. Amount script_data.extend(call.call_parameters.asset_id().iter()); // 2. Asset ID + script_data.extend(call.contract_id.hash().as_ref()); // 3. Contract ID + script_data.extend((encoded_selector_offset as Word).to_be_bytes()); // 4. Fun. selector offset + script_data.extend((encoded_args_offset as Word).to_be_bytes()); // 5. Calldata offset + script_data.extend(call.encoded_selector.clone()); // 6. Encoded function selector - let gas_forwarded_size = gas_forwarded // 3. Gas to be forwarded - Optional - .map(|gf| { - script_data.extend((gf as Word).to_be_bytes()); - - WORD_SIZE - }) - .unwrap_or_default(); - - let call_param_offsets = CallOpcodeParamsOffset { - amount_offset: segment_offset, - asset_id_offset: segment_offset + WORD_SIZE, - gas_forwarded_offset: gas_forwarded.map(|_| segment_offset + WORD_SIZE + AssetId::LEN), - call_data_offset: segment_offset + WORD_SIZE + AssetId::LEN + gas_forwarded_size, - }; - - let encoded_selector_offset = - call_param_offsets.call_data_offset + ContractId::LEN + WORD_SIZE + WORD_SIZE; - - param_offsets.push(call_param_offsets); - - let custom_input_offset = encoded_selector_offset + call.encoded_selector.len(); - - let bytes = call + let encoded_args = call .encoded_args .as_ref() - .map(|ub| ub.resolve(custom_input_offset as Word)) + .map(|ub| ub.resolve(encoded_args_offset as Word)) .map_err(|e| error!(Codec, "cannot encode contract call arguments: {e}"))?; + let encoded_args_len = encoded_args.len(); + + script_data.extend(encoded_args); // 7. Encoded arguments + + let gas_forwarded_offset = call.call_parameters.gas_forwarded().map(|gf| { + script_data.extend((gf as Word).to_be_bytes()); // 8. Gas to be forwarded - Optional - script_data.extend(call.contract_id.hash().as_ref()); // 4. Contract ID - script_data.extend((encoded_selector_offset as Word).to_be_bytes()); // 5. Fun. selector offset - script_data.extend((custom_input_offset as Word).to_be_bytes()); // 6. Calldata offset - script_data.extend(call.encoded_selector.clone()); // 7. Encoded function selector - script_data.extend(bytes); // 8. Encoded arguments + encoded_args_offset + encoded_args_len + }); + + param_offsets.push(CallOpcodeParamsOffset { + amount_offset, + asset_id_offset, + gas_forwarded_offset, + call_data_offset, + }); // the data segment that holds the parameters for the next call // begins at the original offset + the data we added so far diff --git a/packages/fuels/tests/contracts.rs b/packages/fuels/tests/contracts.rs index 3f686c760b..151d7cac86 100644 --- a/packages/fuels/tests/contracts.rs +++ b/packages/fuels/tests/contracts.rs @@ -1,6 +1,5 @@ #[cfg(experimental)] use fuels::core::codec::{calldata, fn_selector}; - use fuels::{ core::codec::{DecoderConfig, EncoderConfig}, prelude::*, From ea5880327fc0ad1ed4859ee49a709fc83347520c Mon Sep 17 00:00:00 2001 From: hal3e Date: Thu, 21 Mar 2024 15:44:16 +0100 Subject: [PATCH 16/30] refactor --- packages/fuels-programs/src/call_utils.rs | 7 +------ packages/fuels/tests/contracts.rs | 2 +- packages/fuels/tests/types/contracts/bytes/src/main.sw | 1 - 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/fuels-programs/src/call_utils.rs b/packages/fuels-programs/src/call_utils.rs index d3e13daaf5..2b9d3cf0a8 100644 --- a/packages/fuels-programs/src/call_utils.rs +++ b/packages/fuels-programs/src/call_utils.rs @@ -5,7 +5,6 @@ use fuel_asm::{op, RegId}; use fuel_tx::{AssetId, Bytes32, ContractId, Output, PanicReason, Receipt, TxPointer, UtxoId}; use fuel_types::{Address, Word}; use fuels_accounts::Account; -#[cfg(experimental)] use fuels_core::constants::WORD_SIZE; use fuels_core::{ error, @@ -339,8 +338,6 @@ pub(crate) fn build_script_data_from_contract_calls( calls: &[ContractCall], data_offset: usize, ) -> Result<(Vec, Vec)> { - use fuel_types::bytes::WORD_SIZE; - let mut script_data = vec![]; let mut param_offsets = vec![]; @@ -439,7 +436,7 @@ pub(crate) fn get_single_call_instructions( op::call(0x10, 0x11, 0x12, 0x13), ]); } - // If `gas_forwarded` was not set use `REG_CGAS` + // if `gas_forwarded` was not set use `REG_CGAS` None => instructions.push(op::call(0x10, 0x11, 0x12, RegId::CGAS)), }; @@ -675,8 +672,6 @@ mod test { use super::*; use crate::contract::CallParameters; - #[cfg(not(experimental))] - impl ContractCall { pub fn new_with_random_id() -> Self { ContractCall { diff --git a/packages/fuels/tests/contracts.rs b/packages/fuels/tests/contracts.rs index 151d7cac86..2ec61a3765 100644 --- a/packages/fuels/tests/contracts.rs +++ b/packages/fuels/tests/contracts.rs @@ -1220,7 +1220,7 @@ async fn multi_call_from_calls_with_different_account_types() -> Result<()> { } #[tokio::test] -#[cfg(experimental)] // TODO: @hal3e add other example with new the new call function +#[cfg(experimental)] async fn low_level_call() -> Result<()> { use fuels::types::SizedAsciiString; diff --git a/packages/fuels/tests/types/contracts/bytes/src/main.sw b/packages/fuels/tests/types/contracts/bytes/src/main.sw index f1d859132d..84ff054e93 100644 --- a/packages/fuels/tests/types/contracts/bytes/src/main.sw +++ b/packages/fuels/tests/types/contracts/bytes/src/main.sw @@ -68,7 +68,6 @@ impl MyContract for Contract { } fn return_bytes(len: u8) -> Bytes { - log(len); let mut bytes = Bytes::new(); let mut i: u8 = 0; while i < len { From 4a4e2d3bd8605b1dac2a86dd468a557d5ea1c46a Mon Sep 17 00:00:00 2001 From: hal3e Date: Thu, 21 Mar 2024 15:49:36 +0100 Subject: [PATCH 17/30] forc-fmt --- .../fuels/tests/types/contracts/heap_types/src/main.sw | 8 ++++---- .../tests/types/predicates/predicate_vector/src/main.sw | 2 +- .../tests/types/scripts/script_heap_types/src/main.sw | 9 ++++----- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/packages/fuels/tests/types/contracts/heap_types/src/main.sw b/packages/fuels/tests/types/contracts/heap_types/src/main.sw index e8550552d0..fdac828583 100644 --- a/packages/fuels/tests/types/contracts/heap_types/src/main.sw +++ b/packages/fuels/tests/types/contracts/heap_types/src/main.sw @@ -4,14 +4,14 @@ use std::bytes::Bytes; use std::string::String; #[allow(dead_code)] -struct StructGenerics { +struct StructGenerics { one: T, two: K, - three: U + three: U, } #[allow(dead_code)] -enum EnumGeneric { +enum EnumGeneric { One: H, Two: I, } @@ -30,7 +30,7 @@ impl HeapTypesContract for Contract { let struct_generics = StructGenerics { one: Bytes::from(some_vec), two: String::from_ascii_str("fuel"), - three: some_vec.as_raw_slice() + three: some_vec.as_raw_slice(), }; let mut enum_vec = Vec::new(); diff --git a/packages/fuels/tests/types/predicates/predicate_vector/src/main.sw b/packages/fuels/tests/types/predicates/predicate_vector/src/main.sw index 8664900b44..d23cd2200d 100644 --- a/packages/fuels/tests/types/predicates/predicate_vector/src/main.sw +++ b/packages/fuels/tests/types/predicates/predicate_vector/src/main.sw @@ -2,5 +2,5 @@ predicate; fn main(a: u32, b: u64, c: Vec) -> bool { let number: u64 = c.get(2).unwrap(); - number == (b + a.as_u64()) + number == (b + a.as_u64()) } diff --git a/packages/fuels/tests/types/scripts/script_heap_types/src/main.sw b/packages/fuels/tests/types/scripts/script_heap_types/src/main.sw index 83f5f4763e..e1e1199c9b 100644 --- a/packages/fuels/tests/types/scripts/script_heap_types/src/main.sw +++ b/packages/fuels/tests/types/scripts/script_heap_types/src/main.sw @@ -4,19 +4,18 @@ use std::bytes::Bytes; use std::string::String; #[allow(dead_code)] -struct StructGenerics { +struct StructGenerics { one: T, two: K, - three: U + three: U, } #[allow(dead_code)] -enum EnumGeneric { +enum EnumGeneric { One: H, Two: I, } - fn main() -> EnumGeneric>>, String> { let mut some_vec = Vec::new(); some_vec.push(2u8); @@ -26,7 +25,7 @@ fn main() -> EnumGeneric>>, String> { let struct_generics = StructGenerics { one: Bytes::from(some_vec), two: String::from_ascii_str("fuel"), - three: some_vec + three: some_vec, }; let mut enum_vec = Vec::new(); From 42390bede8cd8d7e638a67f0a98f9492e6991210 Mon Sep 17 00:00:00 2001 From: hal3e Date: Thu, 21 Mar 2024 16:06:26 +0100 Subject: [PATCH 18/30] invert experimental flag --- examples/contracts/src/lib.rs | 10 +- examples/debugging/src/lib.rs | 12 +-- packages/fuels-core/src/codec.rs | 4 +- packages/fuels-core/src/codec/abi_decoder.rs | 60 ++++++------ .../codec/abi_decoder/decode_as_debug_str.rs | 4 +- packages/fuels-core/src/codec/abi_encoder.rs | 92 +++++++++---------- .../fuels-core/src/codec/function_selector.rs | 22 ++--- packages/fuels-core/src/codec/logs.rs | 6 +- packages/fuels-core/src/types.rs | 4 +- .../src/types/param_types/param_type.rs | 4 +- packages/fuels-programs/src/call_utils.rs | 36 ++++---- packages/fuels-programs/src/contract.rs | 6 +- packages/fuels-programs/src/receipt_parser.rs | 12 +-- packages/fuels/tests/bindings.rs | 28 +++--- packages/fuels/tests/contracts.rs | 11 ++- packages/fuels/tests/from_token.rs | 6 +- packages/fuels/tests/logs.rs | 2 +- packages/fuels/tests/predicates.rs | 8 +- packages/fuels/tests/providers.rs | 4 +- packages/fuels/tests/types_contracts.rs | 6 +- packages/fuels/tests/types_scripts.rs | 2 +- 21 files changed, 174 insertions(+), 165 deletions(-) diff --git a/examples/contracts/src/lib.rs b/examples/contracts/src/lib.rs index 5b65d98572..d51da7aac0 100644 --- a/examples/contracts/src/lib.rs +++ b/examples/contracts/src/lib.rs @@ -107,9 +107,9 @@ mod tests { .await?; // ANCHOR_END: contract_call_cost_estimation - #[cfg(experimental)] - let expected_gas = 791; #[cfg(not(experimental))] + let expected_gas = 795; + #[cfg(experimental)] let expected_gas = 2086; assert_eq!(transaction_cost.gas_used, expected_gas); @@ -607,9 +607,9 @@ mod tests { .await?; // ANCHOR_END: multi_call_cost_estimation - #[cfg(experimental)] - let expected_gas = 1162; #[cfg(not(experimental))] + let expected_gas = 1170; + #[cfg(experimental)] let expected_gas = 3511; assert_eq!(transaction_cost.gas_used, expected_gas); @@ -686,7 +686,7 @@ mod tests { Ok(()) } - #[cfg(experimental)] + #[cfg(not(experimental))] #[tokio::test] async fn low_level_call_example() -> Result<()> { use fuels::{ diff --git a/examples/debugging/src/lib.rs b/examples/debugging/src/lib.rs index a2700ebefd..f086359e70 100644 --- a/examples/debugging/src/lib.rs +++ b/examples/debugging/src/lib.rs @@ -3,7 +3,7 @@ mod tests { use std::collections::HashMap; use fuel_abi_types::abi::program::ProgramABI; - #[cfg(experimental)] + #[cfg(not(experimental))] use fuels::core::codec::{calldata, fn_selector}; use fuels::{ core::codec::ABIDecoder, @@ -11,7 +11,7 @@ mod tests { types::{errors::Result, param_types::ParamType, SizedAsciiString}, }; - #[cfg(experimental)] + #[cfg(not(experimental))] #[test] fn get_a_fn_selector() { use fuels::core::{codec::resolve_fn_selector, traits::Parameterize}; @@ -27,7 +27,7 @@ mod tests { // ANCHOR_END: example_fn_selector } - #[cfg(experimental)] + #[cfg(not(experimental))] #[test] fn a_fn_selector_from_json_abi() -> Result<()> { use fuels::core::codec::resolve_fn_selector; @@ -65,7 +65,7 @@ mod tests { Ok(()) } - #[cfg(experimental)] + #[cfg(not(experimental))] #[test] fn test_macros() -> Result<()> { let function_selector = fn_selector!(initialize_counter(u64)); @@ -167,9 +167,9 @@ mod tests { let expected_u8 = 1; - #[cfg(experimental)] - let data = [0, 0, 0, 0, 0, 0, 0, 1]; #[cfg(not(experimental))] + let data = [0, 0, 0, 0, 0, 0, 0, 1]; + #[cfg(experimental)] let data = [1]; assert_eq!( diff --git a/packages/fuels-core/src/codec.rs b/packages/fuels-core/src/codec.rs index 09bc586e38..e1dacba4c2 100644 --- a/packages/fuels-core/src/codec.rs +++ b/packages/fuels-core/src/codec.rs @@ -34,9 +34,9 @@ mod tests { #[test] fn can_convert_bytes_into_tuple() -> Result<()> { - #[cfg(experimental)] - let tuple_in_bytes: Vec = vec![0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2]; #[cfg(not(experimental))] + let tuple_in_bytes: Vec = vec![0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2]; + #[cfg(experimental)] let tuple_in_bytes: Vec = vec![0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2]; let the_tuple: (u64, u32) = try_from_bytes(&tuple_in_bytes, DecoderConfig::default())?; diff --git a/packages/fuels-core/src/codec/abi_decoder.rs b/packages/fuels-core/src/codec/abi_decoder.rs index 8f8b587860..f997dfca46 100644 --- a/packages/fuels-core/src/codec/abi_decoder.rs +++ b/packages/fuels-core/src/codec/abi_decoder.rs @@ -1,12 +1,12 @@ -#[cfg(experimental)] +#[cfg(not(experimental))] mod bounded_decoder; mod decode_as_debug_str; -#[cfg(not(experimental))] +#[cfg(experimental)] mod experimental_bounded_decoder; -#[cfg(experimental)] -use crate::codec::abi_decoder::bounded_decoder::BoundedDecoder; #[cfg(not(experimental))] +use crate::codec::abi_decoder::bounded_decoder::BoundedDecoder; +#[cfg(experimental)] use crate::codec::abi_decoder::experimental_bounded_decoder::BoundedDecoder; use crate::{ codec::abi_decoder::decode_as_debug_str::decode_as_debug_str, @@ -129,9 +129,9 @@ mod tests { #[test] fn decode_int() -> Result<()> { - #[cfg(experimental)] - let data = [0, 0, 0, 0, 255, 255, 255, 255]; #[cfg(not(experimental))] + let data = [0, 0, 0, 0, 255, 255, 255, 255]; + #[cfg(experimental)] let data = [255, 255, 255, 255]; let decoded = ABIDecoder::default().decode(&ParamType::U32, &data)?; @@ -152,7 +152,7 @@ mod tests { ParamType::U256, ]; - #[cfg(experimental)] + #[cfg(not(experimental))] let data = [ 0, 0, 0, 0, 255, 255, 255, 255, // u32 255, // u8 @@ -163,7 +163,7 @@ mod tests { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // u256 ]; - #[cfg(not(experimental))] + #[cfg(experimental)] let data = [ 255, 255, 255, 255, // u32 255, // u8 @@ -221,13 +221,13 @@ mod tests { #[test] fn decode_string_array() -> Result<()> { let types = vec![ParamType::StringArray(23), ParamType::StringArray(5)]; - #[cfg(experimental)] + #[cfg(not(experimental))] let data = [ 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, - 116, 101, 110, 99, 101, //This is a full sentence - 72, 101, 108, 108, 111, // Hello + 116, 101, 110, 99, 101, 0, //This is a full sentence + 72, 101, 108, 108, 111, 0, 0, 0, // Hello ]; - #[cfg(not(experimental))] + #[cfg(experimental)] let data = [ 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, 116, 101, 110, 99, 101, //This is a full sentence @@ -252,12 +252,12 @@ mod tests { #[test] fn decode_string_slice() -> Result<()> { let types = vec![ParamType::StringSlice]; - #[cfg(experimental)] + #[cfg(not(experimental))] let data = [ 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, 116, 101, 110, 99, 101, //This is a full sentence ]; - #[cfg(not(experimental))] + #[cfg(experimental)] let data = [ 0, 0, 0, 0, 0, 0, 0, 23, // [length] 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, @@ -296,9 +296,9 @@ mod tests { // bar: bool, // } - #[cfg(experimental)] - let data = [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]; #[cfg(not(experimental))] + let data = [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]; + #[cfg(experimental)] let data = [1, 1]; let param_type = ParamType::Struct { @@ -318,9 +318,9 @@ mod tests { #[test] fn decode_bytes() -> Result<()> { - #[cfg(experimental)] - let data = [255, 0, 1, 2, 3, 4, 5]; #[cfg(not(experimental))] + let data = [255, 0, 1, 2, 3, 4, 5]; + #[cfg(experimental)] let data = [0, 0, 0, 0, 0, 0, 0, 7, 255, 0, 1, 2, 3, 4, 5]; let decoded = ABIDecoder::default().decode(&ParamType::Bytes, &data)?; @@ -348,9 +348,9 @@ mod tests { }]; // "0" discriminant and 42 enum value - #[cfg(experimental)] - let data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42]; #[cfg(not(experimental))] + let data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42]; + #[cfg(experimental)] let data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42]; let decoded = ABIDecoder::default().decode_multiple(&types, &data)?; @@ -361,7 +361,7 @@ mod tests { Ok(()) } - #[cfg(experimental)] + #[cfg(not(experimental))] #[test] fn decoder_will_skip_enum_padding_and_decode_next_arg() -> Result<()> { // struct MyStruct { @@ -446,11 +446,11 @@ mod tests { generics: vec![], }; - #[cfg(experimental)] + #[cfg(not(experimental))] let data = [ 0, 0, 0, 0, 0, 0, 0, 10, 1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, ]; - #[cfg(not(experimental))] + #[cfg(experimental)] let data = [0, 10, 1, 1, 2]; let decoded = ABIDecoder::default().decode(&nested_struct, &data)?; @@ -505,7 +505,7 @@ mod tests { let types = [nested_struct, u8_arr, b256]; - #[cfg(experimental)] + #[cfg(not(experimental))] let bytes = [ 0, 0, 0, 0, 0, 0, 0, 10, // u16 1, 0, 0, 0, 0, 0, 0, 0, // bool @@ -515,7 +515,7 @@ mod tests { 152, 244, 172, 69, 123, 168, 248, 39, 67, 243, 30, 147, 11, // b256 ]; - #[cfg(not(experimental))] + #[cfg(experimental)] let bytes = [ 0, 10, // u16 1, // bool @@ -550,7 +550,7 @@ mod tests { Ok(()) } - #[cfg(experimental)] + #[cfg(not(experimental))] #[test] fn units_in_structs_are_decoded_as_one_word() -> Result<()> { let data = [ @@ -570,7 +570,7 @@ mod tests { Ok(()) } - #[cfg(experimental)] + #[cfg(not(experimental))] #[test] fn enums_with_all_unit_variants_are_decoded_from_one_word() -> Result<()> { let data = [0, 0, 0, 0, 0, 0, 0, 1]; @@ -688,7 +688,7 @@ mod tests { assert!(matches!(result, Err(Error::Codec(_)))); } - #[cfg(experimental)] + #[cfg(not(experimental))] #[test] fn decoding_enum_with_more_than_one_heap_type_variant_fails() -> Result<()> { let mut param_types = vec![ @@ -728,7 +728,7 @@ mod tests { Ok(()) } - #[cfg(experimental)] + #[cfg(not(experimental))] #[test] fn enums_w_too_deeply_nested_heap_types_not_allowed() { let variants = to_named(&[ @@ -846,7 +846,7 @@ mod tests { } } - #[cfg(experimental)] + #[cfg(not(experimental))] #[test] fn vectors_of_zst_are_not_supported() { let param_type = ParamType::Vector(Box::new(ParamType::StringArray(0))); diff --git a/packages/fuels-core/src/codec/abi_decoder/decode_as_debug_str.rs b/packages/fuels-core/src/codec/abi_decoder/decode_as_debug_str.rs index 60ca568dfc..a3e54d2074 100644 --- a/packages/fuels-core/src/codec/abi_decoder/decode_as_debug_str.rs +++ b/packages/fuels-core/src/codec/abi_decoder/decode_as_debug_str.rs @@ -104,7 +104,7 @@ mod tests { }, }; - #[cfg(experimental)] + #[cfg(not(experimental))] #[test] fn param_type_decode_debug() -> Result<()> { let decoder = ABIDecoder::default(); @@ -261,7 +261,7 @@ mod tests { Ok(()) } - #[cfg(not(experimental))] + #[cfg(experimental)] #[test] fn param_type_decode_debug() -> Result<()> { let decoder = ABIDecoder::default(); diff --git a/packages/fuels-core/src/codec/abi_encoder.rs b/packages/fuels-core/src/codec/abi_encoder.rs index cb2b576cae..d1bb816924 100644 --- a/packages/fuels-core/src/codec/abi_encoder.rs +++ b/packages/fuels-core/src/codec/abi_encoder.rs @@ -1,10 +1,10 @@ mod bounded_encoder; -#[cfg(not(experimental))] +#[cfg(experimental)] mod experimental_bounded_encoder; use std::default::Default; -#[cfg(not(experimental))] +#[cfg(experimental)] use crate::codec::abi_encoder::experimental_bounded_encoder::ExperimentalBoundedEncoder; use crate::{ codec::abi_encoder::bounded_encoder::BoundedEncoder, @@ -49,9 +49,9 @@ impl ABIEncoder { /// Encodes `Token`s in `args` following the ABI specs defined /// [here](https://github.com/FuelLabs/fuel-specs/blob/master/specs/protocol/abi.md) pub fn encode(&self, args: &[Token]) -> Result { - #[cfg(experimental)] - let res = BoundedEncoder::new(self.config, false).encode(args); #[cfg(not(experimental))] + let res = BoundedEncoder::new(self.config, false).encode(args); + #[cfg(experimental)] let res = ExperimentalBoundedEncoder::new(self.config, false).encode(args); res @@ -79,15 +79,15 @@ impl ConfigurablesEncoder { mod tests { use std::slice; - #[cfg(experimental)] + #[cfg(not(experimental))] use itertools::chain; - #[cfg(experimental)] + #[cfg(not(experimental))] use sha2::{Digest, Sha256}; use super::*; - #[cfg(experimental)] + #[cfg(not(experimental))] use crate::codec::first_four_bytes_of_sha256_hash; - #[cfg(experimental)] + #[cfg(not(experimental))] use crate::constants::WORD_SIZE; use crate::{ to_named, @@ -98,13 +98,13 @@ mod tests { }, }; - #[cfg(experimental)] + #[cfg(not(experimental))] const VEC_METADATA_SIZE: usize = 3 * WORD_SIZE; - #[cfg(experimental)] + #[cfg(not(experimental))] const DISCRIMINANT_SIZE: usize = WORD_SIZE; #[test] - #[cfg(experimental)] + #[cfg(not(experimental))] fn encode_function_signature() { let fn_signature = "entry_one(u64)"; @@ -116,7 +116,7 @@ mod tests { } #[test] - #[cfg(experimental)] + #[cfg(not(experimental))] fn encode_function_with_u32_type() -> Result<()> { // @todo eventually we must update the json abi examples in here. // They're in the old format. @@ -154,7 +154,7 @@ mod tests { } #[test] - #[cfg(experimental)] + #[cfg(not(experimental))] fn encode_function_with_u32_type_multiple_args() -> Result<()> { // let json_abi = // r#" @@ -191,7 +191,7 @@ mod tests { } #[test] - #[cfg(experimental)] + #[cfg(not(experimental))] fn encode_function_with_u64_type() -> Result<()> { // let json_abi = // r#" @@ -226,7 +226,7 @@ mod tests { } #[test] - #[cfg(experimental)] + #[cfg(not(experimental))] fn encode_function_with_bool_type() -> Result<()> { // let json_abi = // r#" @@ -261,7 +261,7 @@ mod tests { } #[test] - #[cfg(experimental)] + #[cfg(not(experimental))] fn encode_function_with_two_different_type() -> Result<()> { // let json_abi = // r#" @@ -301,7 +301,7 @@ mod tests { } #[test] - #[cfg(experimental)] + #[cfg(not(experimental))] fn encode_function_with_bits256_type() -> Result<()> { // let json_abi = // r#" @@ -346,7 +346,7 @@ mod tests { } #[test] - #[cfg(experimental)] + #[cfg(not(experimental))] fn encode_function_with_array_type() -> Result<()> { // let json_abi = // r#" @@ -388,7 +388,7 @@ mod tests { } #[test] - #[cfg(experimental)] + #[cfg(not(experimental))] fn encode_function_with_string_array_type() -> Result<()> { // let json_abi = // r#" @@ -428,7 +428,7 @@ mod tests { } #[test] - #[cfg(experimental)] + #[cfg(not(experimental))] fn encode_function_with_string_slice_type() -> Result<()> { // let json_abi = // r#" @@ -471,7 +471,7 @@ mod tests { } #[test] - #[cfg(experimental)] + #[cfg(not(experimental))] fn encode_function_with_struct() -> Result<()> { // let json_abi = // r#" @@ -521,7 +521,7 @@ mod tests { } #[test] - #[cfg(experimental)] + #[cfg(not(experimental))] fn encode_function_with_enum() -> Result<()> { // let json_abi = // r#" @@ -570,7 +570,7 @@ mod tests { } // The encoding follows the ABI specs defined [here](https://github.com/FuelLabs/fuel-specs/blob/master/specs/protocol/abi.md) - #[cfg(experimental)] + #[cfg(not(experimental))] #[test] fn enums_are_sized_to_fit_the_biggest_variant() -> Result<()> { // Our enum has two variants: B256, and U64. So the enum will set aside @@ -655,7 +655,7 @@ mod tests { .encode(slice::from_ref(&top_level_enum_token))? .resolve(0); - #[cfg(experimental)] + #[cfg(not(experimental))] let expected = [ 0, 0, 0, 0, 0, 0, 0, 0, // TopLevelEnum::v1 discriminant 0, 0, 0, 0, 0, 0, 0, 1, // DeeperEnum::v2 discriminant @@ -663,7 +663,7 @@ mod tests { 0, 0, 0, 0, 0, 0, // DeeperEnum padding 0, 0, 0, 0, 0, 0, 44, 68, // StructA.some_number ]; - #[cfg(not(experimental))] + #[cfg(experimental)] let expected = [ 0, 0, 0, 0, 0, 0, 0, 0, // TopLevelEnum::v1 discriminant 0, 0, 0, 0, 0, 0, 0, 1, // DeeperEnum::v2 discriminant @@ -677,7 +677,7 @@ mod tests { } #[test] - #[cfg(experimental)] + #[cfg(not(experimental))] fn encode_function_with_nested_structs() -> Result<()> { // let json_abi = // r#" @@ -733,7 +733,7 @@ mod tests { } #[test] - #[cfg(experimental)] + #[cfg(not(experimental))] fn encode_comprehensive_function() -> Result<()> { // let json_abi = // r#" @@ -845,7 +845,7 @@ mod tests { Ok(()) } - #[cfg(experimental)] + #[cfg(not(experimental))] #[test] fn units_in_composite_types_are_encoded_in_one_word() -> Result<()> { let expected = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5]; @@ -858,7 +858,7 @@ mod tests { Ok(()) } - #[cfg(experimental)] + #[cfg(not(experimental))] #[test] fn enums_with_units_are_correctly_padded() -> Result<()> { let discriminant = vec![0, 0, 0, 0, 0, 0, 0, 1]; @@ -876,7 +876,7 @@ mod tests { Ok(()) } - #[cfg(experimental)] + #[cfg(not(experimental))] #[test] fn vector_has_ptr_cap_len_and_then_data() -> Result<()> { // arrange @@ -901,7 +901,7 @@ mod tests { Ok(()) } - #[cfg(experimental)] + #[cfg(not(experimental))] #[test] fn data_from_two_vectors_aggregated_at_the_end() -> Result<()> { // arrange @@ -952,7 +952,7 @@ mod tests { .resolve(offset as u64); // assert - #[cfg(experimental)] + #[cfg(not(experimental))] let expected = { let discriminant = vec![0, 0, 0, 0, 0, 0, 0, 1]; @@ -975,7 +975,7 @@ mod tests { ) .collect::>() }; - #[cfg(not(experimental))] + #[cfg(experimental)] let expected = [ 0, 0, 0, 0, 0, 0, 0, 1, // enum dicsriminant 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5, // vec[len, u64] @@ -1003,7 +1003,7 @@ mod tests { .resolve(offset as u64); // assert - #[cfg(experimental)] + #[cfg(not(experimental))] let expected = { const PADDING: usize = std::mem::size_of::<[u8; 32]>() - WORD_SIZE; @@ -1016,7 +1016,7 @@ mod tests { chain!(vec1_ptr, vec1_cap, vec1_len, vec1_data).collect::>() }; - #[cfg(not(experimental))] + #[cfg(experimental)] let expected = [ 0, 0, 0, 0, 0, 0, 0, 1, // vec len 0, 0, 0, 0, 0, 0, 0, 1, 8, // enum discriminant and u8 value @@ -1039,7 +1039,7 @@ mod tests { .resolve(offset as u64); // assert - #[cfg(experimental)] + #[cfg(not(experimental))] let expected = { let vec1_ptr = ((VEC_METADATA_SIZE + WORD_SIZE + offset) as u64) .to_be_bytes() @@ -1050,7 +1050,7 @@ mod tests { chain!(vec1_ptr, vec1_cap, vec1_len, [9], [0; 7], vec1_data).collect::>() }; - #[cfg(not(experimental))] + #[cfg(experimental)] let expected = [ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5, // vec[len, u64] 9, // u8 @@ -1073,7 +1073,7 @@ mod tests { .resolve(offset as u64); // assert - #[cfg(experimental)] + #[cfg(not(experimental))] let expected = { let vec1_data_offset = (VEC_METADATA_SIZE + offset) as u64; let vec1_ptr = vec1_data_offset.to_be_bytes().to_vec(); @@ -1091,7 +1091,7 @@ mod tests { chain!(vec1_ptr, vec1_cap, vec1_len, vec1_data).collect::>() }; - #[cfg(not(experimental))] + #[cfg(experimental)] let expected = [ 0, 0, 0, 0, 0, 0, 0, 1, // vec1 len 0, 0, 0, 0, 0, 0, 0, 2, 5, 6, // vec2 [len, u8, u8] @@ -1112,7 +1112,7 @@ mod tests { let result = ABIEncoder::default().encode(&[token])?.resolve(offset); // assert - #[cfg(experimental)] + #[cfg(not(experimental))] let expected = { let ptr = [0, 0, 0, 0, 0, 0, 0, 64]; let cap = [0, 0, 0, 0, 0, 0, 0, 8]; @@ -1121,7 +1121,7 @@ mod tests { [ptr, cap, len, data].concat() }; - #[cfg(not(experimental))] + #[cfg(experimental)] let expected = [0, 0, 0, 0, 0, 0, 0, 3, 1, 2, 3]; // bytes[len, u8, u8, u8] assert_eq!(result, expected); @@ -1139,7 +1139,7 @@ mod tests { let result = ABIEncoder::default().encode(&[token])?.resolve(offset); // assert - #[cfg(experimental)] + #[cfg(not(experimental))] let expected = { let ptr = [0, 0, 0, 0, 0, 0, 0, 56].to_vec(); let len = [0, 0, 0, 0, 0, 0, 0, 3].to_vec(); @@ -1148,7 +1148,7 @@ mod tests { [ptr, len, data, padding].concat() }; - #[cfg(not(experimental))] + #[cfg(experimental)] let expected = [0, 0, 0, 0, 0, 0, 0, 3, 1, 2, 3]; // raw_slice[len, u8, u8, u8] assert_eq!(result, expected); @@ -1167,7 +1167,7 @@ mod tests { let result = ABIEncoder::default().encode(&[token])?.resolve(offset); // assert - #[cfg(experimental)] + #[cfg(not(experimental))] let expected = { let ptr = [0, 0, 0, 0, 0, 0, 0, 64]; let cap = [0, 0, 0, 0, 0, 0, 0, 8]; @@ -1176,7 +1176,7 @@ mod tests { [ptr, cap, len, data].concat() }; - #[cfg(not(experimental))] + #[cfg(experimental)] let expected = [0, 0, 0, 0, 0, 0, 0, 5, 84, 104, 105, 115, 32]; // string[len, data] assert_eq!(result, expected); @@ -1206,7 +1206,7 @@ mod tests { Ok(()) } - #[cfg(experimental)] + #[cfg(not(experimental))] #[test] fn capacity_overflow_is_caught() -> Result<()> { let token = Token::Enum(Box::new(( diff --git a/packages/fuels-core/src/codec/function_selector.rs b/packages/fuels-core/src/codec/function_selector.rs index dcb01a1416..3d3ed20918 100644 --- a/packages/fuels-core/src/codec/function_selector.rs +++ b/packages/fuels-core/src/codec/function_selector.rs @@ -1,13 +1,13 @@ -#[cfg(experimental)] +#[cfg(not(experimental))] use sha2::{Digest, Sha256}; -#[cfg(experimental)] +#[cfg(not(experimental))] use crate::types::param_types::NamedParamType; use crate::types::param_types::ParamType; -#[cfg(experimental)] +#[cfg(not(experimental))] use crate::types::ByteArray; -#[cfg(experimental)] +#[cfg(not(experimental))] /// Given a function name and its inputs will return a ByteArray representing /// the function selector as specified in the Fuel specs. pub fn resolve_fn_selector(name: &str, inputs: &[ParamType]) -> ByteArray { @@ -16,7 +16,7 @@ pub fn resolve_fn_selector(name: &str, inputs: &[ParamType]) -> ByteArray { first_four_bytes_of_sha256_hash(&fn_signature) } -#[cfg(not(experimental))] +#[cfg(experimental)] pub fn resolve_fn_selector(name: &str, _inputs: &[ParamType]) -> Vec { let bytes = name.as_bytes().to_vec(); let len = bytes.len() as u64; @@ -24,19 +24,19 @@ pub fn resolve_fn_selector(name: &str, _inputs: &[ParamType]) -> Vec { [len.to_be_bytes().to_vec(), bytes].concat() } -#[cfg(experimental)] +#[cfg(not(experimental))] fn resolve_fn_signature(name: &str, inputs: &[ParamType]) -> String { let fn_args = resolve_args(inputs); format!("{name}({fn_args})") } -#[cfg(experimental)] +#[cfg(not(experimental))] fn resolve_args(args: &[ParamType]) -> String { args.iter().map(resolve_arg).collect::>().join(",") } -#[cfg(experimental)] +#[cfg(not(experimental))] fn resolve_named_args(args: &[NamedParamType]) -> String { args.iter() .map(|(_, param_type)| resolve_arg(param_type)) @@ -44,7 +44,7 @@ fn resolve_named_args(args: &[NamedParamType]) -> String { .join(",") } -#[cfg(experimental)] +#[cfg(not(experimental))] fn resolve_arg(arg: &ParamType) -> String { match &arg { ParamType::U8 => "u8".to_owned(), @@ -104,7 +104,7 @@ fn resolve_arg(arg: &ParamType) -> String { } } -#[cfg(experimental)] +#[cfg(not(experimental))] /// Hashes an encoded function selector using SHA256 and returns the first 4 bytes. /// The function selector has to have been already encoded following the ABI specs defined /// [here](https://github.com/FuelLabs/fuel-specs/blob/1be31f70c757d8390f74b9e1b3beb096620553eb/specs/protocol/abi.md) @@ -142,7 +142,7 @@ macro_rules! calldata { pub use calldata; -#[cfg(experimental)] +#[cfg(not(experimental))] #[cfg(test)] mod tests { use super::*; diff --git a/packages/fuels-core/src/codec/logs.rs b/packages/fuels-core/src/codec/logs.rs index 3a028afed6..a763378e86 100644 --- a/packages/fuels-core/src/codec/logs.rs +++ b/packages/fuels-core/src/codec/logs.rs @@ -31,7 +31,7 @@ impl LogFormatter { decoder_config: DecoderConfig, bytes: &[u8], ) -> Result { - #[cfg(experimental)] + #[cfg(not(experimental))] Self::can_decode_log_with_type::()?; let token = ABIDecoder::new(decoder_config).decode(&T::param_type(), bytes)?; @@ -39,8 +39,10 @@ impl LogFormatter { Ok(format!("{:?}", T::from_token(token)?)) } - #[cfg(experimental)] + #[cfg(not(experimental))] fn can_decode_log_with_type() -> Result<()> { + use crate::types::param_types::ParamType; + match T::param_type() { // String slices cannot be decoded from logs as they are encoded as ptr, len // TODO: Once https://github.com/FuelLabs/sway/issues/5110 is resolved we can remove this diff --git a/packages/fuels-core/src/types.rs b/packages/fuels-core/src/types.rs index 95ff93a485..75fe20e6ef 100644 --- a/packages/fuels-core/src/types.rs +++ b/packages/fuels-core/src/types.rs @@ -17,9 +17,9 @@ pub mod unresolved_bytes; mod wrappers; pub type ByteArray = [u8; 8]; -#[cfg(experimental)] -pub type Selector = ByteArray; #[cfg(not(experimental))] +pub type Selector = ByteArray; +#[cfg(experimental)] pub type Selector = Vec; /// Converts a u16 to a right aligned array of 8 bytes. diff --git a/packages/fuels-core/src/types/param_types/param_type.rs b/packages/fuels-core/src/types/param_types/param_type.rs index a0d0f35d35..bc7ee9cc06 100644 --- a/packages/fuels-core/src/types/param_types/param_type.rs +++ b/packages/fuels-core/src/types/param_types/param_type.rs @@ -50,7 +50,7 @@ impl ParamType { // Depending on the type, the returned value will be stored // either in `Return` or `ReturnData`. pub fn get_return_location(&self) -> ReturnLocation { - #[cfg(experimental)] + #[cfg(not(experimental))] match self { Self::Unit | Self::U8 | Self::U16 | Self::U32 | Self::U64 | Self::Bool => { ReturnLocation::Return @@ -59,7 +59,7 @@ impl ParamType { _ => ReturnLocation::ReturnData, } - #[cfg(not(experimental))] + #[cfg(experimental)] ReturnLocation::ReturnData } diff --git a/packages/fuels-programs/src/call_utils.rs b/packages/fuels-programs/src/call_utils.rs index 2b9d3cf0a8..837512d05d 100644 --- a/packages/fuels-programs/src/call_utils.rs +++ b/packages/fuels-programs/src/call_utils.rs @@ -5,8 +5,8 @@ use fuel_asm::{op, RegId}; use fuel_tx::{AssetId, Bytes32, ContractId, Output, PanicReason, Receipt, TxPointer, UtxoId}; use fuel_types::{Address, Word}; use fuels_accounts::Account; -use fuels_core::constants::WORD_SIZE; use fuels_core::{ + constants::WORD_SIZE, error, offsets::call_script_data_offset, types::{ @@ -244,7 +244,7 @@ pub(crate) fn get_instructions( }) } -#[cfg(experimental)] +#[cfg(not(experimental))] /// Returns script data, consisting of the following items in the given order: /// 1. Amount to be forwarded `(1 * `[`WORD_SIZE`]`)` /// 2. Asset ID to be forwarded ([`AssetId::LEN`]) @@ -324,7 +324,7 @@ pub(crate) fn build_script_data_from_contract_calls( Ok((script_data, param_offsets)) } -#[cfg(not(experimental))] +#[cfg(experimental)] /// Returns script data, consisting of the following items in the given order: /// 1. Amount to be forwarded `(1 * `[`WORD_SIZE`]`)` /// 2. Asset ID to be forwarded ([`AssetId::LEN`]) @@ -440,14 +440,14 @@ pub(crate) fn get_single_call_instructions( None => instructions.push(op::call(0x10, 0x11, 0x12, RegId::CGAS)), }; - #[cfg(experimental)] + #[cfg(not(experimental))] instructions.extend(extract_heap_data(_output_param_type)?); #[allow(clippy::iter_cloned_collect)] Ok(instructions.into_iter().collect::>()) } -#[cfg(experimental)] +#[cfg(not(experimental))] fn extract_heap_data(param_type: &ParamType) -> Result> { match param_type { ParamType::Enum { enum_variants, .. } => { @@ -483,7 +483,7 @@ fn extract_heap_data(param_type: &ParamType) -> Result Vec { mod test { use std::slice; - #[cfg(experimental)] + #[cfg(not(experimental))] use fuel_types::bytes::WORD_SIZE; use fuels_accounts::wallet::WalletUnlocked; use fuels_core::types::{ @@ -665,7 +665,7 @@ mod test { coin::{Coin, CoinStatus}, coin_type::CoinType, }; - #[cfg(experimental)] + #[cfg(not(experimental))] use fuels_core::{codec::ABIEncoder, types::Token}; use rand::Rng; @@ -677,9 +677,9 @@ mod test { ContractCall { contract_id: random_bech32_contract_id(), encoded_args: Ok(Default::default()), - #[cfg(experimental)] - encoded_selector: [0; 8], #[cfg(not(experimental))] + encoded_selector: [0; 8], + #[cfg(experimental)] encoded_selector: [0; 8].to_vec(), call_parameters: Default::default(), compute_custom_input_offset: false, @@ -700,7 +700,7 @@ mod test { Bech32ContractId::new("fuel", rand::thread_rng().gen::<[u8; 32]>()) } - #[cfg(experimental)] + #[cfg(not(experimental))] #[tokio::test] async fn test_script_data() { // Arrange @@ -730,9 +730,9 @@ mod test { let calls: Vec = (0..NUM_CALLS) .map(|i| ContractCall { contract_id: contract_ids[i].clone(), - #[cfg(experimental)] - encoded_selector: selectors[i], #[cfg(not(experimental))] + encoded_selector: selectors[i], + #[cfg(experimental)] encoded_selector: selectors[i].to_vec(), encoded_args: Ok(args[i].clone()), call_parameters: CallParameters::new(i as u64, asset_ids[i], i as u64), @@ -1028,10 +1028,10 @@ mod test { const BASE_INSTRUCTION_COUNT: usize = 5; // 2 instructions (movi and lw) added in get_single_call_instructions when gas_offset is set const GAS_OFFSET_INSTRUCTION_COUNT: usize = 2; - #[cfg(experimental)] + #[cfg(not(experimental))] // 4 instructions (lw, lw, muli, retd) added by extract_data_receipt const EXTRACT_DATA_RECEIPT_INSTRUCTION_COUNT: usize = 4; - #[cfg(experimental)] + #[cfg(not(experimental))] // 4 instructions (movi, lw, jnef, retd) added by extract_heap_data const EXTRACT_HEAP_DATA_INSTRUCTION_COUNT: usize = 4; @@ -1053,7 +1053,7 @@ mod test { ); } - #[cfg(experimental)] + #[cfg(not(experimental))] #[test] fn test_with_heap_type() { let output_params = vec![ @@ -1073,7 +1073,7 @@ mod test { } } - #[cfg(experimental)] + #[cfg(not(experimental))] #[test] fn test_with_gas_offset_and_heap_type() { let mut call = ContractCall::new_with_random_id(); @@ -1090,7 +1090,7 @@ mod test { ); } - #[cfg(experimental)] + #[cfg(not(experimental))] #[test] fn test_with_enum_with_heap_and_non_heap_variant() { let variant_sets = vec![ diff --git a/packages/fuels-programs/src/contract.rs b/packages/fuels-programs/src/contract.rs index fe2feb406a..a6fc6269e7 100644 --- a/packages/fuels-programs/src/contract.rs +++ b/packages/fuels-programs/src/contract.rs @@ -726,9 +726,9 @@ pub fn method_hash( let tx_policies = TxPolicies::default(); let call_parameters = CallParameters::default(); - #[cfg(experimental)] - let compute_custom_input_offset = should_compute_custom_input_offset(args); #[cfg(not(experimental))] + let compute_custom_input_offset = should_compute_custom_input_offset(args); + #[cfg(experimental)] let compute_custom_input_offset = true; let unresolved_bytes = ABIEncoder::new(encoder_config).encode(args); @@ -759,7 +759,7 @@ pub fn method_hash( // If the data passed into the contract method is an integer or a // boolean, then the data itself should be passed. Otherwise, it // should simply pass a pointer to the data in memory. -#[cfg(experimental)] +#[cfg(not(experimental))] fn should_compute_custom_input_offset(args: &[Token]) -> bool { args.len() > 1 || args.iter().any(|t| { diff --git a/packages/fuels-programs/src/receipt_parser.rs b/packages/fuels-programs/src/receipt_parser.rs index a7c70ff514..d31a61cca8 100644 --- a/packages/fuels-programs/src/receipt_parser.rs +++ b/packages/fuels-programs/src/receipt_parser.rs @@ -43,7 +43,7 @@ impl ReceiptParser { // During a script execution, the script's contract id is the **null** contract id .unwrap_or_else(ContractId::zeroed); - #[cfg(experimental)] + #[cfg(not(experimental))] output_param.validate_is_decodable(self.decoder.config.max_depth)?; let data = self @@ -65,9 +65,9 @@ impl ReceiptParser { output_param: &ParamType, contract_id: &ContractId, ) -> Option> { - #[cfg(experimental)] - let extra_receipts_needed = output_param.is_extra_receipt_needed(true); #[cfg(not(experimental))] + let extra_receipts_needed = output_param.is_extra_receipt_needed(true); + #[cfg(experimental)] let extra_receipts_needed = false; match output_param.get_return_location() { @@ -324,9 +324,9 @@ mod tests { let contract_id = target_contract(); let mut receipts = expected_receipts.clone(); - #[cfg(experimental)] + #[cfg(not(experimental))] receipts.push(get_return_receipt(contract_id, RECEIPT_VAL)); - #[cfg(not(experimental))] // all data is returned as RETD + #[cfg(experimental)] // all data is returned as RETD receipts.push(get_return_data_receipt( contract_id, &RECEIPT_VAL.to_be_bytes(), @@ -343,7 +343,7 @@ mod tests { Ok(()) } - #[cfg(experimental)] + #[cfg(not(experimental))] #[tokio::test] async fn receipt_parser_extract_return_data_heap() -> Result<()> { let expected_receipts = get_relevant_receipts(); diff --git a/packages/fuels/tests/bindings.rs b/packages/fuels/tests/bindings.rs index 227a726d83..edc76b63da 100644 --- a/packages/fuels/tests/bindings.rs +++ b/packages/fuels/tests/bindings.rs @@ -1,14 +1,14 @@ -#[cfg(experimental)] +#[cfg(not(experimental))] use std::slice; use std::str::FromStr; use fuels::prelude::*; -#[cfg(experimental)] +#[cfg(not(experimental))] use fuels::{ core::{codec::ABIEncoder, traits::Tokenizable}, types::{Bits256, EvmAddress}, }; -#[cfg(experimental)] +#[cfg(not(experimental))] use sha2::{Digest, Sha256}; pub fn null_contract_id() -> Bech32ContractId { @@ -17,7 +17,7 @@ pub fn null_contract_id() -> Bech32ContractId { .unwrap() } -#[cfg(experimental)] +#[cfg(not(experimental))] #[tokio::test] async fn compile_bindings_from_contract_file() { // Generates the bindings from an ABI definition in a JSON file @@ -49,7 +49,7 @@ async fn compile_bindings_from_contract_file() { assert_eq!("000000005f68ee3d000000000000002a", encoded); } -#[cfg(experimental)] +#[cfg(not(experimental))] #[tokio::test] async fn compile_bindings_from_inline_contract() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -110,7 +110,7 @@ async fn compile_bindings_from_inline_contract() -> Result<()> { Ok(()) } -#[cfg(experimental)] +#[cfg(not(experimental))] #[tokio::test] async fn compile_bindings_array_input() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -188,7 +188,7 @@ async fn compile_bindings_array_input() -> Result<()> { Ok(()) } -#[cfg(experimental)] +#[cfg(not(experimental))] #[tokio::test] async fn compile_bindings_bool_array_input() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -263,7 +263,7 @@ async fn compile_bindings_bool_array_input() -> Result<()> { Ok(()) } -#[cfg(experimental)] +#[cfg(not(experimental))] #[tokio::test] async fn compile_bindings_string_input() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -334,7 +334,7 @@ async fn compile_bindings_string_input() -> Result<()> { Ok(()) } -#[cfg(experimental)] +#[cfg(not(experimental))] #[tokio::test] async fn compile_bindings_b256_input() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -406,7 +406,7 @@ async fn compile_bindings_b256_input() -> Result<()> { Ok(()) } -#[cfg(experimental)] +#[cfg(not(experimental))] #[tokio::test] async fn compile_bindings_evm_address_input() -> Result<()> { abigen!(Contract( @@ -477,7 +477,7 @@ async fn compile_bindings_evm_address_input() -> Result<()> { Ok(()) } -#[cfg(experimental)] +#[cfg(not(experimental))] #[tokio::test] async fn compile_bindings_struct_input() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -580,7 +580,7 @@ async fn compile_bindings_struct_input() -> Result<()> { Ok(()) } -#[cfg(experimental)] +#[cfg(not(experimental))] #[tokio::test] async fn compile_bindings_nested_struct_input() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -689,7 +689,7 @@ async fn compile_bindings_nested_struct_input() -> Result<()> { Ok(()) } -#[cfg(experimental)] +#[cfg(not(experimental))] #[tokio::test] async fn compile_bindings_enum_input() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -777,7 +777,7 @@ async fn compile_bindings_enum_input() -> Result<()> { Ok(()) } -#[cfg(experimental)] +#[cfg(not(experimental))] #[tokio::test] async fn shared_types() -> Result<()> { setup_program_test!( diff --git a/packages/fuels/tests/contracts.rs b/packages/fuels/tests/contracts.rs index 2ec61a3765..ec5ca89111 100644 --- a/packages/fuels/tests/contracts.rs +++ b/packages/fuels/tests/contracts.rs @@ -1,4 +1,4 @@ -#[cfg(experimental)] +#[cfg(not(experimental))] use fuels::core::codec::{calldata, fn_selector}; use fuels::{ core::codec::{DecoderConfig, EncoderConfig}, @@ -276,7 +276,14 @@ async fn test_contract_call_fee_estimation() -> Result<()> { let tolerance = Some(0.2); let block_horizon = Some(1); + #[cfg(not(experimental))] + let expected_gas_used = 954; + #[cfg(experimental)] let expected_gas_used = 960; + + #[cfg(not(experimental))] + let expected_metered_bytes_size = 784; + #[cfg(experimental)] let expected_metered_bytes_size = 824; let estimated_transaction_cost = contract_instance @@ -1220,7 +1227,7 @@ async fn multi_call_from_calls_with_different_account_types() -> Result<()> { } #[tokio::test] -#[cfg(experimental)] +#[cfg(not(experimental))] async fn low_level_call() -> Result<()> { use fuels::types::SizedAsciiString; diff --git a/packages/fuels/tests/from_token.rs b/packages/fuels/tests/from_token.rs index b17d35bf2f..f27235b4f5 100644 --- a/packages/fuels/tests/from_token.rs +++ b/packages/fuels/tests/from_token.rs @@ -1,7 +1,7 @@ use std::str::FromStr; use fuels::prelude::*; -#[cfg(experimental)] +#[cfg(not(experimental))] use fuels::{core::traits::Tokenizable, types::Token}; pub fn null_contract_id() -> Bech32ContractId { @@ -10,7 +10,7 @@ pub fn null_contract_id() -> Bech32ContractId { .unwrap() } -#[cfg(experimental)] +#[cfg(not(experimental))] #[tokio::test] async fn create_struct_from_decoded_tokens() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -105,7 +105,7 @@ async fn create_struct_from_decoded_tokens() -> Result<()> { Ok(()) } -#[cfg(experimental)] +#[cfg(not(experimental))] #[tokio::test] async fn create_nested_struct_from_decoded_tokens() -> Result<()> { // Generates the bindings from the an ABI definition inline. diff --git a/packages/fuels/tests/logs.rs b/packages/fuels/tests/logs.rs index 4ededc1a05..746e9b96bc 100644 --- a/packages/fuels/tests/logs.rs +++ b/packages/fuels/tests/logs.rs @@ -1453,7 +1453,7 @@ async fn can_configure_decoder_for_script_log_decoding() -> Result<()> { // String slices cannot be decoded from logs as they are encoded as ptr, len // TODO: Once https://github.com/FuelLabs/sway/issues/5110 is resolved we can remove this #[tokio::test] -#[cfg(experimental)] +#[cfg(not(experimental))] async fn string_slice_log() -> Result<()> { setup_program_test!( Wallets("wallet"), diff --git a/packages/fuels/tests/predicates.rs b/packages/fuels/tests/predicates.rs index c7f6a9005c..e70043187e 100644 --- a/packages/fuels/tests/predicates.rs +++ b/packages/fuels/tests/predicates.rs @@ -797,12 +797,12 @@ async fn predicate_can_access_manually_added_witnesses() -> Result<()> { .build(&provider) .await?; - #[cfg(experimental)] + #[cfg(not(experimental))] let witness = ABIEncoder::default() .encode(&[64u8.into_token()])? .resolve(0); - #[cfg(not(experimental))] + #[cfg(experimental)] let witness = ABIEncoder::default() .encode(&[64u64.into_token()])? // u64 because this is VM memory .resolve(0); @@ -876,12 +876,12 @@ async fn tx_id_not_changed_after_adding_witnesses() -> Result<()> { let tx_id = tx.id(provider.chain_id()); - #[cfg(experimental)] + #[cfg(not(experimental))] let witness = ABIEncoder::default() .encode(&[64u8.into_token()])? .resolve(0); - #[cfg(not(experimental))] + #[cfg(experimental)] let witness = ABIEncoder::default() .encode(&[64u64.into_token()])? // u64 because this is VM memory .resolve(0); diff --git a/packages/fuels/tests/providers.rs b/packages/fuels/tests/providers.rs index a61f1fcbfa..fb9559a286 100644 --- a/packages/fuels/tests/providers.rs +++ b/packages/fuels/tests/providers.rs @@ -323,9 +323,9 @@ async fn test_gas_forwarded_defaults_to_tx_limit() -> Result<()> { ); // The gas used by the script to call a contract and forward remaining gas limit. - #[cfg(experimental)] - let gas_used_by_script = 360; #[cfg(not(experimental))] + let gas_used_by_script = 364; + #[cfg(experimental)] let gas_used_by_script = 876; let gas_limit = 225_883; let response = contract_instance diff --git a/packages/fuels/tests/types_contracts.rs b/packages/fuels/tests/types_contracts.rs index ac4553499e..41363f6412 100644 --- a/packages/fuels/tests/types_contracts.rs +++ b/packages/fuels/tests/types_contracts.rs @@ -1872,7 +1872,7 @@ async fn test_composite_types_in_vec_output() -> Result<()> { Ok(()) } -#[cfg(experimental)] +#[cfg(not(experimental))] #[tokio::test] async fn test_nested_vector_methods_fail() -> Result<()> { // This is just an E2E test of the method `ParamType::contains_nested_heap_types`, hence it's @@ -2166,7 +2166,7 @@ async fn test_heap_type_in_enums() -> Result<()> { assert!(resp.value.is_none()); } - #[cfg(experimental)] + #[cfg(not(experimental))] { // If the LW(RET) instruction was not executed only conditionally, then the FuelVM would OOM. let _ = contract_methods @@ -2187,7 +2187,7 @@ async fn test_heap_type_in_enums() -> Result<()> { Ok(()) } -#[cfg(not(experimental))] +#[cfg(experimental)] #[tokio::test] async fn nested_heap_types() -> Result<()> { setup_program_test!( diff --git a/packages/fuels/tests/types_scripts.rs b/packages/fuels/tests/types_scripts.rs index beb6060bcf..12dc459d18 100644 --- a/packages/fuels/tests/types_scripts.rs +++ b/packages/fuels/tests/types_scripts.rs @@ -323,7 +323,7 @@ async fn script_handles_std_string() -> Result<()> { Ok(()) } -#[cfg(not(experimental))] +#[cfg(experimental)] #[tokio::test] async fn nested_heap_types() -> Result<()> { setup_program_test!( From 214a60e5ebd55e0df28a0d1c1c0c8bca25302b2d Mon Sep 17 00:00:00 2001 From: hal3e Date: Thu, 21 Mar 2024 17:00:25 +0100 Subject: [PATCH 19/30] update ci --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 88d9f1b9cd..304604879c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ env: FUEL_CORE_PATCH_BRANCH: RUST_VERSION: 1.74.0 FORC_VERSION: 0.51.1 - FORC_PATCH_BRANCH: "" + FORC_PATCH_BRANCH: "xunilrj/new-encoding-fixes" FORC_PATCH_REVISION: "" jobs: From c03e8031cb2a8e56db4ba9fb3d6da2fb4660f4ac Mon Sep 17 00:00:00 2001 From: hal3e Date: Fri, 22 Mar 2024 12:11:50 +0100 Subject: [PATCH 20/30] temporarily disable the `generics` forc project --- examples/debugging/src/lib.rs | 206 +++++++++--------- packages/fuels/Forc.toml | 2 +- packages/fuels/tests/types_contracts.rs | 268 ++++++++++++------------ 3 files changed, 238 insertions(+), 238 deletions(-) diff --git a/examples/debugging/src/lib.rs b/examples/debugging/src/lib.rs index f086359e70..807677e5e4 100644 --- a/examples/debugging/src/lib.rs +++ b/examples/debugging/src/lib.rs @@ -77,107 +77,107 @@ mod tests { Ok(()) } - #[test] - fn decoded_debug_matches_rust_debug() -> Result<()> { - abigen!(Contract( - name = "MyContract", - abi = "packages/fuels/tests/types/contracts/generics/out/debug/generics-abi.json" - )); - - let json_abi_file = - "../../packages/fuels/tests/types/contracts/generics/out/debug/generics-abi.json"; - let abi_file_contents = std::fs::read_to_string(json_abi_file)?; - - let parsed_abi: ProgramABI = serde_json::from_str(&abi_file_contents)?; - - let type_lookup = parsed_abi - .types - .into_iter() - .map(|decl| (decl.type_id, decl)) - .collect::>(); - - let get_first_fn_argument = |fn_name: &str| { - parsed_abi - .functions - .iter() - .find(|abi_fun| abi_fun.name == fn_name) - .expect("should be there") - .inputs - .first() - .expect("should be there") - }; - let decoder = ABIDecoder::default(); - - { - // simple struct with a single generic parameter - let type_application = get_first_fn_argument("struct_w_generic"); - let param_type = ParamType::try_from_type_application(type_application, &type_lookup)?; - - let expected_struct = SimpleGeneric { - single_generic_param: 123u64, - }; - - assert_eq!( - format!("{expected_struct:?}"), - decoder.decode_as_debug_str(¶m_type, &[0, 0, 0, 0, 0, 0, 0, 123])? - ); - } - { - // struct that delegates the generic param internally - let type_application = get_first_fn_argument("struct_delegating_generic"); - let param_type = ParamType::try_from_type_application(type_application, &type_lookup)?; - - let expected_struct = PassTheGenericOn { - one: SimpleGeneric { - single_generic_param: SizedAsciiString::<3>::try_from("abc")?, - }, - }; - - assert_eq!( - format!("{expected_struct:?}"), - decoder.decode_as_debug_str(¶m_type, &[97, 98, 99])? - ); - } - { - // enum with generic in variant - let type_application = get_first_fn_argument("enum_w_generic"); - let param_type = ParamType::try_from_type_application(type_application, &type_lookup)?; - - let expected_enum = EnumWGeneric::B(10u64); - - assert_eq!( - format!("{expected_enum:?}"), - decoder.decode_as_debug_str( - ¶m_type, - &[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 10] - )? - ); - } - { - // logged type - let logged_type = parsed_abi - .logged_types - .as_ref() - .expect("has logs") - .first() - .expect("has log"); - - let param_type = - ParamType::try_from_type_application(&logged_type.application, &type_lookup)?; - - let expected_u8 = 1; - - #[cfg(not(experimental))] - let data = [0, 0, 0, 0, 0, 0, 0, 1]; - #[cfg(experimental)] - let data = [1]; - - assert_eq!( - format!("{expected_u8}"), - decoder.decode_as_debug_str(¶m_type, &data)? - ); - } - - Ok(()) - } + // #[test] // TODO: @hal3e temporarily disabled the test + // fn decoded_debug_matches_rust_debug() -> Result<()> { + // abigen!(Contract( + // name = "MyContract", + // abi = "packages/fuels/tests/types/contracts/generics/out/debug/generics-abi.json" + // )); + + // let json_abi_file = + // "../../packages/fuels/tests/types/contracts/generics/out/debug/generics-abi.json"; + // let abi_file_contents = std::fs::read_to_string(json_abi_file)?; + + // let parsed_abi: ProgramABI = serde_json::from_str(&abi_file_contents)?; + + // let type_lookup = parsed_abi + // .types + // .into_iter() + // .map(|decl| (decl.type_id, decl)) + // .collect::>(); + + // let get_first_fn_argument = |fn_name: &str| { + // parsed_abi + // .functions + // .iter() + // .find(|abi_fun| abi_fun.name == fn_name) + // .expect("should be there") + // .inputs + // .first() + // .expect("should be there") + // }; + // let decoder = ABIDecoder::default(); + + // { + // // simple struct with a single generic parameter + // let type_application = get_first_fn_argument("struct_w_generic"); + // let param_type = ParamType::try_from_type_application(type_application, &type_lookup)?; + + // let expected_struct = SimpleGeneric { + // single_generic_param: 123u64, + // }; + + // assert_eq!( + // format!("{expected_struct:?}"), + // decoder.decode_as_debug_str(¶m_type, &[0, 0, 0, 0, 0, 0, 0, 123])? + // ); + // } + // { + // // struct that delegates the generic param internally + // let type_application = get_first_fn_argument("struct_delegating_generic"); + // let param_type = ParamType::try_from_type_application(type_application, &type_lookup)?; + + // let expected_struct = PassTheGenericOn { + // one: SimpleGeneric { + // single_generic_param: SizedAsciiString::<3>::try_from("abc")?, + // }, + // }; + + // assert_eq!( + // format!("{expected_struct:?}"), + // decoder.decode_as_debug_str(¶m_type, &[97, 98, 99])? + // ); + // } + // { + // // enum with generic in variant + // let type_application = get_first_fn_argument("enum_w_generic"); + // let param_type = ParamType::try_from_type_application(type_application, &type_lookup)?; + + // let expected_enum = EnumWGeneric::B(10u64); + + // assert_eq!( + // format!("{expected_enum:?}"), + // decoder.decode_as_debug_str( + // ¶m_type, + // &[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 10] + // )? + // ); + // } + // { + // // logged type + // let logged_type = parsed_abi + // .logged_types + // .as_ref() + // .expect("has logs") + // .first() + // .expect("has log"); + + // let param_type = + // ParamType::try_from_type_application(&logged_type.application, &type_lookup)?; + + // let expected_u8 = 1; + + // #[cfg(not(experimental))] + // let data = [0, 0, 0, 0, 0, 0, 0, 1]; + // #[cfg(experimental)] + // let data = [1]; + + // assert_eq!( + // format!("{expected_u8}"), + // decoder.decode_as_debug_str(¶m_type, &data)? + // ); + // } + + // Ok(()) + // } } diff --git a/packages/fuels/Forc.toml b/packages/fuels/Forc.toml index 81a728a60d..e281ccbc1b 100644 --- a/packages/fuels/Forc.toml +++ b/packages/fuels/Forc.toml @@ -60,7 +60,7 @@ members = [ 'tests/types/contracts/enum_encoding', 'tests/types/contracts/enum_inside_struct', 'tests/types/contracts/evm_address', - 'tests/types/contracts/generics', + #'tests/types/contracts/generics', 'tests/types/contracts/heap_type_in_enums', 'tests/types/contracts/heap_types', 'tests/types/contracts/identity', diff --git a/packages/fuels/tests/types_contracts.rs b/packages/fuels/tests/types_contracts.rs index 41363f6412..ba75562577 100644 --- a/packages/fuels/tests/types_contracts.rs +++ b/packages/fuels/tests/types_contracts.rs @@ -1408,140 +1408,140 @@ async fn test_identity_with_two_contracts() -> Result<()> { Ok(()) } -#[tokio::test] -async fn generics_test() -> Result<()> { - setup_program_test!( - Wallets("wallet"), - Abigen(Contract( - name = "TypesContract", - project = "packages/fuels/tests/types/contracts/generics" - )), - Deploy( - name = "contract_instance", - contract = "TypesContract", - wallet = "wallet" - ), - ); - let contract_methods = contract_instance.methods(); - - { - // ANCHOR: generic - // simple struct with a single generic param - let arg1 = SimpleGeneric { - single_generic_param: 123u64, - }; - - let result = contract_methods - .struct_w_generic(arg1.clone()) - .call() - .await? - .value; - - assert_eq!(result, arg1); - // ANCHOR_END: generic - } - { - // struct that delegates the generic param internally - let arg1 = PassTheGenericOn { - one: SimpleGeneric { - single_generic_param: "abc".try_into()?, - }, - }; - - let result = contract_methods - .struct_delegating_generic(arg1.clone()) - .call() - .await? - .value; - - assert_eq!(result, arg1); - } - { - // struct that has the generic in an array - let arg1 = StructWArrayGeneric { a: [1u32, 2u32] }; - - let result = contract_methods - .struct_w_generic_in_array(arg1.clone()) - .call() - .await? - .value; - - assert_eq!(result, arg1); - } - { - // struct that has the generic in a tuple - let arg1 = StructWTupleGeneric { a: (1, 2) }; - - let result = contract_methods - .struct_w_generic_in_tuple(arg1.clone()) - .call() - .await? - .value; - - assert_eq!(result, arg1); - } - { - // enum with generic in variant - let arg1 = EnumWGeneric::B(10); - let result = contract_methods - .enum_w_generic(arg1.clone()) - .call() - .await? - .value; - - assert_eq!(result, arg1); - } - { - contract_methods - .unused_generic_args( - StructOneUnusedGenericParam::default(), - EnumOneUnusedGenericParam::One, - ) - .call() - .await?; - - let (the_struct, the_enum) = contract_methods - .used_and_unused_generic_args( - StructUsedAndUnusedGenericParams::new(10u8), - EnumUsedAndUnusedGenericParams::Two(11u8), - ) - .call() - .await? - .value; - - assert_eq!(the_struct.field, 12u8); - if let EnumUsedAndUnusedGenericParams::Two(val) = the_enum { - assert_eq!(val, 13) - } else { - panic!("Expected the variant EnumUsedAndUnusedGenericParams::Two"); - } - } - { - // complex case - let pass_through = PassTheGenericOn { - one: SimpleGeneric { - single_generic_param: "ab".try_into()?, - }, - }; - let w_arr_generic = StructWArrayGeneric { - a: [pass_through.clone(), pass_through], - }; - - let arg1 = MegaExample { - a: ([Bits256([0; 32]), Bits256([0; 32])], "ab".try_into()?), - b: vec![( - [EnumWGeneric::B(StructWTupleGeneric { - a: (w_arr_generic.clone(), w_arr_generic), - })], - 10u32, - )], - }; - - contract_methods.complex_test(arg1.clone()).call().await?; - } - - Ok(()) -} +// #[tokio::test] // TODO: @hal3e temporarily disabled the test +// async fn generics_test() -> Result<()> { +// setup_program_test!( +// Wallets("wallet"), +// Abigen(Contract( +// name = "TypesContract", +// project = "packages/fuels/tests/types/contracts/generics" +// )), +// Deploy( +// name = "contract_instance", +// contract = "TypesContract", +// wallet = "wallet" +// ), +// ); +// let contract_methods = contract_instance.methods(); + +// { +// // ANCHOR: generic +// // simple struct with a single generic param +// let arg1 = SimpleGeneric { +// single_generic_param: 123u64, +// }; + +// let result = contract_methods +// .struct_w_generic(arg1.clone()) +// .call() +// .await? +// .value; + +// assert_eq!(result, arg1); +// // ANCHOR_END: generic +// } +// { +// // struct that delegates the generic param internally +// let arg1 = PassTheGenericOn { +// one: SimpleGeneric { +// single_generic_param: "abc".try_into()?, +// }, +// }; + +// let result = contract_methods +// .struct_delegating_generic(arg1.clone()) +// .call() +// .await? +// .value; + +// assert_eq!(result, arg1); +// } +// { +// // struct that has the generic in an array +// let arg1 = StructWArrayGeneric { a: [1u32, 2u32] }; + +// let result = contract_methods +// .struct_w_generic_in_array(arg1.clone()) +// .call() +// .await? +// .value; + +// assert_eq!(result, arg1); +// } +// { +// // struct that has the generic in a tuple +// let arg1 = StructWTupleGeneric { a: (1, 2) }; + +// let result = contract_methods +// .struct_w_generic_in_tuple(arg1.clone()) +// .call() +// .await? +// .value; + +// assert_eq!(result, arg1); +// } +// { +// // enum with generic in variant +// let arg1 = EnumWGeneric::B(10); +// let result = contract_methods +// .enum_w_generic(arg1.clone()) +// .call() +// .await? +// .value; + +// assert_eq!(result, arg1); +// } +// { +// contract_methods +// .unused_generic_args( +// StructOneUnusedGenericParam::default(), +// EnumOneUnusedGenericParam::One, +// ) +// .call() +// .await?; + +// let (the_struct, the_enum) = contract_methods +// .used_and_unused_generic_args( +// StructUsedAndUnusedGenericParams::new(10u8), +// EnumUsedAndUnusedGenericParams::Two(11u8), +// ) +// .call() +// .await? +// .value; + +// assert_eq!(the_struct.field, 12u8); +// if let EnumUsedAndUnusedGenericParams::Two(val) = the_enum { +// assert_eq!(val, 13) +// } else { +// panic!("Expected the variant EnumUsedAndUnusedGenericParams::Two"); +// } +// } +// { +// // complex case +// let pass_through = PassTheGenericOn { +// one: SimpleGeneric { +// single_generic_param: "ab".try_into()?, +// }, +// }; +// let w_arr_generic = StructWArrayGeneric { +// a: [pass_through.clone(), pass_through], +// }; + +// let arg1 = MegaExample { +// a: ([Bits256([0; 32]), Bits256([0; 32])], "ab".try_into()?), +// b: vec![( +// [EnumWGeneric::B(StructWTupleGeneric { +// a: (w_arr_generic.clone(), w_arr_generic), +// })], +// 10u32, +// )], +// }; + +// contract_methods.complex_test(arg1.clone()).call().await?; +// } + +// Ok(()) +// } #[tokio::test] async fn test_vector() -> Result<()> { From 3cdc2044a239d9c00e2aaf3c1465e9f7127a0e8a Mon Sep 17 00:00:00 2001 From: hal3e Date: Fri, 22 Mar 2024 12:30:56 +0100 Subject: [PATCH 21/30] temporarily disable the `generics` forc project --- packages/fuels/Forc.toml | 1 + packages/fuels/tests/types_contracts.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/fuels/Forc.toml b/packages/fuels/Forc.toml index e281ccbc1b..2488bcccf4 100644 --- a/packages/fuels/Forc.toml +++ b/packages/fuels/Forc.toml @@ -60,6 +60,7 @@ members = [ 'tests/types/contracts/enum_encoding', 'tests/types/contracts/enum_inside_struct', 'tests/types/contracts/evm_address', + # TODO: @hal3e tempoarily disabled this forc project #'tests/types/contracts/generics', 'tests/types/contracts/heap_type_in_enums', 'tests/types/contracts/heap_types', diff --git a/packages/fuels/tests/types_contracts.rs b/packages/fuels/tests/types_contracts.rs index ba75562577..1ea0453ef3 100644 --- a/packages/fuels/tests/types_contracts.rs +++ b/packages/fuels/tests/types_contracts.rs @@ -1425,7 +1425,7 @@ async fn test_identity_with_two_contracts() -> Result<()> { // let contract_methods = contract_instance.methods(); // { -// // ANCHOR: generic +// ANCHOR: generic // // simple struct with a single generic param // let arg1 = SimpleGeneric { // single_generic_param: 123u64, @@ -1438,7 +1438,7 @@ async fn test_identity_with_two_contracts() -> Result<()> { // .value; // assert_eq!(result, arg1); -// // ANCHOR_END: generic +// ANCHOR_END: generic // } // { // // struct that delegates the generic param internally From 7e0c130710a8cef7569c01fae7d4ac6fc55b4a8b Mon Sep 17 00:00:00 2001 From: hal3e Date: Fri, 22 Mar 2024 15:17:23 +0100 Subject: [PATCH 22/30] fix warning --- examples/debugging/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/debugging/src/lib.rs b/examples/debugging/src/lib.rs index 807677e5e4..c62744d608 100644 --- a/examples/debugging/src/lib.rs +++ b/examples/debugging/src/lib.rs @@ -6,8 +6,8 @@ mod tests { #[cfg(not(experimental))] use fuels::core::codec::{calldata, fn_selector}; use fuels::{ - core::codec::ABIDecoder, - macros::abigen, + //core::codec::ABIDecoder, // TODO: @hal3e temporarily disabled + //macros::abigen, // TODO: @hal3e temporarily disabled types::{errors::Result, param_types::ParamType, SizedAsciiString}, }; From db7de207dffe73d23cb66ef5a1ceee58b75312a6 Mon Sep 17 00:00:00 2001 From: hal3e Date: Wed, 27 Mar 2024 10:23:49 +0100 Subject: [PATCH 23/30] pr comments --- packages/fuels-core/src/codec/abi_decoder.rs | 1 - packages/fuels-core/src/codec/abi_encoder/bounded_encoder.rs | 2 -- .../src/codec/abi_encoder/experimental_bounded_encoder.rs | 2 -- 3 files changed, 5 deletions(-) diff --git a/packages/fuels-core/src/codec/abi_decoder.rs b/packages/fuels-core/src/codec/abi_decoder.rs index f997dfca46..d51bc33f9e 100644 --- a/packages/fuels-core/src/codec/abi_decoder.rs +++ b/packages/fuels-core/src/codec/abi_decoder.rs @@ -570,7 +570,6 @@ mod tests { Ok(()) } - #[cfg(not(experimental))] #[test] fn enums_with_all_unit_variants_are_decoded_from_one_word() -> Result<()> { let data = [0, 0, 0, 0, 0, 0, 0, 1]; diff --git a/packages/fuels-core/src/codec/abi_encoder/bounded_encoder.rs b/packages/fuels-core/src/codec/abi_encoder/bounded_encoder.rs index 9abd009790..7d2087d5f6 100644 --- a/packages/fuels-core/src/codec/abi_encoder/bounded_encoder.rs +++ b/packages/fuels-core/src/codec/abi_encoder/bounded_encoder.rs @@ -36,8 +36,6 @@ impl BoundedEncoder { } } - /// Encodes `Token`s in `args` following the ABI specs defined - /// [here](https://github.com/FuelLabs/fuel-specs/blob/master/specs/protocol/abi.md) pub fn encode(&mut self, args: &[Token]) -> Result { // Checking that the tokens can be encoded is not done here, because it would require // going through the whole array of tokens, which can be pretty inefficient. diff --git a/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs b/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs index 0fc33ce7ee..7c1db32868 100644 --- a/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs +++ b/packages/fuels-core/src/codec/abi_encoder/experimental_bounded_encoder.rs @@ -27,8 +27,6 @@ impl ExperimentalBoundedEncoder { } } - /// Encodes `Token`s in `args` following the ABI specs defined - /// [here](https://github.com/FuelLabs/fuel-specs/blob/master/specs/protocol/abi.md) pub fn encode(&mut self, args: &[Token]) -> Result { let data = vec![Data::Inline(self.encode_tokens(args)?)]; From 65135c63bb3f2d55cd2950365f4ba403802f75fd Mon Sep 17 00:00:00 2001 From: hal3e Date: Wed, 27 Mar 2024 10:59:55 +0100 Subject: [PATCH 24/30] use feature flag --- examples/contracts/Cargo.toml | 1 + examples/contracts/src/lib.rs | 10 +- examples/debugging/Cargo.toml | 3 + examples/debugging/src/lib.rs | 12 +-- packages/fuels-core/Cargo.toml | 1 + packages/fuels-core/src/codec.rs | 4 +- packages/fuels-core/src/codec/abi_decoder.rs | 54 +++++------ .../codec/abi_decoder/decode_as_debug_str.rs | 4 +- packages/fuels-core/src/codec/abi_encoder.rs | 92 +++++++++---------- .../fuels-core/src/codec/function_selector.rs | 22 ++--- packages/fuels-core/src/codec/logs.rs | 4 +- packages/fuels-core/src/types.rs | 4 +- .../src/types/param_types/param_type.rs | 4 +- packages/fuels-programs/Cargo.toml | 1 + packages/fuels-programs/src/call_utils.rs | 34 +++---- packages/fuels-programs/src/contract.rs | 6 +- packages/fuels-programs/src/receipt_parser.rs | 12 +-- packages/fuels/Cargo.toml | 1 + packages/fuels/tests/bindings.rs | 28 +++--- packages/fuels/tests/contracts.rs | 12 +-- packages/fuels/tests/from_token.rs | 6 +- packages/fuels/tests/logs.rs | 6 +- packages/fuels/tests/predicates.rs | 8 +- packages/fuels/tests/providers.rs | 4 +- packages/fuels/tests/types_contracts.rs | 6 +- packages/fuels/tests/types_scripts.rs | 2 +- 26 files changed, 174 insertions(+), 167 deletions(-) diff --git a/examples/contracts/Cargo.toml b/examples/contracts/Cargo.toml index 0a02a9290c..dabd063d66 100644 --- a/examples/contracts/Cargo.toml +++ b/examples/contracts/Cargo.toml @@ -17,3 +17,4 @@ tokio = { workspace = true, features = ["full"] } [features] fuel-core-lib = ["fuels/fuel-core-lib"] rocksdb = ["fuels/rocksdb"] +experimental = ["fuels/experimental"] diff --git a/examples/contracts/src/lib.rs b/examples/contracts/src/lib.rs index d51da7aac0..d365e9d2db 100644 --- a/examples/contracts/src/lib.rs +++ b/examples/contracts/src/lib.rs @@ -107,9 +107,9 @@ mod tests { .await?; // ANCHOR_END: contract_call_cost_estimation - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let expected_gas = 795; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let expected_gas = 2086; assert_eq!(transaction_cost.gas_used, expected_gas); @@ -607,9 +607,9 @@ mod tests { .await?; // ANCHOR_END: multi_call_cost_estimation - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let expected_gas = 1170; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let expected_gas = 3511; assert_eq!(transaction_cost.gas_used, expected_gas); @@ -686,8 +686,8 @@ mod tests { Ok(()) } - #[cfg(not(experimental))] #[tokio::test] + #[cfg(not(feature = "experimental"))] async fn low_level_call_example() -> Result<()> { use fuels::{ core::codec::{calldata, fn_selector}, diff --git a/examples/debugging/Cargo.toml b/examples/debugging/Cargo.toml index 68d1780837..5c4f7c89f5 100644 --- a/examples/debugging/Cargo.toml +++ b/examples/debugging/Cargo.toml @@ -15,3 +15,6 @@ fuels = { workspace = true } rand = { workspace = true } serde_json = { workspace = true } tokio = { workspace = true, features = ["full"] } + +[features] +experimental = ["fuels/experimental"] diff --git a/examples/debugging/src/lib.rs b/examples/debugging/src/lib.rs index c62744d608..b976059370 100644 --- a/examples/debugging/src/lib.rs +++ b/examples/debugging/src/lib.rs @@ -3,7 +3,7 @@ mod tests { use std::collections::HashMap; use fuel_abi_types::abi::program::ProgramABI; - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] use fuels::core::codec::{calldata, fn_selector}; use fuels::{ //core::codec::ABIDecoder, // TODO: @hal3e temporarily disabled @@ -11,7 +11,7 @@ mod tests { types::{errors::Result, param_types::ParamType, SizedAsciiString}, }; - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] #[test] fn get_a_fn_selector() { use fuels::core::{codec::resolve_fn_selector, traits::Parameterize}; @@ -27,7 +27,7 @@ mod tests { // ANCHOR_END: example_fn_selector } - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] #[test] fn a_fn_selector_from_json_abi() -> Result<()> { use fuels::core::codec::resolve_fn_selector; @@ -65,7 +65,7 @@ mod tests { Ok(()) } - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] #[test] fn test_macros() -> Result<()> { let function_selector = fn_selector!(initialize_counter(u64)); @@ -167,9 +167,9 @@ mod tests { // let expected_u8 = 1; - // #[cfg(not(experimental))] + // #[cfg(not(feature = "experimental"))] // let data = [0, 0, 0, 0, 0, 0, 0, 1]; - // #[cfg(experimental)] + // #[cfg(feature = "experimental")] // let data = [1]; // assert_eq!( diff --git a/packages/fuels-core/Cargo.toml b/packages/fuels-core/Cargo.toml index c9b2dfe5c1..02f0a559ac 100644 --- a/packages/fuels-core/Cargo.toml +++ b/packages/fuels-core/Cargo.toml @@ -37,3 +37,4 @@ tokio = { workspace = true, features = ["test-util", "macros"] } [features] default = ["std"] std = ["dep:fuel-core-client"] +experimental = [] diff --git a/packages/fuels-core/src/codec.rs b/packages/fuels-core/src/codec.rs index e1dacba4c2..b33c519707 100644 --- a/packages/fuels-core/src/codec.rs +++ b/packages/fuels-core/src/codec.rs @@ -34,9 +34,9 @@ mod tests { #[test] fn can_convert_bytes_into_tuple() -> Result<()> { - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let tuple_in_bytes: Vec = vec![0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2]; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let tuple_in_bytes: Vec = vec![0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2]; let the_tuple: (u64, u32) = try_from_bytes(&tuple_in_bytes, DecoderConfig::default())?; diff --git a/packages/fuels-core/src/codec/abi_decoder.rs b/packages/fuels-core/src/codec/abi_decoder.rs index d51bc33f9e..4901f0a756 100644 --- a/packages/fuels-core/src/codec/abi_decoder.rs +++ b/packages/fuels-core/src/codec/abi_decoder.rs @@ -1,12 +1,12 @@ -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] mod bounded_decoder; mod decode_as_debug_str; -#[cfg(experimental)] +#[cfg(feature = "experimental")] mod experimental_bounded_decoder; -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] use crate::codec::abi_decoder::bounded_decoder::BoundedDecoder; -#[cfg(experimental)] +#[cfg(feature = "experimental")] use crate::codec::abi_decoder::experimental_bounded_decoder::BoundedDecoder; use crate::{ codec::abi_decoder::decode_as_debug_str::decode_as_debug_str, @@ -129,9 +129,9 @@ mod tests { #[test] fn decode_int() -> Result<()> { - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let data = [0, 0, 0, 0, 255, 255, 255, 255]; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let data = [255, 255, 255, 255]; let decoded = ABIDecoder::default().decode(&ParamType::U32, &data)?; @@ -152,7 +152,7 @@ mod tests { ParamType::U256, ]; - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let data = [ 0, 0, 0, 0, 255, 255, 255, 255, // u32 255, // u8 @@ -163,7 +163,7 @@ mod tests { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // u256 ]; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let data = [ 255, 255, 255, 255, // u32 255, // u8 @@ -221,13 +221,13 @@ mod tests { #[test] fn decode_string_array() -> Result<()> { let types = vec![ParamType::StringArray(23), ParamType::StringArray(5)]; - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let data = [ 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, 116, 101, 110, 99, 101, 0, //This is a full sentence 72, 101, 108, 108, 111, 0, 0, 0, // Hello ]; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let data = [ 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, 116, 101, 110, 99, 101, //This is a full sentence @@ -252,12 +252,12 @@ mod tests { #[test] fn decode_string_slice() -> Result<()> { let types = vec![ParamType::StringSlice]; - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let data = [ 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, 116, 101, 110, 99, 101, //This is a full sentence ]; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let data = [ 0, 0, 0, 0, 0, 0, 0, 23, // [length] 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, @@ -296,9 +296,9 @@ mod tests { // bar: bool, // } - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let data = [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let data = [1, 1]; let param_type = ParamType::Struct { @@ -318,9 +318,9 @@ mod tests { #[test] fn decode_bytes() -> Result<()> { - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let data = [255, 0, 1, 2, 3, 4, 5]; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let data = [0, 0, 0, 0, 0, 0, 0, 7, 255, 0, 1, 2, 3, 4, 5]; let decoded = ABIDecoder::default().decode(&ParamType::Bytes, &data)?; @@ -348,9 +348,9 @@ mod tests { }]; // "0" discriminant and 42 enum value - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42]; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42]; let decoded = ABIDecoder::default().decode_multiple(&types, &data)?; @@ -361,7 +361,7 @@ mod tests { Ok(()) } - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] #[test] fn decoder_will_skip_enum_padding_and_decode_next_arg() -> Result<()> { // struct MyStruct { @@ -446,11 +446,11 @@ mod tests { generics: vec![], }; - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let data = [ 0, 0, 0, 0, 0, 0, 0, 10, 1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, ]; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let data = [0, 10, 1, 1, 2]; let decoded = ABIDecoder::default().decode(&nested_struct, &data)?; @@ -505,7 +505,7 @@ mod tests { let types = [nested_struct, u8_arr, b256]; - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let bytes = [ 0, 0, 0, 0, 0, 0, 0, 10, // u16 1, 0, 0, 0, 0, 0, 0, 0, // bool @@ -515,7 +515,7 @@ mod tests { 152, 244, 172, 69, 123, 168, 248, 39, 67, 243, 30, 147, 11, // b256 ]; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let bytes = [ 0, 10, // u16 1, // bool @@ -550,7 +550,7 @@ mod tests { Ok(()) } - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] #[test] fn units_in_structs_are_decoded_as_one_word() -> Result<()> { let data = [ @@ -687,7 +687,7 @@ mod tests { assert!(matches!(result, Err(Error::Codec(_)))); } - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] #[test] fn decoding_enum_with_more_than_one_heap_type_variant_fails() -> Result<()> { let mut param_types = vec![ @@ -727,7 +727,7 @@ mod tests { Ok(()) } - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] #[test] fn enums_w_too_deeply_nested_heap_types_not_allowed() { let variants = to_named(&[ @@ -845,7 +845,7 @@ mod tests { } } - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] #[test] fn vectors_of_zst_are_not_supported() { let param_type = ParamType::Vector(Box::new(ParamType::StringArray(0))); diff --git a/packages/fuels-core/src/codec/abi_decoder/decode_as_debug_str.rs b/packages/fuels-core/src/codec/abi_decoder/decode_as_debug_str.rs index a3e54d2074..75f1082a1f 100644 --- a/packages/fuels-core/src/codec/abi_decoder/decode_as_debug_str.rs +++ b/packages/fuels-core/src/codec/abi_decoder/decode_as_debug_str.rs @@ -104,7 +104,7 @@ mod tests { }, }; - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] #[test] fn param_type_decode_debug() -> Result<()> { let decoder = ABIDecoder::default(); @@ -261,7 +261,7 @@ mod tests { Ok(()) } - #[cfg(experimental)] + #[cfg(feature = "experimental")] #[test] fn param_type_decode_debug() -> Result<()> { let decoder = ABIDecoder::default(); diff --git a/packages/fuels-core/src/codec/abi_encoder.rs b/packages/fuels-core/src/codec/abi_encoder.rs index d1bb816924..e586fba250 100644 --- a/packages/fuels-core/src/codec/abi_encoder.rs +++ b/packages/fuels-core/src/codec/abi_encoder.rs @@ -1,10 +1,10 @@ mod bounded_encoder; -#[cfg(experimental)] +#[cfg(feature = "experimental")] mod experimental_bounded_encoder; use std::default::Default; -#[cfg(experimental)] +#[cfg(feature = "experimental")] use crate::codec::abi_encoder::experimental_bounded_encoder::ExperimentalBoundedEncoder; use crate::{ codec::abi_encoder::bounded_encoder::BoundedEncoder, @@ -49,9 +49,9 @@ impl ABIEncoder { /// Encodes `Token`s in `args` following the ABI specs defined /// [here](https://github.com/FuelLabs/fuel-specs/blob/master/specs/protocol/abi.md) pub fn encode(&self, args: &[Token]) -> Result { - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let res = BoundedEncoder::new(self.config, false).encode(args); - #[cfg(experimental)] + #[cfg(feature = "experimental")] let res = ExperimentalBoundedEncoder::new(self.config, false).encode(args); res @@ -79,15 +79,15 @@ impl ConfigurablesEncoder { mod tests { use std::slice; - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] use itertools::chain; - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] use sha2::{Digest, Sha256}; use super::*; - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] use crate::codec::first_four_bytes_of_sha256_hash; - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] use crate::constants::WORD_SIZE; use crate::{ to_named, @@ -98,13 +98,13 @@ mod tests { }, }; - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] const VEC_METADATA_SIZE: usize = 3 * WORD_SIZE; - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] const DISCRIMINANT_SIZE: usize = WORD_SIZE; #[test] - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] fn encode_function_signature() { let fn_signature = "entry_one(u64)"; @@ -116,7 +116,7 @@ mod tests { } #[test] - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] fn encode_function_with_u32_type() -> Result<()> { // @todo eventually we must update the json abi examples in here. // They're in the old format. @@ -154,7 +154,7 @@ mod tests { } #[test] - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] fn encode_function_with_u32_type_multiple_args() -> Result<()> { // let json_abi = // r#" @@ -191,7 +191,7 @@ mod tests { } #[test] - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] fn encode_function_with_u64_type() -> Result<()> { // let json_abi = // r#" @@ -226,7 +226,7 @@ mod tests { } #[test] - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] fn encode_function_with_bool_type() -> Result<()> { // let json_abi = // r#" @@ -261,7 +261,7 @@ mod tests { } #[test] - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] fn encode_function_with_two_different_type() -> Result<()> { // let json_abi = // r#" @@ -301,7 +301,7 @@ mod tests { } #[test] - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] fn encode_function_with_bits256_type() -> Result<()> { // let json_abi = // r#" @@ -346,7 +346,7 @@ mod tests { } #[test] - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] fn encode_function_with_array_type() -> Result<()> { // let json_abi = // r#" @@ -388,7 +388,7 @@ mod tests { } #[test] - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] fn encode_function_with_string_array_type() -> Result<()> { // let json_abi = // r#" @@ -428,7 +428,7 @@ mod tests { } #[test] - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] fn encode_function_with_string_slice_type() -> Result<()> { // let json_abi = // r#" @@ -471,7 +471,7 @@ mod tests { } #[test] - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] fn encode_function_with_struct() -> Result<()> { // let json_abi = // r#" @@ -521,7 +521,7 @@ mod tests { } #[test] - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] fn encode_function_with_enum() -> Result<()> { // let json_abi = // r#" @@ -570,7 +570,7 @@ mod tests { } // The encoding follows the ABI specs defined [here](https://github.com/FuelLabs/fuel-specs/blob/master/specs/protocol/abi.md) - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] #[test] fn enums_are_sized_to_fit_the_biggest_variant() -> Result<()> { // Our enum has two variants: B256, and U64. So the enum will set aside @@ -655,7 +655,7 @@ mod tests { .encode(slice::from_ref(&top_level_enum_token))? .resolve(0); - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let expected = [ 0, 0, 0, 0, 0, 0, 0, 0, // TopLevelEnum::v1 discriminant 0, 0, 0, 0, 0, 0, 0, 1, // DeeperEnum::v2 discriminant @@ -663,7 +663,7 @@ mod tests { 0, 0, 0, 0, 0, 0, // DeeperEnum padding 0, 0, 0, 0, 0, 0, 44, 68, // StructA.some_number ]; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let expected = [ 0, 0, 0, 0, 0, 0, 0, 0, // TopLevelEnum::v1 discriminant 0, 0, 0, 0, 0, 0, 0, 1, // DeeperEnum::v2 discriminant @@ -677,7 +677,7 @@ mod tests { } #[test] - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] fn encode_function_with_nested_structs() -> Result<()> { // let json_abi = // r#" @@ -733,7 +733,7 @@ mod tests { } #[test] - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] fn encode_comprehensive_function() -> Result<()> { // let json_abi = // r#" @@ -845,7 +845,7 @@ mod tests { Ok(()) } - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] #[test] fn units_in_composite_types_are_encoded_in_one_word() -> Result<()> { let expected = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5]; @@ -858,7 +858,7 @@ mod tests { Ok(()) } - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] #[test] fn enums_with_units_are_correctly_padded() -> Result<()> { let discriminant = vec![0, 0, 0, 0, 0, 0, 0, 1]; @@ -876,7 +876,7 @@ mod tests { Ok(()) } - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] #[test] fn vector_has_ptr_cap_len_and_then_data() -> Result<()> { // arrange @@ -901,7 +901,7 @@ mod tests { Ok(()) } - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] #[test] fn data_from_two_vectors_aggregated_at_the_end() -> Result<()> { // arrange @@ -952,7 +952,7 @@ mod tests { .resolve(offset as u64); // assert - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let expected = { let discriminant = vec![0, 0, 0, 0, 0, 0, 0, 1]; @@ -975,7 +975,7 @@ mod tests { ) .collect::>() }; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let expected = [ 0, 0, 0, 0, 0, 0, 0, 1, // enum dicsriminant 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5, // vec[len, u64] @@ -1003,7 +1003,7 @@ mod tests { .resolve(offset as u64); // assert - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let expected = { const PADDING: usize = std::mem::size_of::<[u8; 32]>() - WORD_SIZE; @@ -1016,7 +1016,7 @@ mod tests { chain!(vec1_ptr, vec1_cap, vec1_len, vec1_data).collect::>() }; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let expected = [ 0, 0, 0, 0, 0, 0, 0, 1, // vec len 0, 0, 0, 0, 0, 0, 0, 1, 8, // enum discriminant and u8 value @@ -1039,7 +1039,7 @@ mod tests { .resolve(offset as u64); // assert - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let expected = { let vec1_ptr = ((VEC_METADATA_SIZE + WORD_SIZE + offset) as u64) .to_be_bytes() @@ -1050,7 +1050,7 @@ mod tests { chain!(vec1_ptr, vec1_cap, vec1_len, [9], [0; 7], vec1_data).collect::>() }; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let expected = [ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5, // vec[len, u64] 9, // u8 @@ -1073,7 +1073,7 @@ mod tests { .resolve(offset as u64); // assert - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let expected = { let vec1_data_offset = (VEC_METADATA_SIZE + offset) as u64; let vec1_ptr = vec1_data_offset.to_be_bytes().to_vec(); @@ -1091,7 +1091,7 @@ mod tests { chain!(vec1_ptr, vec1_cap, vec1_len, vec1_data).collect::>() }; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let expected = [ 0, 0, 0, 0, 0, 0, 0, 1, // vec1 len 0, 0, 0, 0, 0, 0, 0, 2, 5, 6, // vec2 [len, u8, u8] @@ -1112,7 +1112,7 @@ mod tests { let result = ABIEncoder::default().encode(&[token])?.resolve(offset); // assert - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let expected = { let ptr = [0, 0, 0, 0, 0, 0, 0, 64]; let cap = [0, 0, 0, 0, 0, 0, 0, 8]; @@ -1121,7 +1121,7 @@ mod tests { [ptr, cap, len, data].concat() }; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let expected = [0, 0, 0, 0, 0, 0, 0, 3, 1, 2, 3]; // bytes[len, u8, u8, u8] assert_eq!(result, expected); @@ -1139,7 +1139,7 @@ mod tests { let result = ABIEncoder::default().encode(&[token])?.resolve(offset); // assert - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let expected = { let ptr = [0, 0, 0, 0, 0, 0, 0, 56].to_vec(); let len = [0, 0, 0, 0, 0, 0, 0, 3].to_vec(); @@ -1148,7 +1148,7 @@ mod tests { [ptr, len, data, padding].concat() }; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let expected = [0, 0, 0, 0, 0, 0, 0, 3, 1, 2, 3]; // raw_slice[len, u8, u8, u8] assert_eq!(result, expected); @@ -1167,7 +1167,7 @@ mod tests { let result = ABIEncoder::default().encode(&[token])?.resolve(offset); // assert - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let expected = { let ptr = [0, 0, 0, 0, 0, 0, 0, 64]; let cap = [0, 0, 0, 0, 0, 0, 0, 8]; @@ -1176,7 +1176,7 @@ mod tests { [ptr, cap, len, data].concat() }; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let expected = [0, 0, 0, 0, 0, 0, 0, 5, 84, 104, 105, 115, 32]; // string[len, data] assert_eq!(result, expected); @@ -1206,7 +1206,7 @@ mod tests { Ok(()) } - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] #[test] fn capacity_overflow_is_caught() -> Result<()> { let token = Token::Enum(Box::new(( diff --git a/packages/fuels-core/src/codec/function_selector.rs b/packages/fuels-core/src/codec/function_selector.rs index 3d3ed20918..2a82d89174 100644 --- a/packages/fuels-core/src/codec/function_selector.rs +++ b/packages/fuels-core/src/codec/function_selector.rs @@ -1,13 +1,13 @@ -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] use sha2::{Digest, Sha256}; -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] use crate::types::param_types::NamedParamType; use crate::types::param_types::ParamType; -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] use crate::types::ByteArray; -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] /// Given a function name and its inputs will return a ByteArray representing /// the function selector as specified in the Fuel specs. pub fn resolve_fn_selector(name: &str, inputs: &[ParamType]) -> ByteArray { @@ -16,7 +16,7 @@ pub fn resolve_fn_selector(name: &str, inputs: &[ParamType]) -> ByteArray { first_four_bytes_of_sha256_hash(&fn_signature) } -#[cfg(experimental)] +#[cfg(feature = "experimental")] pub fn resolve_fn_selector(name: &str, _inputs: &[ParamType]) -> Vec { let bytes = name.as_bytes().to_vec(); let len = bytes.len() as u64; @@ -24,19 +24,19 @@ pub fn resolve_fn_selector(name: &str, _inputs: &[ParamType]) -> Vec { [len.to_be_bytes().to_vec(), bytes].concat() } -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] fn resolve_fn_signature(name: &str, inputs: &[ParamType]) -> String { let fn_args = resolve_args(inputs); format!("{name}({fn_args})") } -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] fn resolve_args(args: &[ParamType]) -> String { args.iter().map(resolve_arg).collect::>().join(",") } -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] fn resolve_named_args(args: &[NamedParamType]) -> String { args.iter() .map(|(_, param_type)| resolve_arg(param_type)) @@ -44,7 +44,7 @@ fn resolve_named_args(args: &[NamedParamType]) -> String { .join(",") } -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] fn resolve_arg(arg: &ParamType) -> String { match &arg { ParamType::U8 => "u8".to_owned(), @@ -104,7 +104,7 @@ fn resolve_arg(arg: &ParamType) -> String { } } -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] /// Hashes an encoded function selector using SHA256 and returns the first 4 bytes. /// The function selector has to have been already encoded following the ABI specs defined /// [here](https://github.com/FuelLabs/fuel-specs/blob/1be31f70c757d8390f74b9e1b3beb096620553eb/specs/protocol/abi.md) @@ -142,7 +142,7 @@ macro_rules! calldata { pub use calldata; -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] #[cfg(test)] mod tests { use super::*; diff --git a/packages/fuels-core/src/codec/logs.rs b/packages/fuels-core/src/codec/logs.rs index a763378e86..7ca63bc1c4 100644 --- a/packages/fuels-core/src/codec/logs.rs +++ b/packages/fuels-core/src/codec/logs.rs @@ -31,7 +31,7 @@ impl LogFormatter { decoder_config: DecoderConfig, bytes: &[u8], ) -> Result { - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] Self::can_decode_log_with_type::()?; let token = ABIDecoder::new(decoder_config).decode(&T::param_type(), bytes)?; @@ -39,7 +39,7 @@ impl LogFormatter { Ok(format!("{:?}", T::from_token(token)?)) } - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] fn can_decode_log_with_type() -> Result<()> { use crate::types::param_types::ParamType; diff --git a/packages/fuels-core/src/types.rs b/packages/fuels-core/src/types.rs index 75fe20e6ef..836b57246e 100644 --- a/packages/fuels-core/src/types.rs +++ b/packages/fuels-core/src/types.rs @@ -17,9 +17,9 @@ pub mod unresolved_bytes; mod wrappers; pub type ByteArray = [u8; 8]; -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] pub type Selector = ByteArray; -#[cfg(experimental)] +#[cfg(feature = "experimental")] pub type Selector = Vec; /// Converts a u16 to a right aligned array of 8 bytes. diff --git a/packages/fuels-core/src/types/param_types/param_type.rs b/packages/fuels-core/src/types/param_types/param_type.rs index bc7ee9cc06..ddca1530e4 100644 --- a/packages/fuels-core/src/types/param_types/param_type.rs +++ b/packages/fuels-core/src/types/param_types/param_type.rs @@ -50,7 +50,7 @@ impl ParamType { // Depending on the type, the returned value will be stored // either in `Return` or `ReturnData`. pub fn get_return_location(&self) -> ReturnLocation { - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] match self { Self::Unit | Self::U8 | Self::U16 | Self::U32 | Self::U64 | Self::Bool => { ReturnLocation::Return @@ -59,7 +59,7 @@ impl ParamType { _ => ReturnLocation::ReturnData, } - #[cfg(experimental)] + #[cfg(feature = "experimental")] ReturnLocation::ReturnData } diff --git a/packages/fuels-programs/Cargo.toml b/packages/fuels-programs/Cargo.toml index 64116ac7fd..9dc5ff1ff8 100644 --- a/packages/fuels-programs/Cargo.toml +++ b/packages/fuels-programs/Cargo.toml @@ -29,3 +29,4 @@ tempfile = "3.8.1" [features] default = ["std"] std = ["fuels-core/std", "fuels-accounts/std"] +experimental = ["fuels-core/experimental"] diff --git a/packages/fuels-programs/src/call_utils.rs b/packages/fuels-programs/src/call_utils.rs index 837512d05d..7d359dc40c 100644 --- a/packages/fuels-programs/src/call_utils.rs +++ b/packages/fuels-programs/src/call_utils.rs @@ -244,7 +244,7 @@ pub(crate) fn get_instructions( }) } -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] /// Returns script data, consisting of the following items in the given order: /// 1. Amount to be forwarded `(1 * `[`WORD_SIZE`]`)` /// 2. Asset ID to be forwarded ([`AssetId::LEN`]) @@ -324,7 +324,7 @@ pub(crate) fn build_script_data_from_contract_calls( Ok((script_data, param_offsets)) } -#[cfg(experimental)] +#[cfg(feature = "experimental")] /// Returns script data, consisting of the following items in the given order: /// 1. Amount to be forwarded `(1 * `[`WORD_SIZE`]`)` /// 2. Asset ID to be forwarded ([`AssetId::LEN`]) @@ -440,14 +440,14 @@ pub(crate) fn get_single_call_instructions( None => instructions.push(op::call(0x10, 0x11, 0x12, RegId::CGAS)), }; - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] instructions.extend(extract_heap_data(_output_param_type)?); #[allow(clippy::iter_cloned_collect)] Ok(instructions.into_iter().collect::>()) } -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] fn extract_heap_data(param_type: &ParamType) -> Result> { match param_type { ParamType::Enum { enum_variants, .. } => { @@ -483,7 +483,7 @@ fn extract_heap_data(param_type: &ParamType) -> Result Vec { mod test { use std::slice; - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] use fuel_types::bytes::WORD_SIZE; use fuels_accounts::wallet::WalletUnlocked; use fuels_core::types::{ @@ -665,7 +665,7 @@ mod test { coin::{Coin, CoinStatus}, coin_type::CoinType, }; - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] use fuels_core::{codec::ABIEncoder, types::Token}; use rand::Rng; @@ -677,9 +677,9 @@ mod test { ContractCall { contract_id: random_bech32_contract_id(), encoded_args: Ok(Default::default()), - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] encoded_selector: [0; 8], - #[cfg(experimental)] + #[cfg(feature = "experimental")] encoded_selector: [0; 8].to_vec(), call_parameters: Default::default(), compute_custom_input_offset: false, @@ -700,7 +700,7 @@ mod test { Bech32ContractId::new("fuel", rand::thread_rng().gen::<[u8; 32]>()) } - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] #[tokio::test] async fn test_script_data() { // Arrange @@ -730,9 +730,9 @@ mod test { let calls: Vec = (0..NUM_CALLS) .map(|i| ContractCall { contract_id: contract_ids[i].clone(), - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] encoded_selector: selectors[i], - #[cfg(experimental)] + #[cfg(feature = "experimental")] encoded_selector: selectors[i].to_vec(), encoded_args: Ok(args[i].clone()), call_parameters: CallParameters::new(i as u64, asset_ids[i], i as u64), @@ -1028,10 +1028,10 @@ mod test { const BASE_INSTRUCTION_COUNT: usize = 5; // 2 instructions (movi and lw) added in get_single_call_instructions when gas_offset is set const GAS_OFFSET_INSTRUCTION_COUNT: usize = 2; - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] // 4 instructions (lw, lw, muli, retd) added by extract_data_receipt const EXTRACT_DATA_RECEIPT_INSTRUCTION_COUNT: usize = 4; - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] // 4 instructions (movi, lw, jnef, retd) added by extract_heap_data const EXTRACT_HEAP_DATA_INSTRUCTION_COUNT: usize = 4; @@ -1053,7 +1053,7 @@ mod test { ); } - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] #[test] fn test_with_heap_type() { let output_params = vec![ @@ -1073,7 +1073,7 @@ mod test { } } - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] #[test] fn test_with_gas_offset_and_heap_type() { let mut call = ContractCall::new_with_random_id(); @@ -1090,7 +1090,7 @@ mod test { ); } - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] #[test] fn test_with_enum_with_heap_and_non_heap_variant() { let variant_sets = vec![ diff --git a/packages/fuels-programs/src/contract.rs b/packages/fuels-programs/src/contract.rs index a6fc6269e7..d0d388370d 100644 --- a/packages/fuels-programs/src/contract.rs +++ b/packages/fuels-programs/src/contract.rs @@ -726,9 +726,9 @@ pub fn method_hash( let tx_policies = TxPolicies::default(); let call_parameters = CallParameters::default(); - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let compute_custom_input_offset = should_compute_custom_input_offset(args); - #[cfg(experimental)] + #[cfg(feature = "experimental")] let compute_custom_input_offset = true; let unresolved_bytes = ABIEncoder::new(encoder_config).encode(args); @@ -759,7 +759,7 @@ pub fn method_hash( // If the data passed into the contract method is an integer or a // boolean, then the data itself should be passed. Otherwise, it // should simply pass a pointer to the data in memory. -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] fn should_compute_custom_input_offset(args: &[Token]) -> bool { args.len() > 1 || args.iter().any(|t| { diff --git a/packages/fuels-programs/src/receipt_parser.rs b/packages/fuels-programs/src/receipt_parser.rs index d31a61cca8..4c61ca21c7 100644 --- a/packages/fuels-programs/src/receipt_parser.rs +++ b/packages/fuels-programs/src/receipt_parser.rs @@ -43,7 +43,7 @@ impl ReceiptParser { // During a script execution, the script's contract id is the **null** contract id .unwrap_or_else(ContractId::zeroed); - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] output_param.validate_is_decodable(self.decoder.config.max_depth)?; let data = self @@ -65,9 +65,9 @@ impl ReceiptParser { output_param: &ParamType, contract_id: &ContractId, ) -> Option> { - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let extra_receipts_needed = output_param.is_extra_receipt_needed(true); - #[cfg(experimental)] + #[cfg(feature = "experimental")] let extra_receipts_needed = false; match output_param.get_return_location() { @@ -324,9 +324,9 @@ mod tests { let contract_id = target_contract(); let mut receipts = expected_receipts.clone(); - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] receipts.push(get_return_receipt(contract_id, RECEIPT_VAL)); - #[cfg(experimental)] // all data is returned as RETD + #[cfg(feature = "experimental")] // all data is returned as RETD receipts.push(get_return_data_receipt( contract_id, &RECEIPT_VAL.to_be_bytes(), @@ -343,7 +343,7 @@ mod tests { Ok(()) } - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] #[tokio::test] async fn receipt_parser_extract_return_data_heap() -> Result<()> { let expected_receipts = get_relevant_receipts(); diff --git a/packages/fuels/Cargo.toml b/packages/fuels/Cargo.toml index 4a213e9a64..99b296b25f 100644 --- a/packages/fuels/Cargo.toml +++ b/packages/fuels/Cargo.toml @@ -40,6 +40,7 @@ tai64 = { workspace = true } [features] default = ["std", "fuels-test-helpers?/fuels-accounts", "coin-cache"] coin-cache = ["fuels-accounts/coin-cache"] +experimental = ["fuels-core/experimental", "fuels-programs/experimental"] # The crates enabled via `dep:` below are not currently wasm compatible, as # such they are only available if `std` is enabled. The `dep:` syntax was diff --git a/packages/fuels/tests/bindings.rs b/packages/fuels/tests/bindings.rs index edc76b63da..8ca5011778 100644 --- a/packages/fuels/tests/bindings.rs +++ b/packages/fuels/tests/bindings.rs @@ -1,14 +1,14 @@ -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] use std::slice; use std::str::FromStr; use fuels::prelude::*; -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] use fuels::{ core::{codec::ABIEncoder, traits::Tokenizable}, types::{Bits256, EvmAddress}, }; -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] use sha2::{Digest, Sha256}; pub fn null_contract_id() -> Bech32ContractId { @@ -17,7 +17,7 @@ pub fn null_contract_id() -> Bech32ContractId { .unwrap() } -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] #[tokio::test] async fn compile_bindings_from_contract_file() { // Generates the bindings from an ABI definition in a JSON file @@ -49,7 +49,7 @@ async fn compile_bindings_from_contract_file() { assert_eq!("000000005f68ee3d000000000000002a", encoded); } -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] #[tokio::test] async fn compile_bindings_from_inline_contract() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -110,7 +110,7 @@ async fn compile_bindings_from_inline_contract() -> Result<()> { Ok(()) } -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] #[tokio::test] async fn compile_bindings_array_input() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -188,7 +188,7 @@ async fn compile_bindings_array_input() -> Result<()> { Ok(()) } -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] #[tokio::test] async fn compile_bindings_bool_array_input() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -263,7 +263,7 @@ async fn compile_bindings_bool_array_input() -> Result<()> { Ok(()) } -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] #[tokio::test] async fn compile_bindings_string_input() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -334,7 +334,7 @@ async fn compile_bindings_string_input() -> Result<()> { Ok(()) } -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] #[tokio::test] async fn compile_bindings_b256_input() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -406,7 +406,7 @@ async fn compile_bindings_b256_input() -> Result<()> { Ok(()) } -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] #[tokio::test] async fn compile_bindings_evm_address_input() -> Result<()> { abigen!(Contract( @@ -477,7 +477,7 @@ async fn compile_bindings_evm_address_input() -> Result<()> { Ok(()) } -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] #[tokio::test] async fn compile_bindings_struct_input() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -580,7 +580,7 @@ async fn compile_bindings_struct_input() -> Result<()> { Ok(()) } -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] #[tokio::test] async fn compile_bindings_nested_struct_input() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -689,7 +689,7 @@ async fn compile_bindings_nested_struct_input() -> Result<()> { Ok(()) } -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] #[tokio::test] async fn compile_bindings_enum_input() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -777,7 +777,7 @@ async fn compile_bindings_enum_input() -> Result<()> { Ok(()) } -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] #[tokio::test] async fn shared_types() -> Result<()> { setup_program_test!( diff --git a/packages/fuels/tests/contracts.rs b/packages/fuels/tests/contracts.rs index ec5ca89111..142c401d39 100644 --- a/packages/fuels/tests/contracts.rs +++ b/packages/fuels/tests/contracts.rs @@ -1,4 +1,4 @@ -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] use fuels::core::codec::{calldata, fn_selector}; use fuels::{ core::codec::{DecoderConfig, EncoderConfig}, @@ -276,14 +276,14 @@ async fn test_contract_call_fee_estimation() -> Result<()> { let tolerance = Some(0.2); let block_horizon = Some(1); - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let expected_gas_used = 954; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let expected_gas_used = 960; - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let expected_metered_bytes_size = 784; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let expected_metered_bytes_size = 824; let estimated_transaction_cost = contract_instance @@ -1227,7 +1227,7 @@ async fn multi_call_from_calls_with_different_account_types() -> Result<()> { } #[tokio::test] -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] async fn low_level_call() -> Result<()> { use fuels::types::SizedAsciiString; diff --git a/packages/fuels/tests/from_token.rs b/packages/fuels/tests/from_token.rs index f27235b4f5..73fef9c9b2 100644 --- a/packages/fuels/tests/from_token.rs +++ b/packages/fuels/tests/from_token.rs @@ -1,7 +1,7 @@ use std::str::FromStr; use fuels::prelude::*; -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] use fuels::{core::traits::Tokenizable, types::Token}; pub fn null_contract_id() -> Bech32ContractId { @@ -10,7 +10,7 @@ pub fn null_contract_id() -> Bech32ContractId { .unwrap() } -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] #[tokio::test] async fn create_struct_from_decoded_tokens() -> Result<()> { // Generates the bindings from the an ABI definition inline. @@ -105,7 +105,7 @@ async fn create_struct_from_decoded_tokens() -> Result<()> { Ok(()) } -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] #[tokio::test] async fn create_nested_struct_from_decoded_tokens() -> Result<()> { // Generates the bindings from the an ABI definition inline. diff --git a/packages/fuels/tests/logs.rs b/packages/fuels/tests/logs.rs index 746e9b96bc..5b92fc9302 100644 --- a/packages/fuels/tests/logs.rs +++ b/packages/fuels/tests/logs.rs @@ -1453,7 +1453,7 @@ async fn can_configure_decoder_for_script_log_decoding() -> Result<()> { // String slices cannot be decoded from logs as they are encoded as ptr, len // TODO: Once https://github.com/FuelLabs/sway/issues/5110 is resolved we can remove this #[tokio::test] -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] async fn string_slice_log() -> Result<()> { setup_program_test!( Wallets("wallet"), @@ -1486,7 +1486,7 @@ async fn string_slice_log() -> Result<()> { } #[tokio::test] -#[cfg(experimental)] +#[cfg(feature = "experimental")] async fn contract_experimental_log() -> Result<()> { use fuels_core::types::AsciiString; @@ -1545,7 +1545,7 @@ async fn contract_experimental_log() -> Result<()> { } #[tokio::test] -#[cfg(experimental)] +#[cfg(feature = "experimental")] async fn script_experimental_log() -> Result<()> { use fuels_core::types::AsciiString; diff --git a/packages/fuels/tests/predicates.rs b/packages/fuels/tests/predicates.rs index 615670ede0..e1ce244b03 100644 --- a/packages/fuels/tests/predicates.rs +++ b/packages/fuels/tests/predicates.rs @@ -797,12 +797,12 @@ async fn predicate_can_access_manually_added_witnesses() -> Result<()> { .build(&provider) .await?; - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let witness = ABIEncoder::default() .encode(&[64u8.into_token()])? .resolve(0); - #[cfg(experimental)] + #[cfg(feature = "experimental")] let witness = ABIEncoder::default() .encode(&[64u64.into_token()])? // u64 because this is VM memory .resolve(0); @@ -876,12 +876,12 @@ async fn tx_id_not_changed_after_adding_witnesses() -> Result<()> { let tx_id = tx.id(provider.chain_id()); - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let witness = ABIEncoder::default() .encode(&[64u8.into_token()])? .resolve(0); - #[cfg(experimental)] + #[cfg(feature = "experimental")] let witness = ABIEncoder::default() .encode(&[64u64.into_token()])? // u64 because this is VM memory .resolve(0); diff --git a/packages/fuels/tests/providers.rs b/packages/fuels/tests/providers.rs index e75794d904..688bc51726 100644 --- a/packages/fuels/tests/providers.rs +++ b/packages/fuels/tests/providers.rs @@ -324,9 +324,9 @@ async fn test_gas_forwarded_defaults_to_tx_limit() -> Result<()> { ); // The gas used by the script to call a contract and forward remaining gas limit. - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] let gas_used_by_script = 364; - #[cfg(experimental)] + #[cfg(feature = "experimental")] let gas_used_by_script = 876; let gas_limit = 225_883; let response = contract_instance diff --git a/packages/fuels/tests/types_contracts.rs b/packages/fuels/tests/types_contracts.rs index 1ea0453ef3..b089e47771 100644 --- a/packages/fuels/tests/types_contracts.rs +++ b/packages/fuels/tests/types_contracts.rs @@ -1872,7 +1872,7 @@ async fn test_composite_types_in_vec_output() -> Result<()> { Ok(()) } -#[cfg(not(experimental))] +#[cfg(not(feature = "experimental"))] #[tokio::test] async fn test_nested_vector_methods_fail() -> Result<()> { // This is just an E2E test of the method `ParamType::contains_nested_heap_types`, hence it's @@ -2166,7 +2166,7 @@ async fn test_heap_type_in_enums() -> Result<()> { assert!(resp.value.is_none()); } - #[cfg(not(experimental))] + #[cfg(not(feature = "experimental"))] { // If the LW(RET) instruction was not executed only conditionally, then the FuelVM would OOM. let _ = contract_methods @@ -2187,7 +2187,7 @@ async fn test_heap_type_in_enums() -> Result<()> { Ok(()) } -#[cfg(experimental)] +#[cfg(feature = "experimental")] #[tokio::test] async fn nested_heap_types() -> Result<()> { setup_program_test!( diff --git a/packages/fuels/tests/types_scripts.rs b/packages/fuels/tests/types_scripts.rs index 12dc459d18..0dfb184786 100644 --- a/packages/fuels/tests/types_scripts.rs +++ b/packages/fuels/tests/types_scripts.rs @@ -323,7 +323,7 @@ async fn script_handles_std_string() -> Result<()> { Ok(()) } -#[cfg(experimental)] +#[cfg(feature = "experimental")] #[tokio::test] async fn nested_heap_types() -> Result<()> { setup_program_test!( From 0fd5c786c71e162e5e32a76cbc6e0ff412aed22a Mon Sep 17 00:00:00 2001 From: hal3e Date: Wed, 27 Mar 2024 11:29:11 +0100 Subject: [PATCH 25/30] add wasm experimental test --- packages/wasm-tests/Cargo.toml | 4 ++++ packages/wasm-tests/src/lib.rs | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/packages/wasm-tests/Cargo.toml b/packages/wasm-tests/Cargo.toml index 7da0e53c4d..f332cffca8 100644 --- a/packages/wasm-tests/Cargo.toml +++ b/packages/wasm-tests/Cargo.toml @@ -18,5 +18,9 @@ crate-type = ['cdylib'] # that our examples don't inherit `fuels` with disabled features). # Cargo wouldn't respect any attempts here to disable them again. fuels = { path = "../fuels", default-features = false } +fuels-core = { path = "../fuels-core", default-features = false } getrandom = { version = "0.2.11", features = ["js"] } wasm-bindgen-test = "0.3.39" + +[features] +experimental = ["fuels-core/experimental"] diff --git a/packages/wasm-tests/src/lib.rs b/packages/wasm-tests/src/lib.rs index ad34baf7dd..c6f7f4f250 100644 --- a/packages/wasm-tests/src/lib.rs +++ b/packages/wasm-tests/src/lib.rs @@ -116,6 +116,22 @@ mod tests { .encode(&[original.clone().into_token()])? .resolve(0); + #[cfg(not(feature = "experimental"))] + let expected_bytes = [ + 0, 0, 0, 0, 0, 0, 0, 1, // enum discriminant + 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, // SomeStruct + ] + .to_vec(); + + #[cfg(feature = "experimental")] + let expected_bytes = [ + 0, 0, 0, 0, 0, 0, 0, 1, // enum discriminant + 0, 0, 0, 123, 0, // SomeStruct + ] + .to_vec(); + + assert_eq!(expected_bytes, bytes); + let reconstructed = bytes.try_into().unwrap(); assert_eq!(original, reconstructed); From b1fa647a9cc9389c590395fc84e3294520e7781b Mon Sep 17 00:00:00 2001 From: hal3e Date: Wed, 27 Mar 2024 11:29:24 +0100 Subject: [PATCH 26/30] update CI --- .github/workflows/ci.yml | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 68b7d5fdf6..7b46c3d6e5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -98,14 +98,14 @@ jobs: !packages/fuels/tests/.gitignore # TODO: To be removed once experimental encoding is the default - - name: Build Sway test projects w experimental logs + - name: Build Sway test projects w experimental encoding run: forc build --terse --error-on-warnings --json-abi-with-callpaths --experimental-new-encoding working-directory: packages/fuels - uses: actions/upload-artifact@v2 with: retention-days: 2 - name: sway-examples-w-experimental-logs + name: sway-examples-w-experimental-encoding # cache only the sway build artifacts, skip all src files path: | packages/fuels/tests @@ -202,9 +202,9 @@ jobs: - command: check_doc_unresolved_links args: # TODO: To be removed once experimental encoding is the default - - command: test_experimental_logs - args: - download_sway_artifacts: sway-examples-w-experimental-logs + - cargo_command: nextest + args: run --all-targets --features "experimental" --workspace + download_sway_artifacts: sway-examples-w-experimental-encoding install_fuel_core: true steps: - name: Checkout repository @@ -242,9 +242,8 @@ jobs: name: ${{ matrix.download_sway_artifacts }} path: packages/fuels/tests/ - # TODO: `test_experimental_logs` to be removed once experimental encoding is the default. - name: Install nextest - if: ${{ matrix.cargo_command == 'nextest' || matrix.command == 'test_experimental_logs' }} + if: ${{ matrix.cargo_command == 'nextest' }} uses: taiki-e/install-action@nextest - name: Install cargo-machete @@ -272,6 +271,7 @@ jobs: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh cd packages/wasm-tests wasm-pack test --node + wasm-pack test --node --features experimental - name: Check for invalid documentation anchors if: ${{ matrix.command == 'check_doc_anchors_valid' }} @@ -282,11 +282,6 @@ jobs: run: | ! cargo doc --document-private-items |& grep -A 6 "warning: unresolved link to" - # TODO: To be removed once experimental encoding is the default. - - name: Test experimental logs - if: ${{ matrix.command == 'test_experimental_logs' }} - run: RUSTFLAGS='--cfg experimental' cargo nextest run --test logs - publish: needs: - cargo-verifications From 0bb6ec03f8ee7dc5fb2fdda3181a2a069383d691 Mon Sep 17 00:00:00 2001 From: hal3e Date: Wed, 27 Mar 2024 12:11:27 +0100 Subject: [PATCH 27/30] fix imports --- examples/debugging/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/debugging/src/lib.rs b/examples/debugging/src/lib.rs index b976059370..5eb70b9c47 100644 --- a/examples/debugging/src/lib.rs +++ b/examples/debugging/src/lib.rs @@ -1,10 +1,13 @@ #[cfg(test)] mod tests { + #[cfg(not(feature = "experimental"))] use std::collections::HashMap; + #[cfg(not(feature = "experimental"))] use fuel_abi_types::abi::program::ProgramABI; #[cfg(not(feature = "experimental"))] use fuels::core::codec::{calldata, fn_selector}; + #[cfg(not(feature = "experimental"))] use fuels::{ //core::codec::ABIDecoder, // TODO: @hal3e temporarily disabled //macros::abigen, // TODO: @hal3e temporarily disabled From 4eda2173755a82d2016e746d10ead6c53324d79d Mon Sep 17 00:00:00 2001 From: hal3e Date: Wed, 27 Mar 2024 13:10:59 +0100 Subject: [PATCH 28/30] use forc 0.52.0 --- .github/workflows/ci.yml | 4 ++-- packages/fuels/Forc.toml | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7b46c3d6e5..a45770c9d9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,8 +19,8 @@ env: FUEL_CORE_VERSION: 0.23.0 FUEL_CORE_PATCH_BRANCH: RUST_VERSION: 1.76.0 - FORC_VERSION: 0.51.1 - FORC_PATCH_BRANCH: "xunilrj/new-encoding-fixes" + FORC_VERSION: 0.52.0 + FORC_PATCH_BRANCH: "" FORC_PATCH_REVISION: "" jobs: diff --git a/packages/fuels/Forc.toml b/packages/fuels/Forc.toml index 2488bcccf4..0349cb7c68 100644 --- a/packages/fuels/Forc.toml +++ b/packages/fuels/Forc.toml @@ -107,6 +107,3 @@ members = [ 'tests/types/scripts/script_u256', 'tests/types/scripts/script_vectors', ] - -[patch.'https://github.com/fuellabs/sway'] -std = { git = "https://github.com/fuellabs/sway", branch = "xunilrj/new-encoding-fixes" } From 396ac2f711685002dda9f586684b7d78ac36d6d2 Mon Sep 17 00:00:00 2001 From: hal3e Date: Wed, 27 Mar 2024 14:13:27 +0100 Subject: [PATCH 29/30] fix test with forc 0.52.0 --- examples/contracts/src/lib.rs | 8 ++++---- packages/fuels/tests/contracts.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/contracts/src/lib.rs b/examples/contracts/src/lib.rs index d365e9d2db..aed238ccd2 100644 --- a/examples/contracts/src/lib.rs +++ b/examples/contracts/src/lib.rs @@ -108,9 +108,9 @@ mod tests { // ANCHOR_END: contract_call_cost_estimation #[cfg(not(feature = "experimental"))] - let expected_gas = 795; + let expected_gas = 796; #[cfg(feature = "experimental")] - let expected_gas = 2086; + let expected_gas = 2087; assert_eq!(transaction_cost.gas_used, expected_gas); @@ -608,9 +608,9 @@ mod tests { // ANCHOR_END: multi_call_cost_estimation #[cfg(not(feature = "experimental"))] - let expected_gas = 1170; + let expected_gas = 1172; #[cfg(feature = "experimental")] - let expected_gas = 3511; + let expected_gas = 3513; assert_eq!(transaction_cost.gas_used, expected_gas); diff --git a/packages/fuels/tests/contracts.rs b/packages/fuels/tests/contracts.rs index 142c401d39..d4e44a3834 100644 --- a/packages/fuels/tests/contracts.rs +++ b/packages/fuels/tests/contracts.rs @@ -277,7 +277,7 @@ async fn test_contract_call_fee_estimation() -> Result<()> { let block_horizon = Some(1); #[cfg(not(feature = "experimental"))] - let expected_gas_used = 954; + let expected_gas_used = 955; #[cfg(feature = "experimental")] let expected_gas_used = 960; From 06fa97012a7dc940020b36f28d135079af8fc947 Mon Sep 17 00:00:00 2001 From: hal3e Date: Fri, 29 Mar 2024 16:56:12 +0100 Subject: [PATCH 30/30] pr comments --- docs/src/types/custom_types.md | 13 +- examples/contracts/src/lib.rs | 9 +- examples/debugging/src/lib.rs | 110 +-- packages/fuels-core/src/codec/abi_decoder.rs | 93 +- packages/fuels-core/src/codec/abi_encoder.rs | 831 +++++------------- .../fuels-core/src/codec/function_selector.rs | 156 ++++ packages/fuels/Forc.toml | 2 - packages/fuels/tests/scripts.rs | 1 + packages/fuels/tests/types_contracts.rs | 135 --- 9 files changed, 463 insertions(+), 887 deletions(-) diff --git a/docs/src/types/custom_types.md b/docs/src/types/custom_types.md index c151db9f0c..336318298d 100644 --- a/docs/src/types/custom_types.md +++ b/docs/src/types/custom_types.md @@ -57,7 +57,18 @@ impl MyContract for Contract { Your Rust code would look like this: ```rust,ignore -{{#include ../../../packages/fuels/tests/types_contracts.rs:generic}} + // simple struct with a single generic param + let arg1 = SimpleGeneric { + single_generic_param: 123u64, + }; + + let result = contract_methods + .struct_w_generic(arg1.clone()) + .call() + .await? + .value; + + assert_eq!(result, arg1); ``` ### Unused generic type parameters diff --git a/examples/contracts/src/lib.rs b/examples/contracts/src/lib.rs index aed238ccd2..2b12d035c2 100644 --- a/examples/contracts/src/lib.rs +++ b/examples/contracts/src/lib.rs @@ -107,10 +107,11 @@ mod tests { .await?; // ANCHOR_END: contract_call_cost_estimation - #[cfg(not(feature = "experimental"))] - let expected_gas = 796; - #[cfg(feature = "experimental")] - let expected_gas = 2087; + let expected_gas = if cfg!(feature = "experimental") { + 2087 + } else { + 796 + }; assert_eq!(transaction_cost.gas_used, expected_gas); diff --git a/examples/debugging/src/lib.rs b/examples/debugging/src/lib.rs index 5eb70b9c47..be39d8dbd6 100644 --- a/examples/debugging/src/lib.rs +++ b/examples/debugging/src/lib.rs @@ -8,11 +8,7 @@ mod tests { #[cfg(not(feature = "experimental"))] use fuels::core::codec::{calldata, fn_selector}; #[cfg(not(feature = "experimental"))] - use fuels::{ - //core::codec::ABIDecoder, // TODO: @hal3e temporarily disabled - //macros::abigen, // TODO: @hal3e temporarily disabled - types::{errors::Result, param_types::ParamType, SizedAsciiString}, - }; + use fuels::types::{errors::Result, param_types::ParamType, SizedAsciiString}; #[cfg(not(feature = "experimental"))] #[test] @@ -79,108 +75,4 @@ mod tests { Ok(()) } - - // #[test] // TODO: @hal3e temporarily disabled the test - // fn decoded_debug_matches_rust_debug() -> Result<()> { - // abigen!(Contract( - // name = "MyContract", - // abi = "packages/fuels/tests/types/contracts/generics/out/debug/generics-abi.json" - // )); - - // let json_abi_file = - // "../../packages/fuels/tests/types/contracts/generics/out/debug/generics-abi.json"; - // let abi_file_contents = std::fs::read_to_string(json_abi_file)?; - - // let parsed_abi: ProgramABI = serde_json::from_str(&abi_file_contents)?; - - // let type_lookup = parsed_abi - // .types - // .into_iter() - // .map(|decl| (decl.type_id, decl)) - // .collect::>(); - - // let get_first_fn_argument = |fn_name: &str| { - // parsed_abi - // .functions - // .iter() - // .find(|abi_fun| abi_fun.name == fn_name) - // .expect("should be there") - // .inputs - // .first() - // .expect("should be there") - // }; - // let decoder = ABIDecoder::default(); - - // { - // // simple struct with a single generic parameter - // let type_application = get_first_fn_argument("struct_w_generic"); - // let param_type = ParamType::try_from_type_application(type_application, &type_lookup)?; - - // let expected_struct = SimpleGeneric { - // single_generic_param: 123u64, - // }; - - // assert_eq!( - // format!("{expected_struct:?}"), - // decoder.decode_as_debug_str(¶m_type, &[0, 0, 0, 0, 0, 0, 0, 123])? - // ); - // } - // { - // // struct that delegates the generic param internally - // let type_application = get_first_fn_argument("struct_delegating_generic"); - // let param_type = ParamType::try_from_type_application(type_application, &type_lookup)?; - - // let expected_struct = PassTheGenericOn { - // one: SimpleGeneric { - // single_generic_param: SizedAsciiString::<3>::try_from("abc")?, - // }, - // }; - - // assert_eq!( - // format!("{expected_struct:?}"), - // decoder.decode_as_debug_str(¶m_type, &[97, 98, 99])? - // ); - // } - // { - // // enum with generic in variant - // let type_application = get_first_fn_argument("enum_w_generic"); - // let param_type = ParamType::try_from_type_application(type_application, &type_lookup)?; - - // let expected_enum = EnumWGeneric::B(10u64); - - // assert_eq!( - // format!("{expected_enum:?}"), - // decoder.decode_as_debug_str( - // ¶m_type, - // &[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 10] - // )? - // ); - // } - // { - // // logged type - // let logged_type = parsed_abi - // .logged_types - // .as_ref() - // .expect("has logs") - // .first() - // .expect("has log"); - - // let param_type = - // ParamType::try_from_type_application(&logged_type.application, &type_lookup)?; - - // let expected_u8 = 1; - - // #[cfg(not(feature = "experimental"))] - // let data = [0, 0, 0, 0, 0, 0, 0, 1]; - // #[cfg(feature = "experimental")] - // let data = [1]; - - // assert_eq!( - // format!("{expected_u8}"), - // decoder.decode_as_debug_str(¶m_type, &data)? - // ); - // } - - // Ok(()) - // } } diff --git a/packages/fuels-core/src/codec/abi_decoder.rs b/packages/fuels-core/src/codec/abi_decoder.rs index 4901f0a756..c32055f752 100644 --- a/packages/fuels-core/src/codec/abi_decoder.rs +++ b/packages/fuels-core/src/codec/abi_decoder.rs @@ -128,25 +128,11 @@ mod tests { }; #[test] - fn decode_int() -> Result<()> { - #[cfg(not(feature = "experimental"))] - let data = [0, 0, 0, 0, 255, 255, 255, 255]; - #[cfg(feature = "experimental")] - let data = [255, 255, 255, 255]; - - let decoded = ABIDecoder::default().decode(&ParamType::U32, &data)?; - - assert_eq!(decoded, Token::U32(u32::MAX)); - - Ok(()) - } - - #[test] - fn decode_multiple_int() -> Result<()> { + fn decode_multiple_uint() -> Result<()> { let types = vec![ - ParamType::U32, ParamType::U8, ParamType::U16, + ParamType::U32, ParamType::U64, ParamType::U128, ParamType::U256, @@ -154,9 +140,9 @@ mod tests { #[cfg(not(feature = "experimental"))] let data = [ - 0, 0, 0, 0, 255, 255, 255, 255, // u32 255, // u8 0, 0, 0, 0, 0, 0, 255, 255, // u16 + 0, 0, 0, 0, 255, 255, 255, 255, // u32 255, 255, 255, 255, 255, 255, 255, 255, // u64 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // u128 @@ -165,9 +151,9 @@ mod tests { ]; #[cfg(feature = "experimental")] let data = [ - 255, 255, 255, 255, // u32 255, // u8 255, 255, // u16 + 255, 255, 255, 255, // u32 255, 255, 255, 255, 255, 255, 255, 255, // u64 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // u128 @@ -178,9 +164,9 @@ mod tests { let decoded = ABIDecoder::default().decode_multiple(&types, &data)?; let expected = vec![ - Token::U32(u32::MAX), Token::U8(u8::MAX), Token::U16(u16::MAX), + Token::U32(u32::MAX), Token::U64(u64::MAX), Token::U128(u128::MAX), Token::U256(U256::MAX), @@ -251,7 +237,6 @@ mod tests { #[test] fn decode_string_slice() -> Result<()> { - let types = vec![ParamType::StringSlice]; #[cfg(not(feature = "experimental"))] let data = [ 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, @@ -264,18 +249,64 @@ mod tests { 116, 101, 110, 99, 101, //This is a full sentence ]; - let decoded = ABIDecoder::default().decode_multiple(&types, &data)?; + let decoded = ABIDecoder::default().decode(&ParamType::StringSlice, &data)?; - let expected = vec![Token::StringSlice(StaticStringToken::new( + let expected = Token::StringSlice(StaticStringToken::new( "This is a full sentence".into(), None, - ))]; + )); assert_eq!(decoded, expected); Ok(()) } + #[test] + fn decode_string() -> Result<()> { + #[cfg(not(feature = "experimental"))] + let data = [ + 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, + 116, 101, 110, 99, 101, //This is a full sentence + ]; + #[cfg(feature = "experimental")] + let data = [ + 0, 0, 0, 0, 0, 0, 0, 23, // [length] + 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, + 116, 101, 110, 99, 101, //This is a full sentence + ]; + + let decoded = ABIDecoder::default().decode(&ParamType::String, &data)?; + + let expected = Token::String("This is a full sentence".to_string()); + + assert_eq!(decoded, expected); + + Ok(()) + } + + #[test] + fn decode_tuple() -> Result<()> { + let param_type = ParamType::Tuple(vec![ParamType::U32, ParamType::Bool]); + #[cfg(not(feature = "experimental"))] + let data = [ + 0, 0, 0, 0, 0, 0, 0, 255, //u32 + 1, 0, 0, 0, 0, 0, 0, 0, //bool + ]; + #[cfg(feature = "experimental")] + let data = [ + 0, 0, 0, 255, //u32 + 1, //bool + ]; + + let result = ABIDecoder::default().decode(¶m_type, &data)?; + + let expected = Token::Tuple(vec![Token::U32(255), Token::Bool(true)]); + + assert_eq!(result, expected); + + Ok(()) + } + #[test] fn decode_array() -> Result<()> { let types = vec![ParamType::Array(Box::new(ParamType::U8), 2)]; @@ -332,6 +363,22 @@ mod tests { Ok(()) } + #[test] + fn decode_raw_slice() -> Result<()> { + #[cfg(not(feature = "experimental"))] + let data = [255, 0, 1, 2, 3, 4, 5]; + #[cfg(feature = "experimental")] + let data = [0, 0, 0, 0, 0, 0, 0, 7, 255, 0, 1, 2, 3, 4, 5]; + + let decoded = ABIDecoder::default().decode(&ParamType::RawSlice, &data)?; + + let expected = Token::RawSlice([255, 0, 1, 2, 3, 4, 5].to_vec()); + + assert_eq!(decoded, expected); + + Ok(()) + } + #[test] fn decode_enum() -> Result<()> { // enum MyEnum { diff --git a/packages/fuels-core/src/codec/abi_encoder.rs b/packages/fuels-core/src/codec/abi_encoder.rs index e586fba250..ce292fa614 100644 --- a/packages/fuels-core/src/codec/abi_encoder.rs +++ b/packages/fuels-core/src/codec/abi_encoder.rs @@ -81,13 +81,9 @@ mod tests { #[cfg(not(feature = "experimental"))] use itertools::chain; - #[cfg(not(feature = "experimental"))] - use sha2::{Digest, Sha256}; use super::*; #[cfg(not(feature = "experimental"))] - use crate::codec::first_four_bytes_of_sha256_hash; - #[cfg(not(feature = "experimental"))] use crate::constants::WORD_SIZE; use crate::{ to_named, @@ -104,468 +100,244 @@ mod tests { const DISCRIMINANT_SIZE: usize = WORD_SIZE; #[test] - #[cfg(not(feature = "experimental"))] - fn encode_function_signature() { - let fn_signature = "entry_one(u64)"; - - let result = first_four_bytes_of_sha256_hash(fn_signature); - - println!("Encoded function selector for ({fn_signature}): {result:#0x?}"); - - assert_eq!(result, [0x0, 0x0, 0x0, 0x0, 0x0c, 0x36, 0xcb, 0x9c]); - } - - #[test] - #[cfg(not(feature = "experimental"))] - fn encode_function_with_u32_type() -> Result<()> { - // @todo eventually we must update the json abi examples in here. - // They're in the old format. - // - // let json_abi = - // r#" - // [ - // { - // "type":"function", - // "inputs": [{"name":"arg","type":"u32"}], - // "name":"entry_one", - // "outputs": [] - // } - // ] - // "#; - - let fn_signature = "entry_one(u32)"; - let arg = Token::U32(u32::MAX); - - let args: Vec = vec![arg]; - - let expected_encoded_abi = [0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff]; - - let expected_function_selector = [0x0, 0x0, 0x0, 0x0, 0xb7, 0x9e, 0xf7, 0x43]; - - let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); - - let encoded = ABIEncoder::default().encode(&args)?.resolve(0); - - println!("Encoded ABI for ({fn_signature}): {encoded:#0x?}"); - - assert_eq!(hex::encode(expected_encoded_abi), hex::encode(encoded)); - assert_eq!(encoded_function_selector, expected_function_selector); - Ok(()) - } - - #[test] - #[cfg(not(feature = "experimental"))] - fn encode_function_with_u32_type_multiple_args() -> Result<()> { - // let json_abi = - // r#" - // [ - // { - // "type":"function", - // "inputs": [{"name":"first","type":"u32"},{"name":"second","type":"u32"}], - // "name":"takes_two", - // "outputs": [] - // } - // ] - // "#; - - let fn_signature = "takes_two(u32,u32)"; - let first = Token::U32(u32::MAX); - let second = Token::U32(u32::MAX); - - let args: Vec = vec![first, second]; - - let expected_encoded_abi = [ - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, + fn encode_multiple_uint() -> Result<()> { + let tokens = [ + Token::U8(u8::MAX), + Token::U16(u16::MAX), + Token::U32(u32::MAX), + Token::U64(u64::MAX), + Token::U128(u128::MAX), + Token::U256(U256::MAX), ]; - let expected_fn_selector = [0x0, 0x0, 0x0, 0x0, 0xa7, 0x07, 0xb0, 0x8e]; + let result = ABIEncoder::default().encode(&tokens)?.resolve(0); - let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); - let encoded = ABIEncoder::default().encode(&args)?.resolve(0); + #[cfg(not(feature = "experimental"))] + let expected = [ + 255, 0, 0, 0, 0, 0, 0, 0, // u8 + 0, 0, 0, 0, 0, 0, 255, 255, // u16 + 0, 0, 0, 0, 255, 255, 255, 255, // u32 + 255, 255, 255, 255, 255, 255, 255, 255, // u64 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // u128 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // u256 + ]; + #[cfg(feature = "experimental")] + let expected = [ + 255, // u8 + 255, 255, // u16 + 255, 255, 255, 255, // u32 + 255, 255, 255, 255, 255, 255, 255, 255, // u64 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // u128 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // u256 + ]; - println!("Encoded ABI for ({fn_signature}): {encoded:#0x?}"); + assert_eq!(result, expected); - assert_eq!(hex::encode(expected_encoded_abi), hex::encode(encoded)); - assert_eq!(encoded_function_selector, expected_fn_selector); Ok(()) } #[test] - #[cfg(not(feature = "experimental"))] - fn encode_function_with_u64_type() -> Result<()> { - // let json_abi = - // r#" - // [ - // { - // "type":"function", - // "inputs": [{"name":"arg","type":"u64"}], - // "name":"entry_one", - // "outputs": [] - // } - // ] - // "#; - - let fn_signature = "entry_one(u64)"; - let arg = Token::U64(u64::MAX); - - let args: Vec = vec![arg]; - - let expected_encoded_abi = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]; + fn encode_bool() -> Result<()> { + let token = Token::Bool(true); - let expected_function_selector = [0x0, 0x0, 0x0, 0x0, 0x0c, 0x36, 0xcb, 0x9c]; + let result = ABIEncoder::default().encode(&[token])?.resolve(0); - let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); - - let encoded = ABIEncoder::default().encode(&args)?.resolve(0); + #[cfg(not(feature = "experimental"))] + let expected = [0, 0, 0, 0, 0, 0, 0, 1]; + #[cfg(feature = "experimental")] + let expected = [1]; - println!("Encoded ABI for ({fn_signature}): {encoded:#0x?}"); + assert_eq!(result, expected); - assert_eq!(hex::encode(expected_encoded_abi), hex::encode(encoded)); - assert_eq!(encoded_function_selector, expected_function_selector); Ok(()) } #[test] - #[cfg(not(feature = "experimental"))] - fn encode_function_with_bool_type() -> Result<()> { - // let json_abi = - // r#" - // [ - // { - // "type":"function", - // "inputs": [{"name":"arg","type":"bool"}], - // "name":"bool_check", - // "outputs": [] - // } - // ] - // "#; - - let fn_signature = "bool_check(bool)"; - let arg = Token::Bool(true); - - let args: Vec = vec![arg]; - - let expected_encoded_abi = [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1]; - - let expected_function_selector = [0x0, 0x0, 0x0, 0x0, 0x66, 0x8f, 0xff, 0x58]; - - let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); + fn encode_b256() -> Result<()> { + let data = [ + 213, 87, 156, 70, 223, 204, 127, 24, 32, 112, 19, 230, 91, 68, 228, 203, 78, 44, 34, + 152, 244, 172, 69, 123, 168, 248, 39, 67, 243, 30, 147, 11, + ]; + let token = Token::B256(data); - let encoded = ABIEncoder::default().encode(&args)?.resolve(0); + let result = ABIEncoder::default().encode(&[token])?.resolve(0); - println!("Encoded ABI for ({fn_signature}): {encoded:#0x?}"); + assert_eq!(result, data); - assert_eq!(hex::encode(expected_encoded_abi), hex::encode(encoded)); - assert_eq!(encoded_function_selector, expected_function_selector); Ok(()) } #[test] - #[cfg(not(feature = "experimental"))] - fn encode_function_with_two_different_type() -> Result<()> { - // let json_abi = - // r#" - // [ - // { - // "type":"function", - // "inputs": [{"name":"first","type":"u32"},{"name":"second","type":"bool"}], - // "name":"takes_two_types", - // "outputs": [] - // } - // ] - // "#; - - let fn_signature = "takes_two_types(u32,bool)"; - let first = Token::U32(u32::MAX); - let second = Token::Bool(true); - - let args: Vec = vec![first, second]; - - let expected_encoded_abi = [ - 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, // u32::MAX - 0x1, // true - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - ]; + fn encode_bytes() -> Result<()> { + let token = Token::Bytes([255, 0, 1, 2, 3, 4, 5].to_vec()); - let expected_function_selector = [0x0, 0x0, 0x0, 0x0, 0xf5, 0x40, 0x73, 0x2b]; + let result = ABIEncoder::default().encode(&[token])?.resolve(0); - let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); - - let encoded = ABIEncoder::default().encode(&args)?.resolve(0); + #[cfg(not(feature = "experimental"))] + let expected = [ + 0, 0, 0, 0, 0, 0, 0, 24, // ptr + 0, 0, 0, 0, 0, 0, 0, 8, // cap + 0, 0, 0, 0, 0, 0, 0, 7, // len + 255, 0, 1, 2, 3, 4, 5, 0, // data + ]; + #[cfg(feature = "experimental")] + let expected = [ + 0, 0, 0, 0, 0, 0, 0, 7, // len + 255, 0, 1, 2, 3, 4, 5, // data + ]; - println!("Encoded ABI for ({fn_signature}): {encoded:#0x?}"); + assert_eq!(result, expected); - assert_eq!(hex::encode(expected_encoded_abi), hex::encode(encoded)); - assert_eq!(encoded_function_selector, expected_function_selector); Ok(()) } #[test] - #[cfg(not(feature = "experimental"))] - fn encode_function_with_bits256_type() -> Result<()> { - // let json_abi = - // r#" - // [ - // { - // "type":"function", - // "inputs": [{"name":"arg","type":"b256"}], - // "name":"takes_bits256", - // "outputs": [] - // } - // ] - // "#; - - let fn_signature = "takes_bits256(b256)"; - - let mut hasher = Sha256::new(); - hasher.update("test string".as_bytes()); - - let arg = hasher.finalize(); - - let arg = Token::B256(arg.into()); - - let args: Vec = vec![arg]; - - let expected_encoded_abi = [ - 0xd5, 0x57, 0x9c, 0x46, 0xdf, 0xcc, 0x7f, 0x18, 0x20, 0x70, 0x13, 0xe6, 0x5b, 0x44, - 0xe4, 0xcb, 0x4e, 0x2c, 0x22, 0x98, 0xf4, 0xac, 0x45, 0x7b, 0xa8, 0xf8, 0x27, 0x43, - 0xf3, 0x1e, 0x93, 0xb, - ]; + fn encode_string() -> Result<()> { + let token = Token::String("This is a full sentence".to_string()); - let expected_function_selector = [0x0, 0x0, 0x0, 0x0, 0x01, 0x49, 0x42, 0x96]; + let result = ABIEncoder::default().encode(&[token])?.resolve(0); - let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); - - let encoded = ABIEncoder::default().encode(&args)?.resolve(0); + #[cfg(not(feature = "experimental"))] + let expected = [ + 0, 0, 0, 0, 0, 0, 0, 24, // ptr + 0, 0, 0, 0, 0, 0, 0, 24, // cap + 0, 0, 0, 0, 0, 0, 0, 23, // len + 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, + 116, 101, 110, 99, 101, 0, //This is a full sentence + ]; + #[cfg(feature = "experimental")] + let expected = [ + 0, 0, 0, 0, 0, 0, 0, 23, // len + 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, + 116, 101, 110, 99, 101, //This is a full sentence + ]; - println!("Encoded ABI for ({fn_signature}): {encoded:#0x?}"); + assert_eq!(result, expected); - assert_eq!(hex::encode(expected_encoded_abi), hex::encode(encoded)); - assert_eq!(encoded_function_selector, expected_function_selector); Ok(()) } #[test] - #[cfg(not(feature = "experimental"))] - fn encode_function_with_array_type() -> Result<()> { - // let json_abi = - // r#" - // [ - // { - // "type":"function", - // "inputs": [{"name":"arg","type":"u8[3]"}], - // "name":"takes_integer_array", - // "outputs": [] - // } - // ] - // "#; - - let fn_signature = "takes_integer_array(u8[3])"; + fn encode_raw_slice() -> Result<()> { + let token = Token::RawSlice([255, 0, 1, 2, 3, 4, 5].to_vec()); - // Keeping the construction of the arguments array separate for better readability. - let first = Token::U8(1); - let second = Token::U8(2); - let third = Token::U8(3); + let result = ABIEncoder::default().encode(&[token])?.resolve(0); - let arg = vec![first, second, third]; - let arg_array = Token::Array(arg); - - let args: Vec = vec![arg_array]; - - let expected_encoded_abi = [0x1, 0x2, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0]; - - let expected_function_selector = [0x0, 0x0, 0x0, 0x0, 0x2c, 0x5a, 0x10, 0x2e]; - - let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); - - let encoded = ABIEncoder::default().encode(&args)?.resolve(0); + #[cfg(not(feature = "experimental"))] + let expected = [ + 0, 0, 0, 0, 0, 0, 0, 16, // cap + 0, 0, 0, 0, 0, 0, 0, 7, // len + 255, 0, 1, 2, 3, 4, 5, 0, // data + ]; + #[cfg(feature = "experimental")] + let expected = [ + 0, 0, 0, 0, 0, 0, 0, 7, // len + 255, 0, 1, 2, 3, 4, 5, // data + ]; - println!("Encoded ABI for ({fn_signature}): {encoded:#0x?}"); + assert_eq!(result, expected); - assert_eq!(hex::encode(expected_encoded_abi), hex::encode(encoded)); - assert_eq!(encoded_function_selector, expected_function_selector); Ok(()) } #[test] - #[cfg(not(feature = "experimental"))] - fn encode_function_with_string_array_type() -> Result<()> { - // let json_abi = - // r#" - // [ - // { - // "type":"function", - // "inputs": [{"name":"arg","type":"str[23]"}], - // "name":"takes_string", - // "outputs": [] - // } - // ] - // "#; - - let fn_signature = "takes_string(str[23])"; - - let args: Vec = vec![Token::StringArray(StaticStringToken::new( + fn encode_string_array() -> Result<()> { + let token = Token::StringArray(StaticStringToken::new( "This is a full sentence".into(), Some(23), - ))]; - - let expected_encoded_abi = [ - 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x66, 0x75, 0x6c, 0x6c, - 0x20, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x0, - ]; - - let expected_function_selector = [0x0, 0x0, 0x0, 0x0, 0xd5, 0x6e, 0x76, 0x51]; + )); - let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); + let result = ABIEncoder::default().encode(&[token])?.resolve(0); - let encoded = ABIEncoder::default().encode(&args)?.resolve(0); + #[cfg(not(feature = "experimental"))] + let expected = [ + 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, + 116, 101, 110, 99, 101, 0, //This is a full sentence + ]; + #[cfg(feature = "experimental")] + let expected = [ + 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, + 116, 101, 110, 99, 101, //This is a full sentence + ]; - println!("Encoded ABI for ({fn_signature}): {encoded:#0x?}"); + assert_eq!(result, expected); - assert_eq!(hex::encode(expected_encoded_abi), hex::encode(encoded)); - assert_eq!(encoded_function_selector, expected_function_selector); Ok(()) } #[test] - #[cfg(not(feature = "experimental"))] - fn encode_function_with_string_slice_type() -> Result<()> { - // let json_abi = - // r#" - // [ - // { - // "type":"function", - // "inputs": [{"name":"arg","type":"str"}], - // "name":"takes_string", - // "outputs": [] - // } - // ] - // "#; - - let fn_signature = "takes_string(str)"; - - let args: Vec = vec![Token::StringSlice(StaticStringToken::new( + fn encode_string_slice() -> Result<()> { + let token = Token::StringSlice(StaticStringToken::new( "This is a full sentence".into(), None, - ))]; - - let expected_encoded_abi = [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, // str at data index 16 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, // str of lenght 23 - 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, // - 0x61, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x73, // - 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, // - ]; - - let expected_function_selector = [0, 0, 0, 0, 239, 77, 222, 230]; + )); - let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); + let result = ABIEncoder::default().encode(&[token])?.resolve(0); - let encoded = ABIEncoder::default().encode(&args)?.resolve(0); + #[cfg(not(feature = "experimental"))] + let expected = [ + 0, 0, 0, 0, 0, 0, 0, 16, // ptr + 0, 0, 0, 0, 0, 0, 0, 23, // len + 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, + 116, 101, 110, 99, 101, //This is a full sentence + ]; + #[cfg(feature = "experimental")] + let expected = [ + 0, 0, 0, 0, 0, 0, 0, 23, // len + 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, + 116, 101, 110, 99, 101, //This is a full sentence + ]; - println!("Encoded ABI for ({fn_signature}): {encoded:#0x?}"); + assert_eq!(result, expected); - assert_eq!(hex::encode(expected_encoded_abi), hex::encode(encoded)); - assert_eq!(encoded_function_selector, expected_function_selector); Ok(()) } #[test] - #[cfg(not(feature = "experimental"))] - fn encode_function_with_struct() -> Result<()> { - // let json_abi = - // r#" - // [ - // { - // "type":"function", - // "inputs": [{"name":"arg","type":"MyStruct"}], - // "name":"takes_my_struct", - // "outputs": [] - // } - // ] - // "#; - - let fn_signature = "takes_my_struct(MyStruct)"; - - // struct MyStruct { - // foo: u8, - // bar: bool, - // } - - let foo = Token::U8(1); - let bar = Token::Bool(true); - - // Create the custom struct token using the array of tuples above - let arg = Token::Struct(vec![foo, bar]); - - let args: Vec = vec![arg]; - - let expected_encoded_abi = [ - 0x1, // 1u8 - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // padding - 0x1, // true - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // padding - ]; - - let expected_function_selector = [0x0, 0x0, 0x0, 0x0, 0xa8, 0x1e, 0x8d, 0xd7]; + fn encode_tuple() -> Result<()> { + let token = Token::Tuple(vec![Token::U32(255), Token::Bool(true)]); - let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); + let result = ABIEncoder::default().encode(&[token])?.resolve(0); - let encoded = ABIEncoder::default().encode(&args)?.resolve(0); + #[cfg(not(feature = "experimental"))] + let expected = [ + 0, 0, 0, 0, 0, 0, 0, 255, //u32 + 1, 0, 0, 0, 0, 0, 0, 0, //bool + ]; + #[cfg(feature = "experimental")] + let expected = [ + 0, 0, 0, 255, //u32 + 1, //bool + ]; - println!("Encoded ABI for ({fn_signature}): {encoded:#0x?}"); + assert_eq!(result, expected); - assert_eq!(hex::encode(expected_encoded_abi), hex::encode(encoded)); - assert_eq!(encoded_function_selector, expected_function_selector); Ok(()) } #[test] - #[cfg(not(feature = "experimental"))] - fn encode_function_with_enum() -> Result<()> { - // let json_abi = - // r#" - // [ - // { - // "type":"function", - // "inputs": [{"name":"arg","type":"MyEnum"}], - // "name":"takes_my_enum", - // "outputs": [] - // } - // ] - // "#; - - let fn_signature = "takes_my_enum(MyEnum)"; - - // enum MyEnum { - // x: u32, - // y: bool, - // } - let types = to_named(&[ParamType::U32, ParamType::Bool]); - let params = EnumVariants::new(types)?; - - // An `EnumSelector` indicating that we've chosen the first Enum variant, - // whose value is 42 of the type ParamType::U32 and that the Enum could - // have held any of the other types present in `params`. - - let enum_selector = Box::new((0, Token::U32(42), params)); - - let arg = Token::Enum(enum_selector); - - let args: Vec = vec![arg]; - - let expected_encoded_abi = [ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2a, - ]; + fn encode_array() -> Result<()> { + let token = Token::Tuple(vec![Token::U32(255), Token::U32(128)]); - let expected_function_selector = [0x0, 0x0, 0x0, 0x0, 0x35, 0x5c, 0xa6, 0xfa]; + let result = ABIEncoder::default().encode(&[token])?.resolve(0); - let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); + #[cfg(not(feature = "experimental"))] + let expected = [ + 0, 0, 0, 0, 0, 0, 0, 255, //u32 + 0, 0, 0, 0, 0, 0, 0, 128, //u32 + ]; + #[cfg(feature = "experimental")] + let expected = [ + 0, 0, 0, 255, //u32 + 0, 0, 0, 128, //u32 + ]; - let encoded = ABIEncoder::default().encode(&args)?.resolve(0); + assert_eq!(result, expected); - assert_eq!(hex::encode(expected_encoded_abi), hex::encode(encoded)); - assert_eq!(encoded_function_selector, expected_function_selector); Ok(()) } @@ -600,7 +372,7 @@ mod tests { } #[test] - fn encoding_enums_with_deeply_nested_types() -> Result<()> { + fn encode_enum_with_deeply_nested_types() -> Result<()> { /* enum DeeperEnum { v1: bool, @@ -677,105 +449,39 @@ mod tests { } #[test] - #[cfg(not(feature = "experimental"))] - fn encode_function_with_nested_structs() -> Result<()> { - // let json_abi = - // r#" - // [ - // { - // "type":"function", - // "inputs": [{"name":"arg","type":"Foo"}], - // "name":"takes_my_nested_struct", - // "outputs": [] - // } - // ] - // "#; - - // struct Foo { - // x: u16, - // y: Bar, - // } - // - // struct Bar { - // a: bool, - // b: u8[2], - // } - - let fn_signature = "takes_my_nested_struct(Foo)"; - - let args: Vec = vec![Token::Struct(vec![ + fn encode_nested_structs() -> Result<()> { + let token = Token::Struct(vec![ Token::U16(10), Token::Struct(vec![ Token::Bool(true), Token::Array(vec![Token::U8(1), Token::U8(2)]), ]), - ])]; - - let expected_encoded_abi = [ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, // 10u16 - 0x1, // true - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // padding - 0x1, 0x2, // [1u8, 2u8] - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // padding - ]; - - let expected_function_selector = [0x0, 0x0, 0x0, 0x0, 0xea, 0x0a, 0xfd, 0x23]; + ]); - let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); + let result = ABIEncoder::default().encode(&[token])?.resolve(0); - let encoded = ABIEncoder::default().encode(&args)?.resolve(0); + #[cfg(not(feature = "experimental"))] + let expected = [ + 0, 0, 0, 0, 0, 0, 0, 10, // u16 + 1, // bool + 0, 0, 0, 0, 0, 0, 0, // padding + 1, 2, // [u8, u8] + 0, 0, 0, 0, 0, 0, // padding + ]; + #[cfg(feature = "experimental")] + let expected = [ + 0, 10, // u16 + 1, // bool + 1, 2, // [u8, u8] + ]; - println!("Encoded ABI for ({fn_signature}): {encoded:#0x?}"); + assert_eq!(result, expected); - assert_eq!(hex::encode(expected_encoded_abi), hex::encode(encoded)); - assert_eq!(encoded_function_selector, expected_function_selector); Ok(()) } #[test] - #[cfg(not(feature = "experimental"))] - fn encode_comprehensive_function() -> Result<()> { - // let json_abi = - // r#" - // [ - // { - // "type": "contract", - // "inputs": [ - // { - // "name": "arg", - // "type": "Foo" - // }, - // { - // "name": "arg2", - // "type": "u8[2]" - // }, - // { - // "name": "arg3", - // "type": "b256" - // }, - // { - // "name": "arg", - // "type": "str[23]" - // } - // ], - // "name": "long_function", - // "outputs": [] - // } - // ] - // "#; - - // struct Foo { - // x: u16, - // y: Bar, - // } - // - // struct Bar { - // a: bool, - // b: u8[2], - // } - - let fn_signature = "long_function(Foo,u8[2],b256,str[23])"; - + fn encode_comprehensive() -> Result<()> { let foo = Token::Struct(vec![ Token::U16(10), Token::Struct(vec![ @@ -783,49 +489,52 @@ mod tests { Token::Array(vec![Token::U8(1), Token::U8(2)]), ]), ]); - - let u8_arr = Token::Array(vec![Token::U8(1), Token::U8(2)]); - - let mut hasher = Sha256::new(); - hasher.update("test string".as_bytes()); - - let b256 = Token::B256(hasher.finalize().into()); - - let s = Token::StringArray(StaticStringToken::new( + let arr_u8 = Token::Array(vec![Token::U8(1), Token::U8(2)]); + let b256 = Token::B256([255; 32]); + let str_arr = Token::StringArray(StaticStringToken::new( "This is a full sentence".into(), Some(23), )); + let tokens = vec![foo, arr_u8, b256, str_arr]; - let args: Vec = vec![foo, u8_arr, b256, s]; - - let expected_encoded_abi = [ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, // foo.x == 10u16 - 0x1, // foo.y.a == true - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // foo.y.a padding - 0x1, // foo.y.b.0 == 1u8 - 0x2, // foo.y.b.1 == 2u8 - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // foo.y.a - 0x1, // u8[2].0 == 1u8 - 0x2, // u8[2].0 == 2u8 - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd5, 0x57, 0x9c, 0x46, 0xdf, 0xcc, 0x7f, - 0x18, // b256 - 0x20, 0x70, 0x13, 0xe6, 0x5b, 0x44, 0xe4, 0xcb, // b256 - 0x4e, 0x2c, 0x22, 0x98, 0xf4, 0xac, 0x45, 0x7b, // b256 - 0xa8, 0xf8, 0x27, 0x43, 0xf3, 0x1e, 0x93, 0xb, // b256 - 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, // str[23] - 0x61, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x73, // str[23] - 0x65, 0x6e, 0x74, 0x65, 0x6e, 0x63, 0x65, // str[23] - 0x0, - ]; - - let expected_function_selector = [0x0, 0x0, 0x0, 0x0, 0x10, 0x93, 0xb2, 0x12]; + let result = ABIEncoder::default().encode(&tokens)?.resolve(0); - let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); + #[cfg(not(feature = "experimental"))] + let expected = [ + 0, 0, 0, 0, 0, 0, 0, 10, // foo.x == 10u16 + 1, // foo.y.a == true + 0, 0, 0, 0, 0, 0, 0, // foo.y.a padding + 1, // foo.y.b.0 == 1u8 + 2, // foo.y.b.1 == 2u8 + 0, 0, 0, 0, 0, 0, // foo.y.a + 1, // u8[2].0 == 1u8 + 2, // u8[2].0 == 2u8 + 0, 0, 0, 0, 0, 0, // padding + 255, 255, 255, 255, 255, 255, 255, 255, // b256 + 255, 255, 255, 255, 255, 255, 255, 255, // b256 + 255, 255, 255, 255, 255, 255, 255, 255, // b256 + 255, 255, 255, 255, 255, 255, 255, 255, // b256 + 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, + 116, 101, 110, 99, 101, 0, // str[23] + ]; + #[cfg(feature = "experimental")] + let expected = [ + 0, 10, // foo.x == 10u16 + 1, // foo.y.a == true + 1, // foo.y.b.0 == 1u8 + 2, // foo.y.b.1 == 2u8 + 1, // u8[2].0 == 1u8 + 2, // u8[2].0 == 2u8 + 255, 255, 255, 255, 255, 255, 255, 255, // b256 + 255, 255, 255, 255, 255, 255, 255, 255, // b256 + 255, 255, 255, 255, 255, 255, 255, 255, // b256 + 255, 255, 255, 255, 255, 255, 255, 255, // b256 + 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110, + 116, 101, 110, 99, 101, // str[23] + ]; - let encoded = ABIEncoder::default().encode(&args)?.resolve(0); + assert_eq!(result, expected); - assert_eq!(hex::encode(expected_encoded_abi), hex::encode(encoded)); - assert_eq!(encoded_function_selector, expected_function_selector); Ok(()) } @@ -1102,110 +811,6 @@ mod tests { Ok(()) } - #[test] - fn encoding_bytes() -> Result<()> { - // arrange - let token = Token::Bytes(vec![1, 2, 3]); - let offset = 40; - - // act - let result = ABIEncoder::default().encode(&[token])?.resolve(offset); - - // assert - #[cfg(not(feature = "experimental"))] - let expected = { - let ptr = [0, 0, 0, 0, 0, 0, 0, 64]; - let cap = [0, 0, 0, 0, 0, 0, 0, 8]; - let len = [0, 0, 0, 0, 0, 0, 0, 3]; - let data = [1, 2, 3, 0, 0, 0, 0, 0]; - - [ptr, cap, len, data].concat() - }; - #[cfg(feature = "experimental")] - let expected = [0, 0, 0, 0, 0, 0, 0, 3, 1, 2, 3]; // bytes[len, u8, u8, u8] - - assert_eq!(result, expected); - - Ok(()) - } - - #[test] - fn encoding_raw_slices() -> Result<()> { - // arrange - let token = Token::RawSlice(vec![1, 2, 3]); - let offset = 40; - - // act - let result = ABIEncoder::default().encode(&[token])?.resolve(offset); - - // assert - #[cfg(not(feature = "experimental"))] - let expected = { - let ptr = [0, 0, 0, 0, 0, 0, 0, 56].to_vec(); - let len = [0, 0, 0, 0, 0, 0, 0, 3].to_vec(); - let data = [1, 2, 3].to_vec(); - let padding = [0, 0, 0, 0, 0].to_vec(); - - [ptr, len, data, padding].concat() - }; - #[cfg(feature = "experimental")] - let expected = [0, 0, 0, 0, 0, 0, 0, 3, 1, 2, 3]; // raw_slice[len, u8, u8, u8] - - assert_eq!(result, expected); - - Ok(()) - } - - #[test] - fn encoding_std_string() -> Result<()> { - // arrange - let string = String::from("This "); - let token = Token::String(string); - let offset = 40; - - // act - let result = ABIEncoder::default().encode(&[token])?.resolve(offset); - - // assert - #[cfg(not(feature = "experimental"))] - let expected = { - let ptr = [0, 0, 0, 0, 0, 0, 0, 64]; - let cap = [0, 0, 0, 0, 0, 0, 0, 8]; - let len = [0, 0, 0, 0, 0, 0, 0, 5]; - let data = [0x54, 0x68, 0x69, 0x73, 0x20, 0, 0, 0]; - - [ptr, cap, len, data].concat() - }; - #[cfg(feature = "experimental")] - let expected = [0, 0, 0, 0, 0, 0, 0, 5, 84, 104, 105, 115, 32]; // string[len, data] - - assert_eq!(result, expected); - - Ok(()) - } - - #[test] - fn encoding_large_unsigned_integers() -> Result<()> { - { - let token = Token::U128(u128::MAX); - let expected_encoding = [255; 16]; - - let result = ABIEncoder::default().encode(&[token])?.resolve(0); - - assert_eq!(result, expected_encoding); - } - { - let token = Token::U256(U256::MAX); - let expected_encoding = [255; 32]; - - let result = ABIEncoder::default().encode(&[token])?.resolve(0); - - assert_eq!(result, expected_encoding); - } - - Ok(()) - } - #[cfg(not(feature = "experimental"))] #[test] fn capacity_overflow_is_caught() -> Result<()> { diff --git a/packages/fuels-core/src/codec/function_selector.rs b/packages/fuels-core/src/codec/function_selector.rs index 2a82d89174..1b5a55be88 100644 --- a/packages/fuels-core/src/codec/function_selector.rs +++ b/packages/fuels-core/src/codec/function_selector.rs @@ -17,6 +17,8 @@ pub fn resolve_fn_selector(name: &str, inputs: &[ParamType]) -> ByteArray { } #[cfg(feature = "experimental")] +//TODO: remove `_inputs` once the new encoding stabilizes +//https://github.com/FuelLabs/fuels-rs/issues/1318 pub fn resolve_fn_selector(name: &str, _inputs: &[ParamType]) -> Vec { let bytes = name.as_bytes().to_vec(); let len = bytes.len() as u64; @@ -304,4 +306,158 @@ mod tests { assert_eq!(selector, "complex_test(s((a[b256;2],str[2]),(a[e(s(str[2]))>(a[s(s(str[2]));2])>((s(s(str[2]))>(a[s(s(str[2]));2]),s(s(str[2]))>(a[s(s(str[2]));2])))>(u64,s(s(str[2]))>(a[s(s(str[2]));2])>((s(s(str[2]))>(a[s(s(str[2]));2]),s(s(str[2]))>(a[s(s(str[2]));2]))));1],u32)))"); } + + #[test] + #[cfg(not(feature = "experimental"))] + fn encode_function_signature() { + let fn_signature = "entry_one(u64)"; + + let result = first_four_bytes_of_sha256_hash(fn_signature); + + assert_eq!(result, [0x0, 0x0, 0x0, 0x0, 0x0c, 0x36, 0xcb, 0x9c]); + } + + #[test] + #[cfg(not(feature = "experimental"))] + fn encode_function_with_u32_type() { + let fn_signature = "entry_one(u32)"; + + let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); + + let expected_function_selector = [0x0, 0x0, 0x0, 0x0, 0xb7, 0x9e, 0xf7, 0x43]; + + assert_eq!(encoded_function_selector, expected_function_selector); + } + + #[test] + #[cfg(not(feature = "experimental"))] + fn encode_function_with_u32_type_multiple_args() { + let fn_signature = "takes_two(u32,u32)"; + + let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); + + let expected_fn_selector = [0x0, 0x0, 0x0, 0x0, 0xa7, 0x07, 0xb0, 0x8e]; + + assert_eq!(encoded_function_selector, expected_fn_selector); + } + + #[test] + #[cfg(not(feature = "experimental"))] + fn encode_function_with_u64_type() { + let fn_signature = "entry_one(u64)"; + + let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); + + let expected_function_selector = [0x0, 0x0, 0x0, 0x0, 0x0c, 0x36, 0xcb, 0x9c]; + + assert_eq!(encoded_function_selector, expected_function_selector); + } + + #[test] + #[cfg(not(feature = "experimental"))] + fn encode_function_with_bool_type() { + let fn_signature = "bool_check(bool)"; + + let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); + + let expected_function_selector = [0x0, 0x0, 0x0, 0x0, 0x66, 0x8f, 0xff, 0x58]; + + assert_eq!(encoded_function_selector, expected_function_selector); + } + + #[test] + #[cfg(not(feature = "experimental"))] + fn encode_function_with_two_different_type() { + let fn_signature = "takes_two_types(u32,bool)"; + + let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); + + let expected_function_selector = [0x0, 0x0, 0x0, 0x0, 0xf5, 0x40, 0x73, 0x2b]; + + assert_eq!(encoded_function_selector, expected_function_selector); + } + + #[test] + #[cfg(not(feature = "experimental"))] + fn encode_function_with_bits256_type() { + let fn_signature = "takes_bits256(b256)"; + + let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); + + let expected_function_selector = [0x0, 0x0, 0x0, 0x0, 0x01, 0x49, 0x42, 0x96]; + + assert_eq!(encoded_function_selector, expected_function_selector); + } + + #[test] + #[cfg(not(feature = "experimental"))] + fn encode_function_with_array_type() { + let fn_signature = "takes_integer_array(u8[3])"; + + let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); + + let expected_function_selector = [0x0, 0x0, 0x0, 0x0, 0x2c, 0x5a, 0x10, 0x2e]; + + assert_eq!(encoded_function_selector, expected_function_selector); + } + + #[test] + #[cfg(not(feature = "experimental"))] + fn encode_function_with_string_array_type() { + let fn_signature = "takes_string(str[23])"; + + let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); + + let expected_function_selector = [0x0, 0x0, 0x0, 0x0, 0xd5, 0x6e, 0x76, 0x51]; + + assert_eq!(encoded_function_selector, expected_function_selector); + } + + #[test] + #[cfg(not(feature = "experimental"))] + fn encode_function_with_string_slice_type() { + let fn_signature = "takes_string(str)"; + + let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); + + let expected_function_selector = [0, 0, 0, 0, 239, 77, 222, 230]; + + assert_eq!(encoded_function_selector, expected_function_selector); + } + + #[test] + #[cfg(not(feature = "experimental"))] + fn encode_function_with_struct() { + let fn_signature = "takes_my_struct(MyStruct)"; + + let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); + + let expected_function_selector = [0x0, 0x0, 0x0, 0x0, 0xa8, 0x1e, 0x8d, 0xd7]; + + assert_eq!(encoded_function_selector, expected_function_selector); + } + + #[test] + #[cfg(not(feature = "experimental"))] + fn encode_function_with_enum() { + let fn_signature = "takes_my_enum(MyEnum)"; + + let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); + + let expected_function_selector = [0x0, 0x0, 0x0, 0x0, 0x35, 0x5c, 0xa6, 0xfa]; + + assert_eq!(encoded_function_selector, expected_function_selector); + } + + #[test] + #[cfg(not(feature = "experimental"))] + fn encode_comprehensive_function() { + let fn_signature = "long_function(Foo,u8[2],b256,str[23])"; + + let encoded_function_selector = first_four_bytes_of_sha256_hash(fn_signature); + + let expected_function_selector = [0x0, 0x0, 0x0, 0x0, 0x10, 0x93, 0xb2, 0x12]; + + assert_eq!(encoded_function_selector, expected_function_selector); + } } diff --git a/packages/fuels/Forc.toml b/packages/fuels/Forc.toml index 0349cb7c68..7ef5e0901f 100644 --- a/packages/fuels/Forc.toml +++ b/packages/fuels/Forc.toml @@ -60,8 +60,6 @@ members = [ 'tests/types/contracts/enum_encoding', 'tests/types/contracts/enum_inside_struct', 'tests/types/contracts/evm_address', - # TODO: @hal3e tempoarily disabled this forc project - #'tests/types/contracts/generics', 'tests/types/contracts/heap_type_in_enums', 'tests/types/contracts/heap_types', 'tests/types/contracts/identity', diff --git a/packages/fuels/tests/scripts.rs b/packages/fuels/tests/scripts.rs index 860e92ca82..53b315c17f 100644 --- a/packages/fuels/tests/scripts.rs +++ b/packages/fuels/tests/scripts.rs @@ -99,6 +99,7 @@ async fn test_basic_script_with_tx_policies() -> Result<()> { #[tokio::test] // Remove this test once the new encoding lands as the max_input will be irrelevant // for direct script calls as all script_data is `inline` +// TODO: https://github.com/FuelLabs/fuels-rs/issues/1317 async fn test_script_call_with_non_default_max_input() -> Result<()> { use fuels::{ test_helpers::ChainConfig, diff --git a/packages/fuels/tests/types_contracts.rs b/packages/fuels/tests/types_contracts.rs index b089e47771..3efd7d6950 100644 --- a/packages/fuels/tests/types_contracts.rs +++ b/packages/fuels/tests/types_contracts.rs @@ -1408,141 +1408,6 @@ async fn test_identity_with_two_contracts() -> Result<()> { Ok(()) } -// #[tokio::test] // TODO: @hal3e temporarily disabled the test -// async fn generics_test() -> Result<()> { -// setup_program_test!( -// Wallets("wallet"), -// Abigen(Contract( -// name = "TypesContract", -// project = "packages/fuels/tests/types/contracts/generics" -// )), -// Deploy( -// name = "contract_instance", -// contract = "TypesContract", -// wallet = "wallet" -// ), -// ); -// let contract_methods = contract_instance.methods(); - -// { -// ANCHOR: generic -// // simple struct with a single generic param -// let arg1 = SimpleGeneric { -// single_generic_param: 123u64, -// }; - -// let result = contract_methods -// .struct_w_generic(arg1.clone()) -// .call() -// .await? -// .value; - -// assert_eq!(result, arg1); -// ANCHOR_END: generic -// } -// { -// // struct that delegates the generic param internally -// let arg1 = PassTheGenericOn { -// one: SimpleGeneric { -// single_generic_param: "abc".try_into()?, -// }, -// }; - -// let result = contract_methods -// .struct_delegating_generic(arg1.clone()) -// .call() -// .await? -// .value; - -// assert_eq!(result, arg1); -// } -// { -// // struct that has the generic in an array -// let arg1 = StructWArrayGeneric { a: [1u32, 2u32] }; - -// let result = contract_methods -// .struct_w_generic_in_array(arg1.clone()) -// .call() -// .await? -// .value; - -// assert_eq!(result, arg1); -// } -// { -// // struct that has the generic in a tuple -// let arg1 = StructWTupleGeneric { a: (1, 2) }; - -// let result = contract_methods -// .struct_w_generic_in_tuple(arg1.clone()) -// .call() -// .await? -// .value; - -// assert_eq!(result, arg1); -// } -// { -// // enum with generic in variant -// let arg1 = EnumWGeneric::B(10); -// let result = contract_methods -// .enum_w_generic(arg1.clone()) -// .call() -// .await? -// .value; - -// assert_eq!(result, arg1); -// } -// { -// contract_methods -// .unused_generic_args( -// StructOneUnusedGenericParam::default(), -// EnumOneUnusedGenericParam::One, -// ) -// .call() -// .await?; - -// let (the_struct, the_enum) = contract_methods -// .used_and_unused_generic_args( -// StructUsedAndUnusedGenericParams::new(10u8), -// EnumUsedAndUnusedGenericParams::Two(11u8), -// ) -// .call() -// .await? -// .value; - -// assert_eq!(the_struct.field, 12u8); -// if let EnumUsedAndUnusedGenericParams::Two(val) = the_enum { -// assert_eq!(val, 13) -// } else { -// panic!("Expected the variant EnumUsedAndUnusedGenericParams::Two"); -// } -// } -// { -// // complex case -// let pass_through = PassTheGenericOn { -// one: SimpleGeneric { -// single_generic_param: "ab".try_into()?, -// }, -// }; -// let w_arr_generic = StructWArrayGeneric { -// a: [pass_through.clone(), pass_through], -// }; - -// let arg1 = MegaExample { -// a: ([Bits256([0; 32]), Bits256([0; 32])], "ab".try_into()?), -// b: vec![( -// [EnumWGeneric::B(StructWTupleGeneric { -// a: (w_arr_generic.clone(), w_arr_generic), -// })], -// 10u32, -// )], -// }; - -// contract_methods.complex_test(arg1.clone()).call().await?; -// } - -// Ok(()) -// } - #[tokio::test] async fn test_vector() -> Result<()> { setup_program_test!(