I want to use the bytes crate in an ink! smart contract of mine. Also I want to declare a Byte value in the ink_storage struct. However, I cannot figure out how to do this. After hours of trying and not finding a solution. Is there some documentation which could help me, or a predefined way?
2 Answers
It's possible to store custom types in your smart contract as long as they meet all the right requirements.
For ink! this means that your type must at minimum implement the SpreadLayout
and StorageLayout
traits.
This gets slightly tricky when the type comes from an external crate due to Rust's Orphan Rules which don't let you implement foreign traits for foreign types.
One way to work around this is to create a wrapper type and implement the traits on that:
//! In your smart contract
use some_crate::SomeType;
// This is what you'll end up putting in your #[ink(storage)] struct
pub struct Wrapper(SomeType);
// Note, this may end up being hard to implement manually depending on the
// complexity of your type
impl SpreadLayout for Wrapper { ... }
// We only need this during metadata generation, which happens in an environment where we
// have access to the standard library and OS.
#[cfg(feature = "std")]
const _: () = {
impl StorageLayout for Wrapper { ... }
};
Another, as Bruno mentioned, is to open a PR in the ink! repo and implement the traits directly for that type.
It is not that simple as ink! is an embedded Domain Specific Language (eDSL). Also note that ink! works in a no_std
environment so not everything that is std
is compatible. You can find the available ink! data structures in the ink_prelude and in the ink_prelude docs it clearly states:
These definitions are useful since we are operating in a no_std environment and should be used by all ink! crates instead of directly using std or alloc crates. If needed we shall instead enhance the exposed types here.
So if you do see a use case for Bytes
in ink! you can create an issue or PR in their repo to extend the ink! eDSL.
Also note that you can use vectors to store UTF-8 bytes:
data: Vec<u8>
utf8
for the same reasons you shouldn't store arbitrary strings. You should try to minimise your contract storage costs by using hashes instead and then decode on the client side.