Hello everyone!
In an attempt to implement a token contract on fuel I forked swayswap’s token contract and noticed that swayswap’s token doesn’t support the same fields like name
, symbol
, and decimals
.
Then in one of my previous topics @david sent me a topic with src-20 fungible token standard, but there is no name
, symbol
implementation too…
And today I decided to figure out how I can store strings in the storage.
In the progress of my research I found some solutions, let’s take a closer look at them:
- First of all I decided to use
str[n]
like a string. But there is one big minus: we definitely need to know the length of the line.
In that case, we can hardcode some strings before deploying the dApp, but it’s impossible to change the strings.
contract;
abi MyContract {
#[storage(read)]
fn name() -> str[9];
}
storage {
name: str[9] = "sway gang",
}
impl MyContract for Contract {
#[storage(read)]
fn name() -> str[9] {
storage.name
}
}
- The next thing that came to my mind is store strings like
str[32]
. Here we can store and change strings less than 32 symbols likesway gang_______________________
and each time you write/read remove/add to the end of the line symbols_
in quantity32 - string_length
. But it looks ugly and not convenient.
contract;
abi MyContract {
#[storage(read)]
fn name() -> str[32];
#[storage(write)]
fn set_name(name: str[32]);
}
storage {
name: str[32] = "sway gang_______________________",
}
impl MyContract for Contract {
#[storage(read)]
fn name() -> str[32] {
storage.name
}
#[storage(write)]
fn set_name(name: str[32]){
storage.name = name;
}
}
- After that I discovered there is awesome package sway_libs::string::String. And we can use it very well but… Yup the strings library is excellent for dynamically-sized strings. That type does not work in a storage block though because it’s a heap type.
Btw I will show what the code can look like. Anyway you can copy the code and use Strings without storage
Forc.toml
[project]
authors = ["SWAY GANG"]
entry = "main.sw"
license = "Apache-2.0"
name = "name_contract"
[dependencies]
sway_libs = { git = "https://github.com/FuelLabs/sway-libs", tag = "v0.4.1" }
main.sw
contract;
use sway_libs::string::String;
abi MyContract {
#[storage(read)]
fn name() -> String;
#[storage(write)]
fn set_name(name: String);
}
storage {
name: String = String::new(), // here code is wrong
}
impl MyContract for Contract {
#[storage(read)]
fn name() -> String {
storage.name
}
#[storage(write)]
fn set_name(name: String){
storage.name = name;
}
}
- So, as under the hood package sway_libs::string::String use
Vec<u8>
my final try was with usingStorageVec<u8>
. The contract will look like that
contract;
use std::{storage::StorageVec};
abi MyContract {
#[storage(read)]
fn name() -> StorageVec<u8>;
// todo
// #[storage(write)]
// fn set_name(name: StorageVec<u8>);
}
storage {
name: StorageVec<u64> = StorageVec {},
}
impl MyContract for Contract {
#[storage(read)]
fn name() -> StorageVec<u8> {
storage.name
}
// todo
// #[storage(write)]
// fn set_name(name: StorageVec<u8>){
// storage.name = name;
// }
}
and the test will look like tahat:
use fuels::{prelude::*, tx::ContractId};
abigen!(MyContract, "out/debug/name_contract-abi.json");
async fn get_contract_instance() -> (MyContract, ContractId) {
let mut wallets = launch_custom_provider_and_get_wallets(
WalletsConfig::new(
Some(1),
Some(1),
Some(1_000_000_000),
),
None,
None,
)
.await;
let wallet = wallets.pop().unwrap();
let id = Contract::deploy(
"./out/debug/name_contract.bin",
&wallet,
TxParameters::default(),
StorageConfiguration::with_storage_path(Some(
"./out/debug/name_contract-storage_slots.json".to_string(),
)),
)
.await
.unwrap();
let instance = MyContract::new(id.clone(), wallet);
(instance, id.into())
}
#[tokio::test]
async fn can_get_contract_id() {
let (_instance, _id) = get_contract_instance().await;
// todo
// _instance.methods().set_name("SWAY GANG".as_bytes()).call().await.unwrap()
}
But after
forc build
and cargo test
it It’s falling with this error
error[E0392]: parameter `V` is never used
--> tests/harness.rs:3:1
|
3 | abigen!(MyContract, "out/debug/name_contract-abi.json");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused parameter
|
= help: consider removing `V`, referring to it in a field, or using a marker such as `PhantomData`
= note: this error originates in the macro `abigen` (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0392`.
error: could not compile `name-contract` due to previous error
So, can someone explain to me what I’m doing wrong and how I store and update the name in the dApp store?