Troubleshooting Stylus
How does Stylus manage security issues in smart contracts when interacting with so many different languages?
All languages are compiled to WASM for them to be able to work with Stylus. So it just needs to verify that the produced WASM programs behave as they should inside the new virtual machine.
Is there any analogue of the fallback function from Solidity in the Rust Stylus SDK?
Yes, starting with SDK version 0.7.0, the Router trait supports both fallback and receive methods, similar to their Solidity counterparts. The fallback method is called when a transaction has calldata
that doesn't match any defined function, while the receive method is called when a transaction has empty calldata. You can find more information in Fallback and receive
functions.
For older SDK versions (pre-0.7.0), you can use a minimal entrypoint and perform raw delegate calls, forwarding your calldata. You can find more information in Bytes-in, bytes-out programming and call, static_call and delegate_call.
Is it possible to verify Stylus contracts on the block explorer?
Currently it is not possible to verify contracts compiled to WASM on the block explorer, but we are actively working with providers to have the verification process ready for when Stylus reaches mainnet-ready status.
Do Stylus contracts compile down to EVM bytecode like prior other attempts?
No. Stylus contracts are compiled down to WASM. The user writes a program in Rust / C / C++ which is then compiled down to WebAssembly.
How is a Stylus contract deployed?
Stylus contracts are deployed onchain as a blob of bytes, just like EVM ones. The only difference is that when the contract executes, instead of invoking the EVM, we invoke a separate WASM runtime. Note that a special EOF-inspired prefix distinguishes Stylus contracts from traditional EVM contracts: when a contract's bytecode starts with the magic 0xEFF00000 prefix, it's a Stylus WASM contract.
Is there a new transaction type to deploy Stylus contracts?
You deploy a Stylus contract the same way that Solidity contracts are deployed. There are no special transaction types. As a UX note: a WASM will revert until a special instrumentation operation is performed by a call to the new ArbWasm precompile, which readies the program for calls on-chain.
You can find instructions for deploying a Stylus contract in our Quickstart.
Do Stylus contracts use a different type of ABI?
Stylus contracts use solidity ABIs. Methods, signatures, logs, calls, etc. work exactly as in the EVM. From a user's / explorer's perspective, it all just looks and behaves like Solidity.
Does the Stylus SDK for Rust support custom data structures?
For in-memory usage, you should be able to use any implementation of custom data structures without problems.
For storage usage, it may be more complicated. Stylus uses the EVM storage system, so you'll need to define the data structure on top of it. However, in the SDK, there's a storage trait that custom types can implement to back their collections with the EVM state trie. The SDK macros are also compatible with them, although it's still fundamentally a global key-value system.
You can read more about it in the Stylus Rust SDK page.
As an alternative solution, you can use entrypoint-style contracts for your custom data structures.
Why do I get an error "no library targets found in package" when trying to compile and old example?
Some of the first Stylus examples were built and deployed using a previous version of cargo-stylus (0.1.x). In that version, Stylus projects were structured as regular Rust binaries.
Since cargo-stylus v0.2.1, Stylus projects are structured as libraries, so when trying to compile old projects you might get an error no library targets found in package.
To solve this, it's usually enough to rename the main.rs file to a lib.rs file.
How can I generate the ABI of my Stylus contract?
The
has a command that allows you to export the ABI of your Stylus contract: cargo stylus export-abi.
If you're using the Stylus Rust SDK, you'll need to enable the export-abi feature in your Cargo.toml file like so:
[features]
export-abi = ["stylus-sdk/export-abi"]
You'll also need to have a main.rs file that selects that feature.
This is an example of a main.rs file that allows you to export the ABI of the stylus-hello-world example project:
#![cfg_attr(not(feature = "export-abi"), no_main)]
#[cfg(feature = "export-abi")]
fn main() {
stylus_hello_world::main();
}
How can I find out if the smart contract bytecode is from a Stylus contract or Solidity contract?
You can check the first three bytes of the code at the contract address. If they read 0xEFF000, it's a Stylus program. Otherwise, it will be from a Solidity contract.
I'm trying to work with cargo stylus on Windows and got error: failed to resolve: could not find unix in os
Cargo Stylus is just compatible with Unix operating systems and not Windows. You should install WSL (Windows Subsystem for Linux) before using that and then use WSL terminal to install and use cargo stylus.
How can I return a struct from a function?
Currently, the SDK doesn't support external structs directly, but support is in progress. For now, you can use tuples as output instead of structs.
Keep in mind that structs are mapped to tuples by the Solidity ABI. You can read more about this mapping here: Solidity ABI Specification.
Since the current SDK macro doesn't automatically handle struct-to-tuple conversions, you'll need to manually convert your struct into a tuple in the return type.
How can I get the WASM opcodes of the compiled Stylus contracts?
To view the WASM opcodes, you can convert the WebAssembly binary (WASM) to WebAssembly Text (WAT). This conversion is possible using the WebAssembly Binary Toolkit (wabt). An easy way to do this is to use the online tool Wasm-to-Wat converter, which is part of wabt.
For more information or if you'd like to use the toolkit locally, you can find wabt on GitHub.
What is the difference between .set and .setter?
.set**:** This method is used directly to set a value in storage. It's a straightforward way to assign a value if you only need to perform a one-time set operation..setter**:** This method provides a handle to a storage slot. It allows you to bothsetandgetthe value of the storage slot, making it more versatile if you need to access the current value and also update it. If you plan to both retrieve and modify a value frequently, it's more efficient to use.setter, assign it to a variable, and then use the.getand.setmethods on that variable. However, if you only need to set a value, you can use.setdirectly.