Skip to content

Commit f3ad156

Browse files
authored
Merge pull request #2500 from CosmWasm/aw/new-error
New error type
2 parents 531ba59 + 3bba20c commit f3ad156

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+656
-1280
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ and this project adheres to
101101
- cosmwasm-std: Split up `Validator` type into `Validator` and
102102
`ValidatorMetadata` to allow adding more fields to `ValidatorResponse` in the
103103
future. ([#2501])
104+
- cosmwasm-std: Redesigned `StdError` to be more flexible and less immutable
105+
([#2500])
104106

105107
## Fixed
106108

@@ -149,6 +151,7 @@ and this project adheres to
149151
[#2480]: https://github.com/CosmWasm/cosmwasm/pull/2480
150152
[#2484]: https://github.com/CosmWasm/cosmwasm/pull/2484
151153
[#2495]: https://github.com/CosmWasm/cosmwasm/pull/2495
154+
[#2500]: https://github.com/CosmWasm/cosmwasm/pull/2500
152155
[#2501]: https://github.com/CosmWasm/cosmwasm/pull/2501
153156

154157
## [2.2.0] - 2024-12-17

contracts/burner/src/contract.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub fn instantiate(
1313
_info: MessageInfo,
1414
_msg: InstantiateMsg,
1515
) -> StdResult<Response> {
16-
Err(StdError::generic_err(
16+
Err(StdError::msg(
1717
"You can only use this contract for migrations",
1818
))
1919
}
@@ -23,7 +23,7 @@ pub fn migrate(deps: DepsMut, env: Env, msg: MigrateMsg) -> StdResult<Response>
2323
let denom_len = msg.denoms.len();
2424
let denoms = BTreeSet::<String>::from_iter(msg.denoms); // Ensure uniqueness
2525
if denoms.len() != denom_len {
26-
return Err(StdError::generic_err("Denoms not unique"));
26+
return Err(StdError::msg("Denoms not unique"));
2727
}
2828

2929
// get balance and send to recipient
@@ -98,7 +98,7 @@ mod tests {
9898
use cosmwasm_std::testing::{
9999
message_info, mock_dependencies, mock_dependencies_with_balance, mock_env,
100100
};
101-
use cosmwasm_std::{coin, coins, Attribute, StdError, Storage, SubMsg};
101+
use cosmwasm_std::{coin, coins, Attribute, Storage, SubMsg};
102102

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

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

150145
// One denom
151146
let msg = MigrateMsg {

contracts/burner/tests/integration.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ fn instantiate_fails() {
3535
let msg = res.unwrap_err();
3636
assert_eq!(
3737
msg,
38-
"Generic error: You can only use this contract for migrations"
38+
"kind: Other, error: You can only use this contract for migrations"
3939
);
4040
}
4141

contracts/crypto-verify/src/contract.rs

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ pub fn query_verify_ethereum_text(
210210
// Decompose signature
211211
let (v, rs) = match signature.split_last() {
212212
Some(pair) => pair,
213-
None => return Err(StdError::generic_err("Signature must not be empty")),
213+
None => return Err(StdError::msg("Signature must not be empty")),
214214
};
215215
let recovery = get_recovery_param(*v)?;
216216

@@ -326,7 +326,7 @@ mod tests {
326326
use cosmwasm_std::testing::{
327327
message_info, mock_dependencies, mock_env, MockApi, MockQuerier, MockStorage,
328328
};
329-
use cosmwasm_std::{from_json, OwnedDeps, RecoverPubkeyError, VerificationError};
329+
use cosmwasm_std::{from_json, OwnedDeps, StdErrorKind};
330330
use hex_literal::hex;
331331

332332
const CREATOR: &str = "creator";
@@ -426,11 +426,8 @@ mod tests {
426426
let res = query(deps.as_ref(), mock_env(), verify_msg);
427427
assert!(res.is_err());
428428
assert!(matches!(
429-
res.unwrap_err(),
430-
StdError::VerificationErr {
431-
source: VerificationError::InvalidPubkeyFormat,
432-
..
433-
}
429+
res.unwrap_err().kind(),
430+
StdErrorKind::Cryptography,
434431
))
435432
}
436433

@@ -500,11 +497,8 @@ mod tests {
500497
signer_address: signer_address.into(),
501498
};
502499
let result = query(deps.as_ref(), mock_env(), verify_msg);
503-
match result.unwrap_err() {
504-
StdError::RecoverPubkeyErr {
505-
source: RecoverPubkeyError::UnknownErr { .. },
506-
..
507-
} => {}
500+
match result.unwrap_err().kind() {
501+
StdErrorKind::Cryptography => {}
508502
err => panic!("Unexpected error: {err:?}"),
509503
}
510504
}
@@ -715,11 +709,8 @@ mod tests {
715709
let res = query(deps.as_ref(), mock_env(), verify_msg);
716710
assert!(res.is_err());
717711
assert!(matches!(
718-
res.unwrap_err(),
719-
StdError::VerificationErr {
720-
source: VerificationError::InvalidPubkeyFormat,
721-
..
722-
}
712+
res.unwrap_err().kind(),
713+
StdErrorKind::Cryptography
723714
))
724715
}
725716

@@ -781,11 +772,8 @@ mod tests {
781772
let res = query(deps.as_ref(), mock_env(), verify_msg);
782773
assert!(res.is_err());
783774
assert!(matches!(
784-
res.unwrap_err(),
785-
StdError::VerificationErr {
786-
source: VerificationError::InvalidPubkeyFormat,
787-
..
788-
}
775+
res.unwrap_err().kind(),
776+
StdErrorKind::Cryptography,
789777
))
790778
}
791779

contracts/crypto-verify/src/ethereum.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ pub fn get_recovery_param(v: u8) -> StdResult<u8> {
7272
match v {
7373
27 => Ok(0),
7474
28 => Ok(1),
75-
_ => Err(StdError::generic_err("Values of v other than 27 and 28 not supported. Replay protection (EIP-155) cannot be used here."))
75+
_ => Err(StdError::msg("Values of v other than 27 and 28 not supported. Replay protection (EIP-155) cannot be used here."))
7676
}
7777
}
7878

@@ -87,7 +87,7 @@ pub fn get_recovery_param_with_chain_id(v: u64, chain_id: u64) -> StdResult<u8>
8787
let recovery = v - chain_id * 2 - 35;
8888
match recovery {
8989
0 | 1 => Ok(recovery as u8),
90-
_ => Err(StdError::generic_err(format!(
90+
_ => Err(StdError::msg(format_args!(
9191
"Calculated recovery parameter must be 0 or 1 but is {recovery}."
9292
))),
9393
}
@@ -97,13 +97,13 @@ pub fn get_recovery_param_with_chain_id(v: u64, chain_id: u64) -> StdResult<u8>
9797
pub fn ethereum_address_raw(pubkey: &[u8]) -> StdResult<[u8; 20]> {
9898
let (tag, data) = match pubkey.split_first() {
9999
Some(pair) => pair,
100-
None => return Err(StdError::generic_err("Public key must not be empty")),
100+
None => return Err(StdError::msg("Public key must not be empty")),
101101
};
102102
if *tag != 0x04 {
103-
return Err(StdError::generic_err("Public key must start with 0x04"));
103+
return Err(StdError::msg("Public key must start with 0x04"));
104104
}
105105
if data.len() != 64 {
106-
return Err(StdError::generic_err("Public key must be 65 bytes long"));
106+
return Err(StdError::msg("Public key must be 65 bytes long"));
107107
}
108108

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

113113
pub fn decode_address(input: &str) -> StdResult<[u8; 20]> {
114114
if input.len() != 42 {
115-
return Err(StdError::generic_err(
116-
"Ethereum address must be 42 characters long",
117-
));
115+
return Err(StdError::msg("Ethereum address must be 42 characters long"));
118116
}
119117
if !input.starts_with("0x") {
120-
return Err(StdError::generic_err("Ethereum address must start with 0x"));
118+
return Err(StdError::msg("Ethereum address must start with 0x"));
121119
}
122-
let data = hex::decode(&input[2..]).map_err(|_| StdError::generic_err("hex decoding error"))?;
120+
let data = hex::decode(&input[2..])?;
123121
Ok(data.try_into().unwrap())
124122
}
125123

contracts/crypto-verify/tests/integration.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ fn cosmos_signature_verify_errors() {
221221
let res = query(&mut deps, mock_env(), verify_msg);
222222
assert_eq!(
223223
res.unwrap_err(),
224-
"Verification error: Invalid public key format"
224+
"kind: Cryptography, error: Invalid public key format"
225225
)
226226
}
227227

@@ -283,7 +283,7 @@ fn secp256r1_signature_verify_errors() {
283283
let res = query(&mut deps, mock_env(), verify_msg);
284284
assert_eq!(
285285
res.unwrap_err(),
286-
"Verification error: Invalid public key format"
286+
"kind: Cryptography, error: Invalid public key format"
287287
)
288288
}
289289

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

360360
#[test]
@@ -466,7 +466,7 @@ fn tendermint_signature_verify_errors() {
466466
let res = query(&mut deps, mock_env(), verify_msg);
467467
assert_eq!(
468468
res.unwrap_err(),
469-
"Verification error: Invalid public key format"
469+
"kind: Cryptography, error: Invalid public key format"
470470
)
471471
}
472472

@@ -625,7 +625,7 @@ fn tendermint_signatures_batch_verify_errors() {
625625
let res = query(&mut deps, mock_env(), verify_msg);
626626
assert_eq!(
627627
res.unwrap_err(),
628-
"Verification error: Invalid public key format"
628+
"kind: Cryptography, error: Invalid public key format"
629629
)
630630
}
631631

contracts/cyberpunk/src/contract.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ fn execute_argon2(mem_cost: u32, time_cost: u32) -> Result<Response, ContractErr
5656
ad: &[],
5757
hash_length: 32,
5858
};
59-
let hash = argon2::hash_encoded(password, salt, &config)
60-
.map_err(|e| StdError::generic_err(format!("hash_encoded errored: {e}")))?;
59+
let hash = argon2::hash_encoded(password, salt, &config).map_err(StdError::from)?;
6160
// let matches = argon2::verify_encoded(&hash, password).unwrap();
6261
// assert!(matches);
6362
Ok(Response::new().set_data(hash.into_bytes()))
@@ -106,13 +105,13 @@ fn execute_allocate_large_memory(pages: u32) -> Result<Response, ContractError>
106105
use core::arch::wasm32;
107106
let old_size = wasm32::memory_grow(0, pages as usize);
108107
if old_size == usize::max_value() {
109-
return Err(StdError::generic_err("memory.grow failed").into());
108+
return Err(StdError::msg("memory.grow failed").into());
110109
}
111110
Ok(Response::new().set_data((old_size as u32).to_be_bytes()))
112111
}
113112

114113
#[cfg(not(target_arch = "wasm32"))]
115-
Err(StdError::generic_err("Unsupported architecture").into())
114+
Err(StdError::msg("Unsupported architecture").into())
116115
}
117116

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

141140
#[cfg(not(target_arch = "wasm32"))]
142-
Err(StdError::generic_err("Unsupported architecture").into())
141+
Err(StdError::msg("Unsupported architecture").into())
143142
}
144143

145144
fn execute_mirror_env(env: Env) -> Result<Response, ContractError> {

contracts/cyberpunk/src/errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use cosmwasm_std::StdError;
22
use thiserror::Error;
33

4-
#[derive(Error, Debug, PartialEq)]
4+
#[derive(Error, Debug)]
55
pub enum ContractError {
66
#[error("{0}")]
77
/// this is needed so we can use `bucket.load(...)?` and have it auto-converted to the custom error

0 commit comments

Comments
 (0)