Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into bug/unused_generic_…
Browse files Browse the repository at this point in the history
…args
  • Loading branch information
segfault-magnet committed Oct 9, 2023
2 parents 7914b15 + 22f10db commit d911b09
Show file tree
Hide file tree
Showing 55 changed files with 1,089 additions and 340 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ env:
DASEL_VERSION: https://github.com/TomWright/dasel/releases/download/v1.24.3/dasel_linux_amd64
RUSTFLAGS: "-D warnings"
FUEL_CORE_VERSION: 0.20.4
RUST_VERSION: 1.71.1
FORC_VERSION: 0.45.0
RUST_VERSION: 1.72.0
FORC_VERSION: 0.46.0
FORC_PATCH_BRANCH: ""
FORC_PATCH_REVISION: ""

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ jobs:
test:
uses: FuelLabs/github-actions/.github/workflows/mdbook-docs.yml@master
with:
docs-src-path: 'docs/src'

docs-src-path: "docs/src"
pre-command: 'cargo run --package versions-replacer -- ./docs --manifest-path ./Cargo.toml --filename-regex "\.md$"'
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ members = [
"packages/fuels-test-helpers",
"packages/wasm-tests",
"scripts/check-docs",
"scripts/versions-replacer",
]

[workspace.package]
Expand All @@ -34,7 +35,7 @@ homepage = "https://fuel.network/"
readme = "README.md"
license = "Apache-2.0"
repository = "https://github.com/FuelLabs/fuels-rs"
rust-version = "1.71.1"
rust-version = "1.72.0"
version = "0.48.0"

[workspace.dependencies]
Expand Down
2 changes: 1 addition & 1 deletion docs/src/calling-contracts/call-params.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ The parameters for a contract call are:
3. Gas forwarded
<!-- call_params:example:end -->

You can use these to forward coins to a contract. You can configure these parameters by creating an instance of [`CallParameters`](https://docs.rs/fuels/latest/fuels/programs/contract/struct.CallParameters.html) and passing it to a chain method called `call_params`.
You can use these to forward coins to a contract. You can configure these parameters by creating an instance of [`CallParameters`](https://docs.rs/fuels/{{versions.fuels}}/fuels/programs/contract/struct.CallParameters.html) and passing it to a chain method called `call_params`.
<!-- use_call_params:example:end -->

For instance, suppose the following contract that uses Sway's `msg_amount()` to return the amount sent in that transaction.
Expand Down
2 changes: 2 additions & 0 deletions docs/src/calling-contracts/logs.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ You can use the `decode_logs()` function to retrieve a `LogResult` struct contai
```

Due to possible performance hits, it is not recommended to use `decode_logs()` outside of a debugging scenario.

> **Note:** String slices can not be logged directly. Use the `__to_str_array()` function to convert it to a `str[N]` first.
2 changes: 1 addition & 1 deletion docs/src/connecting/querying.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Querying the blockchain

Once you set up a provider, you can interact with the Fuel blockchain. Here are a few examples of what you can do with a provider; for a more in-depth overview of the API, check the [official provider API documentation](https://docs.rs/fuels/latest/fuels/accounts/provider/struct.Provider.html).
Once you set up a provider, you can interact with the Fuel blockchain. Here are a few examples of what you can do with a provider; for a more in-depth overview of the API, check the [official provider API documentation](https://docs.rs/fuels/{{versions.fuels}}/fuels/accounts/provider/struct.Provider.html).

- [Set up](#set-up)
- [Get all coins from an address](#get-all-coins-from-an-address)
Expand Down
4 changes: 2 additions & 2 deletions docs/src/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ cargo test -- --nocapture
Add these dependencies on your `Cargo.toml`:

```toml
fuels = "0.48"
fuels = "{{versions.fuels}}"
```

> **Note** We're using version `0.48` of the SDK, which is the latest version at the time of this writing.
> **Note** We're using version `{{versions.fuels}}` of the SDK, which is the latest version at the time of this writing.
And then, in your Rust file that's going to make use of the SDK:

Expand Down
2 changes: 1 addition & 1 deletion docs/src/reference.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# API Reference

For a more in-depth look at the APIs provided by the Fuel Rust SDK, head over to the [official documentation](https://docs.rs/fuels/latest/fuels/). In the actual Rust docs, you can see the most up-to-date information about the API, which is synced with the code as it changes.
For a more in-depth look at the APIs provided by the Fuel Rust SDK, head over to the [official documentation](https://docs.rs/fuels/{{versions.fuels}}/fuels/). In the actual Rust docs, you can see the most up-to-date information about the API, which is synced with the code as it changes.
2 changes: 1 addition & 1 deletion docs/src/types/address.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Address

Like `Bytes32`, `Address` is a wrapper on `[u8; 32]` with similar methods and implements the same traits (see [fuel-types documentation](https://docs.rs/fuel-types/latest/fuel_types/struct.Address.html)).
Like `Bytes32`, `Address` is a wrapper on `[u8; 32]` with similar methods and implements the same traits (see [fuel-types documentation](https://docs.rs/fuel-types/{{versions.fuel-types}}/fuel_types/struct.Address.html)).

These are the main ways of creating an `Address`:

Expand Down
2 changes: 1 addition & 1 deletion docs/src/types/asset-id.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# AssetId

Like `Bytes32`, `AssetId` is a wrapper on `[u8; 32]` with similar methods and implements the same traits (see [fuel-types documentation](https://docs.rs/fuel-types/latest/fuel_types/struct.AssetId.html)).
Like `Bytes32`, `AssetId` is a wrapper on `[u8; 32]` with similar methods and implements the same traits (see [fuel-types documentation](https://docs.rs/fuel-types/{{versions.fuel-types}}/fuel_types/struct.AssetId.html)).

These are the main ways of creating an `AssetId`:

Expand Down
2 changes: 1 addition & 1 deletion docs/src/types/bytes32.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ These are the main ways of creating a `Bytes32`:
{{#include ../../../examples/types/src/lib.rs:bytes32_format}}
```

For a full list of implemented methods and traits, see the [fuel-types documentation](https://docs.rs/fuel-types/latest/fuel_types/struct.Bytes32.html).
For a full list of implemented methods and traits, see the [fuel-types documentation](https://docs.rs/fuel-types/{{versions.fuel-types}}/fuel_types/struct.Bytes32.html).

> **Note:** In Fuel, there's a special type called `b256`, which is similar to `Bytes32`; also used to represent hashes, and it holds a 256-bit value. In Rust, through the SDK, this is represented as `Bits256(value)` where `value` is a `[u8; 32]`. If your contract method takes a `b256` as input, all you need to do is pass a `Bits256([u8; 32])` when calling it from the SDK.
2 changes: 1 addition & 1 deletion docs/src/types/contract-id.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ContractId

Like `Bytes32`, `ContractId` is a wrapper on `[u8; 32]` with similar methods and implements the same traits (see [fuel-types documentation](https://docs.rs/fuel-types/latest/fuel_types/struct.ContractId.html)).
Like `Bytes32`, `ContractId` is a wrapper on `[u8; 32]` with similar methods and implements the same traits (see [fuel-types documentation](https://docs.rs/fuel-types/{{versions.fuel-types}}/fuel_types/struct.ContractId.html)).

These are the main ways of creating a `ContractId`:

Expand Down
6 changes: 3 additions & 3 deletions examples/contracts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ mod tests {
.await?;
// ANCHOR_END: contract_call_cost_estimation

assert_eq!(transaction_cost.gas_used, 331);
assert_eq!(transaction_cost.gas_used, 397);

Ok(())
}
Expand Down Expand Up @@ -364,7 +364,7 @@ mod tests {
let response = contract_methods.mint_coins(1_000_000).call().await?;
// ANCHOR: variable_outputs
let address = wallet.address();
let asset_id = contract_id.asset_id(&Bits256::zeroed()).into();
let asset_id = contract_id.asset_id(&Bits256::zeroed());

// withdraw some tokens to wallet
let response = contract_methods
Expand Down Expand Up @@ -657,7 +657,7 @@ mod tests {
.await?;
// ANCHOR_END: multi_call_cost_estimation

assert_eq!(transaction_cost.gas_used, 542);
assert_eq!(transaction_cost.gas_used, 618);

Ok(())
}
Expand Down
1 change: 1 addition & 0 deletions packages/fuels-code-gen/src/program_bindings/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ mod tests {
pub(crate) fn sdk_provided_custom_types_lookup() -> HashMap<TypePath, TypePath> {
[
("std::address::Address", "::fuels::types::Address"),
("std::contract_id::AssetId", "::fuels::types::AssetId"),
("std::b512::B512", "::fuels::types::B512"),
("std::bytes::Bytes", "::fuels::types::Bytes"),
("std::contract_id::ContractId", "::fuels::types::ContractId"),
Expand Down
67 changes: 67 additions & 0 deletions packages/fuels-core/src/codec/abi_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,73 @@ mod tests {
Ok(())
}

#[test]
fn decoding_enum_with_more_than_one_heap_type_variant_fails() -> Result<()> {
let mut param_types = vec![
ParamType::U64,
ParamType::Bool,
ParamType::Vector(Box::from(ParamType::U64)),
];
// empty data
let data = [
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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
];
let variants = EnumVariants::new(param_types.clone())?;
let enum_param_type = ParamType::Enum {
variants,
generics: vec![],
};
// it works if there is only one heap type
let _ = ABIDecoder::default().decode(&enum_param_type, &data)?;

param_types.append(&mut vec![ParamType::Bytes]);
let variants = EnumVariants::new(param_types)?;
let enum_param_type = ParamType::Enum {
variants,
generics: vec![],
};
// fails if there is more than one variant using heap type in the enum
let error = ABIDecoder::default()
.decode(&enum_param_type, &data)
.expect_err("Should fail");
let expected_error =
"Invalid type: Enums currently support only one heap-type variant. Found: 2"
.to_string();
assert_eq!(error.to_string(), expected_error);

Ok(())
}

#[test]
fn enums_w_too_deeply_nested_heap_types_not_allowed() {
let param_types = vec![
ParamType::U8,
ParamType::Struct {
fields: vec![ParamType::RawSlice],
generics: vec![],
},
];
let variants = EnumVariants::new(param_types).unwrap();
let enum_param_type = ParamType::Enum {
variants,
generics: vec![],
};

let err = ABIDecoder::default()
.decode(&enum_param_type, &[])
.expect_err("should have failed");

let Error::InvalidType(msg) = err else {
panic!("Unexpected err: {err}");
};

assert_eq!(
msg,
"Enums currently support only one level deep heap types."
);
}

#[test]
fn max_depth_surpassed() {
const MAX_DEPTH: usize = 2;
Expand Down
23 changes: 8 additions & 15 deletions packages/fuels-core/src/codec/abi_decoder/bounded_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ impl BoundedDecoder {
}

pub(crate) fn decode(&mut self, param_type: &ParamType, bytes: &[u8]) -> Result<Token> {
Self::is_type_decodable(param_type)?;
param_type.validate_is_decodable()?;
Ok(self.decode_param(param_type, bytes)?.token)
}

Expand All @@ -46,24 +46,13 @@ impl BoundedDecoder {
bytes: &[u8],
) -> Result<Vec<Token>> {
for param_type in param_types {
Self::is_type_decodable(param_type)?;
param_type.validate_is_decodable()?;
}
let (tokens, _) = self.decode_params(param_types, bytes)?;

Ok(tokens)
}

fn is_type_decodable(param_type: &ParamType) -> Result<()> {
if param_type.contains_nested_heap_types() {
Err(error!(
InvalidType,
"Type {param_type:?} contains nested heap types (`Vec` or `Bytes`), this is not supported."
))
} else {
Ok(())
}
}

fn run_w_depth_tracking(
&mut self,
decoder: impl FnOnce(&mut Self) -> Result<Decoded>,
Expand Down Expand Up @@ -312,8 +301,12 @@ impl BoundedDecoder {

let discriminant = peek_u32(bytes)? as u8;
let selected_variant = variants.param_type_of_variant(discriminant)?;

let words_to_skip = enum_width - selected_variant.compute_encoding_width();
let skip_extra = variants
.heap_type_variant()
.is_some_and(|(heap_discriminant, _)| heap_discriminant == discriminant)
.then_some(3);
let words_to_skip =
enum_width - selected_variant.compute_encoding_width() + skip_extra.unwrap_or_default();
let enum_content_bytes = skip(bytes, words_to_skip * WORD_SIZE)?;
let result = self.decode_token_in_enum(enum_content_bytes, variants, selected_variant)?;

Expand Down
20 changes: 18 additions & 2 deletions packages/fuels-core/src/codec/logs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ use fuel_tx::{ContractId, Receipt};
use crate::{
codec::{try_from_bytes, DecoderConfig},
traits::{Parameterize, Tokenizable},
types::errors::{error, Error, Result},
types::{
errors::{error, Error, Result},
param_types::ParamType,
},
};

#[derive(Clone)]
Expand All @@ -31,9 +34,22 @@ impl LogFormatter {
decoder_config: DecoderConfig,
bytes: &[u8],
) -> Result<String> {
Self::can_decode_log_with_type::<T>()?;
Ok(format!("{:?}", try_from_bytes::<T>(bytes, decoder_config)?))
}

fn can_decode_log_with_type<T: Parameterize>() -> Result<()> {
match T::param_type() {
// String slices can not 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!(
InvalidData,
"String slices can not be decoded from logs. Convert the slice to `str[N]` with `__to_str_array`"
)),
_ => Ok(()),
}
}

pub fn can_handle_type<T: Tokenizable + Parameterize + 'static>(&self) -> bool {
TypeId::of::<T>() == self.type_id
}
Expand Down Expand Up @@ -162,7 +178,7 @@ impl LogDecoder {
let target_ids: HashSet<LogId> = self
.log_formatters
.iter()
.filter(|&(_, log_formatter)| log_formatter.can_handle_type::<T>())
.filter(|(_, log_formatter)| log_formatter.can_handle_type::<T>())
.map(|(log_id, _)| log_id.clone())
.collect();

Expand Down
43 changes: 39 additions & 4 deletions packages/fuels-core/src/types/enum_variants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@ pub struct EnumVariants {

impl EnumVariants {
pub fn new(param_types: Vec<ParamType>) -> Result<EnumVariants> {
if !param_types.is_empty() {
Ok(EnumVariants { param_types })
} else {
Err(error!(InvalidData, "Enum variants can not be empty!"))
if param_types.is_empty() {
return Err(error!(InvalidData, "Enum variants can not be empty!"));
}
Ok(EnumVariants { param_types })
}

pub fn param_types(&self) -> &[ParamType] {
Expand All @@ -34,6 +33,13 @@ impl EnumVariants {
})
}

pub fn heap_type_variant(&self) -> Option<(u8, &ParamType)> {
self.param_types()
.iter()
.enumerate()
.find_map(|(d, p)| p.is_extra_receipt_needed(false).then_some((d as u8, p)))
}

pub fn only_units_inside(&self) -> bool {
self.param_types
.iter()
Expand Down Expand Up @@ -64,3 +70,32 @@ impl EnumVariants {
(biggest_variant_width - variant_width) * WORD_SIZE
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_get_heap_type_variant_discriminant() -> Result<()> {
let param_types = vec![
ParamType::U64,
ParamType::Bool,
ParamType::Vector(Box::from(ParamType::U64)),
];
let variants = EnumVariants::new(param_types)?;
assert_eq!(variants.heap_type_variant().unwrap().0, 2);

let param_types = vec![
ParamType::Vector(Box::from(ParamType::U64)),
ParamType::U64,
ParamType::Bool,
];
let variants = EnumVariants::new(param_types)?;
assert_eq!(variants.heap_type_variant().unwrap().0, 0);

let param_types = vec![ParamType::U64, ParamType::Bool];
let variants = EnumVariants::new(param_types)?;
assert!(variants.heap_type_variant().is_none());
Ok(())
}
}
Loading

0 comments on commit d911b09

Please sign in to comment.