Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Returning a wrapped Bytes type from contracts #940

Closed
bitzoic opened this issue Apr 18, 2023 · 0 comments · Fixed by #1106
Closed

Returning a wrapped Bytes type from contracts #940

bitzoic opened this issue Apr 18, 2023 · 0 comments · Fixed by #1106
Assignees

Comments

@bitzoic
Copy link
Member

bitzoic commented Apr 18, 2023

Returning of a Bytes type has recently been introduced and is playing a vital part in developer's contracts, libraries, and Fuel standards. This has enabled a number of different features such as the String type.
However, returning a wrapped Bytes type is currently prohibited. This is key for certain features, such as returning a String or Option<Bytes>.

The current definition of the String type is the following. This has enabled UTF-8 encoded strings in the Sway language and opened the possibility for NFT's URIs, Fuel Name Service, and more.

pub struct String {
    bytes: Bytes,
}

An example where this is needed is in the FRC-20 and FRC-721 standards that have been introduced. There has recently been a push to create standards for Fuel and having the ability to return a String is critical. We currently have the following ABI definitions for our standards:

    /// Get the name of the token
    /// Example (with trailing padding): "MY_TOKEN                                                        "
    fn name() -> str[64];
    /// A distinct Uniform Resource Identifier (URI) for a given asset.
    /// URIs are defined in RFC-3986.
    fn uri(token_id: u64) -> str[2048];

These definitions suffer from having a static length, requiring lots of white space or possibly not being long enough in certain cases. Instead, we would like to update these to the following:

    /// Get the name of the token
    fn name() -> String;
    /// A distinct Uniform Resource Identifier (URI) for a given asset.
    /// URIs are defined in RFC-3986.
    fn uri(token_id: u64) -> String;

As of today, we are able to pass a String to a contract by manually constructing the struct and passing it to the contract. While this is less than ideal, it still offers the ability to pass a String to a contract. For example, here we construct the String struct and pass it to the contract. This works as expected.

#[tokio::test]
async fn takes_string_test() {
    let instance = setup().await;

    let string = "Fuel is blazingly fast!";
    let input = String {
        bytes: Bytes(string.as_bytes().to_vec()),
    };

    instance.methods().takes_string(input).call().await.unwrap();
}

However, returning of a String is incompatible with the rust sdk. While the following compiles, it will give a runtime error using the rust sdk:

    fn returns_string() -> String {
        let mut my_string = String::new();

        my_string.bytes.push(0u8);
        my_string.bytes.push(1u8);
        my_string.bytes.push(2u8);

        my_string
    }

    fn returns_bytes_option() -> Option<Bytes> {
        let mut my_bytes = Bytes::new();

        my_bytes.push(0u8);
        my_bytes.push(1u8);
        my_bytes.push(2u8);

        Option::Some(my_bytes)
    }

Screenshot 2023-04-18 131334

Returning a wrapped Bytes type is necessary for URIs, token names, FNS, symbols, FRC standards, and more within the Fuel ecosystem.

This has been tested with forc v0.37.0 and fuels-rs v0.41.0

@bitzoic bitzoic changed the title Passing and returning the Bytes type from contracts Returning a wrapped Bytes type from contracts Apr 18, 2023
@bitzoic bitzoic removed the blocked label Apr 18, 2023
@iqdecay iqdecay closed this as completed Apr 18, 2023
@iqdecay iqdecay reopened this Apr 18, 2023
@iqdecay iqdecay self-assigned this Apr 18, 2023
bitzoic added a commit to FuelLabs/sway-libs that referenced this issue Apr 20, 2023
## Type of change

<!--Delete points that do not apply-->

- New feature

## Changes

The following changes have been made:

- Added `StorageString` type
- Added `from_raw_slice()` and `as_raw_slice()` to the `String` type
- Updated src README wording, links, and added `StorageString`
- Moved `String` into `sway-libs/libs/strings` folder with the
`StorageString` type
- Updated `String` README and SPECIFICATION to remove outdated info
- Updated `String` to use non-mutable types in `from_utf8()`

## Notes

- The `From<raw_slice>` implementation for the `String` type is
commented out until FuelLabs/sway#3637 is
resolved. The `from_raw_slice()` shall be removed when this is
reimplemented
- Tests for the `from_raw_slice()` and `as_raw_slice()` functions have
been commented out until FuelLabs/sway#4408 is
resolved
- Until FuelLabs/fuels-rs#940 is resolved,
developers must return any `StorageString`s from storage as a `Bytes`
type
- This should unblock NFT URIs, Fuel Name Service, token standards, and
more

## Related Issues

<!--Delete everything after the "#" symbol and replace it with a number.
No spaces between hash and number-->

Closes #40

---------

Co-authored-by: bitzoic <cameron.carstens@fuel.sh>
iqdecay added a commit that referenced this issue Oct 6, 2023
This PR enables returning heap types surrounded in an `Enum` type. It
notably enables returning a `Result<Vec>` from a contract call.

Closes #940.

Main disavantages from this approach: 
- We are injecting more custom bytecode
- Enum can contain only one variant that uses a heap type inside. It
could be extended to having an arbitrary number of them, but they would
all have to have the same encoding width. This is a personal design
choice. 
Co-authored-by: segfault-magnet <37515857+segfault-magnet@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants