### Setup Project Environment with PNPM Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/contributors/contributing.md Installs project dependencies and builds the project using PNPM. This is the initial setup step for contributors. ```bash git clone https://github.com/CoBuilders-xyz/hardhat-arbitrum-stylus.git cd hardhat-arbitrum-stylus pnpm install pnpm build ``` -------------------------------- ### Node Startup Flow Example (TypeScript) Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/contributors/deep-dive/node.md A simplified TypeScript example demonstrating the sequence of operations during the node startup process. This includes starting the container, performing essential chain setup, prefunding accounts, and deploying Stylus infrastructure. ```typescript const containerInfo = await manager.start(containerConfig); await performEssentialSetup(rpcUrl, devKey, quiet); await prefundAccounts(rpcUrl, devKey, quiet); await deployCreate2Factory(rpcUrl, devKey, quiet); await deployCacheManager(rpcUrl, devKey, quiet); await deployStylusDeployer(rpcUrl, devKey, quiet); ``` -------------------------------- ### Install Rustup (Bash) Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/compile.md This script installs `rustup`, the Rust toolchain installer. It's a prerequisite for using the Host compilation mode in the Hardhat Arbitrum Stylus plugin. ```bash curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` -------------------------------- ### Install Host Mode Prerequisites Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/deploy.md These shell commands outline the necessary steps to install the prerequisites for using Hardhat's host mode deployment. This includes installing rustup, cargo-stylus, and the required Rust toolchain version with the wasm32-unknown-unknown target. ```bash # Install rustup (if not already installed) curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # Install cargo-stylus cargo install cargo-stylus # For each toolchain version your contracts use: rustup install 1.93.0 rustup +1.93.0 target add wasm32-unknown-unknown ``` -------------------------------- ### Clone and Copy Stylus Counter Example Contract Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/compile.md This bash script clones the Hardhat Arbitrum Stylus repository, copies the example stylus-counter contract into the current directory's contracts folder, and then removes the cloned repository. This is a quick way to get started with a minimal Stylus contract. ```bash git clone https://github.com/CoBuilders-xyz/hardhat-arbitrum-stylus.git cp -r hardhat-arbitrum-stylus/packages/hardhat-arb-compile/test/fixture-projects/compile-container-rust/contracts/stylus-counter . rm -rf hardhat-arbitrum-stylus ``` -------------------------------- ### Example: Run Arbitrum Stylus Tests with Host Toolchain Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/test.md This example demonstrates how to run tests using the local Rust toolchain for Stylus compilation and deployment instead of Docker. This option can lead to faster test execution, especially in parallel. ```bash npx hardhat arb:test --host ``` -------------------------------- ### Install Hardhat Arbitrum Stylus Plugin Source: https://context7.com/cobuilders-xyz/hardhat-arbitrum-stylus/llms.txt Installs the Hardhat Arbitrum Stylus plugin bundler and the Hardhat toolbox for viem integration. This command can be used to initialize a new project with scaffolding or add the plugin to an existing Hardhat 3 project. ```bash # Create new project with scaffolding mkdir my-stylus-project && cd my-stylus-project npx @cobuilders/hardhat-arbitrum-stylus --init # Or add to existing Hardhat 3 project npm install -D "@cobuilders/hardhat-arbitrum-stylus" "@nomicfoundation/hardhat-toolbox-viem@^5.0.2" ``` -------------------------------- ### Install Individual Hardhat Arbitrum Stylus Plugin Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/index.md Installs a single plugin, such as `@cobuilders/hardhat-arb-node`, for granular control over Hardhat Arbitrum Stylus development. Use this if you only need specific functionalities. ```bash npm install @cobuilders/hardhat-arb-node ``` -------------------------------- ### Start Local Arbitrum Node (arb:node start) Source: https://context7.com/cobuilders-xyz/hardhat-arbitrum-stylus/llms.txt Starts a local Arbitrum nitro-devnode Docker container. This command supports starting the node in the foreground, detached mode, with custom ports, custom container names, and silent operation. The node includes pre-funded accounts and RPC endpoints. ```bash # Start node in foreground (shows logs) npx hardhat arb:node start # Start in background (detached mode) npx hardhat arb:node start --detach # Start with custom ports npx hardhat arb:node start --http-port 9545 --ws-port 9546 # Start with custom container name npx hardhat arb:node start --name my-arbitrum-node # Silent background start npx hardhat arb:node start --quiet --detach # Expected output: # Started HTTP Server at http://localhost:8547/ # Account #0: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (10 ETH) # Account #1: 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 (10 ETH) # ... ``` -------------------------------- ### Initialize New Hardhat Arbitrum Stylus Project Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/index.md Scaffolds a new Hardhat 3 project with Arbitrum Stylus setup. This command initializes the project structure and configures necessary dependencies for Stylus development. ```bash mkdir my-stylus-project && cd my-stylus-project npx @cobuilders/hardhat-arbitrum-stylus --init ``` -------------------------------- ### Install Toolchain and Target (Bash) Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/compile.md These commands install a specific Rust toolchain version (e.g., 1.93.0) and the `wasm32-unknown-unknown` target, which are required for compiling Stylus contracts in Host mode. ```bash rustup install 1.93.0 rustup +1.93.0 target add wasm32-unknown-unknown ``` -------------------------------- ### Install Hardhat Arbitrum Stylus Plugin Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/README.md Installs the main Hardhat Arbitrum Stylus plugin package using npm. This package serves as a toolbox and includes all other necessary plugins for Arbitrum Stylus development. ```bash npm install @cobuilders/hardhat-arbitrum-stylus ``` -------------------------------- ### Install Hardhat Arbitrum Stylus Plugin in Existing Project Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/index.md Installs the Hardhat Arbitrum Stylus plugin and its required dependencies into an existing Hardhat 3 project. This allows integration of Arbitrum and Stylus features into a current development environment. ```bash npm install -D "@cobuilders/hardhat-arbitrum-stylus" "@nomicfoundation/hardhat-toolbox-viem@^5.0.2" ``` -------------------------------- ### Compile All Contracts with Hardhat Arbitrum Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/compile.md A basic example of running the compile command to process all discovered Solidity and Stylus contracts. ```bash npx hardhat arb:compile ``` -------------------------------- ### Start Local Arbitrum Node (CLI) Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/node.md Starts a persistent local Arbitrum nitro-devnode using the Hardhat CLI. Options allow for background execution, custom ports, and suppressing output. The node runs until explicitly stopped. ```bash npx hardhat arb:node start npx hardhat arb:node start --detach npx hardhat arb:node start --http-port 9545 npx hardhat arb:node start --quiet --detach ``` -------------------------------- ### Install cargo-stylus Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/guides/troubleshooting.md Installs the `cargo-stylus` command-line tool, which is required for compiling Stylus contracts. This command should be run if the `cargo-stylus` command is not found. ```bash cargo install cargo-stylus ``` -------------------------------- ### Host Mode Prerequisites and Usage (Bash) Source: https://context7.com/cobuilders-xyz/hardhat-arbitrum-stylus/llms.txt Provides instructions for setting up and using host mode for faster compilation and deployment. This involves installing `rustup`, `cargo-stylus`, the required Rust toolchain version, and the WASM target, followed by running Hardhat commands with the `--host` flag. ```bash # Install rustup (if not already installed) curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # Install cargo-stylus cargo install cargo-stylus # Install toolchain version required by your contracts rustup install 1.93.0 # Add WASM target for the toolchain rustup +1.93.0 target add wasm32-unknown-unknown # Verify installation cargo stylus --version # Run commands with host toolchain npx hardhat arb:compile --host npx hardhat arb:deploy stylus-counter --host npx hardhat arb:test --host ``` -------------------------------- ### Example: Run Specific Arbitrum Stylus Test File Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/test.md This command allows you to run tests from a specific file. It's useful for focusing on a particular test case or a small set of tests during development. ```bash npx hardhat arb:test test/counter.test.ts ``` -------------------------------- ### Write Tests for Solidity and Stylus Contracts Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/test.md This example demonstrates how to write a test suite that interacts with both Solidity and Stylus contracts. It utilizes the `stylusViem` object provided by the plugin to deploy and interact with contracts, asserting their state after operations. ```typescript import assert from 'node:assert/strict'; import { describe, it } from 'node:test'; import { network } from 'hardhat'; describe('Counter', async function () { const { stylusViem } = await network.connect(); it('deploys and interacts with a Solidity counter', async function () { const counter = await stylusViem.deployContract('SolidityCounter'); await counter.write.increment(); assert.equal(await counter.read.count(), 1n); }); it('deploys and interacts with a Stylus counter', async function () { const counter = await stylusViem.deployContract('stylus-counter'); await counter.write.increment(); assert.equal(await counter.read.count(), 1n); }); }); ``` -------------------------------- ### Example: Filter Arbitrum Stylus Tests by String Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/test.md This example shows how to run only the tests whose descriptions match a given string. This is helpful for isolating tests related to a specific feature or contract. ```bash npx hardhat arb:test --grep "Stylus" ``` -------------------------------- ### Example Typed hardhat.config.ts Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/contributors/deep-dive/plugin-anatomy.md Demonstrates how to use the extended TypeScript types in `hardhat.config.ts` for Stylus node configuration, showing valid and invalid option examples. ```typescript export default { stylus: { node: { httpPort: 8547, // ✓ Valid invalidOption: true, // ✗ TypeScript error }, }, }; ``` -------------------------------- ### Verify Hardhat Arbitrum Stylus Installation Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/index.md Verifies the successful installation of the Hardhat Arbitrum Stylus plugin by checking for the presence of `arb:*` commands in the Hardhat CLI. This command should list the available Arbitrum-specific tasks. ```bash npx hardhat --help # Should show arb:* commands ``` -------------------------------- ### Auto-Start Node for Tests (TypeScript Example) Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/guides/local-development.md Demonstrates how a Hardhat test file (`test/Counter.test.ts`) can leverage the auto-start feature for the development node. The `hre.network.connect()` call triggers the automatic node startup if needed. This allows running tests without manual node management. ```typescript // test/Counter.test.ts import { describe, it } from 'node:test'; describe('Counter', () => { it('should increment', async () => { // Node starts automatically when connecting const connection = await hre.network.connect(); // ... test logic }); }); ``` -------------------------------- ### Check Environment Versions Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/guides/troubleshooting.md Verify that the necessary tools like Node.js and Docker are installed and running correctly. This is a prerequisite for most operations. ```bash node --version # Need v22+ docker info # Docker running? npx hardhat arb:node status # Node running? ``` -------------------------------- ### Write Tests for Solidity and Stylus Contracts with stylusViem Source: https://context7.com/cobuilders-xyz/hardhat-arbitrum-stylus/llms.txt Example TypeScript test file demonstrating how to write tests using the Node.js test runner and `stylusViem`. This allows deploying and interacting with both Solidity and Stylus contracts within the same test suite, showcasing cross-VM interaction. ```typescript // test/counter.test.ts import assert from 'node:assert/strict'; import { describe, it } from 'node:test'; import { network } from 'hardhat'; describe('Counter', async function () { // Connect once - node auto-starts and is reused const { stylusViem } = await network.connect(); it('deploys and interacts with a Solidity counter', async function () { const counter = await stylusViem.deployContract('SolidityCounter'); // Initial count is 0 assert.equal(await counter.read.count(), 0n); // Increment and verify await counter.write.increment(); assert.equal(await counter.read.count(), 1n); // Increment again await counter.write.increment(); assert.equal(await counter.read.count(), 2n); }); it('deploys and interacts with a Stylus counter', async function () { const counter = await stylusViem.deployContract('stylus-counter'); // Same API as Solidity contracts assert.equal(await counter.read.count(), 0n); await counter.write.increment(); assert.equal(await counter.read.count(), 1n); }); it('supports cross-VM interaction', async function () { // Solidity and Stylus contracts share on-chain state const solCounter = await stylusViem.deployContract('SolidityCounter'); const stylusCounter = await stylusViem.deployContract('stylus-counter'); // Both can be used in the same test await solCounter.write.increment(); await stylusCounter.write.increment(); assert.equal(await solCounter.read.count(), 1n); assert.equal(await stylusCounter.read.count(), 1n); }); }); ``` -------------------------------- ### Deploy Stylus Contract using Host Toolchain Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/deploy.md This command deploys a Stylus contract using the host machine's Rust toolchain instead of Docker. This requires 'rustup', 'cargo-stylus', and the 'wasm32-unknown-unknown' target to be installed locally. ```bash npx hardhat arb:deploy stylus-counter --host ``` -------------------------------- ### Example: Skip Solidity Compilation for Arbitrum Stylus Tests Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/test.md This option allows skipping the Solidity compilation step before running tests. It can be useful if you have recently compiled your Solidity contracts and want to speed up the test execution. ```bash npx hardhat arb:test --no-compile ``` -------------------------------- ### Manage Network Connections and Start Temporary Nodes - TypeScript Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/contributors/deep-dive/hooks.md Handles network connections by checking if a node is running when connecting to the default network. If not, it starts a temporary container using the captured HRE. It also cleans up temporary containers on disconnection and registers process exit handlers for cleanup. ```typescript async newConnection(context, next) { const hookHttpPort = getHookHttpPort(); const hookRpcUrl = `http://127.0.0.1:${hookHttpPort}`; // Check if connecting to our default network if (networkUrl === hookRpcUrl) { const nodeRunning = await isNodeRunning(hookRpcUrl); if (!nodeRunning) { const hre = getHre(); // ← From hre hook if (hre) { const tempContainerName = generateTempContainerName(); await hre.tasks.getTask(['arb:node', 'start']).run({ quiet: true, detach: true, name: tempContainerName, httpPort: hookHttpPort, }); } } } return next(context); } ``` -------------------------------- ### Stylus Counter Contract Implementation in Rust Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/guides/first-stylus-contract.md Defines a Counter contract with a storage variable for the value and public functions to get, increment, and set the counter. This code uses the `stylus_sdk` for contract development. ```rust #![cfg_attr(not(feature = "std"), no_std)] use stylus_sdk::prelude::*; sol_storage! { #[entrypoint] pub struct Counter { uint256 value; } } #[public] impl Counter { pub fn get(&self) -> u256 { self.value.get() } pub fn increment(&mut self) { let current = self.value.get(); self.value.set(current + U256::from(1)); } pub fn set(&mut self, new_value: u256) { self.value.set(new_value); } } ``` -------------------------------- ### Run Hardhat Tests Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/guides/local-development.md Executes all tests defined in the project using `npx hardhat test`. This command can automatically start a temporary node if one is not already running, simplifying the testing process. ```bash npx hardhat test ``` -------------------------------- ### Test Stylus Custom Errors with stylusViem Assertions Source: https://context7.com/cobuilders-xyz/hardhat-arbitrum-stylus/llms.txt Test custom errors defined in Stylus contracts using `stylusViem.assertions`. This example demonstrates how to verify that specific custom errors are reverted with the correct parameters. ```typescript // test/custom-errors.test.ts import { describe, it } from 'node:test'; import { network } from 'hardhat'; describe('Stylus Custom Errors', async function () { const { stylusViem } = await network.connect(); const contract = await stylusViem.deployContract('my-contract'); it('reverts with NotOwner error', async function () { await stylusViem.assertions.revertWithCustomError( contract.write.restrictedFn(), contract, 'NotOwner' ); }); it('reverts with InvalidAmount error', async function () { await stylusViem.assertions.revert( contract.write.transfer([2000n]) ); }); }); ``` -------------------------------- ### Compile Stylus Contracts with Docker Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/contributors/deep-dive/compile.md Compiles Stylus contracts using Docker containers for isolated and consistent builds. It sets up Docker volumes for caching, builds a `stylus-compile` image, creates a temporary Docker network, and starts a node container. Contracts are compiled within a container, leveraging cached toolchains and targets. Finally, it cleans up the Docker resources. ```typescript // Shared utility from @cobuilders/hardhat-arb-utils/stylus await runInStylusContainer( imageName, contractPath, ['cargo', `+${toolchain}`, 'stylus', 'check', '--endpoint', rpcEndpoint], { ...options, containerPrefix: 'stylus-compile-tmp' }, ); ``` -------------------------------- ### Compile Stylus Contracts Locally (Host Path) Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/contributors/deep-dive/compile.md Compiles Stylus contracts locally using the host machine's toolchain. It validates the Rust toolchain, starts a temporary Hardhat-Arbitrum node, and then executes `cargo stylus check` and `cargo stylus build` for each discovered contract. Artifacts (ABI and WASM hex) are generated, and the temporary node is stopped. ```typescript // host.ts - core compile flow await execWithProgress(`cargo +${toolchain} stylus check`, { cwd: contractPath, }); await execWithProgress(`cargo +${toolchain} stylus build`, { cwd: contractPath, }); // WASM output: target/wasm32-unknown-unknown/release/{name}.wasm // Note: Cargo converts hyphens to underscores in the filename ``` -------------------------------- ### Initialize Hardhat Project with Stylus Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/guides/first-stylus-contract.md Sets up a new Hardhat project and configures it for Arbitrum Stylus development. This command initializes the project directory and creates the necessary configuration files. ```bash mkdir my-first-stylus && cd my-first-stylus npx hardhat-arbitrum-stylus --init ``` -------------------------------- ### Interact with Deployed Stylus Contract Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/guides/first-stylus-contract.md Demonstrates how to interact with the deployed Counter contract using `cast`. This includes reading the current value, incrementing it, and reading it again. ```bash # Read counter (returns 0) cast call CONTRACT_ADDRESS "get()(uint256)" --rpc-url http://localhost:8547 # Increment cast send CONTRACT_ADDRESS "increment()" \ --rpc-url http://localhost:8547 \ --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 # Read again (returns 1) cast call CONTRACT_ADDRESS "get()(uint256)" --rpc-url http://localhost:8547 ``` -------------------------------- ### Check and Deploy Stylus Contract Locally Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/guides/first-stylus-contract.md Checks the Stylus contract for compatibility and deploys it to the local Arbitrum node. The `--endpoint` flag specifies the connection to the local node. ```bash cargo stylus check --endpoint http://localhost:8547 cargo stylus deploy \ --endpoint http://localhost:8547 \ --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 ``` -------------------------------- ### Create a New Stylus Contract in Rust Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/guides/first-stylus-contract.md Generates a new Stylus contract project using Cargo. This command creates the basic file structure for a Rust-based smart contract compatible with Stylus. ```bash mkdir -p contracts/stylus && cd contracts/stylus cargo stylus new counter && cd counter ``` -------------------------------- ### Start Hardhat Arbitrum Node in Foreground Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/guides/local-development.md Starts the Hardhat Arbitrum node in the foreground, displaying logs directly in the terminal. This is useful for monitoring node activity and debugging. It requires `npx` to execute Hardhat commands. ```bash npx hardhat arb:node start ``` -------------------------------- ### Start Hardhat Arbitrum Node in Background Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/guides/local-development.md Starts the Hardhat Arbitrum node in detached (background) mode. This is useful for keeping the node running while you perform other development tasks. It requires `npx` to execute Hardhat commands. ```bash npx hardhat arb:node start --detach ``` -------------------------------- ### Deployment and Interaction with Stylus Contracts (Bash) Source: https://context7.com/cobuilders-xyz/hardhat-arbitrum-stylus/llms.txt Demonstrates how to deploy Stylus contracts using `cargo-stylus` and interact with deployed contracts using `cast`. It specifies the endpoint, private key for deployment, and commands for calling and sending transactions. ```bash # Use account #0 for deployments cargo stylus deploy \ --endpoint http://localhost:8547 \ --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 # Interact with cast cast call CONTRACT_ADDRESS "count()(uint256)" --rpc-url http://localhost:8547 cast send CONTRACT_ADDRESS "increment()" \ --rpc-url http://localhost:8547 \ --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 ``` -------------------------------- ### Stop Hardhat Arbitrum Node Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/guides/local-development.md Stops a manually started Hardhat Arbitrum node. This command is used to gracefully shut down the development node when it's no longer needed. Temporary nodes started for tests are cleaned up automatically. ```bash npx hardhat arb:node stop ``` -------------------------------- ### Deploy Solidity and Stylus Contracts Programmatically (TypeScript) Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/deploy.md This snippet demonstrates how to deploy both Solidity and Stylus contracts programmatically using the `stylusViem` and `viem` objects obtained from the Hardhat network connection. It shows basic contract interaction after deployment, including reading and writing to the deployed contracts. ```typescript import { network } from 'hardhat'; const { viem, stylusViem } = await network.connect(); // Deploy Solidity (either viem or stylusViem works) const solCounter = await viem.deployContract('SolidityCounter'); await solCounter.write.increment(); const count = await solCounter.read.count(); // 1n // Deploy Stylus (use stylusViem) const stylusCounter = await stylusViem.deployContract('stylus-counter'); await stylusCounter.write.increment(); const stylusCount = await stylusCounter.read.count(); // 1n ``` -------------------------------- ### Task Entry Point Logic - TypeScript Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/contributors/deep-dive/deploy.md This snippet illustrates the decision tree within the `arb:deploy` task for determining the deployment strategy based on contract type, deployment mode (host/Docker), and network configuration. ```typescript const isSol = contract.endsWith('.sol'); const isExternal = externalRpcUrl !== null; const useHost = host || config.stylus.deploy.useHostToolchain; if (isSol) deploySolidity(...) else if (useHost) deployStylusHost(...) else deployStylusContainer(...) ``` -------------------------------- ### Hardhat Configuration for Stylus Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/deploy.md Illustrates the configuration options for integrating Stylus with Hardhat. It specifically shows the `stylus.deploy.useHostToolchain` setting, which controls whether to use the host Rust toolchain or Docker for deployments. ```typescript export default { stylus: { deploy: { useHostToolchain: false, // Set to true to always use host Rust }, }, }; ``` -------------------------------- ### Toolbox Plugin Definition (TypeScript) Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/contributors/deep-dive/packages.md Defines the main 'hardhat-arbitrum-stylus' plugin, which acts as a toolbox by declaring its dependencies on other sub-packages. This allows users to install a single package to access all functionalities. ```typescript const hardhatArbitrumStylusPlugin: HardhatPlugin = { id: 'hardhat-arbitrum-stylus', dependencies: () => [ import('@cobuilders/hardhat-arb-node'), import('@cobuilders/hardhat-arb-compile'), import('@cobuilders/hardhat-arb-deploy'), import('@cobuilders/hardhat-arb-test'), ], npmPackage: '@cobuilders/hardhat-arbitrum-stylus', }; ``` -------------------------------- ### Programmatic Contract Deployment with `stylusViem.deployContract` Source: https://context7.com/cobuilders-xyz/hardhat-arbitrum-stylus/llms.txt Demonstrates programmatic contract deployment using `stylusViem.deployContract` within Hardhat. This function automatically detects contract type (Solidity or Stylus) and handles deployment, including constructor arguments. It integrates with viem for Solidity and `cargo stylus deploy` for Stylus. ```typescript import { network } from 'hardhat'; async function main() { // Connect to network (auto-starts temporary node if default network) const { viem, stylusViem } = await network.connect(); // Deploy Solidity contract const solCounter = await stylusViem.deployContract('SolidityCounter'); console.log('Solidity Counter deployed at:', solCounter.address); // Interact with Solidity contract await solCounter.write.increment(); const count = await solCounter.read.count(); console.log('Solidity count:', count); // 1n // Deploy Stylus contract (compiles and deploys automatically) const stylusCounter = await stylusViem.deployContract('stylus-counter'); console.log('Stylus Counter deployed at:', stylusCounter.address); // Interact with Stylus contract (same API as Solidity) await stylusCounter.write.increment(); const stylusCount = await stylusCounter.read.count(); console.log('Stylus count:', stylusCount); // 1n // Deploy with constructor arguments const token = await stylusViem.deployContract('MyToken', ['MyToken', 'MTK', 1000000n]); } main(); ``` -------------------------------- ### Stylus Contract Stylus.toml Configuration Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/compile.md The Stylus.toml file is required by cargo-stylus and can be minimal. It typically includes workspace configurations and network settings, though these can be empty for basic setups. ```toml [workspace] [workspace.networks] [contract] ``` -------------------------------- ### Pass Constructor Arguments to Solidity Contract Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/deploy.md This command demonstrates how to deploy a Solidity contract named 'MyContract' and pass constructor arguments. Arguments are appended after the contract name and are automatically type-coerced based on the contract's ABI. ```bash npx hardhat arb:deploy MyContract.sol 42 "hello world" 0x1234... ``` -------------------------------- ### Deploy Stylus Contract using Ephemeral Node Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/deploy.md Deploys a Stylus contract using the default ephemeral Arbitrum node. This mode requires no prior setup and automatically manages the temporary node lifecycle. ```bash # Uses a temporary node - no setup needed npx hardhat arb:deploy stylus-counter ``` -------------------------------- ### TypeScript: Configure Docker Container Arguments Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/contributors/deep-dive/deploy.md Sets up arguments for running a Docker container, including volume mounts for the workspace and Rust toolchain, and sets the working directory. This is crucial for preparing the environment for Stylus deployments. ```typescript // Container setup const args = ['run', '--rm', '--name', containerName]; args.push('-v', `${contractPath}:/workspace:rw`); args.push('-v', `${RUSTUP_VOLUME_NAME}:/usr/local/rustup:rw`); args.push('-v', `${CARGO_VOLUME_NAME}:/usr/local/cargo:rw`); args.push('-w', '/workspace'); args.push(imageName, ...command); ``` -------------------------------- ### Automatic Arbitrum Node Connection with Hardhat Source: https://context7.com/cobuilders-xyz/hardhat-arbitrum-stylus/llms.txt Connect to an Arbitrum network using Hardhat's `network.connect()`. When no network is specified, it automatically starts a temporary Arbitrum node that is cleaned up on process exit. ```typescript import { network } from 'hardhat'; async function main() { // Automatically starts temporary node if not running const connection = await network.connect(); const { viem, stylusViem } = connection; // Get wallet clients (pre-funded accounts) const [deployer, user1, user2] = await viem.getWalletClients(); // Deploy contract const counter = await stylusViem.deployContract('stylus-counter'); // Read state const count = await counter.read.count(); console.log('Count:', count); // Write state (uses deployer by default) await counter.write.increment(); // Write as different user await counter.write.increment({ account: user1.account }); // Check public client const block = await viem.getPublicClient().getBlockNumber(); console.log('Block:', block); } main(); ``` -------------------------------- ### Upgrade Hardhat for Plugin Compatibility Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/guides/troubleshooting.md Instructs users to upgrade their Hardhat installation to version 3 or later to ensure compatibility with the `@cobuilders/hardhat-arbitrum-stylus` plugin. This resolves configuration errors like 'plugins is not a valid configuration key'. ```bash npm install hardhat@latest ``` -------------------------------- ### Compile Using Host Rust Toolchain Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/compile.md Forces the compilation process to use the local Rust toolchain instead of Docker containers via the `--host` flag. ```bash npx hardhat arb:compile --host ``` -------------------------------- ### Troubleshooting Common Issues (Bash) Source: https://context7.com/cobuilders-xyz/hardhat-arbitrum-stylus/llms.txt Offers diagnostic commands and solutions for frequent problems encountered during development, such as checking environment versions, managing node ports, restarting services, cleaning Docker containers, and resolving `cargo-stylus` or WASM target issues. ```bash # Quick environment check node --version # Need v22+ docker info # Docker running? npx hardhat arb:node status # Node running? # Port already in use npx hardhat arb:node start --http-port 9545 # Node already running npx hardhat arb:node stop npx hardhat arb:node start # Clean up orphaned temp containers docker rm -f $(docker ps -aq --filter "name=nitro-devnode-tmp") # Clear Docker cache for fresh compile npx hardhat arb:compile --cleanCache # cargo-stylus not found (host mode) cargo install cargo-stylus # WASM target missing rustup target add wasm32-unknown-unknown # Stylus check fails - restart node npx hardhat arb:node stop npx hardhat arb:node start # View node logs for debugging npx hardhat arb:node logs --follow --tail 100 ``` -------------------------------- ### Connect to Temporary Arbitrum Node (HRE) Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/node.md Connects to a temporary Arbitrum node managed by the Hardhat Runtime Environment (HRE). This node is automatically started when needed for scripts or tests and cleaned up upon process exit. ```typescript const connection = await hre.network.connect(); // Temporary Arbitrum node is now running and will be auto-cleaned. ``` -------------------------------- ### Troubleshoot Hardhat Arbitrum Stylus Node Status Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/guides/troubleshooting.md Offers a sequence of commands to diagnose and resolve issues with the Hardhat Arbitrum Stylus node. This includes checking status, starting, stopping, and forcefully removing a stuck node. ```bash npx hardhat arb:node status # If not running: npx hardhat arb:node start # If stuck: npx hardhat arb:node stop docker rm -f nitro-devnode npx hardhat arb:node start ``` -------------------------------- ### Run Arbitrum Stylus Tests with Hardhat CLI Source: https://context7.com/cobuilders-xyz/hardhat-arbitrum-stylus/llms.txt Commands to execute tests for Solidity and Stylus contracts using the `arb:test` command. Supports various options like running in Docker mode, using the host Rust toolchain, specifying test files, filtering tests by pattern or `.only` flag, and skipping compilation. ```bash # Run all tests (Docker mode, sequential) npx hardhat arb:test # Run with host Rust toolchain (faster, parallel) npx hardhat arb:test --host # Run specific test file npx hardhat arb:test test/counter.test.ts # Run tests matching pattern npx hardhat arb:test --grep "Stylus" # Run only tests marked with .only npx hardhat arb:test --only # Skip Solidity compilation npx hardhat arb:test --no-compile ``` -------------------------------- ### Deploy Contracts to Arbitrum Networks using Hardhat CLI Source: https://context7.com/cobuilders-xyz/hardhat-arbitrum-stylus/llms.txt Commands to set the deployer private key and deploy Stylus contracts to Arbitrum Sepolia and Arbitrum One networks. This utilizes the `hardhat-arbitrum-stylus` plugin for deployment. ```bash # Set deployer key npx hardhat vars set DEPLOYER_KEY # Deploy to Arbitrum Sepolia testnet npx hardhat arb:deploy stylus-counter --network arbitrumSepolia # Deploy to Arbitrum One mainnet npx hardhat arb:deploy MyContract.sol --network arbitrumOne ``` -------------------------------- ### Stylus Contract Structure and Dependencies Source: https://context7.com/cobuilders-xyz/hardhat-arbitrum-stylus/llms.txt Defines the standard directory structure for a Stylus contract project, including Cargo.toml for dependencies (like stylus-sdk and alloy crates), Stylus.toml, rust-toolchain.toml, and source files (lib.rs for implementation, main.rs for ABI export). ```toml # Cargo.toml [package] name = "stylus-counter" version = "0.1.0" edition = "2021" [dependencies] alloy-primitives = "=0.8.20" alloy-sol-types = "=0.8.20" stylus-sdk = "=0.9.0" [features] default = ["mini-alloc"] export-abi = ["stylus-sdk/export-abi"] mini-alloc = ["stylus-sdk/mini-alloc"] [[bin]] name = "stylus-counter" path = "src/main.rs" [lib] crate-type = ["lib", "cdylib"] [profile.release] codegen-units = 1 strip = true lto = true panic = "abort" opt-level = 3 ``` ```toml # rust-toolchain.toml [toolchain] channel = "1.93.0" ``` ```toml # Stylus.toml [workspace] [workspace.networks] [contract] ``` -------------------------------- ### Restart Stylus Node for Check/Deploy Issues Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/guides/troubleshooting.md Provides commands to stop and restart the Hardhat Arbitrum Stylus node. This is often required to resolve issues with Stylus contract checks or deployments, as the Stylus infrastructure is deployed automatically on node start. ```bash npx hardhat arb:node stop npx hardhat arb:node start # Redeploy your contract ``` -------------------------------- ### Manage Running Hardhat Arbitrum Stylus Nodes Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/guides/troubleshooting.md Provides commands to stop an existing Hardhat Arbitrum Stylus node or start a new one with a different name to avoid conflicts. Useful when encountering 'Node already running' errors. ```bash npx hardhat arb:node stop # Or use different name npx hardhat arb:node start --name my-node-2 ``` -------------------------------- ### Hardhat Arbitrum Stylus Test Command Reference Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/test.md This shows the basic command structure for running Arbitrum Stylus tests, including optional arguments for specifying test files and options for controlling the test execution environment and filtering. ```bash npx hardhat arb:test [testFiles...] [options] ``` -------------------------------- ### Configure Hardhat Arbitrum Stylus Plugin Source: https://context7.com/cobuilders-xyz/hardhat-arbitrum-stylus/llms.txt Configures the Hardhat Arbitrum Stylus plugin in `hardhat.config.ts`. This includes adding the necessary plugins and optionally customizing Stylus plugin settings such as Docker image, ports, and toolchain usage. ```typescript import type { HardhatUserConfig } from 'hardhat/config'; import hardhatToolboxViemPlugin from '@nomicfoundation/hardhat-toolbox-viem'; import hardhatArbitrumStylus from '@cobuilders/hardhat-arbitrum-stylus'; const config: HardhatUserConfig = { plugins: [hardhatToolboxViemPlugin, hardhatArbitrumStylus], solidity: '0.8.24', // Optional: customize Stylus plugin settings (all values shown are defaults) stylus: { node: { image: 'offchainlabs/nitro-node', tag: 'v3.7.1-926f1ab', httpPort: 8547, wsPort: 8548, chainId: 412346, }, compile: { useHostToolchain: false, // Use Docker by default }, deploy: { useHostToolchain: false, }, test: { useHostToolchain: false, }, }, }; export default config; ``` -------------------------------- ### Stylus Custom Error Definition and Usage Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/deploy.md Shows how to define and use custom errors in Stylus (Rust) contracts. It includes defining a custom error using `alloy_sol_types::sol!` and returning its ABI-encoded data from a function, along with TypeScript examples for asserting reverts with these custom errors. ```rust use alloy_sol_types::{sol, SolError}; sol! { error NotOwner(address caller, address owner); } #[public] impl MyContract { pub fn restricted_fn(&mut self) -> Result<(), Vec> { let caller = self.vm().msg_sender(); let owner = self.owner.get(); if caller != owner { return Err(NotOwner { caller, owner }.abi_encode()); } Ok(()) } } ``` ```typescript await stylusViem.assertions.revert(proxy.write.restrictedFn()); await stylusViem.assertions.revertWithCustomError( proxy.write.restrictedFn(), proxy, 'NotOwner', ); ``` -------------------------------- ### Compile Contracts (arb:compile) Source: https://context7.com/cobuilders-xyz/hardhat-arbitrum-stylus/llms.txt Compiles Solidity and Stylus (Rust) contracts. It auto-discovers Stylus projects and generates Hardhat-compatible artifacts. Options allow compiling specific contract types, specific contracts by name, or using the host Rust toolchain. ```bash # Compile all contracts (Solidity and Stylus) npx hardhat arb:compile # Compile only Stylus contracts npx hardhat arb:compile --stylus # Compile only Solidity contracts npx hardhat arb:compile --sol # Compile specific Stylus contract by folder name npx hardhat arb:compile --contracts stylus-counter # Compile multiple specific contracts npx hardhat arb:compile --contracts counter,nft,token # Use host Rust toolchain instead of Docker npx hardhat arb:compile --host ``` -------------------------------- ### Configuration for Host Toolchain (TypeScript) Source: https://github.com/cobuilders-xyz/hardhat-arbitrum-stylus/blob/main/docs/src/plugins/compile.md This TypeScript configuration snippet shows how to set `useHostToolchain` to `true` within the `hardhat.config.ts` file. This instructs the Hardhat Arbitrum Stylus plugin to use the local Rust toolchain instead of Docker. ```typescript export default { stylus: { compile: { useHostToolchain: false, // Set to true to always use host Rust }, }, }; ```