From 7084c81b58f1b160492288174314353cf44de555 Mon Sep 17 00:00:00 2001 From: iqdecay Date: Tue, 11 Jul 2023 13:02:43 +0200 Subject: [PATCH 01/15] feat: enable `String` type return for contracts --- .../src/program_bindings/resolved_type.rs | 81 ++++++++++++++++++- .../src/program_bindings/utils.rs | 1 + packages/fuels-core/src/codec/abi_decoder.rs | 8 ++ packages/fuels-core/src/codec/abi_encoder.rs | 25 ++++++ .../fuels-core/src/codec/function_selector.rs | 8 +- .../fuels-core/src/traits/parameterize.rs | 6 ++ packages/fuels-core/src/traits/tokenizable.rs | 30 +++++++ packages/fuels-core/src/types.rs | 1 + packages/fuels-core/src/types/param_types.rs | 42 +++++++++- packages/fuels-programs/src/call_utils.rs | 32 ++++---- packages/fuels-programs/src/contract.rs | 1 + 11 files changed, 213 insertions(+), 22 deletions(-) diff --git a/packages/fuels-code-gen/src/program_bindings/resolved_type.rs b/packages/fuels-code-gen/src/program_bindings/resolved_type.rs index 2d06e5432e..1ae7285de6 100644 --- a/packages/fuels-code-gen/src/program_bindings/resolved_type.rs +++ b/packages/fuels-code-gen/src/program_bindings/resolved_type.rs @@ -76,6 +76,7 @@ impl TypeResolver { Self::to_sized_ascii_string, Self::to_ascii_string, Self::to_tuple, + Self::to_std_string, Self::to_bytes, Self::to_raw_slice, Self::to_custom_type, @@ -113,6 +114,21 @@ impl TypeResolver { })) } + fn to_std_string( + &self, + type_application: &FullTypeApplication, + ) -> Result> { + if &type_application.type_decl.type_field == "struct String" { + let type_name = quote! {::std::string::String}; + Ok(Some(ResolvedType { + type_name, + generic_params: vec![], + })) + } else { + Ok(None) + } + } + fn to_bytes(&self, type_application: &FullTypeApplication) -> Result> { if &type_application.type_decl.type_field == "struct Bytes" { let type_name = quote! {::fuels::types::Bytes}; @@ -497,7 +513,70 @@ mod tests { } #[test] - fn test_resolve_string() -> Result<()> { + fn test_resolve_std_string() -> Result<()> { + test_resolve_first_type( + ":: std :: string :: String", + &[ + TypeDeclaration { + type_id: 0, + type_field: "struct String".to_string(), + components: Some(vec![TypeApplication { + name: "bytes".to_string(), + type_id: 1, + ..Default::default() + }]), + ..Default::default() + }, + TypeDeclaration { + type_id: 1, + type_field: "struct std::bytes::Bytes".to_string(), + components: Some(vec![ + TypeApplication { + name: "buf".to_string(), + type_id: 2, + ..Default::default() + }, + TypeApplication { + name: "len".to_string(), + type_id: 4, + ..Default::default() + }, + ]), + ..Default::default() + }, + TypeDeclaration { + type_id: 2, + type_field: "struct std::bytes::RawBytes".to_string(), + components: Some(vec![ + TypeApplication { + name: "ptr".to_string(), + type_id: 3, + ..Default::default() + }, + TypeApplication { + name: "cap".to_string(), + type_id: 4, + ..Default::default() + }, + ]), + ..Default::default() + }, + TypeDeclaration { + type_id: 3, + type_field: "raw untyped ptr".to_string(), + ..Default::default() + }, + TypeDeclaration { + type_id: 4, + type_field: "u64".to_string(), + ..Default::default() + }, + ], + ) + } + + #[test] + fn test_resolve_static_str() -> Result<()> { test_resolve_primitive_type("str[3]", ":: fuels :: types :: SizedAsciiString < 3usize >") } diff --git a/packages/fuels-code-gen/src/program_bindings/utils.rs b/packages/fuels-code-gen/src/program_bindings/utils.rs index a5f42ed882..7fe13d115b 100644 --- a/packages/fuels-code-gen/src/program_bindings/utils.rs +++ b/packages/fuels-code-gen/src/program_bindings/utils.rs @@ -126,6 +126,7 @@ pub(crate) fn sdk_provided_custom_types_lookup() -> HashMap ("std::identity::Identity", "::fuels::types::Identity"), ("std::option::Option", "::core::option::Option"), ("std::result::Result", "::core::result::Result"), + ("std::string::String", "::std::string::String"), ("std::u128::U128", "u128"), ("std::u256::U256", "::fuels::types::U256"), ("std::vec::Vec", "::std::vec::Vec"), diff --git a/packages/fuels-core/src/codec/abi_decoder.rs b/packages/fuels-core/src/codec/abi_decoder.rs index 75a2764486..46ee00df50 100644 --- a/packages/fuels-core/src/codec/abi_decoder.rs +++ b/packages/fuels-core/src/codec/abi_decoder.rs @@ -82,6 +82,7 @@ impl ABIDecoder { ParamType::Tuple(types) => Self::decode_tuple(types, bytes), ParamType::Vector(param_type) => Self::decode_vector(param_type, bytes), ParamType::Bytes => Self::decode_bytes(bytes), + ParamType::StdString => Self::decode_std_string(bytes), } } @@ -92,6 +93,13 @@ impl ABIDecoder { }) } + fn decode_std_string(bytes: &[u8]) -> Result { + Ok(DecodeResult { + token: Token::StdString(str::from_utf8(bytes)?.to_string()), + bytes_read: bytes.len(), + }) + } + fn decode_vector(param_type: &ParamType, bytes: &[u8]) -> Result { let num_of_elements = ParamType::calculate_num_of_elements(param_type, bytes.len())?; let (tokens, bytes_read) = Self::decode_multiple(vec![param_type; num_of_elements], bytes)?; diff --git a/packages/fuels-core/src/codec/abi_encoder.rs b/packages/fuels-core/src/codec/abi_encoder.rs index 0d7a56069b..118f708db1 100644 --- a/packages/fuels-core/src/codec/abi_encoder.rs +++ b/packages/fuels-core/src/codec/abi_encoder.rs @@ -50,6 +50,8 @@ impl ABIEncoder { Token::Unit => vec![Self::encode_unit()], Token::RawSlice(data) => Self::encode_raw_slice(data)?, Token::Bytes(data) => Self::encode_bytes(data.to_vec())?, + // `String` in Sway has the same memory layout as the bytes type + Token::StdString(string) => Self::encode_bytes(string.clone().into_bytes())?, }; Ok(encoded_token) @@ -1171,4 +1173,27 @@ mod tests { Ok(()) } + + #[test] + fn encoding_std_string() -> Result<()> { + // arrange + let string = String::from("This "); + let token = Token::StdString(string.clone()); + let offset = 40; + + // act + let encoded_std_string = ABIEncoder::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]; + + let expected_encoded_std_string = [ptr, cap, len, data].concat(); + + assert_eq!(expected_encoded_std_string, encoded_std_string); + + Ok(()) + } } diff --git a/packages/fuels-core/src/codec/function_selector.rs b/packages/fuels-core/src/codec/function_selector.rs index de66ee0ced..ca811037b8 100644 --- a/packages/fuels-core/src/codec/function_selector.rs +++ b/packages/fuels-core/src/codec/function_selector.rs @@ -75,6 +75,8 @@ fn resolve_arg(arg: &ParamType) -> String { } ParamType::RawSlice => "rawslice".to_string(), ParamType::Bytes => "s(s(rawptr,u64),u64)".to_string(), + // `String` in Sway has the same memory layout as the bytes type + ParamType::StdString => "s(s(s(rawptr,u64),u64))".to_string(), } } @@ -180,12 +182,12 @@ mod tests { } #[test] - fn handles_bytes() { - let inputs = [ParamType::Bytes]; + fn handles_std_string() { + let inputs = [ParamType::StdString]; let selector = resolve_fn_signature("some_fun", &inputs); - assert_eq!(selector, "some_fun(s(s(rawptr,u64),u64))") + assert_eq!(selector, "some_fun(s(s(s(rawptr,u64),u64)))"); } #[test] diff --git a/packages/fuels-core/src/traits/parameterize.rs b/packages/fuels-core/src/traits/parameterize.rs index 65d5c1c0f4..4c2e3d23f1 100644 --- a/packages/fuels-core/src/traits/parameterize.rs +++ b/packages/fuels-core/src/traits/parameterize.rs @@ -41,6 +41,12 @@ impl Parameterize for Bytes { } } +impl Parameterize for String { + fn param_type() -> ParamType { + ParamType::StdString + } +} + impl Parameterize for Address { fn param_type() -> ParamType { ParamType::Struct { diff --git a/packages/fuels-core/src/traits/tokenizable.rs b/packages/fuels-core/src/traits/tokenizable.rs index 07fb33cd83..a36a4bde87 100644 --- a/packages/fuels-core/src/traits/tokenizable.rs +++ b/packages/fuels-core/src/traits/tokenizable.rs @@ -210,6 +210,25 @@ impl Tokenizable for Bytes { } } +impl Tokenizable for String { + fn from_token(token: Token) -> Result + where + Self: Sized, + { + match token { + Token::StdString(string) => Ok(string), + _ => Err(error!( + InvalidData, + "String::from_token expected a token of the variant Token::String, got: {token}" + )), + } + } + + fn into_token(self) -> Token { + Token::StdString(self) + } +} + // Here we implement `Tokenizable` for a given tuple of a given length. // This is done this way because we can't use `impl Tokenizable for (T,)`. // So we implement `Tokenizable` for each tuple length, covering @@ -590,4 +609,15 @@ mod tests { Ok(()) } + + #[test] + fn test_into_token_std_string() -> Result<()> { + let expected = String::from("hello"); + let token = Token::StdString(expected.clone()); + let detokenized = String::from_token(token.into_token())?; + + assert_eq!(detokenized, expected); + + Ok(()) + } } diff --git a/packages/fuels-core/src/types.rs b/packages/fuels-core/src/types.rs index 298a4352f0..169ba92245 100644 --- a/packages/fuels-core/src/types.rs +++ b/packages/fuels-core/src/types.rs @@ -94,6 +94,7 @@ pub enum Token { Tuple(Vec), RawSlice(Vec), Bytes(Vec), + StdString(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 dd31184c7f..86aa33bd5a 100644 --- a/packages/fuels-core/src/types/param_types.rs +++ b/packages/fuels-core/src/types/param_types.rs @@ -42,6 +42,7 @@ pub enum ParamType { Tuple(Vec), RawSlice, Bytes, + StdString, } pub enum ReturnLocation { @@ -83,13 +84,17 @@ impl ParamType { match &self { ParamType::Vector(param_type) => param_type.uses_heap_types(), ParamType::Bytes => false, + // Here, we return false because even though the `StdString` type has an underlying + // `Bytes` type nested, it is an exception that will be generalized as part of + // https://github.com/FuelLabs/fuels-rs/discussions/944 + ParamType::StdString => false, _ => self.uses_heap_types(), } } fn uses_heap_types(&self) -> bool { match &self { - ParamType::Vector(..) | ParamType::Bytes => true, + ParamType::Vector(..) | ParamType::Bytes | ParamType::StdString => true, ParamType::Array(param_type, ..) => param_type.uses_heap_types(), ParamType::Tuple(param_types, ..) => Self::any_nested_heap_types(param_types), ParamType::Enum { @@ -112,7 +117,10 @@ impl ParamType { } pub fn is_vm_heap_type(&self) -> bool { - matches!(self, ParamType::Vector(..) | ParamType::Bytes) + matches!( + self, + ParamType::Vector(..) | ParamType::Bytes | ParamType::StdString + ) } /// Compute the inner memory size of a containing heap type (`Bytes` or `Vec`s). @@ -122,7 +130,7 @@ impl ParamType { Some(inner_param_type.compute_encoding_width() * WORD_SIZE) } // `Bytes` type is byte-packed in the VM, so it's the size of an u8 - ParamType::Bytes => Some(std::mem::size_of::()), + ParamType::Bytes | ParamType::StdString => Some(std::mem::size_of::()), _ => None, } } @@ -146,7 +154,7 @@ impl ParamType { | ParamType::U64 | ParamType::Bool => 1, ParamType::U128 | ParamType::RawSlice | ParamType::StringSlice => 2, - ParamType::Vector(_) | ParamType::Bytes => 3, + ParamType::Vector(_) | ParamType::Bytes | ParamType::StdString => 3, ParamType::U256 | ParamType::B256 => 4, ParamType::Array(param, count) => param.compute_encoding_width() * count, ParamType::String(len) => count_words(*len), @@ -328,6 +336,7 @@ impl TryFrom<&Type> for ParamType { try_tuple, try_vector, try_bytes, + try_std_string, try_raw_slice, try_enum, try_u128, @@ -405,6 +414,12 @@ fn try_bytes(the_type: &Type) -> Result> { .then_some(ParamType::Bytes)) } +fn try_std_string(the_type: &Type) -> Result> { + Ok(["struct std::string::String", "struct String"] + .contains(&the_type.type_field.as_str()) + .then_some(ParamType::StdString)) +} + fn try_raw_slice(the_type: &Type) -> Result> { Ok((the_type.type_field == "raw untyped slice").then_some(ParamType::RawSlice)) } @@ -1295,6 +1310,7 @@ mod tests { assert!(!ParamType::String(10).contains_nested_heap_types()); assert!(!ParamType::RawSlice.contains_nested_heap_types()); assert!(!ParamType::Bytes.contains_nested_heap_types()); + assert!(!ParamType::StdString.contains_nested_heap_types()); Ok(()) } @@ -1452,6 +1468,24 @@ mod tests { assert_eq!(param_type, ParamType::RawSlice); } + fn try_std_string_correctly_resolves_param_type() { + let the_type = given_type_with_path("std::string::String"); + + let param_type = try_std_string(&the_type).unwrap().unwrap(); + + assert_eq!(param_type, ParamType::StdString); + } + + #[test] + fn try_std_string_is_type_path_backward_compatible() { + // TODO: To be removed once https://github.com/FuelLabs/fuels-rs/issues/881 is unblocked. + let the_type = given_type_with_path("String"); + + let param_type = try_std_string(&the_type).unwrap().unwrap(); + + assert_eq!(param_type, ParamType::StdString); + } + fn given_type_with_path(path: &str) -> Type { Type { type_field: format!("struct {path}"), diff --git a/packages/fuels-programs/src/call_utils.rs b/packages/fuels-programs/src/call_utils.rs index 0eb9ca43c6..eb2c4a9ce9 100644 --- a/packages/fuels-programs/src/call_utils.rs +++ b/packages/fuels-programs/src/call_utils.rs @@ -146,26 +146,28 @@ pub(crate) async fn build_tx_from_contract_calls( /// Compute the length of the calling scripts for the two types of contract calls: those that return /// a heap type, and those that don't. -/// Use placeholder for `call_param_offsets` and `output_param_type`, because the length of the -/// calling script doesn't depend on the underlying type, just on whether or not the contract call -/// output type is a heap type. fn compute_calls_instructions_len(calls: &[ContractCall]) -> usize { - let n_heap_data_calls = calls + let n_heap_type_calls = calls .iter() .filter(|c| c.output_param.is_vm_heap_type()) .count(); + let n_stack_type_calls = calls.len() - n_heap_type_calls; - let calls_instructions_len_stack_data = + let total_instructions_len_stack_data = + // Use placeholder for `call_param_offsets` and `output_param_type`, because the length of + // the calling script doesn't depend on the underlying type, just on whether or not the + // contract call output type is a heap type. get_single_call_instructions(&CallOpcodeParamsOffset::default(), &ParamType::U64).len() - * (calls.len() - n_heap_data_calls); - let calls_instructions_len_heap_data = get_single_call_instructions( + * n_stack_type_calls; + + let total_instructions_len_heap_data = get_single_call_instructions( &CallOpcodeParamsOffset::default(), &ParamType::Vector(Box::from(ParamType::U64)), ) .len() - * n_heap_data_calls; + * n_heap_type_calls; - calls_instructions_len_stack_data + calls_instructions_len_heap_data + total_instructions_len_stack_data + total_instructions_len_heap_data } /// Compute how much of each asset is required based on all `CallParameters` of the `ContractCalls` @@ -339,14 +341,16 @@ pub(crate) fn get_single_call_instructions( instructions.extend([ // The RET register contains the pointer address of the `CALL` return (a stack // address). - // The RETL register contains the length of the `CALL` return (=24 because the Vec/Bytes - // struct takes 3 WORDs). We don't actually need it unless the Vec/Bytes struct encoding - // changes in the compiler. + // The RETL register contains the length of the `CALL` return (=24 because the + // Vec/Bytes/String struct takes 3 WORDs). + // We don't actually need it unless the Vec/Bytes/String struct encoding changes in the + // compiler. // Load the word located at the address contained in RET, it's a word that // translates to a heap address. 0x15 is a free register. op::lw(0x15, RegId::RET, 0), - // We know a Vec/Bytes struct has its third WORD contain the length of the underlying - // vector, so use a 2 offset to store the length in 0x16, which is a free register. + // We know a Vec/Bytes/String struct has its third WORD contain the length of the + // underlying vector, so use a 2 offset to store the length in 0x16, which is a free + // register. op::lw(0x16, RegId::RET, 2), // The in-memory size of the type is (in-memory size of the inner type) * length op::muli(0x16, 0x16, inner_type_byte_size as u16), diff --git a/packages/fuels-programs/src/contract.rs b/packages/fuels-programs/src/contract.rs index 86fec4b0f6..fa1438d6ee 100644 --- a/packages/fuels-programs/src/contract.rs +++ b/packages/fuels-programs/src/contract.rs @@ -492,6 +492,7 @@ where let consensus_parameters = provider.consensus_parameters(); self.cached_tx_id = Some(tx.id(consensus_parameters.chain_id.into())); + println!("This is the tx script data:\n{:?}", tx.script_data()); let receipts = if simulate { provider.checked_dry_run(&tx).await? } else { From 480677d1e812b5d89322253140a7d3160a2bed0a Mon Sep 17 00:00:00 2001 From: iqdecay Date: Tue, 11 Jul 2023 13:03:30 +0200 Subject: [PATCH 02/15] test: show test for returning `String` type from contracts --- .../types/contracts/std_lib_string/Forc.toml | 9 +++++++ .../contracts/std_lib_string/src/main.sw | 13 ++++++++++ packages/fuels/tests/types_contracts.rs | 26 +++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 packages/fuels/tests/types/contracts/std_lib_string/Forc.toml create mode 100644 packages/fuels/tests/types/contracts/std_lib_string/src/main.sw diff --git a/packages/fuels/tests/types/contracts/std_lib_string/Forc.toml b/packages/fuels/tests/types/contracts/std_lib_string/Forc.toml new file mode 100644 index 0000000000..885035af8c --- /dev/null +++ b/packages/fuels/tests/types/contracts/std_lib_string/Forc.toml @@ -0,0 +1,9 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "std_lib_string" + +[dependencies] + +std = { git = "https://github.com/FuelLabs/sway/", branch = "master" } diff --git a/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw b/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw new file mode 100644 index 0000000000..e9753f536c --- /dev/null +++ b/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw @@ -0,0 +1,13 @@ +contract; + +use std::string::String; + +abi MyContract { + fn return_dynamic_string() -> String; +} + +impl MyContract for Contract { + fn return_dynamic_string() -> String { + String::from_ascii_str("hello world") + } +} diff --git a/packages/fuels/tests/types_contracts.rs b/packages/fuels/tests/types_contracts.rs index 7434a1c1f6..7bc2a00f12 100644 --- a/packages/fuels/tests/types_contracts.rs +++ b/packages/fuels/tests/types_contracts.rs @@ -1,9 +1,14 @@ +#![allow(unused_imports, unused_variables)] +use fuel_tx::Receipt; use std::{result::Result as StdResult, str::FromStr}; use fuels::{ prelude::*, types::{Bits256, EvmAddress, Identity, SizedAsciiString, B512, U256}, }; +use fuels_core::codec::ABIDecoder; +use fuels_core::fn_selector; +use fuels_core::types::param_types::ParamType; pub fn null_contract_id() -> Bech32ContractId { // a bech32 contract address that decodes to [0u8;32] @@ -1967,3 +1972,24 @@ async fn test_contract_raw_slice() -> Result<()> { Ok(()) } + +#[tokio::test] +async fn test_contract_std_lib_string() -> Result<()> { + let wallet = launch_provider_and_get_wallet().await; + setup_program_test!( + Abigen(Contract( + name = "StdLibString", + project = "packages/fuels/tests/types/contracts/std_lib_string" + )), + Deploy( + name = "contract_instance", + contract = "StdLibString", + wallet = "wallet" + ), + ); + let contract_methods = contract_instance.methods(); + let resp = contract_methods.return_dynamic_string().call().await?; + let expected = String::from("hello world"); + assert_eq!(resp.value, expected); + Ok(()) +} From 3af030363a40a9618e2acbfbe90a68276afdef09 Mon Sep 17 00:00:00 2001 From: iqdecay Date: Tue, 11 Jul 2023 13:17:30 +0200 Subject: [PATCH 03/15] test: fix tests for `String` --- packages/fuels-programs/src/contract.rs | 1 - packages/fuels/Forc.toml | 1 + .../tests/types/contracts/std_lib_string/src/main.sw | 11 +++++++++++ packages/fuels/tests/types_contracts.rs | 6 ++++++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/fuels-programs/src/contract.rs b/packages/fuels-programs/src/contract.rs index fa1438d6ee..86fec4b0f6 100644 --- a/packages/fuels-programs/src/contract.rs +++ b/packages/fuels-programs/src/contract.rs @@ -492,7 +492,6 @@ where let consensus_parameters = provider.consensus_parameters(); self.cached_tx_id = Some(tx.id(consensus_parameters.chain_id.into())); - println!("This is the tx script data:\n{:?}", tx.script_data()); let receipts = if simulate { provider.checked_dry_run(&tx).await? } else { diff --git a/packages/fuels/Forc.toml b/packages/fuels/Forc.toml index 8e668a8cf7..d5299b2551 100644 --- a/packages/fuels/Forc.toml +++ b/packages/fuels/Forc.toml @@ -64,6 +64,7 @@ members = [ 'tests/types/contracts/u128', 'tests/types/contracts/u256', 'tests/types/contracts/vector_output', + 'tests/types/contracts/std_lib_string', 'tests/types/contracts/vectors', 'tests/types/predicates/address', 'tests/types/predicates/enums', diff --git a/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw b/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw index e9753f536c..5ff71e3618 100644 --- a/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw +++ b/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw @@ -4,10 +4,21 @@ use std::string::String; abi MyContract { fn return_dynamic_string() -> String; + // The content of the `String` passed as argument is not tested because it doesn't seem like + // it is stable (https://github com/FuelLabs/sway/issues/4788). We just to check that the + // function can be called + fn accepts_dynamic_string(s: String) -> bool; } impl MyContract for Contract { fn return_dynamic_string() -> String { String::from_ascii_str("hello world") } + + fn accepts_dynamic_string(s: String) -> bool { + assert(s.capacity() == 0); // this is true even when `s` is not empty + assert(s.as_bytes().len() == 1_000_000); // this is true as well and contr + assert(s.as_bytes().capacity() == 0); // this is also true and seems not coherent + true + } } diff --git a/packages/fuels/tests/types_contracts.rs b/packages/fuels/tests/types_contracts.rs index 7bc2a00f12..9049009572 100644 --- a/packages/fuels/tests/types_contracts.rs +++ b/packages/fuels/tests/types_contracts.rs @@ -1991,5 +1991,11 @@ async fn test_contract_std_lib_string() -> Result<()> { let resp = contract_methods.return_dynamic_string().call().await?; let expected = String::from("hello world"); assert_eq!(resp.value, expected); + + let resp = contract_methods + .accepts_dynamic_string("world".to_string()) + .call() + .await?; + assert!(resp.value); Ok(()) } From 3380c800d2e2cf1445ee15837500bb16e4224dd7 Mon Sep 17 00:00:00 2001 From: iqdecay Date: Tue, 11 Jul 2023 13:18:51 +0200 Subject: [PATCH 04/15] style: appease clippy and all formatting gods --- .../contracts/std_lib_string/src/main.sw | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw b/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw index 5ff71e3618..e85b8b7ba3 100644 --- a/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw +++ b/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw @@ -3,22 +3,22 @@ contract; use std::string::String; abi MyContract { - fn return_dynamic_string() -> String; - // The content of the `String` passed as argument is not tested because it doesn't seem like - // it is stable (https://github com/FuelLabs/sway/issues/4788). We just to check that the - // function can be called - fn accepts_dynamic_string(s: String) -> bool; + fn return_dynamic_string() -> String; + // The content of the `String` passed as argument is not tested because it doesn't seem like + // it is stable (https://github com/FuelLabs/sway/issues/4788). We just to check that the + // function can be called + fn accepts_dynamic_string(s: String) -> bool; } impl MyContract for Contract { - fn return_dynamic_string() -> String { - String::from_ascii_str("hello world") - } + fn return_dynamic_string() -> String { + String::from_ascii_str("hello world") + } - fn accepts_dynamic_string(s: String) -> bool { - assert(s.capacity() == 0); // this is true even when `s` is not empty - assert(s.as_bytes().len() == 1_000_000); // this is true as well and contr - assert(s.as_bytes().capacity() == 0); // this is also true and seems not coherent - true - } + fn accepts_dynamic_string(s: String) -> bool { + assert(s.capacity() == 0); // this is true even when `s` is not empty + assert(s.as_bytes().len() == 1_000_000); // this is true as well and contr + assert(s.as_bytes().capacity() == 0); // this is also true and seems not coherent + true + } } From ab18e6cd4567fa79720b9c61664db83129c57bbe Mon Sep 17 00:00:00 2001 From: iqdecay Date: Tue, 11 Jul 2023 13:22:33 +0200 Subject: [PATCH 05/15] style --- .../fuels/tests/types/contracts/std_lib_string/src/main.sw | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw b/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw index e85b8b7ba3..1241f82d1a 100644 --- a/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw +++ b/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw @@ -5,8 +5,8 @@ use std::string::String; abi MyContract { fn return_dynamic_string() -> String; // The content of the `String` passed as argument is not tested because it doesn't seem like - // it is stable (https://github com/FuelLabs/sway/issues/4788). We just to check that the - // function can be called + // it is stable (https://github com/FuelLabs/sway/issues/4788). We just check that the + // function can be called. fn accepts_dynamic_string(s: String) -> bool; } From 1c95cb81d40887e468d4cacf639874e2ac17501e Mon Sep 17 00:00:00 2001 From: iqdecay Date: Tue, 11 Jul 2023 13:30:46 +0200 Subject: [PATCH 06/15] test --- .github/workflows/ci.yml | 2 +- packages/fuels-core/src/types/param_types.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b9a6436677..5baf7f205a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ env: RUSTFLAGS: "-D warnings" FUEL_CORE_VERSION: 0.19.1 RUST_VERSION: 1.70.0 - FORC_VERSION: 0.40.1 + FORC_VERSION: 0.42.1 FORC_PATCH_BRANCH: "" FORC_PATCH_REVISION: "" diff --git a/packages/fuels-core/src/types/param_types.rs b/packages/fuels-core/src/types/param_types.rs index 86aa33bd5a..fe4538f86a 100644 --- a/packages/fuels-core/src/types/param_types.rs +++ b/packages/fuels-core/src/types/param_types.rs @@ -1468,6 +1468,7 @@ mod tests { assert_eq!(param_type, ParamType::RawSlice); } + #[test] fn try_std_string_correctly_resolves_param_type() { let the_type = given_type_with_path("std::string::String"); From 892c887db9abd96f449c72a99e9d217e79d43f82 Mon Sep 17 00:00:00 2001 From: iqdecay Date: Tue, 11 Jul 2023 13:37:59 +0200 Subject: [PATCH 07/15] test: fix gas cost estimations due to forc 0.42 --- examples/contracts/src/lib.rs | 4 ++-- packages/fuels/tests/contracts.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/contracts/src/lib.rs b/examples/contracts/src/lib.rs index c9835164dd..776889b22e 100644 --- a/examples/contracts/src/lib.rs +++ b/examples/contracts/src/lib.rs @@ -104,7 +104,7 @@ mod tests { .await?; // ANCHOR_END: contract_call_cost_estimation - assert_eq!(transaction_cost.gas_used, 498); + assert_eq!(transaction_cost.gas_used, 499); Ok(()) } @@ -628,7 +628,7 @@ mod tests { .await?; // ANCHOR_END: multi_call_cost_estimation - assert_eq!(transaction_cost.gas_used, 783); + assert_eq!(transaction_cost.gas_used, 786); Ok(()) } diff --git a/packages/fuels/tests/contracts.rs b/packages/fuels/tests/contracts.rs index d308de5e69..5130f46810 100644 --- a/packages/fuels/tests/contracts.rs +++ b/packages/fuels/tests/contracts.rs @@ -280,7 +280,7 @@ async fn test_contract_call_fee_estimation() -> Result<()> { let tolerance = 0.2; let expected_min_gas_price = 0; // This is the default min_gas_price from the ConsensusParameters - let expected_gas_used = 597; + let expected_gas_used = 598; let expected_metered_bytes_size = 728; let expected_total_fee = 372; From 831336de8d593714067e7c6d5e2fe98d5a0642f3 Mon Sep 17 00:00:00 2001 From: iqdecay Date: Tue, 11 Jul 2023 14:02:26 +0200 Subject: [PATCH 08/15] style: appease clippy and all formatting gods --- packages/fuels-core/src/codec/abi_encoder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fuels-core/src/codec/abi_encoder.rs b/packages/fuels-core/src/codec/abi_encoder.rs index 118f708db1..131f1d08d5 100644 --- a/packages/fuels-core/src/codec/abi_encoder.rs +++ b/packages/fuels-core/src/codec/abi_encoder.rs @@ -1178,7 +1178,7 @@ mod tests { fn encoding_std_string() -> Result<()> { // arrange let string = String::from("This "); - let token = Token::StdString(string.clone()); + let token = Token::StdString(string); let offset = 40; // act From 5c55f000c99ca1d15f3d61fcedc12b1bff24ae00 Mon Sep 17 00:00:00 2001 From: Ahmed Sagdati Date: Wed, 26 Jul 2023 11:40:40 +0200 Subject: [PATCH 09/15] fix gas estimation expectations --- examples/contracts/src/lib.rs | 4 ++-- packages/fuels/tests/contracts.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/contracts/src/lib.rs b/examples/contracts/src/lib.rs index 776889b22e..213dbe28c6 100644 --- a/examples/contracts/src/lib.rs +++ b/examples/contracts/src/lib.rs @@ -104,7 +104,7 @@ mod tests { .await?; // ANCHOR_END: contract_call_cost_estimation - assert_eq!(transaction_cost.gas_used, 499); + assert_eq!(transaction_cost.gas_used, 497); Ok(()) } @@ -628,7 +628,7 @@ mod tests { .await?; // ANCHOR_END: multi_call_cost_estimation - assert_eq!(transaction_cost.gas_used, 786); + assert_eq!(transaction_cost.gas_used, 782); Ok(()) } diff --git a/packages/fuels/tests/contracts.rs b/packages/fuels/tests/contracts.rs index 5130f46810..d7b7d23a49 100644 --- a/packages/fuels/tests/contracts.rs +++ b/packages/fuels/tests/contracts.rs @@ -280,7 +280,7 @@ async fn test_contract_call_fee_estimation() -> Result<()> { let tolerance = 0.2; let expected_min_gas_price = 0; // This is the default min_gas_price from the ConsensusParameters - let expected_gas_used = 598; + let expected_gas_used = 596; let expected_metered_bytes_size = 728; let expected_total_fee = 372; From 81b85a562005c5f7f652a6bd358011fc0e0b0428 Mon Sep 17 00:00:00 2001 From: Ahmed Sagdati Date: Wed, 26 Jul 2023 12:27:13 +0200 Subject: [PATCH 10/15] wip --- .../types/contracts/std_lib_string/src/main.sw | 17 ++++++++--------- packages/fuels/tests/types_contracts.rs | 16 +++++++++------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw b/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw index 1241f82d1a..da5ac5ad96 100644 --- a/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw +++ b/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw @@ -1,13 +1,12 @@ contract; use std::string::String; +use std::assert::assert_eq; +use std::bytes::Bytes; abi MyContract { fn return_dynamic_string() -> String; - // The content of the `String` passed as argument is not tested because it doesn't seem like - // it is stable (https://github com/FuelLabs/sway/issues/4788). We just check that the - // function can be called. - fn accepts_dynamic_string(s: String) -> bool; + fn accepts_dynamic_string(s: String); } impl MyContract for Contract { @@ -15,10 +14,10 @@ impl MyContract for Contract { String::from_ascii_str("hello world") } - fn accepts_dynamic_string(s: String) -> bool { - assert(s.capacity() == 0); // this is true even when `s` is not empty - assert(s.as_bytes().len() == 1_000_000); // this is true as well and contr - assert(s.as_bytes().capacity() == 0); // this is also true and seems not coherent - true + fn accepts_dynamic_string(s: String) { + let inner = String::from_ascii_str("hello wol"); + log(inner.bytes.len()); + log(s.bytes.len()); + assert_eq(inner.as_bytes(), s.as_bytes()); } } diff --git a/packages/fuels/tests/types_contracts.rs b/packages/fuels/tests/types_contracts.rs index 9049009572..c36cc6020c 100644 --- a/packages/fuels/tests/types_contracts.rs +++ b/packages/fuels/tests/types_contracts.rs @@ -1988,14 +1988,16 @@ async fn test_contract_std_lib_string() -> Result<()> { ), ); let contract_methods = contract_instance.methods(); - let resp = contract_methods.return_dynamic_string().call().await?; - let expected = String::from("hello world"); - assert_eq!(resp.value, expected); - let resp = contract_methods - .accepts_dynamic_string("world".to_string()) + let resp = contract_methods.return_dynamic_string().call().await?.value; + assert_eq!(resp, "hello world"); + + let logs = contract_methods + .accepts_dynamic_string("hello world".to_string()) .call() - .await?; - assert!(resp.value); + .await? + .decode_logs(); + + dbg!(logs.filter_succeeded()); Ok(()) } From 87bb46e51f9bc3cdfa9c0653a4c6627a4dd3c955 Mon Sep 17 00:00:00 2001 From: Ahmed Sagdati Date: Wed, 26 Jul 2023 18:36:09 +0200 Subject: [PATCH 11/15] fix stdstring as arg --- packages/fuels-programs/src/contract.rs | 1 + .../contracts/std_lib_string/src/main.sw | 27 ++++++++++++++----- packages/fuels/tests/types_contracts.rs | 19 ++++++------- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/packages/fuels-programs/src/contract.rs b/packages/fuels-programs/src/contract.rs index 86fec4b0f6..662f8a2533 100644 --- a/packages/fuels-programs/src/contract.rs +++ b/packages/fuels-programs/src/contract.rs @@ -631,6 +631,7 @@ fn should_compute_custom_input_offset(args: &[Token]) -> bool { | Token::Vector(_) | Token::StringArray(_) | Token::StringSlice(_) + | Token::StdString(_) ) }) } diff --git a/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw b/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw index da5ac5ad96..de67fb984c 100644 --- a/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw +++ b/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw @@ -9,15 +9,30 @@ abi MyContract { fn accepts_dynamic_string(s: String); } +fn validate_string(arg: String) { + // to be replaced with a simpler assert_eq once + // https://github.com/FuelLabs/sway/issues/4868 is done + + let bytes = arg.as_bytes(); + + let inner = String::from_ascii_str("Hello World"); + let expected_bytes = inner.as_bytes(); + + assert_eq(expected_bytes.len(), bytes.len()); + + let mut i = 0; + while i < bytes.len() { + assert(expected_bytes.get(i).unwrap() == bytes.get(i).unwrap()); + i+= 1; + } +} + impl MyContract for Contract { fn return_dynamic_string() -> String { - String::from_ascii_str("hello world") + String::from_ascii_str("Hello World") } - fn accepts_dynamic_string(s: String) { - let inner = String::from_ascii_str("hello wol"); - log(inner.bytes.len()); - log(s.bytes.len()); - assert_eq(inner.as_bytes(), s.as_bytes()); + fn accepts_dynamic_string(s: String) { + validate_string(s); } } diff --git a/packages/fuels/tests/types_contracts.rs b/packages/fuels/tests/types_contracts.rs index c36cc6020c..17fb2b95a5 100644 --- a/packages/fuels/tests/types_contracts.rs +++ b/packages/fuels/tests/types_contracts.rs @@ -1989,15 +1989,16 @@ async fn test_contract_std_lib_string() -> Result<()> { ); let contract_methods = contract_instance.methods(); - let resp = contract_methods.return_dynamic_string().call().await?.value; - assert_eq!(resp, "hello world"); - - let logs = contract_methods - .accepts_dynamic_string("hello world".to_string()) - .call() - .await? - .decode_logs(); + { + let resp = contract_methods.return_dynamic_string().call().await?.value; + assert_eq!(resp, "Hello World"); + } + { + let _resp = contract_methods + .accepts_dynamic_string(String::from("Hello World")) + .call() + .await?; + } - dbg!(logs.filter_succeeded()); Ok(()) } From d81ebd4dfe09f2f4e9f68acd43d72298abfb7c79 Mon Sep 17 00:00:00 2001 From: Ahmed Sagdati Date: Wed, 26 Jul 2023 19:49:16 +0200 Subject: [PATCH 12/15] add string tests for scripts and predicates --- examples/contracts/src/lib.rs | 4 +-- packages/fuels/Forc.toml | 4 ++- packages/fuels/tests/contracts.rs | 2 +- .../predicate_std_lib_string/Forc.toml | 7 +++++ .../predicate_std_lib_string/src/main.sw | 31 +++++++++++++++++++ .../scripts/script_std_lib_string/Forc.toml | 7 +++++ .../scripts/script_std_lib_string/src/main.sw | 25 +++++++++++++++ packages/fuels/tests/types_predicates.rs | 13 ++++++++ packages/fuels/tests/types_scripts.rs | 21 +++++++++++++ 9 files changed, 110 insertions(+), 4 deletions(-) create mode 100644 packages/fuels/tests/types/predicates/predicate_std_lib_string/Forc.toml create mode 100644 packages/fuels/tests/types/predicates/predicate_std_lib_string/src/main.sw create mode 100644 packages/fuels/tests/types/scripts/script_std_lib_string/Forc.toml create mode 100644 packages/fuels/tests/types/scripts/script_std_lib_string/src/main.sw diff --git a/examples/contracts/src/lib.rs b/examples/contracts/src/lib.rs index 213dbe28c6..776889b22e 100644 --- a/examples/contracts/src/lib.rs +++ b/examples/contracts/src/lib.rs @@ -104,7 +104,7 @@ mod tests { .await?; // ANCHOR_END: contract_call_cost_estimation - assert_eq!(transaction_cost.gas_used, 497); + assert_eq!(transaction_cost.gas_used, 499); Ok(()) } @@ -628,7 +628,7 @@ mod tests { .await?; // ANCHOR_END: multi_call_cost_estimation - assert_eq!(transaction_cost.gas_used, 782); + assert_eq!(transaction_cost.gas_used, 786); Ok(()) } diff --git a/packages/fuels/Forc.toml b/packages/fuels/Forc.toml index a7b581cd40..2c6a9bcfcc 100644 --- a/packages/fuels/Forc.toml +++ b/packages/fuels/Forc.toml @@ -61,6 +61,7 @@ members = [ 'tests/types/contracts/options', 'tests/types/contracts/raw_slice', 'tests/types/contracts/results', + 'tests/types/contracts/std_lib_string', 'tests/types/contracts/str_in_array', 'tests/types/contracts/tuples', 'tests/types/contracts/two_structs', @@ -68,13 +69,13 @@ members = [ 'tests/types/contracts/u128', 'tests/types/contracts/u256', 'tests/types/contracts/vector_output', - 'tests/types/contracts/std_lib_string', 'tests/types/contracts/vectors', 'tests/types/predicates/address', 'tests/types/predicates/enums', 'tests/types/predicates/predicate_bytes', 'tests/types/predicates/predicate_generics', 'tests/types/predicates/predicate_raw_slice', + 'tests/types/predicates/predicate_std_lib_string', 'tests/types/predicates/predicate_tuples', 'tests/types/predicates/predicate_u128', 'tests/types/predicates/predicate_u256', @@ -86,6 +87,7 @@ members = [ 'tests/types/scripts/script_bytes', 'tests/types/scripts/script_generics', 'tests/types/scripts/script_raw_slice', + 'tests/types/scripts/script_std_lib_string', 'tests/types/scripts/script_tuples', 'tests/types/scripts/script_u128', 'tests/types/scripts/script_u256', diff --git a/packages/fuels/tests/contracts.rs b/packages/fuels/tests/contracts.rs index d7b7d23a49..5130f46810 100644 --- a/packages/fuels/tests/contracts.rs +++ b/packages/fuels/tests/contracts.rs @@ -280,7 +280,7 @@ async fn test_contract_call_fee_estimation() -> Result<()> { let tolerance = 0.2; let expected_min_gas_price = 0; // This is the default min_gas_price from the ConsensusParameters - let expected_gas_used = 596; + let expected_gas_used = 598; let expected_metered_bytes_size = 728; let expected_total_fee = 372; diff --git a/packages/fuels/tests/types/predicates/predicate_std_lib_string/Forc.toml b/packages/fuels/tests/types/predicates/predicate_std_lib_string/Forc.toml new file mode 100644 index 0000000000..3572429ca4 --- /dev/null +++ b/packages/fuels/tests/types/predicates/predicate_std_lib_string/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "predicate_std_lib_string" + +[dependencies] diff --git a/packages/fuels/tests/types/predicates/predicate_std_lib_string/src/main.sw b/packages/fuels/tests/types/predicates/predicate_std_lib_string/src/main.sw new file mode 100644 index 0000000000..959c54b4ef --- /dev/null +++ b/packages/fuels/tests/types/predicates/predicate_std_lib_string/src/main.sw @@ -0,0 +1,31 @@ +predicate; + +use std::string::String; + +fn validate_string(arg: String) -> bool { + // to be replaced with a simpler assert_eq once + // https://github.com/FuelLabs/sway/issues/4868 is done + + let bytes = arg.as_bytes(); + + let inner = String::from_ascii_str("Hello World"); + let expected_bytes = inner.as_bytes(); + + if expected_bytes.len() != bytes.len() { + return false; + } + + let mut i = 0; + while i < bytes.len() { + if expected_bytes.get(i).unwrap() != bytes.get(i).unwrap() { + return false; + } + i+= 1; + } + + true +} + +fn main(_arg_0: u64, _arg_1: u64, arg_2: String) -> bool { + validate_string(arg_2) +} diff --git a/packages/fuels/tests/types/scripts/script_std_lib_string/Forc.toml b/packages/fuels/tests/types/scripts/script_std_lib_string/Forc.toml new file mode 100644 index 0000000000..02cf5a2661 --- /dev/null +++ b/packages/fuels/tests/types/scripts/script_std_lib_string/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "script_std_lib_string" + +[dependencies] diff --git a/packages/fuels/tests/types/scripts/script_std_lib_string/src/main.sw b/packages/fuels/tests/types/scripts/script_std_lib_string/src/main.sw new file mode 100644 index 0000000000..073e03a180 --- /dev/null +++ b/packages/fuels/tests/types/scripts/script_std_lib_string/src/main.sw @@ -0,0 +1,25 @@ +script; + +use std::string::String; + +fn validate_string(arg: String) { + // to be replaced with a simpler assert_eq once + // https://github.com/FuelLabs/sway/issues/4868 is done + + let bytes = arg.as_bytes(); + + let inner = String::from_ascii_str("Hello World"); + let expected_bytes = inner.as_bytes(); + + assert_eq(expected_bytes.len(), bytes.len()); + + let mut i = 0; + while i < bytes.len() { + assert(expected_bytes.get(i).unwrap() == bytes.get(i).unwrap()); + i+= 1; + } +} + +fn main(arg: String) { + validate_string(arg); +} diff --git a/packages/fuels/tests/types_predicates.rs b/packages/fuels/tests/types_predicates.rs index 8ff439b651..2cd83df44b 100644 --- a/packages/fuels/tests/types_predicates.rs +++ b/packages/fuels/tests/types_predicates.rs @@ -364,3 +364,16 @@ async fn predicate_handles_u256() -> Result<()> { Ok(()) } + +#[tokio::test] +async fn predicate_handles_std_string() -> Result<()> { + abigen!(Predicate( + name = "MyPredicate", + abi = "packages/fuels/tests/types/predicates/predicate_std_lib_string/out/debug/predicate_std_lib_string-abi.json" + )); + + let data = MyPredicateEncoder::encode_data(10, 11, String::from("Hello World")); + assert_predicate_spendable(data, "tests/types/predicates/predicate_std_lib_string").await?; + + Ok(()) +} diff --git a/packages/fuels/tests/types_scripts.rs b/packages/fuels/tests/types_scripts.rs index 61b5b57343..7d8bfae6f1 100644 --- a/packages/fuels/tests/types_scripts.rs +++ b/packages/fuels/tests/types_scripts.rs @@ -288,3 +288,24 @@ async fn script_handles_u256() -> Result<()> { Ok(()) } + +#[tokio::test] +async fn script_handles_std_string() -> Result<()> { + setup_program_test!( + Wallets("wallet"), + Abigen(Script( + name = "MyScript", + project = "packages/fuels/tests/types/scripts/script_std_lib_string", + )), + LoadScript( + name = "script_instance", + script = "MyScript", + wallet = "wallet" + ) + ); + + let arg = String::from("Hello World"); + script_instance.main(arg).call().await?; + + Ok(()) +} From a1e5b1a6dc0d702e02aea3e37503478d92fd7ca0 Mon Sep 17 00:00:00 2001 From: Ahmed Sagdati Date: Wed, 26 Jul 2023 19:49:51 +0200 Subject: [PATCH 13/15] imports --- packages/fuels/tests/types_contracts.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/fuels/tests/types_contracts.rs b/packages/fuels/tests/types_contracts.rs index 17fb2b95a5..84f3ad31fc 100644 --- a/packages/fuels/tests/types_contracts.rs +++ b/packages/fuels/tests/types_contracts.rs @@ -1,14 +1,12 @@ #![allow(unused_imports, unused_variables)] -use fuel_tx::Receipt; use std::{result::Result as StdResult, str::FromStr}; +use fuel_tx::Receipt; use fuels::{ prelude::*, types::{Bits256, EvmAddress, Identity, SizedAsciiString, B512, U256}, }; -use fuels_core::codec::ABIDecoder; -use fuels_core::fn_selector; -use fuels_core::types::param_types::ParamType; +use fuels_core::{codec::ABIDecoder, fn_selector, types::param_types::ParamType}; pub fn null_contract_id() -> Bech32ContractId { // a bech32 contract address that decodes to [0u8;32] From b9d761318259cfc95333d51bbaa02fee86ab0c19 Mon Sep 17 00:00:00 2001 From: Ahmed Sagdati Date: Wed, 26 Jul 2023 19:51:39 +0200 Subject: [PATCH 14/15] forc fmt --- .../contracts/std_lib_string/src/main.sw | 25 ++++++++-------- .../predicate_std_lib_string/src/main.sw | 29 +++++++++---------- .../scripts/script_std_lib_string/src/main.sw | 23 +++++++-------- 3 files changed, 37 insertions(+), 40 deletions(-) diff --git a/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw b/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw index de67fb984c..ff1cb333a3 100644 --- a/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw +++ b/packages/fuels/tests/types/contracts/std_lib_string/src/main.sw @@ -10,21 +10,20 @@ abi MyContract { } fn validate_string(arg: String) { - // to be replaced with a simpler assert_eq once - // https://github.com/FuelLabs/sway/issues/4868 is done + // to be replaced with a simpler assert_eq once + // https://github.com/FuelLabs/sway/issues/4868 is done + let bytes = arg.as_bytes(); - let bytes = arg.as_bytes(); + let inner = String::from_ascii_str("Hello World"); + let expected_bytes = inner.as_bytes(); - let inner = String::from_ascii_str("Hello World"); - let expected_bytes = inner.as_bytes(); + assert_eq(expected_bytes.len(), bytes.len()); - assert_eq(expected_bytes.len(), bytes.len()); - - let mut i = 0; - while i < bytes.len() { - assert(expected_bytes.get(i).unwrap() == bytes.get(i).unwrap()); - i+= 1; - } + let mut i = 0; + while i < bytes.len() { + assert(expected_bytes.get(i).unwrap() == bytes.get(i).unwrap()); + i += 1; + } } impl MyContract for Contract { @@ -32,7 +31,7 @@ impl MyContract for Contract { String::from_ascii_str("Hello World") } - fn accepts_dynamic_string(s: String) { + fn accepts_dynamic_string(s: String) { validate_string(s); } } diff --git a/packages/fuels/tests/types/predicates/predicate_std_lib_string/src/main.sw b/packages/fuels/tests/types/predicates/predicate_std_lib_string/src/main.sw index 959c54b4ef..13594352ff 100644 --- a/packages/fuels/tests/types/predicates/predicate_std_lib_string/src/main.sw +++ b/packages/fuels/tests/types/predicates/predicate_std_lib_string/src/main.sw @@ -3,27 +3,26 @@ predicate; use std::string::String; fn validate_string(arg: String) -> bool { - // to be replaced with a simpler assert_eq once - // https://github.com/FuelLabs/sway/issues/4868 is done + // to be replaced with a simpler assert_eq once + // https://github.com/FuelLabs/sway/issues/4868 is done + let bytes = arg.as_bytes(); - let bytes = arg.as_bytes(); + let inner = String::from_ascii_str("Hello World"); + let expected_bytes = inner.as_bytes(); - let inner = String::from_ascii_str("Hello World"); - let expected_bytes = inner.as_bytes(); + if expected_bytes.len() != bytes.len() { + return false; + } - if expected_bytes.len() != bytes.len() { + let mut i = 0; + while i < bytes.len() { + if expected_bytes.get(i).unwrap() != bytes.get(i).unwrap() { return false; } + i += 1; + } - let mut i = 0; - while i < bytes.len() { - if expected_bytes.get(i).unwrap() != bytes.get(i).unwrap() { - return false; - } - i+= 1; - } - - true + true } fn main(_arg_0: u64, _arg_1: u64, arg_2: String) -> bool { diff --git a/packages/fuels/tests/types/scripts/script_std_lib_string/src/main.sw b/packages/fuels/tests/types/scripts/script_std_lib_string/src/main.sw index 073e03a180..14ed91e311 100644 --- a/packages/fuels/tests/types/scripts/script_std_lib_string/src/main.sw +++ b/packages/fuels/tests/types/scripts/script_std_lib_string/src/main.sw @@ -3,21 +3,20 @@ script; use std::string::String; fn validate_string(arg: String) { - // to be replaced with a simpler assert_eq once - // https://github.com/FuelLabs/sway/issues/4868 is done + // to be replaced with a simpler assert_eq once + // https://github.com/FuelLabs/sway/issues/4868 is done + let bytes = arg.as_bytes(); - let bytes = arg.as_bytes(); + let inner = String::from_ascii_str("Hello World"); + let expected_bytes = inner.as_bytes(); - let inner = String::from_ascii_str("Hello World"); - let expected_bytes = inner.as_bytes(); + assert_eq(expected_bytes.len(), bytes.len()); - assert_eq(expected_bytes.len(), bytes.len()); - - let mut i = 0; - while i < bytes.len() { - assert(expected_bytes.get(i).unwrap() == bytes.get(i).unwrap()); - i+= 1; - } + let mut i = 0; + while i < bytes.len() { + assert(expected_bytes.get(i).unwrap() == bytes.get(i).unwrap()); + i += 1; + } } fn main(arg: String) { From a8d1c44eae8f2407c3bb429137d6b6a01d826cf9 Mon Sep 17 00:00:00 2001 From: Ahmed Sagdati Date: Wed, 26 Jul 2023 20:04:36 +0200 Subject: [PATCH 15/15] cleanup --- .../src/program_bindings/resolved_type.rs | 29 ------------------- .../fuels-core/src/codec/function_selector.rs | 16 +++++++--- .../types/contracts/std_lib_string/Forc.toml | 2 -- packages/fuels/tests/types_contracts.rs | 3 -- 4 files changed, 12 insertions(+), 38 deletions(-) diff --git a/packages/fuels-code-gen/src/program_bindings/resolved_type.rs b/packages/fuels-code-gen/src/program_bindings/resolved_type.rs index 1ae7285de6..5c49b64445 100644 --- a/packages/fuels-code-gen/src/program_bindings/resolved_type.rs +++ b/packages/fuels-code-gen/src/program_bindings/resolved_type.rs @@ -76,8 +76,6 @@ impl TypeResolver { Self::to_sized_ascii_string, Self::to_ascii_string, Self::to_tuple, - Self::to_std_string, - Self::to_bytes, Self::to_raw_slice, Self::to_custom_type, ]; @@ -114,33 +112,6 @@ impl TypeResolver { })) } - fn to_std_string( - &self, - type_application: &FullTypeApplication, - ) -> Result> { - if &type_application.type_decl.type_field == "struct String" { - let type_name = quote! {::std::string::String}; - Ok(Some(ResolvedType { - type_name, - generic_params: vec![], - })) - } else { - Ok(None) - } - } - - fn to_bytes(&self, type_application: &FullTypeApplication) -> Result> { - if &type_application.type_decl.type_field == "struct Bytes" { - let type_name = quote! {::fuels::types::Bytes}; - Ok(Some(ResolvedType { - type_name, - generic_params: vec![], - })) - } else { - Ok(None) - } - } - fn to_array(&self, type_application: &FullTypeApplication) -> Result> { let type_decl = &type_application.type_decl; let Some(len) = extract_array_len(&type_decl.type_field) else { diff --git a/packages/fuels-core/src/codec/function_selector.rs b/packages/fuels-core/src/codec/function_selector.rs index ca811037b8..74802a2873 100644 --- a/packages/fuels-core/src/codec/function_selector.rs +++ b/packages/fuels-core/src/codec/function_selector.rs @@ -75,7 +75,6 @@ fn resolve_arg(arg: &ParamType) -> String { } ParamType::RawSlice => "rawslice".to_string(), ParamType::Bytes => "s(s(rawptr,u64),u64)".to_string(), - // `String` in Sway has the same memory layout as the bytes type ParamType::StdString => "s(s(s(rawptr,u64),u64))".to_string(), } } @@ -143,6 +142,15 @@ mod tests { } } + #[test] + fn handles_std_strings() { + let inputs = [ParamType::StdString]; + + let signature = resolve_fn_signature("some_fn", &inputs); + + assert_eq!(signature, "some_fn(s(s(s(rawptr,u64),u64)))"); + } + #[test] fn handles_arrays() { let inputs = [ParamType::Array(Box::new(ParamType::U8), 1)]; @@ -182,12 +190,12 @@ mod tests { } #[test] - fn handles_std_string() { - let inputs = [ParamType::StdString]; + fn handles_bytes() { + let inputs = [ParamType::Bytes]; let selector = resolve_fn_signature("some_fun", &inputs); - assert_eq!(selector, "some_fun(s(s(s(rawptr,u64),u64)))"); + assert_eq!(selector, "some_fun(s(s(rawptr,u64),u64))") } #[test] diff --git a/packages/fuels/tests/types/contracts/std_lib_string/Forc.toml b/packages/fuels/tests/types/contracts/std_lib_string/Forc.toml index 885035af8c..db2113c449 100644 --- a/packages/fuels/tests/types/contracts/std_lib_string/Forc.toml +++ b/packages/fuels/tests/types/contracts/std_lib_string/Forc.toml @@ -5,5 +5,3 @@ license = "Apache-2.0" name = "std_lib_string" [dependencies] - -std = { git = "https://github.com/FuelLabs/sway/", branch = "master" } diff --git a/packages/fuels/tests/types_contracts.rs b/packages/fuels/tests/types_contracts.rs index 84f3ad31fc..dcd89acad0 100644 --- a/packages/fuels/tests/types_contracts.rs +++ b/packages/fuels/tests/types_contracts.rs @@ -1,12 +1,9 @@ -#![allow(unused_imports, unused_variables)] use std::{result::Result as StdResult, str::FromStr}; -use fuel_tx::Receipt; use fuels::{ prelude::*, types::{Bits256, EvmAddress, Identity, SizedAsciiString, B512, U256}, }; -use fuels_core::{codec::ABIDecoder, fn_selector, types::param_types::ParamType}; pub fn null_contract_id() -> Bech32ContractId { // a bech32 contract address that decodes to [0u8;32]