Skip to content

New error type #2500

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 8 additions & 13 deletions contracts/burner/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub fn instantiate(
_info: MessageInfo,
_msg: InstantiateMsg,
) -> StdResult<Response> {
Err(StdError::generic_err(
Err(StdError::msg(
"You can only use this contract for migrations",
))
}
Expand All @@ -23,7 +23,7 @@ pub fn migrate(deps: DepsMut, env: Env, msg: MigrateMsg) -> StdResult<Response>
let denom_len = msg.denoms.len();
let denoms = BTreeSet::<String>::from_iter(msg.denoms); // Ensure uniqueness
if denoms.len() != denom_len {
return Err(StdError::generic_err("Denoms not unique"));
return Err(StdError::msg("Denoms not unique"));
}

// get balance and send to recipient
Expand Down Expand Up @@ -98,7 +98,7 @@ mod tests {
use cosmwasm_std::testing::{
message_info, mock_dependencies, mock_dependencies_with_balance, mock_env,
};
use cosmwasm_std::{coin, coins, Attribute, StdError, Storage, SubMsg};
use cosmwasm_std::{coin, coins, Attribute, Storage, SubMsg};

/// Gets the value of the first attribute with the given key
fn first_attr(data: impl AsRef<[Attribute]>, search_key: &str) -> Option<String> {
Expand All @@ -121,12 +121,10 @@ mod tests {
let info = message_info(&creator, &coins(1000, "earth"));
// we can just call .unwrap() to assert this was a success
let res = instantiate(deps.as_mut(), mock_env(), info, msg);
match res.unwrap_err() {
StdError::GenericErr { msg, .. } => {
assert_eq!(msg, "You can only use this contract for migrations")
}
_ => panic!("expected migrate error message"),
}
assert!(res
.unwrap_err()
.to_string()
.ends_with("You can only use this contract for migrations"));
}

#[test]
Expand All @@ -142,10 +140,7 @@ mod tests {
delete: 0,
};
let err = migrate(deps.as_mut(), mock_env(), msg).unwrap_err();
match err {
StdError::GenericErr { msg, .. } => assert_eq!(msg, "Denoms not unique"),
err => panic!("Unexpected error: {err:?}"),
}
assert!(err.to_string().ends_with("Denoms not unique"));

// One denom
let msg = MigrateMsg {
Expand Down
2 changes: 1 addition & 1 deletion contracts/burner/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ fn instantiate_fails() {
let msg = res.unwrap_err();
assert_eq!(
msg,
"Generic error: You can only use this contract for migrations"
"kind: Other, error: You can only use this contract for migrations"
);
}

Expand Down
32 changes: 10 additions & 22 deletions contracts/crypto-verify/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ pub fn query_verify_ethereum_text(
// Decompose signature
let (v, rs) = match signature.split_last() {
Some(pair) => pair,
None => return Err(StdError::generic_err("Signature must not be empty")),
None => return Err(StdError::msg("Signature must not be empty")),
};
let recovery = get_recovery_param(*v)?;

Expand Down Expand Up @@ -326,7 +326,7 @@ mod tests {
use cosmwasm_std::testing::{
message_info, mock_dependencies, mock_env, MockApi, MockQuerier, MockStorage,
};
use cosmwasm_std::{from_json, OwnedDeps, RecoverPubkeyError, VerificationError};
use cosmwasm_std::{from_json, OwnedDeps, StdErrorKind};
use hex_literal::hex;

const CREATOR: &str = "creator";
Expand Down Expand Up @@ -426,11 +426,8 @@ mod tests {
let res = query(deps.as_ref(), mock_env(), verify_msg);
assert!(res.is_err());
assert!(matches!(
res.unwrap_err(),
StdError::VerificationErr {
source: VerificationError::InvalidPubkeyFormat,
..
}
res.unwrap_err().kind(),
StdErrorKind::Cryptography,
))
}

Expand Down Expand Up @@ -500,11 +497,8 @@ mod tests {
signer_address: signer_address.into(),
};
let result = query(deps.as_ref(), mock_env(), verify_msg);
match result.unwrap_err() {
StdError::RecoverPubkeyErr {
source: RecoverPubkeyError::UnknownErr { .. },
..
} => {}
match result.unwrap_err().kind() {
StdErrorKind::Cryptography => {}
err => panic!("Unexpected error: {err:?}"),
}
}
Expand Down Expand Up @@ -715,11 +709,8 @@ mod tests {
let res = query(deps.as_ref(), mock_env(), verify_msg);
assert!(res.is_err());
assert!(matches!(
res.unwrap_err(),
StdError::VerificationErr {
source: VerificationError::InvalidPubkeyFormat,
..
}
res.unwrap_err().kind(),
StdErrorKind::Cryptography
))
}

Expand Down Expand Up @@ -781,11 +772,8 @@ mod tests {
let res = query(deps.as_ref(), mock_env(), verify_msg);
assert!(res.is_err());
assert!(matches!(
res.unwrap_err(),
StdError::VerificationErr {
source: VerificationError::InvalidPubkeyFormat,
..
}
res.unwrap_err().kind(),
StdErrorKind::Cryptography,
))
}

Expand Down
18 changes: 8 additions & 10 deletions contracts/crypto-verify/src/ethereum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ pub fn get_recovery_param(v: u8) -> StdResult<u8> {
match v {
27 => Ok(0),
28 => Ok(1),
_ => Err(StdError::generic_err("Values of v other than 27 and 28 not supported. Replay protection (EIP-155) cannot be used here."))
_ => Err(StdError::msg("Values of v other than 27 and 28 not supported. Replay protection (EIP-155) cannot be used here."))
}
}

Expand All @@ -87,7 +87,7 @@ pub fn get_recovery_param_with_chain_id(v: u64, chain_id: u64) -> StdResult<u8>
let recovery = v - chain_id * 2 - 35;
match recovery {
0 | 1 => Ok(recovery as u8),
_ => Err(StdError::generic_err(format!(
_ => Err(StdError::msg(format_args!(
"Calculated recovery parameter must be 0 or 1 but is {recovery}."
))),
}
Expand All @@ -97,13 +97,13 @@ pub fn get_recovery_param_with_chain_id(v: u64, chain_id: u64) -> StdResult<u8>
pub fn ethereum_address_raw(pubkey: &[u8]) -> StdResult<[u8; 20]> {
let (tag, data) = match pubkey.split_first() {
Some(pair) => pair,
None => return Err(StdError::generic_err("Public key must not be empty")),
None => return Err(StdError::msg("Public key must not be empty")),
};
if *tag != 0x04 {
return Err(StdError::generic_err("Public key must start with 0x04"));
return Err(StdError::msg("Public key must start with 0x04"));
}
if data.len() != 64 {
return Err(StdError::generic_err("Public key must be 65 bytes long"));
return Err(StdError::msg("Public key must be 65 bytes long"));
}

let hash = Keccak256::digest(data);
Expand All @@ -112,14 +112,12 @@ pub fn ethereum_address_raw(pubkey: &[u8]) -> StdResult<[u8; 20]> {

pub fn decode_address(input: &str) -> StdResult<[u8; 20]> {
if input.len() != 42 {
return Err(StdError::generic_err(
"Ethereum address must be 42 characters long",
));
return Err(StdError::msg("Ethereum address must be 42 characters long"));
}
if !input.starts_with("0x") {
return Err(StdError::generic_err("Ethereum address must start with 0x"));
return Err(StdError::msg("Ethereum address must start with 0x"));
}
let data = hex::decode(&input[2..]).map_err(|_| StdError::generic_err("hex decoding error"))?;
let data = hex::decode(&input[2..])?;
Ok(data.try_into().unwrap())
}

Expand Down
10 changes: 5 additions & 5 deletions contracts/crypto-verify/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ fn cosmos_signature_verify_errors() {
let res = query(&mut deps, mock_env(), verify_msg);
assert_eq!(
res.unwrap_err(),
"Verification error: Invalid public key format"
"kind: Cryptography, error: Invalid public key format"
)
}

Expand Down Expand Up @@ -283,7 +283,7 @@ fn secp256r1_signature_verify_errors() {
let res = query(&mut deps, mock_env(), verify_msg);
assert_eq!(
res.unwrap_err(),
"Verification error: Invalid public key format"
"kind: Cryptography, error: Invalid public key format"
)
}

Expand Down Expand Up @@ -354,7 +354,7 @@ fn ethereum_signature_verify_fails_for_corrupted_signature() {
};
let result = query(&mut deps, mock_env(), verify_msg);
let msg = result.unwrap_err();
assert_eq!(msg, "Recover pubkey error: Unknown error: 10");
assert_eq!(msg, "kind: Cryptography, error: Unknown error: 10");
}

#[test]
Expand Down Expand Up @@ -466,7 +466,7 @@ fn tendermint_signature_verify_errors() {
let res = query(&mut deps, mock_env(), verify_msg);
assert_eq!(
res.unwrap_err(),
"Verification error: Invalid public key format"
"kind: Cryptography, error: Invalid public key format"
)
}

Expand Down Expand Up @@ -625,7 +625,7 @@ fn tendermint_signatures_batch_verify_errors() {
let res = query(&mut deps, mock_env(), verify_msg);
assert_eq!(
res.unwrap_err(),
"Verification error: Invalid public key format"
"kind: Cryptography, error: Invalid public key format"
)
}

Expand Down
9 changes: 4 additions & 5 deletions contracts/cyberpunk/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ fn execute_argon2(mem_cost: u32, time_cost: u32) -> Result<Response, ContractErr
ad: &[],
hash_length: 32,
};
let hash = argon2::hash_encoded(password, salt, &config)
.map_err(|e| StdError::generic_err(format!("hash_encoded errored: {e}")))?;
let hash = argon2::hash_encoded(password, salt, &config).map_err(StdError::from)?;
// let matches = argon2::verify_encoded(&hash, password).unwrap();
// assert!(matches);
Ok(Response::new().set_data(hash.into_bytes()))
Expand Down Expand Up @@ -106,13 +105,13 @@ fn execute_allocate_large_memory(pages: u32) -> Result<Response, ContractError>
use core::arch::wasm32;
let old_size = wasm32::memory_grow(0, pages as usize);
if old_size == usize::max_value() {
return Err(StdError::generic_err("memory.grow failed").into());
return Err(StdError::msg("memory.grow failed").into());
}
Ok(Response::new().set_data((old_size as u32).to_be_bytes()))
}

#[cfg(not(target_arch = "wasm32"))]
Err(StdError::generic_err("Unsupported architecture").into())
Err(StdError::msg("Unsupported architecture").into())
}

fn execute_panic() -> Result<Response, ContractError> {
Expand All @@ -139,7 +138,7 @@ fn execute_unreachable() -> Result<Response, ContractError> {
core::arch::wasm32::unreachable();

#[cfg(not(target_arch = "wasm32"))]
Err(StdError::generic_err("Unsupported architecture").into())
Err(StdError::msg("Unsupported architecture").into())
}

fn execute_mirror_env(env: Env) -> Result<Response, ContractError> {
Expand Down
2 changes: 1 addition & 1 deletion contracts/cyberpunk/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use cosmwasm_std::StdError;
use thiserror::Error;

#[derive(Error, Debug, PartialEq)]
#[derive(Error, Debug)]
pub enum ContractError {
#[error("{0}")]
/// this is needed so we can use `bucket.load(...)?` and have it auto-converted to the custom error
Expand Down
38 changes: 19 additions & 19 deletions contracts/hackatom/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use sha2::{Digest, Sha256};
use cosmwasm_std::{
entry_point, from_json, to_json_binary, to_json_vec, Addr, Api, BankMsg, CanonicalAddr, Deps,
DepsMut, Env, Event, MessageInfo, MigrateInfo, QueryRequest, QueryResponse, Response, StdError,
StdResult, WasmMsg, WasmQuery,
StdErrorKind, StdResult, WasmMsg, WasmQuery,
};

use crate::errors::HackError;
Expand Down Expand Up @@ -53,7 +53,7 @@ pub fn migrate(
let data = deps
.storage
.get(CONFIG_KEY)
.ok_or_else(|| StdError::not_found("State"))?;
.ok_or_else(|| StdError::msg("State not found"))?;
let mut config: State = from_json(data)?;
config.verifier = deps.api.addr_validate(&msg.verifier)?;
deps.storage.set(CONFIG_KEY, &to_json_vec(&config)?);
Expand Down Expand Up @@ -102,7 +102,7 @@ fn do_release(
let data = deps
.storage
.get(CONFIG_KEY)
.ok_or_else(|| StdError::not_found("State"))?;
.ok_or_else(|| StdError::msg("State not found"))?;
let state: State = from_json(data)?;

if info.sender == state.verifier {
Expand Down Expand Up @@ -171,13 +171,13 @@ fn do_allocate_large_memory(pages: u32) -> Result<Response, HackError> {
use core::arch::wasm32;
let old_size = wasm32::memory_grow(0, pages as usize);
if old_size == usize::max_value() {
return Err(StdError::generic_err("memory.grow failed").into());
return Err(StdError::msg("memory.grow failed").into());
}
Ok(Response::new().set_data((old_size as u32).to_be_bytes()))
}

#[cfg(not(target_arch = "wasm32"))]
Err(StdError::generic_err("Unsupported architecture").into())
Err(StdError::msg("Unsupported architecture").into())
}

fn do_panic() -> Result<Response, HackError> {
Expand All @@ -203,32 +203,32 @@ fn do_user_errors_in_api_calls(api: &dyn Api) -> Result<Response, HackError> {
// Canonicalize

let empty = "";
match api.addr_canonicalize(empty).unwrap_err() {
StdError::GenericErr { .. } => {}
match api.addr_canonicalize(empty).unwrap_err().kind() {
StdErrorKind::Other => {}
err => {
return Err(StdError::generic_err(format!(
return Err(StdError::msg(format_args!(
"Unexpected error in do_user_errors_in_api_calls: {err:?}"
))
.into())
}
}

let invalid = "bn9hhssomeltvhzgvuqkwjkpwxoj";
match api.addr_canonicalize(invalid).unwrap_err() {
StdError::GenericErr { .. } => {}
match api.addr_canonicalize(invalid).unwrap_err().kind() {
StdErrorKind::Other => {}
err => {
return Err(StdError::generic_err(format!(
return Err(StdError::msg(format_args!(
"Unexpected error in do_user_errors_in_api_calls: {err:?}"
))
.into())
}
}

let too_long = "cosmwasm1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqehqqkz";
match api.addr_canonicalize(too_long).unwrap_err() {
StdError::GenericErr { .. } => {}
match api.addr_canonicalize(too_long).unwrap_err().kind() {
StdErrorKind::Other => {}
err => {
return Err(StdError::generic_err(format!(
return Err(StdError::msg(format_args!(
"Unexpected error in do_user_errors_in_api_calls: {err:?}"
))
.into())
Expand All @@ -237,10 +237,10 @@ fn do_user_errors_in_api_calls(api: &dyn Api) -> Result<Response, HackError> {

// Humanize
let empty: CanonicalAddr = vec![].into();
match api.addr_humanize(&empty).unwrap_err() {
StdError::GenericErr { .. } => {}
match api.addr_humanize(&empty).unwrap_err().kind() {
StdErrorKind::Other => {}
err => {
return Err(StdError::generic_err(format!(
return Err(StdError::msg(format_args!(
"Unexpected error in do_user_errors_in_api_calls: {err:?}"
))
.into())
Expand All @@ -265,7 +265,7 @@ fn query_verifier(deps: Deps) -> StdResult<VerifierResponse> {
let data = deps
.storage
.get(CONFIG_KEY)
.ok_or_else(|| StdError::not_found("State"))?;
.ok_or_else(|| StdError::msg("State not found"))?;
let state: State = from_json(data)?;
Ok(VerifierResponse {
verifier: state.verifier.into(),
Expand Down Expand Up @@ -582,7 +582,7 @@ mod tests {
denom: "earth".to_string(),
},
);
assert_eq!(execute_res.unwrap_err(), HackError::Unauthorized {});
assert_eq!(execute_res.unwrap_err().to_string(), "Unauthorized");

// state should not change
let data = deps.storage.get(CONFIG_KEY).expect("no data stored");
Expand Down
Loading
Loading