diff --git a/README.md b/README.md index 6f9ee6c..bdd0228 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![linux](https://github.com/OffchainLabs/cargo-stylus/actions/workflows/linux.yml/badge.svg)](https://github.com/OffchainLabs/cargo-stylus/actions/workflows/linux.yml) [![mac](https://github.com/OffchainLabs/cargo-stylus/actions/workflows/mac.yml/badge.svg)](https://github.com/OffchainLabs/cargo-stylus/actions/workflows/mac.yml) [![windows](https://github.com/OffchainLabs/cargo-stylus/actions/workflows/windows.yml/badge.svg)](https://github.com/OffchainLabs/cargo-stylus/actions/workflows/windows.yml) [![lint](https://github.com/OffchainLabs/cargo-stylus/actions/workflows/check.yml/badge.svg)](https://github.com/OffchainLabs/cargo-stylus/actions/workflows/check.yml) -A cargo subcommand for building, verifying, and deploying Arbitrum Stylus WASM programs in Rust. +A cargo subcommand for building, verifying, and deploying Arbitrum Stylus WASM contracts in Rust. ## Quick Start @@ -38,7 +38,7 @@ Usage: ### Overview -The cargo stylus command comes with useful commands such as `new`, `check` and `deploy`, and `export-abi` for developing and deploying Stylus programs to Arbitrum chains. Here's a common workflow: +The cargo stylus command comes with useful commands such as `new`, `check` and `deploy`, and `export-abi` for developing and deploying Stylus contracts to Arbitrum chains. Here's a common workflow: Start a new Stylus project with @@ -57,21 +57,21 @@ All testnet information, including faucets and RPC endpoints can be found [here] ### Developing With Stylus -Then, develop your Rust program normally and take advantage of all the features the [stylus-sdk](https://github.com/OffchainLabs/stylus-sdk-rs) has to offer. To check whether or not your program will successfully deploy and activate onchain, use the `cargo stylus check` subcommand: +Then, develop your Rust contract normally and take advantage of all the features the [stylus-sdk](https://github.com/OffchainLabs/stylus-sdk-rs) has to offer. To check whether or not your contract will successfully deploy and activate onchain, use the `cargo stylus check` subcommand: ``` cargo stylus check ``` -This command will attempt to verify that your program can be deployed and activated onchain without requiring a transaction by specifying a JSON-RPC endpoint. By default, it will use the public URL of the Stylus testnet as its endpoint. See [here](https://docs.arbitrum.io/stylus/reference/testnet-information) for available testnet RPC URLs. See `cargo stylus check --help` for more options. +This command will attempt to verify that your contract can be deployed and activated onchain without requiring a transaction by specifying a JSON-RPC endpoint. By default, it will use the public URL of the Stylus testnet as its endpoint. See [here](https://docs.arbitrum.io/stylus/reference/testnet-information) for available testnet RPC URLs. See `cargo stylus check --help` for more options. If the command above fails, you'll see detailed information about why your WASM will be rejected: ``` Reading WASM file at bad-export.wat Compressed WASM size: 55 B -Stylus checks failed: program predeployment check failed when checking against -ARB_WASM_ADDRESS 0x0000…0071: (code: -32000, message: program activation failed: failed to parse program) +Stylus checks failed: contract predeployment check failed when checking against +ARB_WASM_ADDRESS 0x0000…0071: (code: -32000, message: contract activation failed: failed to parse contract) Caused by: binary exports reserved symbol stylus_ink_left @@ -80,18 +80,18 @@ Location: prover/src/binary.rs:493:9, data: None) ``` -To read more about what counts as valid vs. invalid user WASM programs, see [VALID_WASM](./check/VALID_WASM.md). +To read more about what counts as valid vs. invalid user WASM contracts, see [VALID_WASM](./check/VALID_WASM.md). -If your program succeeds, you'll see the following message: +If your contract succeeds, you'll see the following message: ``` Finished release [optimized] target(s) in 1.88s Reading WASM file at hello-stylus/target/wasm32-unknown-unknown/release/hello-stylus.wasm Compressed WASM size: 3 KB -Program succeeded Stylus onchain activation checks with Stylus version: 1 +Contract succeeded Stylus onchain activation checks with Stylus version: 1 ``` -Once you're ready to deploy your program onchain, you can use the `cargo stylus deploy` subcommand as follows: +Once you're ready to deploy your contract onchain, you can use the `cargo stylus deploy` subcommand as follows: First, we can estimate the gas required to perform our deployment and activation with: @@ -105,7 +105,7 @@ and see: ``` Compressed WASM size: 3 KB -Deploying program to address 0x457b1ba688e9854bdbed2f473f7510c476a3da09 +Deploying contract to address 0x457b1ba688e9854bdbed2f473f7510c476a3da09 Estimated gas: 12756792 ``` @@ -120,21 +120,21 @@ and see: ``` Compressed WASM size: 3 KB -Deploying program to address 0x457b1ba688e9854bdbed2f473f7510c476a3da09 +Deploying contract to address 0x457b1ba688e9854bdbed2f473f7510c476a3da09 Estimated gas: 12756792 Submitting tx... Confirmed tx 0x42db…7311, gas used 11657164 -Activating program at address 0x457b1ba688e9854bdbed2f473f7510c476a3da09 +Activating contract at address 0x457b1ba688e9854bdbed2f473f7510c476a3da09 Estimated gas: 14251759 Submitting tx... Confirmed tx 0x0bdb…3307, gas used 14204908 ``` -## Compiling and Checking Stylus Programs +## Compiling and Checking Stylus Contracts **cargo stylus check** -Instruments a Rust project using Stylus. This command runs compiled WASM code through Stylus instrumentation checks and reports any failures. It **verifies the program can compile onchain** by making an eth_call to a Arbitrum chain RPC endpoint. +Instruments a Rust project using Stylus. This command runs compiled WASM code through Stylus instrumentation checks and reports any failures. It **verifies the contract can compile onchain** by making an eth_call to a Arbitrum chain RPC endpoint. ``` Usage: cargo stylus check [OPTIONS] @@ -142,11 +142,11 @@ Usage: cargo stylus check [OPTIONS] See `--help` for all available flags and default values. -## Deploying Stylus Programs +## Deploying Stylus Contracts **cargo stylus deploy** -Instruments a Rust project using Stylus and by outputting its brotli-compressed WASM code. Then, it submits **two transactions** by default: the first **deploys** the WASM program code to an address and the second triggers an **activation onchain**. Developers can choose to split up the deploy and activate steps via this command as desired. +Instruments a Rust project using Stylus and by outputting its brotli-compressed WASM code. Then, it submits **two transactions** by default: the first **deploys** the WASM contract code to an address and the second triggers an **activation onchain**. Developers can choose to split up the deploy and activate steps via this command as desired. ``` Usage: cargo stylus deploy [OPTIONS] @@ -154,14 +154,14 @@ Usage: cargo stylus deploy [OPTIONS] See `--help` for all available flags and default values. -## Verifying Stylus Programs +## Verifying Stylus Contracts **cargo stylus verify** Verifies that a deployed smart contract is identical to that produced by the current project. Since Stylus smart contracts include a hash of all project files, this additionally verifies that code comments and other files are -identical. To ensure build reproducibility, if a program is to be verified, +identical. To ensure build reproducibility, if a contract is to be verified, it should be both deployed and verified using `cargo stylus reproducible`. See `--help` for all available flags and default values. @@ -209,9 +209,9 @@ cargo stylus export-abi ## Optimizing Binary Sizes -Brotli-compressed, Stylus program WASM binaries must fit within the **24Kb** [code-size limit](https://ethereum.org/en/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/) of Ethereum smart contracts. By default, the `cargo stylus check` will attempt to compile a Rust program into WASM with reasonable optimizations and verify its compressed size fits within the limit. However, there are additional options available in case a program exceeds the 24Kb limit from using default settings. Deploying smaller binaries onchain is cheaper and better for the overall network, as deployed WASM programs will exist on the Arbitrum chain's storage forever. +Brotli-compressed, Stylus contract WASM binaries must fit within the **24Kb** [code-size limit](https://ethereum.org/en/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/) of Ethereum smart contracts. By default, the `cargo stylus check` will attempt to compile a Rust contract into WASM with reasonable optimizations and verify its compressed size fits within the limit. However, there are additional options available in case a contract exceeds the 24Kb limit from using default settings. Deploying smaller binaries onchain is cheaper and better for the overall network, as deployed WASM contracts will exist on the Arbitrum chain's storage forever. -We recommend optimizing your Stylus program's sizes to smaller sizes, but keep in mind the safety tradeoffs of using some of the more advanced optimizations. However, some small programs when compiled to much smaller sizes can suffer performance penalties. +We recommend optimizing your Stylus contract's sizes to smaller sizes, but keep in mind the safety tradeoffs of using some of the more advanced optimizations. However, some small contracts when compiled to much smaller sizes can suffer performance penalties. For a deep-dive into the different options for optimizing binary sizes using cargo stylus, see [OPTIMIZING_BINARIES.md](./check/OPTIMIZING_BINARIES.md). diff --git a/check/OPTIMIZING_BINARIES.md b/check/OPTIMIZING_BINARIES.md index 45c66b3..24e2240 100644 --- a/check/OPTIMIZING_BINARIES.md +++ b/check/OPTIMIZING_BINARIES.md @@ -1,6 +1,6 @@ -# Optimizing Stylus Program WASM Binaries +# Optimizing Stylus Contract WASM Binaries -WASM programs need to be small to be deployed onchain. Stylus applies [brotli compression](https://github.com/google/brotli), which empirically reduces the footprint of common Rust WASMs by over 50%, the Stylus runtime obeys the EVM contract size limit of 24KB. This means that, after compression, **all WASMs must not exceed 24KB**. +WASM contracts need to be small to be deployed onchain. Stylus applies [brotli compression](https://github.com/google/brotli), which empirically reduces the footprint of common Rust WASMs by over 50%, the Stylus runtime obeys the EVM contract size limit of 24KB. This means that, after compression, **all WASMs must not exceed 24KB**. **Uncompressed WASM** files also have an enforced limit of **128Kb**. diff --git a/check/VALID_WASM.md b/check/VALID_WASM.md index 219246b..95b7ff9 100644 --- a/check/VALID_WASM.md +++ b/check/VALID_WASM.md @@ -1,8 +1,8 @@ -# Invalid Stylus WASM Programs +# Invalid Stylus WASM Contracts -This document explains the limitations of Stylus WASM programs and why certain programs might fail `cargo stylus check`. Stylus programs are bound by similar rules to Ethereum smart contracts when it comes to bounded execution, bounded memory use, and determinism. +This document explains the limitations of Stylus WASM contracts and why certain contracts might fail `cargo stylus check`. Stylus contracts are bound by similar rules to Ethereum smart contracts when it comes to bounded execution, bounded memory use, and determinism. -WASM programs must fit within the **24Kb** code size limit of Arbitrum chains _after_ compression. Uncompressed WASMs must have a size less than **128Kb**. +WASM contracts must fit within the **24Kb** code size limit of Arbitrum chains _after_ compression. Uncompressed WASMs must have a size less than **128Kb**. While Stylus includes a large portion of available WASM opcodes, not all of them are supported. To see the set of allowed / disallowed opcodes, see [here](https://github.com/OffchainLabs/stylus/blob/stylus/arbitrator/prover/src/wavm.rs#L731). @@ -15,4 +15,4 @@ When a user WASM gets "activated" on chain, it goes through a series of checks t 5. Check for **disallowed opcodes**, such as SIMD or other features 6. Disallow WASMs with an enormous amount of **functions and exports** -Stylus programs should use `#[no_std]` to avoid including the Rust standard library and keep code small. Many crates that build without the standard library make for great dependencies to use in Stylus programs, as long as the total, compressed WASM size is within the 24Kb code size limit. +Stylus contracts should use `#[no_std]` to avoid including the Rust standard library and keep code small. Many crates that build without the standard library make for great dependencies to use in Stylus contracts, as long as the total, compressed WASM size is within the 24Kb code size limit. diff --git a/check/src/activate.rs b/check/src/activate.rs index 8a80481..c84f59f 100644 --- a/check/src/activate.rs +++ b/check/src/activate.rs @@ -28,8 +28,8 @@ sol! { } } -/// Activates an already deployed Stylus program by address. -pub async fn activate_program(cfg: &ActivateConfig) -> Result<()> { +/// Activates an already deployed Stylus contract by address. +pub async fn activate_contract(cfg: &ActivateConfig) -> Result<()> { let provider = sys::new_provider(&cfg.common_cfg.endpoint)?; let chain_id = provider .get_chainid() @@ -54,8 +54,8 @@ pub async fn activate_program(cfg: &ActivateConfig) -> Result<()> { ); data_fee = bump_data_fee(data_fee, cfg.data_fee_bump_percent); - let program: Address = cfg.address.to_fixed_bytes().into(); - let data = ArbWasm::activateProgramCall { program }.abi_encode(); + let contract: Address = cfg.address.to_fixed_bytes().into(); + let data = ArbWasm::activateProgramCall { program: contract }.abi_encode(); let tx = Eip1559TransactionRequest::new() .from(client.address()) .to(*ARB_WASM_H160) @@ -66,14 +66,14 @@ pub async fn activate_program(cfg: &ActivateConfig) -> Result<()> { match tx.await? { Some(receipt) => { greyln!( - "successfully activated program 0x{} with tx {}", + "successfully activated contract 0x{} with tx {}", hex::encode(cfg.address), hex::encode(receipt.transaction_hash).debug_lavender() ); } None => { bail!( - "failed to fetch receipt for program activation {}", + "failed to fetch receipt for contract activation {}", cfg.address ); } diff --git a/check/src/cache.rs b/check/src/cache.rs index 607db6c..7d907e1 100644 --- a/check/src/cache.rs +++ b/check/src/cache.rs @@ -33,7 +33,7 @@ sol! { } } -pub async fn cache_program(cfg: &CacheConfig) -> Result<()> { +pub async fn cache_contract(cfg: &CacheConfig) -> Result<()> { let provider = sys::new_provider(&cfg.common_cfg.endpoint)?; let chain_id = provider .get_chainid() @@ -59,8 +59,8 @@ pub async fn cache_program(cfg: &CacheConfig) -> Result<()> { let cache_manager = *cache_manager_addrs.last().unwrap(); let cache_manager = H160::from_slice(cache_manager.as_slice()); - let program: Address = cfg.address.to_fixed_bytes().into(); - let data = CacheManager::placeBidCall { program }.abi_encode(); + let contract: Address = cfg.address.to_fixed_bytes().into(); + let data = CacheManager::placeBidCall { program: contract }.abi_encode(); let mut tx = Eip1559TransactionRequest::new() .to(cache_manager) .data(data); @@ -80,13 +80,13 @@ pub async fn cache_program(cfg: &CacheConfig) -> Result<()> { }; use CacheManager::CacheManagerErrors as C; match error { - C::AsmTooLarge(_) => bail!("program too large"), - C::AlreadyCached(_) => bail!("program already cached"), + C::AsmTooLarge(_) => bail!("Stylus contract was too large to cache"), + C::AlreadyCached(_) => bail!("Stylus contract is already cached"), C::BidsArePaused(_) => { - bail!("bidding is currently paused for the Stylus cache manager") + bail!("Bidding is currently paused for the Stylus cache manager") } C::BidTooSmall(_) => { - bail!("bid amount {} (wei) too small", cfg.bid.unwrap_or_default()) + bail!("Bid amount {} (wei) too small", cfg.bid.unwrap_or_default()) } } } @@ -106,11 +106,11 @@ pub async fn cache_program(cfg: &CacheConfig) -> Result<()> { if verbose { let gas = format_gas(receipt.gas_used.unwrap_or_default()); greyln!( - "Successfully cached program at address: {address} {} {gas}", + "Successfully cached contract at address: {address} {} {gas}", "with".grey() ); } else { - greyln!("Successfully cached program at address: {address}"); + greyln!("Successfully cached contract at address: {address}"); } let tx_hash = receipt.transaction_hash.debug_lavender(); greyln!("Sent Stylus cache tx with hash: {tx_hash}"); diff --git a/check/src/check.rs b/check/src/check.rs index 137a14d..0716e62 100644 --- a/check/src/check.rs +++ b/check/src/check.rs @@ -44,9 +44,9 @@ sol! { } } -/// Checks that a program is valid and can be deployed onchain. +/// Checks that a contract is valid and can be deployed onchain. /// Returns whether the WASM is already up-to-date and activated onchain, and the data fee. -pub async fn check(cfg: &CheckConfig) -> Result { +pub async fn check(cfg: &CheckConfig) -> Result { if cfg.common_cfg.endpoint == "https://stylus-testnet.arbitrum.io/rpc" { let version = "cargo stylus version 0.2.1".to_string().red(); bail!("The old Stylus testnet is no longer supported.\nPlease downgrade to {version}",); @@ -78,31 +78,31 @@ pub async fn check(cfg: &CheckConfig) -> Result { greyln!("connecting to RPC: {}", &cfg.common_cfg.endpoint.lavender()); } - // check if the program already exists + // Check if the contract already exists. let provider = sys::new_provider(&cfg.common_cfg.endpoint)?; let codehash = alloy_primitives::keccak256(&code); - if program_exists(codehash, &provider).await? { - return Ok(ProgramCheck::Active { code }); + if contract_exists(codehash, &provider).await? { + return Ok(ContractCheck::Active { code }); } - let address = cfg.program_address.unwrap_or(H160::random()); + let address = cfg.contract_address.unwrap_or(H160::random()); let fee = check_activate(code.clone().into(), address, &provider).await?; let visual_fee = format_data_fee(fee).unwrap_or("???".red()); greyln!("wasm data fee: {visual_fee}"); - Ok(ProgramCheck::Ready { code, fee }) + Ok(ContractCheck::Ready { code, fee }) } -/// Whether a program is active, or needs activation. +/// Whether a contract is active, or needs activation. #[derive(PartialEq)] -pub enum ProgramCheck { - /// Program already exists onchain. +pub enum ContractCheck { + /// Contract already exists onchain. Active { code: Vec }, - /// Program can be activated with the given data fee. + /// Contract can be activated with the given data fee. Ready { code: Vec, fee: U256 }, } -impl ProgramCheck { +impl ContractCheck { pub fn code(&self) -> &[u8] { match self { Self::Active { code, .. } => code, @@ -200,8 +200,8 @@ pub async fn eth_call( } } -/// Checks whether a program has already been activated with the most recent version of Stylus. -async fn program_exists(codehash: B256, provider: &Provider) -> Result { +/// Checks whether a contract has already been activated with the most recent version of Stylus. +async fn contract_exists(codehash: B256, provider: &Provider) -> Result { let data = ArbWasm::codehashVersionCall { codehash }.abi_encode(); let tx = Eip1559TransactionRequest::new() .to(*ARB_WASM_H160) @@ -220,7 +220,7 @@ async fn program_exists(codehash: B256, provider: &Provider) -> Result bail!("not a Stylus program"), + A::ProgramNotWasm(_) => bail!("not a Stylus contract"), A::ProgramNotActivated(_) | A::ProgramNeedsUpgrade(_) | A::ProgramExpired(_) => { return Ok(false); } @@ -240,10 +240,10 @@ async fn program_exists(codehash: B256, provider: &Provider) -> Result) -> Result { - let program = Address::from(address.to_fixed_bytes()); - let data = ArbWasm::activateProgramCall { program }.abi_encode(); + let contract = Address::from(address.to_fixed_bytes()); + let data = ArbWasm::activateProgramCall { program: contract }.abi_encode(); let tx = Eip1559TransactionRequest::new() .to(*ARB_WASM_H160) .data(data) diff --git a/check/src/constants.rs b/check/src/constants.rs index d2bb12a..b923821 100644 --- a/check/src/constants.rs +++ b/check/src/constants.rs @@ -8,7 +8,7 @@ use lazy_static::lazy_static; /// EOF prefix used in Stylus compressed WASMs on-chain pub const EOF_PREFIX_NO_DICT: &str = "EFF00000"; -/// Maximum brotli compression level used for Stylus programs. +/// Maximum brotli compression level used for Stylus contracts. pub const BROTLI_COMPRESSION_LEVEL: u32 = 11; lazy_static! { diff --git a/check/src/deploy.rs b/check/src/deploy.rs index 600de07..f146e0b 100644 --- a/check/src/deploy.rs +++ b/check/src/deploy.rs @@ -3,7 +3,7 @@ #![allow(clippy::println_empty_string)] use crate::{ - check::{self, ProgramCheck}, + check::{self, ContractCheck}, constants::ARB_WASM_H160, macros::*, DeployConfig, @@ -36,7 +36,7 @@ sol! { pub type SignerClient = SignerMiddleware, Wallet>; -/// Deploys a stylus program, activating if needed. +/// Deploys a stylus contract, activating if needed. pub async fn deploy(cfg: DeployConfig) -> Result<()> { macro_rules! run { ($expr:expr) => { @@ -47,7 +47,7 @@ pub async fn deploy(cfg: DeployConfig) -> Result<()> { }; } - let program = run!(check::check(&cfg.check_config), "cargo stylus check failed"); + let contract = run!(check::check(&cfg.check_config), "cargo stylus check failed"); let verbose = cfg.check_config.common_cfg.verbose; let client = sys::new_provider(&cfg.check_config.common_cfg.endpoint)?; @@ -62,9 +62,9 @@ pub async fn deploy(cfg: DeployConfig) -> Result<()> { greyln!("sender address: {}", sender.debug_lavender()); } - let data_fee = program.suggest_fee(); + let data_fee = contract.suggest_fee(); - if let ProgramCheck::Ready { .. } = &program { + if let ContractCheck::Ready { .. } = &contract { // check balance early let balance = run!(client.get_balance(sender, None), "failed to get balance"); let balance = alloy_ethers_typecast::ethers_u256_to_alloy(balance); @@ -82,11 +82,16 @@ pub async fn deploy(cfg: DeployConfig) -> Result<()> { } } - let contract = cfg.deploy_contract(program.code(), sender, &client).await?; + let contract_addr = cfg + .deploy_contract(contract.code(), sender, &client) + .await?; - match program { - ProgramCheck::Ready { .. } => cfg.activate(sender, contract, data_fee, &client).await?, - ProgramCheck::Active { .. } => greyln!("wasm already activated!"), + match contract { + ContractCheck::Ready { .. } => { + cfg.activate(sender, contract_addr, data_fee, &client) + .await? + } + ContractCheck::Active { .. } => greyln!("wasm already activated!"), } Ok(()) } @@ -98,7 +103,7 @@ impl DeployConfig { sender: H160, client: &SignerClient, ) -> Result { - let init_code = program_deployment_calldata(code); + let init_code = contract_deployment_calldata(code); let tx = Eip1559TransactionRequest::new() .from(sender) @@ -141,8 +146,8 @@ impl DeployConfig { let tx_hash = receipt.transaction_hash.debug_lavender(); greyln!("deployment tx hash: {tx_hash}"); println!( - r#"we recommend running cargo stylus cache --address={} to cache your activated program in ArbOS. -Cached programs benefit from cheaper calls. To read more about the Stylus program cache, see + r#"we recommend running cargo stylus cache --address={} to cache your activated contract in ArbOS. +Cached contracts benefit from cheaper calls. To read more about the Stylus contract cache, see https://docs.arbitrum.io/stylus/concepts/stylus-cache-manager"#, hex::encode(contract) ); @@ -158,9 +163,12 @@ https://docs.arbitrum.io/stylus/concepts/stylus-cache-manager"#, ) -> Result<()> { let verbose = self.check_config.common_cfg.verbose; let data_fee = alloy_ethers_typecast::alloy_u256_to_ethers(data_fee); - let program: Address = contract.to_fixed_bytes().into(); + let contract_addr: Address = contract.to_fixed_bytes().into(); - let data = ArbWasm::activateProgramCall { program }.abi_encode(); + let data = ArbWasm::activateProgramCall { + program: contract_addr, + } + .abi_encode(); let tx = Eip1559TransactionRequest::new() .from(sender) @@ -195,7 +203,7 @@ https://docs.arbitrum.io/stylus/concepts/stylus-cache-manager"#, greyln!("activated with {gas}"); } greyln!( - "program activated and ready onchain with tx hash: {}", + "contract activated and ready onchain with tx hash: {}", receipt.transaction_hash.debug_lavender() ); Ok(()) @@ -233,7 +241,7 @@ pub async fn run_tx( } /// Prepares an EVM bytecode prelude for contract creation. -pub fn program_deployment_calldata(code: &[u8]) -> Vec { +pub fn contract_deployment_calldata(code: &[u8]) -> Vec { let mut code_len = [0u8; 32]; U256::from(code.len()).to_big_endian(&mut code_len); let mut deploy: Vec = vec![]; @@ -253,7 +261,7 @@ pub fn program_deployment_calldata(code: &[u8]) -> Vec { deploy } -pub fn extract_program_evm_deployment_prelude(calldata: &[u8]) -> Vec { +pub fn extract_contract_evm_deployment_prelude(calldata: &[u8]) -> Vec { // The length of the prelude, version part is 42 + 1 as per the code let metadata_length = 42 + 1; // Extract and return the metadata part diff --git a/check/src/export_abi.rs b/check/src/export_abi.rs index d508395..2eb0eda 100644 --- a/check/src/export_abi.rs +++ b/check/src/export_abi.rs @@ -10,7 +10,7 @@ use std::{ process::{self, Command, Stdio}, }; -/// Exports Solidity ABIs by running the program natively. +/// Exports Solidity ABIs by running the contract natively. pub fn export_abi(file: Option, json: bool) -> Result<()> { if json && !sys::command_exists("solc") { let link = "https://docs.soliditylang.org/en/latest/installing-solidity.html".red(); @@ -30,7 +30,7 @@ pub fn export_abi(file: Option, json: bool) -> Result<()> { let out = (out != "") .then_some(format!(": {out}")) .unwrap_or_default(); - egreyln!("failed to run program{out}"); + egreyln!("failed to run contract {out}"); process::exit(1); } diff --git a/check/src/main.rs b/check/src/main.rs index a57b1c3..9f8912b 100644 --- a/check/src/main.rs +++ b/check/src/main.rs @@ -38,7 +38,7 @@ enum Apis { New { /// Project name. name: PathBuf, - /// Create a minimal program. + /// Create a minimal contract. #[arg(long)] minimal: bool, }, @@ -62,7 +62,7 @@ enum Apis { /// Deploy a contract. #[command(alias = "d")] Deploy(DeployConfig), - /// Verify the deployment of a Stylus program. + /// Verify the deployment of a Stylus contract. #[command(alias = "v")] Verify(VerifyConfig), } @@ -94,10 +94,10 @@ pub struct CacheConfig { /// Wallet source to use. #[command(flatten)] auth: AuthOpts, - /// Deployed and activated program address to cache. + /// Deployed and activated contract address to cache. #[arg(long)] address: H160, - /// Bid, in wei, to place on the desired program to cache + /// Bid, in wei, to place on the desired contract to cache #[arg(short, long, hide(true))] bid: Option, } @@ -109,7 +109,7 @@ pub struct ActivateConfig { /// Wallet source to use. #[command(flatten)] auth: AuthOpts, - /// Deployed Stylus program address to activate. + /// Deployed Stylus contract address to activate. #[arg(long)] address: H160, /// Percent to bump the estimated activation data fee by. Default of 20% @@ -124,9 +124,9 @@ pub struct CheckConfig { /// The WASM to check (defaults to any found in the current directory). #[arg(long)] wasm_file: Option, - /// Where to deploy and activate the program (defaults to a random address). + /// Where to deploy and activate the contract (defaults to a random address). #[arg(long)] - program_address: Option, + contract_address: Option, /// If specified, will not run the command in a reproducible docker container. Useful for local /// builds, but at the risk of not having a reproducible contract for verification purposes. #[arg(long)] @@ -212,8 +212,8 @@ impl fmt::Display for CheckConfig { Some(path) => format!("--wasm-file={}", path.display()), None => "".to_string(), }, - match &self.program_address { - Some(addr) => format!("--program-address={:?}", addr), + match &self.contract_address { + Some(addr) => format!("--contract-address={:?}", addr), None => "".to_string(), }, match self.no_verify { @@ -301,12 +301,12 @@ async fn main_impl(args: Opts) -> Result<()> { } Apis::Activate(config) => { run!( - activate::activate_program(&config).await, + activate::activate_contract(&config).await, "stylus activate failed" ); } Apis::Cache(config) => { - run!(cache::cache_program(&config).await, "stylus cache failed"); + run!(cache::cache_contract(&config).await, "stylus cache failed"); } Apis::Check(config) => { if config.no_verify { diff --git a/check/src/project.rs b/check/src/project.rs index 0530ca6..ee327ec 100644 --- a/check/src/project.rs +++ b/check/src/project.rs @@ -310,7 +310,7 @@ pub fn compress_wasm(wasm: &PathBuf, project_hash: [u8; 32]) -> Result<(Vec, // Adds the hash of the project's source files to the wasm as a custom section // if it does not already exist. This allows for reproducible builds by cargo stylus -// for all Rust stylus programs. See `cargo stylus verify --help` for more information. +// for all Rust stylus contracts. See `cargo stylus verify --help` for more information. fn add_project_hash_to_wasm_file( wasm_file_bytes: &[u8], project_hash: [u8; 32], diff --git a/check/src/verify.rs b/check/src/verify.rs index 8eee240..9c55f8b 100644 --- a/check/src/verify.rs +++ b/check/src/verify.rs @@ -15,7 +15,7 @@ use serde::{Deserialize, Serialize}; use crate::{ check, constants::TOOLCHAIN_FILE_NAME, - deploy::{self, extract_compressed_wasm, extract_program_evm_deployment_prelude}, + deploy::{self, extract_compressed_wasm, extract_contract_evm_deployment_prelude}, project::{self, extract_toolchain_channel}, CheckConfig, VerifyConfig, }; @@ -53,7 +53,7 @@ pub async fn verify(cfg: VerifyConfig) -> eyre::Result<()> { let check_cfg = CheckConfig { common_cfg: cfg.common_cfg.clone(), wasm_file: None, - program_address: None, + contract_address: None, no_verify: cfg.no_verify, }; let _ = check::check(&check_cfg) @@ -68,14 +68,14 @@ pub async fn verify(cfg: VerifyConfig) -> eyre::Result<()> { let project_hash = project::hash_files(cfg.common_cfg.source_files_for_project_hash, build_cfg)?; let (_, init_code) = project::compress_wasm(&wasm_file, project_hash)?; - let deployment_data = deploy::program_deployment_calldata(&init_code); + let deployment_data = deploy::contract_deployment_calldata(&init_code); if deployment_data == *result.input { - println!("Verified - program matches local project's file hashes"); + println!("Verified - contract matches local project's file hashes"); } else { - let tx_prelude = extract_program_evm_deployment_prelude(&result.input); - let reconstructed_prelude = extract_program_evm_deployment_prelude(&deployment_data); + let tx_prelude = extract_contract_evm_deployment_prelude(&result.input); + let reconstructed_prelude = extract_contract_evm_deployment_prelude(&deployment_data); println!( - "{} - program deployment did not verify against local project's file hashes", + "{} - contract deployment did not verify against local project's file hashes", "FAILED".red() ); if tx_prelude != reconstructed_prelude { diff --git a/main/src/main.rs b/main/src/main.rs index a6ee7d6..5240e1b 100644 --- a/main/src/main.rs +++ b/main/src/main.rs @@ -38,7 +38,7 @@ enum Subcommands { /// Check a contract. #[command(alias = "c")] Check, - /// Activate an already deployed program + /// Activate an already deployed contract #[command(alias = "a")] Activate, /// Deploy a contract. @@ -50,7 +50,7 @@ enum Subcommands { /// Trace a transaction. #[command()] Trace, - /// Verify the deployment of a Stylus program against a local project. + /// Verify the deployment of a Stylus contract against a local project. #[command(alias = "v")] Verify, /// Generate C code. diff --git a/replay/src/hostio.rs b/replay/src/hostio.rs index 1674ee4..ce03b56 100644 --- a/replay/src/hostio.rs +++ b/replay/src/hostio.rs @@ -37,7 +37,7 @@ macro_rules! copy { }; } -/// Reads the program calldata. The semantics are equivalent to that of the EVM's +/// Reads the contract calldata. The semantics are equivalent to that of the EVM's /// [`CALLDATA_COPY`] opcode when requesting the entirety of the current call's calldata. /// /// [`CALLDATA_COPY`]: https://www.evm.codes/#37 @@ -48,8 +48,8 @@ pub unsafe extern "C" fn read_args(dest: *mut u8) { copy!(args, dest, args.len()); } -/// Writes the final return data. If not called before the program exists, the return data will -/// be 0 bytes long. Note that this hostio does not cause the program to exit, which happens +/// Writes the final return data. If not called before the contract exists, the return data will +/// be 0 bytes long. Note that this hostio does not cause the contract to exit, which happens /// naturally when `user_entrypoint` returns. #[named] #[no_mangle] @@ -313,7 +313,7 @@ pub unsafe extern "C" fn static_call_contract( status } -/// Gets the address of the current program. The semantics are equivalent to that of the EVM's +/// Gets the address of the current contract. The semantics are equivalent to that of the EVM's /// [`ADDRESS`] opcode. /// /// [`ADDRESS`]: https://www.evm.codes/#30 @@ -326,9 +326,9 @@ pub unsafe extern "C" fn contract_address(dest: *mut u8) { /// Deploys a new contract using the init code provided, which the EVM executes to construct /// the code of the newly deployed contract. The init code must be written in EVM bytecode, but -/// the code it deploys can be that of a Stylus program. The code returned will be treated as +/// the code it deploys can be that of a Stylus contract. The code returned will be treated as /// WASM if it begins with the EOF-inspired header `0xEFF000`. Otherwise the code will be -/// interpreted as that of a traditional EVM-style contract. See [`Deploying Stylus Programs`] +/// interpreted as that of a traditional EVM-style contract. See [`Deploying Stylus Contracts`] /// for more information on writing init code. /// /// On success, this hostio returns the address of the newly created account whose address is @@ -337,7 +337,7 @@ pub unsafe extern "C" fn contract_address(dest: *mut u8) { /// `read_return_data` hostio. The semantics are equivalent to that of the EVM's [`CREATE`] /// opcode, which notably includes the exact address returned. /// -/// [`Deploying Stylus Programs`]: https://developer.arbitrum.io/TODO +/// [`Deploying Stylus Contracts`]: https://developer.arbitrum.io/TODO /// [`CREATE`]: https://www.evm.codes/#f0 #[named] #[no_mangle] @@ -362,9 +362,9 @@ pub unsafe extern "C" fn create1( /// Deploys a new contract using the init code provided, which the EVM executes to construct /// the code of the newly deployed contract. The init code must be written in EVM bytecode, but -/// the code it deploys can be that of a Stylus program. The code returned will be treated as +/// the code it deploys can be that of a Stylus contract. The code returned will be treated as /// WASM if it begins with the EOF-inspired header `0xEFF000`. Otherwise the code will be -/// interpreted as that of a traditional EVM-style contract. See [`Deploying Stylus Programs`] +/// interpreted as that of a traditional EVM-style contract. See [`Deploying Stylus Contracts`] /// for more information on writing init code. /// /// On success, this hostio returns the address of the newly created account whose address is a @@ -373,7 +373,7 @@ pub unsafe extern "C" fn create1( /// via the `read_return_data` hostio. The semantics are equivalent to that of the EVM's /// `[CREATE2`] opcode, which notably includes the exact address returned. /// -/// [`Deploying Stylus Programs`]: https://developer.arbitrum.io/TODO +/// [`Deploying Stylus Contracts`]: https://developer.arbitrum.io/TODO /// [`CREATE2`]: https://www.evm.codes/#f5 #[named] #[no_mangle] @@ -442,7 +442,7 @@ pub unsafe extern "C" fn evm_ink_left() -> u64 { } /// The `entrypoint!` macro handles importing this hostio, which is required if the -/// program's memory grows. Otherwise compilation through the `ArbWasm` precompile will revert. +/// contract's memory grows. Otherwise compilation through the `ArbWasm` precompile will revert. /// Internally the Stylus VM forces calls to this hostio whenever new WASM pages are allocated. /// Calls made voluntarily will unproductively consume gas. #[named] @@ -460,7 +460,7 @@ pub unsafe extern "C" fn msg_reentrant() -> bool { reentrant } -/// Gets the address of the account that called the program. For normal L2-to-L2 transactions +/// Gets the address of the account that called the contract. For normal L2-to-L2 transactions /// the semantics are equivalent to that of the EVM's [`CALLER`] opcode, including in cases /// arising from [`DELEGATE_CALL`]. /// @@ -477,7 +477,7 @@ pub unsafe extern "C" fn msg_sender(dest: *mut u8) { copy!(sender, dest); } -/// Get the ETH value in wei sent to the program. The semantics are equivalent to that of the +/// Get the ETH value in wei sent to the contract. The semantics are equivalent to that of the /// EVM's [`CALLVALUE`] opcode. /// /// [`CALLVALUE`]: https://www.evm.codes/#34 @@ -521,7 +521,7 @@ pub unsafe extern "C" fn read_return_data( } /// Returns the length of the last EVM call or deployment return result, or `0` if neither have -/// happened during the program's execution. The semantics are equivalent to that of the EVM's +/// happened during the contract's execution. The semantics are equivalent to that of the EVM's /// [`RETURN_DATA_SIZE`] opcode. /// /// [`RETURN_DATA_SIZE`]: https://www.evm.codes/#3d diff --git a/replay/src/trace.rs b/replay/src/trace.rs index fecd5c6..37fc656 100644 --- a/replay/src/trace.rs +++ b/replay/src/trace.rs @@ -44,13 +44,13 @@ impl Trace { if let Value::Array(arr) = json.clone() { if arr.is_empty() { - bail!("No trace frames found, perhaps you are attempting to trace the program deployment transaction"); + bail!("No trace frames found, perhaps you are attempting to trace the contract deployment transaction"); } } let maybe_activation_trace: Result, _> = from_value(json.clone()); if maybe_activation_trace.is_ok() { - bail!("Your tx was a program activation transaction. It has no trace frames"); + bail!("Your tx was a contract activation transaction. It has no trace frames"); } let to = receipt.to.map(|x| Address::from(x.0));