diff --git a/docs/stylus/gentle-introduction.mdx b/docs/stylus/gentle-introduction.mdx index a5190b6e2b..bf13daffeb 100644 --- a/docs/stylus/gentle-introduction.mdx +++ b/docs/stylus/gentle-introduction.mdx @@ -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 @@ -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. -::: + + +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. + + ### Execution diff --git a/docs/stylus/quickstart.mdx b/docs/stylus/quickstart.mdx index 930bd96f34..aa99618a91 100644 --- a/docs/stylus/quickstart.mdx +++ b/docs/stylus/quickstart.mdx @@ -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 + + Ensure your Docker service runs so this command works correctly. -::: + + ```shell cargo stylus check @@ -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 @@ -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)); } } ``` diff --git a/docs/stylus/troubleshooting/common-issues.mdx b/docs/stylus/troubleshooting/common-issues.mdx index e0a5b4fa3e..96f524848c 100644 --- a/docs/stylus/troubleshooting/common-issues.mdx +++ b/docs/stylus/troubleshooting/common-issues.mdx @@ -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**: @@ -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> { - ensure!(!b.is_zero(), "Division by zero"); + if b.is_zero() { + return Err(b"Division by zero".to_vec()); + } Ok(a / b) } ``` @@ -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); @@ -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