- Docs
- Developers
- Troubleshooting
Troubleshooting Development Issues
Here you'll find instructions for troubleshooting common issues and problems that can occur during Archway development.
- General errors
- Creating project fails
- Deployment failures
- RPC errors
- Testing
- File permissions
- Miscellaneous
General Errors
Process exited with code 1 (ChildProcess)
There are times during development where you may receive unclear error messages from the developer CLI. This could be because the error message itself doesn't explain which part of the command has failed. These errors are usually triggered by Node's Child Process module panicking and failing to complete a Promise.
Failed to deploy projectError: Process exited with code 1at ChildProcess.done (/home/user/.nvm/versions/node/v17.9.0/lib/node_modules/@archwayhq/cli/node_modules/promisify-child-process/index.cjs:70:19)at ChildProcess.emit (node:events:527:28)at maybeClose (node:internal/child_process:1090:16)at Process.ChildProcess._handle.onexit (node:internal/child_process:302:5)
To understand the real source of the error, you'll need to execute your command with some debugging flags enabled. To understand how to enable debugging on the developer CLI, review our debugging instructions.
SyntaxError: Invalid or unexpected token
You'll get this error message for all Archway commands, if the NPM package for the developer CLI was installed using a legacy version of Node.js. To solve this problem update Node.js and reinstall the NPM package. For information about which versions of Node.js are supported, review the developer installation instructions.
Project Creation
Error: no such subcommand
When creating a new project with the archway new command, if you encounter an error message stating error: no such subcommand: run-script or error: no such subcommand: generate, it means you're missing a required Cargo package.
To resolve the issue, ensure that you've installed both cargo-generate and cargo-run-script.
Example:
cargo install cargo-generate --features vendored-opensslcargo install cargo-run-script
Deployment Failures
CosmWasm Rust optimizer fails
If you are having issues with the cosmwasm/rust-optimizer, you may need to update the Cargo.toml file at the root of your project with a different version of the optimizer.
Example (Old Cargo.toml):
[package.metadata.scripts]optimize = """docker run --rm -v "$(pwd)":/code \ -e CARGO_TERM_COLOR=always \ --mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \ --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ cosmwasm/rust-optimizer:0.12.5"""
Example (Updated Cargo.toml):
[package.metadata.scripts]optimize = """docker run --rm -v "$(pwd)":/code \ -e CARGO_TERM_COLOR=always \ --mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \ --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ cosmwasm/rust-optimizer:0.12.6"""
Deployment stuck at downloading WASM
This could be an issue with the RPC node. If your deployment is continually getting stuck downloading wasm, try downloading it manually or use the flag --no-verify to skip checksum verification entirely.
To manually download and verify the wasm uploaded, you'll need to know the code id which you can get by searching the block explorer for your upload transaction by its hash, or using the archway history command if your config.json was successfully updated after the transaction. Once you've got the code id, see below for an example of how to download and verify your wasm storage transaction.
Example:
mainnet
testnet
archwayd query wasm code $YOUR_CODE_ID --node https://rpc.mainnet.archway.io:443 download.wasm$ diff artifacts/YOUR_DOCKER_WASM_OUTPUT_FILE.wasm download.wasm
WASM stores but contract fails to instantiate
The most common reason for deployments failing during instantiation is incorrect arguments submitted to the --args flags. See test passed but on-chain tx fails for more information.
Testing
Can't print data from tests
Ever wondered why you can't use macros like println! and dbg! to write to stdout from tests? This happens because Rust tests hide the stdout stream of successful tests to keep test output tidy. You can disable this behavior by passing the --nocapture option to the test binary or to cargo test (but, in this case after -- – see below):
Examples:
$ rustc --test main.rs; ./mainrunning 1 testtest test ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured$ ./main --nocapturerunning 1 testHidden outputtest test ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s$ cargo test -- --nocapturerunning 1 testHidden outputtest test ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
If you need to make this the default behavior of the archway test command, you can do so by modifying the value of developer.scripts.test in config.json at the root of your project.
Example:
Default JSON (excerpt)
{ "developer": { "scripts": { "test": "cargo unit-test", "build": "cargo build", "optimize": "cargo run-script optimize", "wasm": "cargo wasm", "query": "archwayd query wasm", "tx": "archwayd tx wasm execute" } }}
Updated JSON (excerpt)
{ "developer": { "scripts": { "test": "cargo unit-test -- --nocapture", "build": "cargo build", "optimize": "cargo run-script optimize", "wasm": "cargo wasm", "query": "archwayd query wasm", "tx": "archwayd tx wasm execute" } }}
Test passed but on-chain tx fails
A frequent cause for this issue is an error in the arguments specified in the --args flag of the archway deploy or archway tx command.
There are several things to consider when constructing your JSON arguments for the --args flag. Below are a few use cases that will cause instantiation to fail.
1) Invalid JSON
If your arguments are not submitted in valid JSON format the instantiation will fail. The full error response looks like this:
error: option '-a, --args <value>' argument '{count:0}' is invalid. Please inform a valid JSON string.
2) Invalid JSON key
If your JSON values are all correct, but one or more of their keys are not recognized, you'll get an Error parsing into type response from the developer CLI. The full error message might look like this:
Error: rpc error: code = InvalidArgument desc = failed to execute message; message index: 0: Error parsing into type increment_project::msg::InstantiateMsg: missing field `count`: instantiate wasm contract failed: invalid request
3) Invalid JSON value
If the JSON keys are correct, but one or more values are not, you'll get an Invalid type error response from the developer CLI. The full error message looks like this:
Error: rpc error: code = InvalidArgument desc = failed to execute message; message index: 0: Error parsing into type increment_project::msg::InstantiateMsg: Invalid type: instantiate wasm contract failed: invalid request
Info
For help finding the source of problems with transaction aguments, see how to debug failing transactions for more information about regenerating your schema.
RPC Errors
My code used to work, I didn't change anything
This can happen if the RPC node you're connecting to is running a different version of archwayd.
If you are using the Docker version of archwayd, pull again from Docker Hub to get the latest image.
Example:
docker pull ghcr.io/archway-network/archwayd-dev:v9.0.0
If you have installed archwayd locally from GitHub, you will need to pull the latest changes and reinstall archwayd.
Example:
git fetchgit checkout tags/${tag_name} # e.g. git checkout tags/v0.0.5make install
InvalidArgument desc = account sequence mismatch
Error: rpc error: code = InvalidArgument desc = account sequence mismatch, expected 13898, got 13884: incorrect account sequence: invalid request
The above error isn't caused by your code. It seems to occur during periods of high network activity. You can have a look at this GitHub issue for additional context.
We are actively looking for ways to solve it, but in the meantime your best bet is to continue broadcasting the transaction until it works. In some cases, you may also be able to get your transaction through by switching the --broadcast-mode flag sent to archwayd. The developer CLI currently defaults to --broadcast-mode block, to switch to --broadcast-mode sync you'll need to call archwayd directly.
Example (Instantiate):
mainnet
testnet
archwayd tx wasm instantiate ${YOUR_CODE_ID} '{"key":"value"}' --from ${YOUR_WALLET_NAME} --label ${YOUR_DAPP_LABEL} --node https://rpc.mainnet.archway.io:443 --chain-id archway-1 --gas auto --gas-prices $(archwayd q rewards estimate-fees 1 --node 'https://rpc.mainnet.archway.io:443' --output json | jq -r '.gas_unit_price | (.amount + .denom)') --gas-adjustment 1.3 --broadcast-mode sync -y
Example (Tx):
mainnet
testnet
archwayd tx wasm execute ${YOUR_CONTRACT_ADDRESS} '{"entrypoint":{}}' --from ${YOUR_WALLET_NAME} --node "https://rpc.constantine.archway.io:443" --chain-id archway-1 --gas auto --gas-prices $(archwayd q rewards estimate-fees 1 --node 'https://rpc.mainnet.archway.io:443' --output json | jq -r '.gas_unit_price | (.amount + .denom)') --gas-adjustment 1.3 --broadcast-mode sync -y
Permissions Errors
Docker setups are the source of most permissions errors, and by default Docker runs as the root user. If you're not running the Docker daemon in rootless mode you may need to install the Archway developer CLI as root, or give your user permissions to the Archway directory on your filesystem.
Example:
sudo chown YOUR_USERNAME:YOUR_GROUPNAME -R ~/.archway
This problem can be avoided by installing archwayd locally. For those instructions see: install archwayd from source
Miscellaneous
Providing flags to archwayd without passing them to docker
If you are running docker and want to pass flags to archwayd without having those flags being used by docker, you can run docker in interactive mode:
docker run -it
Cannot find module ‘fs/promises’
If you are getting the error Cannot find module ‘fs/promises’. Requires stack: while using the developer cli or arhc3js make sure that you are using a node version higher than v14.
Transaction submitted but was not yet found on the chain
If you get the error Transaction with ID … was submitted but was not yet found on the chain, you may want to check if your transaction requires more gas than the max gas setting. If the computation requires more gas than that it will never be included in a block.
Error: spawn archwayd ENOENT
If you are getting the error spawn archwayd ENOENT, make sure to correctly set the GOPATH, as documented here. If you are using Linux, you can launch:
export GOPATH=$HOME/go export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
And then update your terminal shell by launching:
source ~/.profile"
Also, you can clean up your environment, so that you know exactly where archwayd is located and avoid complications.
If using the Developer CLI v1, you can try using the Developer CLI v2 instead,does not have any dependency on archwayd. Also, the CLI v2 provides additional features with a smoother development cycle.
Invalid type: instantiate wasm contract failed
Make sure to pass the right variable type. For example, if you are trying to pass a bigint, keep in mind that serde deserializes uint128 by expecting a string on the input.
For example, instead of having the price
field like this:
""max"": 250, ""price"": 1000000000, ""denom"": ""aconst""
you should have it quoted:
""max"": 250, ""price"": "1000000000", ""denom"": ""aconst""
How can i get a smart contract's balance?
Using something like the following:
let balance = BankQuery::Balance { denom, address };
would get you a BankQuery. If you need a String or u128 you would need to declare a querier and then use that to perform the query. similarly to:
let balance_response = querier.query(&balance_query.into())
And then convert the response into a Balance object, from which you can extract the amount, and convert it into a u128 or String:
let balance: Balance = Balance::from(balance_response)
An example of that would be:
pub fn get_balance( deps: &DepsMut, env: Env,) -> Result<u128, StdError> { let denom = DENOM.load(deps.storage)?; let address = env.contract.address.to_string(); let balance_query = BankQuery::Balance { denom, address }; let balance_response: BalanceResponse = deps.querier.query(&balance_query.into())?; let balance_u128 = balance_response.amount.amount.u128(); Ok(balance_u128)}
How to send a contract multiMsg?
If you want to send a transaction with multiple signers to complete the transaction, you can use the signer.executeMultiple
with:
const signer = await SigningCosmWasmClient.connectWithSigner(network.endpoint, offlineSigner, {gasPrice,prefix: network.prefix,});
How to mint NFTs from another smart contract?
You could use the following example:
let metadata = Metadata { image: None, image_data: None, external_url: None, description: None, name: None, attributes: None, background_color: None, animation_url: None, youtube_url: None,};let mint_msg = MintMsg { token_id: token_id, owner: info.sender.to_string(), token_uri: None, extension: metadata.clone(),};let exec_msg = ExecuteMsg::Mint(mint_msg.clone());let message = SubMsg::new(WasmMsg::Execute { contract_addr: state.nft_address.ok_or(ContractError::EmptyNftMinter {})?.to_string(), msg: to_binary(&exec_msg)?, funds: vec![],});
How can i create a CW-20 token on Archway?
You can use the Developer CLI, choose the CW20 template and set the following parameters in the Instantiate transaction:
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, PartialEq)]pub struct InstantiateMsg { pub name: String, pub symbol: String, pub decimals: u8, pub initial_balances: Vec<Cw20Coin>, pub mint: Option<MinterResponse>, pub marketing: Option<InstantiateMarketingInfo>,}
The types you need for MinterResponse and InstantaiteMarketingInfo are:
// Imported from `cw20`pub struct MinterResponse { pub minter: String, pub cap: Option<Uint128>,}// Imported from `cw20`pub enum Logo { Url(String), Embedded(EmbeddedLogo),}// Imported from `cw20`pub enum EmbeddedLogo { Svg(Binary), Png(Binary),}// Defined in your msg.rs#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, PartialEq)]pub struct InstantiateMarketingInfo { pub project: Option<String>, pub description: Option<String>, pub marketing: Option<String>, pub logo: Option<Logo>,}
What is the max gas limit on the transaction payload size for CosmWasm contracts?
The following RPC endpoint will pull in the max bytes per block and the maximum of gas that can be used per block: https://rpc.mainnet.archway.io/consensus_params.
Shoulf i use global constants or dynamic cw_storage_plus types?
You may wonder why sticking with global const (such as Items, Maps..) instead of dynamic cw_storage_plus types.
For example, if you have a contract that represents a game with multiple rounds, where you'd want to have a query to get a list of player's ticket counts in a given round, you could eiether:
- Use a map with a composite key, like:
ROUND_TICKETS = Map<(RoundNo, PlayerId), u32>
andROUND_TICKETS.prefix(round_no).range(...)
- Or use an approach similar to the following:
fn get_player_ticket_counts(storage, round_no) { let map: Map<PlayerId, u32> = Map::new(format!("tickets{}", round_no).as_str()); Ok(map.range(...).map(...).collect()) }
and wonder what would be the correct approach.
The reason why it is a common design pattern to use global consts is that creating and managing variables dynamically might have higher gas costs compared to using pre-defined constants, especially if the dynamic creation is done frequently. Also gobal constants can make it easier to understand contract's behavior and potential vulnerabilities easier.
Using a dynamic approach for variables can be way more convenient, as you can create state variables on-the-fly without the need to predefine them all. Anywaysm it can also lead to possible bugs where one accidentally crosses into the prefix range of some other "round" (as in the example) or corrupts the entire map in some other way. Keeping each round's ticket count in a separate map would help with preserve data integrity.
Depending on the use case, using dynamic types could lead to a more complex logic flow if not managed carefully. In this specific example, the approach of using separate maps for each round's ticket counts simplifies the data structure and by isolating the data for each round gives easier understanding of contract's state, as well as an easier code readibility.
Re-instantiating the map on each call might introduce some minor overhead, but the additional cost of map instantiation might not be a significant factor.
Keep in mind though that in the latter approach re-instantiates the map on each call, and a block explorer probably wouldn't be an effective way to browse this contract's state.
Should i use u32 or Uint32?
Using the Uint32 cosmwasm wrapper, compared to u32 can help prevent potential issues related to type mismatch and serialization. It is considered to be a safer approach for cw contract development. Additional info regarding uint128 and u128 can be alrady found here.
Error: SIGN_MODE_DIRECT can’t be signed on Ledger
As Ledger does not support Direct Signing Mode,you would need to use the Amino Signing Mode instead:
return window.keplr?.getOfflineSignerAuto(chainId);