Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions docs/stylus/gentle-introduction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Stylus is an upgrade to Arbitrum Nitro [(ArbOS 32)](/run-arbitrum-node/arbos-rel

This second virtual machine executes WebAssembly (WASM) rather than EVM bytecode. WASM is a binary format used in web standards and browsers for efficient computation. Its design is to be portable and human-readable, with sandboxed execution environments for security. Working with WASM is nothing new for Arbitrum chains. Ever since the [Nitro upgrade](https://medium.com/offchainlabs/arbitrum-nitro-one-small-step-for-l2-one-giant-leap-for-ethereum-bc9108047450), WASM has been a fundamental component of Arbitrum's fraud proofs.

With a WASM VM, any programming language compilable to WASM is within Stylus's scope. While many popular programming languages can compile to WASM, some compilers are better suited to smart contract development than others, such as Rust, C, and C++. Other languages like Go, Sway, Move, and Cairo are also supported. Languages that include their own runtimes, like Python and JavaScript, are more complex for Stylus to support, although not impossible. WASM programs tend to be more efficient than EVM bytecode for memory-intensive applications. This efficiency comes from mature compiler toolchains for languages like Rust and C, which have benefited from decades of optimization work. The WASM runtime also executes faster than the EVM interpreter. Third-party contributions in the form of libraries for new and existing languages are welcome.
With a WASM VM, any programming language compilable to WASM is within Stylus's scope. In practice, some compilers are better suited to smart contract development than others. Rust has the first-class, fully supported SDK, and C and C++ are also supported. Any other language that compiles to WASM is theoretically possible, but support for those is experimental rather than officially maintained. Languages that include their own runtimes, like Python and JavaScript, are more complex for Stylus to support, although not impossible. WASM programs tend to be more efficient than EVM bytecode for memory-intensive applications. This efficiency comes from mature compiler toolchains for languages like Rust and C, which have benefited from decades of optimization work. The WASM runtime also executes faster than the EVM interpreter. Third-party contributions in the form of libraries for new and existing languages are welcome.

## How Stylus works

Expand All @@ -44,9 +44,11 @@ To make your contract callable, it must undergo an [activation process](/stylus/

Stylus measures computational costs using ink instead of gas. Ink works like gas but is thousands of times smaller. WASM executes faster than the EVM, so a single EVM operation takes as long as thousands of WASM operations. A finer-grained unit makes pricing more precise.

:::note
Stylus contracts need to be reactivated once per year (365 days) or after any Stylus upgrade. You can do this using [`cargo-stylus`](/stylus/cli-tools/commands-reference) or the [ArbWasm precompile](/arbitrum-essentials/precompiles/reference#common-precompiles). If a contract isn't reactivated, it becomes uncallable.
:::
<VanillaAdmonition type="note">

Stylus contracts need to be reactivated once per year (365 days) or after any Stylus upgrade. You can do this using [`cargo-stylus`](/stylus/cli-tools/commands-reference) or the [ArbWasm precompile](/arbitrum-essentials/precompiles/reference#common-precompiles). If a contract isn't reactivated, it becomes uncallable. The 365-day expiry and a minimum age of about 31 days before a contract can be kept alive are both configurable chain parameters; these are the current defaults.

</VanillaAdmonition>

### Execution

Expand Down
31 changes: 15 additions & 16 deletions docs/stylus/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,11 @@ At this point, you can move on to the next step of this guide or develop your fi

By running `cargo stylus check` against your first contract, you can check if your program can be successfully **deployed and activated** onchain.

:::warning Important
<VanillaAdmonition type="warning" title="Important">

Ensure your Docker service runs so this command works correctly.
:::

</VanillaAdmonition>

```shell
cargo stylus check
Expand Down Expand Up @@ -285,15 +287,14 @@ Our contract is a counter; in its initial state, it should store a counter value
You can call your contract so it returns its current counter value by sending it the following command:

```shell title="Call to the function: number()(uint256)"
cast call --rpc-url 'http://localhost:8547' --private-key 0xb6b15c8cb491557369f3c7d2c287b053eb229daa9c22138887752191c9520659 \
cast call --rpc-url 'http://localhost:8547' \
[deployed-contract-address] "number()(uint256)"
```

Let's break down the command:

- `cast call` command sends a call to your contract
- `cast call` command sends a read-only call to your contract (no transaction is sent, so no private key is needed)
- The `--rpc-url` option is the `RPC URL` endpoint of our testnode: http://localhost:8547
- The `--private-key` option is the private key of our pre-funded development account. It corresponds to the address `0x3f1eae7d46d88f08fc2f8ed27fcb2ab183eb2d0e`
- The [deployed-contract-address] is the address we want to interact with, it's the address that was returned by `cargo stylus deploy`
- `number()(uint256)` is the function we want to call in Solidity-style signature. The function returns the counter's current value

Expand Down Expand Up @@ -347,26 +348,24 @@ to test the counter contract:
#[cfg(test)]
mod test {
use super::*;
use alloy_primitives::address;
use stylus_sdk::testing::*;

#[test]
fn test_counter_operations() {
// Set up test environment
// Set up the test VM and instantiate the contract
let vm = TestVM::default();
// Initialize your contract
let mut contract = Counter::from(&vm);

// Test initial state
assert_eq!(contract.number().unwrap(), U256::ZERO);
// Initial state: the counter starts at zero
assert_eq!(contract.number(), U256::ZERO);

// Test increment
contract.increment().unwrap();
assert_eq!(contract.number().unwrap(), U256::from(1));
// increment() updates storage
contract.increment();
assert_eq!(contract.number(), U256::from(1));

// Test set number
contract.set_number(U256::from(5)).unwrap();
assert_eq!(contract.number().unwrap(), U256::from(5));
// set_number() overwrites the stored value
contract.set_number(U256::from(5));
assert_eq!(contract.number(), U256::from(5));
}
}
```
Expand Down
17 changes: 10 additions & 7 deletions docs/stylus/troubleshooting/common-issues.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -102,17 +102,18 @@ strip = true # Remove debug symbols
panic = "abort" # Smaller panic handling
```

2. **Use wasm-opt**:
2. **Run `wasm-opt` on the compiled binary**:

```shell
cargo stylus check --wasm-opt
wasm-opt -Oz target/wasm32-unknown-unknown/release/your_contract.wasm \
-o optimized.wasm
```

3. **Remove unused dependencies**:

```toml
# Remove unnecessary features
stylus-sdk = { version = "0.8", default-features = false }
stylus-sdk = { version = "0.10.7", default-features = false }
```

4. **Check binary size**:
Expand Down Expand Up @@ -259,7 +260,9 @@ pub fn divide(&self, a: U256, b: U256) -> U256 {

// ✅ Good: Returns error
pub fn divide(&self, a: U256, b: U256) -> Result<U256, Vec<u8>> {
ensure!(!b.is_zero(), "Division by zero");
if b.is_zero() {
return Err(b"Division by zero".to_vec());
}
Ok(a / b)
}
```
Expand Down Expand Up @@ -363,7 +366,7 @@ mod tests {
let mut contract = MyContract::from(&vm);

// Configure test environment
vm.set_caller(address!("0x0000000000000000000000000000000000000001"));
vm.set_sender(address!("0x0000000000000000000000000000000000000001"));

// Run tests
assert_eq!(contract.get_value().unwrap(), U256::ZERO);
Expand Down Expand Up @@ -580,12 +583,12 @@ Include:
| ------------------------------------------ | ------------------------- | ------------------------------------------ |
| "target not found: wasm32-unknown-unknown" | WASM target not installed | `rustup target add wasm32-unknown-unknown` |
| "Cannot connect to Docker daemon" | Docker not running | Start Docker Desktop |
| "Program too large" | Binary exceeds size limit | Add optimization flags, use `--wasm-opt` |
| "Program too large" | Binary exceeds size limit | Add optimization flags, run `wasm-opt` |
| "Insufficient funds" | Not enough ETH for gas | Fund account from faucet |
| "Nonce too low" | Nonce mismatch | Let tooling manage nonces |
| "Out of gas" | Gas limit exceeded | Increase gas limit or optimize code |
| "Storage not initialized" | Missing TestVM setup | Initialize `TestVM::default()` in tests |
| "Division by zero" | Unchecked arithmetic | Use `ensure!()` or `checked_div()` |
| "Division by zero" | Unchecked arithmetic | Return an error or use `checked_div()` |

## Next steps

Expand Down
Loading