diff --git a/.beaker/state.json b/.beaker/state.json deleted file mode 100644 index 9e26dfee..00000000 --- a/.beaker/state.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 283425bb..273f52bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ panic = "abort" rpath = false [workspace.package] -version = "0.0.6-rc6" +version = "0.0.6-rc7" authors = [ "byeongsu-hong ", "Eric ", @@ -42,17 +42,17 @@ keywords = ["hyperlane", "cosmos", "cosmwasm"] [workspace.dependencies] # cosmwasm -cosmwasm-std = { version = "1.2.7", features = ["stargate"] } -cosmwasm-storage = "1.2.7" -cosmwasm-schema = "1.2.7" -cosmwasm-crypto = "1.2.7" +cosmwasm-std = { version = "1.5.0", features = ["stargate", "cosmwasm_1_1"] } +cosmwasm-storage = "1.5.0" +cosmwasm-schema = "1.5.0" +cosmwasm-crypto = "1.5.0" # cosmwasm extension -cw-storage-plus = "1.1.0" -cw-utils = "1.0.1" -cw2 = "1.0.0" -cw20 = "1.1.0" -cw20-base = { version = "1.1.0", features = ["library"] } +cw-storage-plus = "1.2.0" +cw-utils = "1.0.3" +cw2 = "1.1.2" +cw20 = "1.1.2" +cw20-base = { version = "1.1.2", features = ["library"] } # utilities thiserror = { version = "1.0.37" } @@ -80,10 +80,10 @@ k256 = { version = "0.13.1", default-features = false, features = ["ecdsa"] } digest = { version = "0.10.7" } # testing -cw-multi-test = "0.17.0" +cw-multi-test = "0.20.0" rstest = "0.18.2" -test-tube = { version = "0.1.7" } -osmosis-test-tube = { version = "19.2.0" } +test-tube = { version = "0.3.0" } +osmosis-test-tube = { version = "21.0.0" } ibcx-test-utils = { version = "0.1.2" } tokio = { version = "1", features = ["full"] } diff --git a/contracts/core/mailbox/Cargo.toml b/contracts/core/mailbox/Cargo.toml index e39ae0e1..4f982939 100644 --- a/contracts/core/mailbox/Cargo.toml +++ b/contracts/core/mailbox/Cargo.toml @@ -34,7 +34,6 @@ bech32.workspace = true thiserror.workspace = true hpl-ownable.workspace = true -hpl-pausable.workspace = true hpl-interface.workspace = true [dev-dependencies] diff --git a/contracts/core/mailbox/src/contract.rs b/contracts/core/mailbox/src/contract.rs index e74ca14f..7b64d3f0 100644 --- a/contracts/core/mailbox/src/contract.rs +++ b/contracts/core/mailbox/src/contract.rs @@ -1,6 +1,6 @@ #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; -use cosmwasm_std::{Deps, DepsMut, Empty, Env, MessageInfo, QueryResponse, Response}; +use cosmwasm_std::{ensure, Deps, DepsMut, Empty, Env, MessageInfo, QueryResponse, Response}; use hpl_interface::{ core::mailbox::{ExecuteMsg, InstantiateMsg, MailboxHookQueryMsg, MailboxQueryMsg, QueryMsg}, @@ -23,6 +23,12 @@ pub fn instantiate( ) -> Result { cw2::set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + // check hrp is lowercase + ensure!( + msg.hrp.chars().all(|v| v.is_lowercase()), + ContractError::invalid_config("hrp must be lowercase") + ); + let config = Config { hrp: msg.hrp, local_domain: msg.domain, @@ -31,12 +37,12 @@ pub fn instantiate( required_hook: None, }; + let owner = deps.api.addr_validate(&msg.owner)?; + CONFIG.save(deps.storage, &config)?; NONCE.save(deps.storage, &0u32)?; - let owner = deps.api.addr_validate(&msg.owner)?; hpl_ownable::initialize(deps.storage, &owner)?; - hpl_pausable::initialize(deps.storage, &false)?; Ok(Response::new().add_event(emit_instantiated(owner))) } @@ -71,7 +77,9 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result Ok(hpl_ownable::handle_query(deps, env, msg)?), QueryMsg::Hook(msg) => match msg { - MailboxHookQueryMsg::QuoteDispatch(msg) => to_binary(quote_dispatch(deps, msg)), + MailboxHookQueryMsg::QuoteDispatch { sender, msg } => { + to_binary(quote_dispatch(deps, sender, msg)) + } }, QueryMsg::Mailbox(msg) => match msg { Hrp {} => to_binary(get_hrp(deps)), diff --git a/contracts/core/mailbox/src/error.rs b/contracts/core/mailbox/src/error.rs index cdf4805a..18d56746 100644 --- a/contracts/core/mailbox/src/error.rs +++ b/contracts/core/mailbox/src/error.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{Coin, StdError}; +use cosmwasm_std::StdError; use thiserror::Error; #[derive(Error, Debug, PartialEq)] @@ -9,12 +9,18 @@ pub enum ContractError { #[error("{0}")] Payment(#[from] cw_utils::PaymentError), + #[error("{0}")] + CoinsError(#[from] cosmwasm_std::CoinsError), + #[error("unauthorized")] Unauthorized {}, #[error("ism verify failed")] VerifyFailed {}, + #[error("invalid config. reason: {reason:?}")] + InvalidConfig { reason: String }, + #[error("invalid address length: {len:?}")] InvalidAddressLength { len: usize }, @@ -24,12 +30,14 @@ pub enum ContractError { #[error("invalid destination domain: {domain:?}")] InvalidDestinationDomain { domain: u32 }, - #[error("insufficient funds. required: {required}, received: {received}")] - InsufficientFunds { required: Coin, received: Coin }, - #[error("message already delivered")] AlreadyDeliveredMessage {}, +} - #[error("message not found")] - MessageNotFound {}, +impl ContractError { + pub fn invalid_config(reason: &str) -> Self { + Self::InvalidConfig { + reason: reason.to_string(), + } + } } diff --git a/contracts/core/mailbox/src/execute.rs b/contracts/core/mailbox/src/execute.rs index 2170c952..3e43a62f 100644 --- a/contracts/core/mailbox/src/execute.rs +++ b/contracts/core/mailbox/src/execute.rs @@ -1,14 +1,13 @@ use cosmwasm_std::{ - coin, ensure, ensure_eq, to_binary, wasm_execute, Coin, Deps, DepsMut, Env, HexBinary, - MessageInfo, Response, + ensure, ensure_eq, to_json_binary, wasm_execute, BankMsg, Coins, DepsMut, Env, HexBinary, + MessageInfo, Response, StdResult, }; -use cw_utils::PaymentError; use hpl_interface::{ core::{ mailbox::{DispatchMsg, DispatchResponse}, HandleMsg, }, - hook::{post_dispatch, quote_dispatch}, + hook::{self, post_dispatch}, ism, types::Message, }; @@ -24,53 +23,6 @@ use crate::{ ContractError, MAILBOX_VERSION, }; -fn get_required_value( - deps: Deps, - info: &MessageInfo, - hook: impl Into, - metadata: HexBinary, - msg_body: HexBinary, -) -> Result<(Option, Option), ContractError> { - let required = quote_dispatch(&deps.querier, hook, metadata, msg_body)?.gas_amount; - let required = match required { - Some(v) => v, - None => return Ok((None, None)), - }; - - if info.funds.is_empty() { - return Ok((None, None)); - } - - if info.funds.len() > 1 { - return Err(PaymentError::MultipleDenoms {}.into()); - } - - let received = &info.funds[0]; - - deps.api.debug(&format!( - "mailbox::dispatch: required: {:?}, received: {:?}", - required, received - )); - - ensure_eq!( - &received.denom, - &required.denom, - PaymentError::ExtraDenom(received.clone().denom) - ); - - if received.amount <= required.amount { - return Ok((Some(received.clone()), None)); - } - - Ok(( - Some(required.clone()), - Some(coin( - (received.amount - required.amount).u128(), - required.denom, - )), - )) -} - pub fn set_default_ism( deps: DepsMut, info: MessageInfo, @@ -156,6 +108,7 @@ pub fn dispatch( ); // calculate gas + let default_hook = config.get_default_hook(); let required_hook = config.get_required_hook(); let msg = @@ -164,17 +117,33 @@ pub fn dispatch( .to_msg(MAILBOX_VERSION, nonce, config.local_domain, &info.sender)?; let msg_id = msg.id(); - let (required_hook_value, hook_value) = get_required_value( - deps.as_ref(), - &info, - required_hook.as_str(), + let base_fee = hook::quote_dispatch( + &deps.querier, + dispatch_msg.get_hook_addr(deps.api, default_hook)?, dispatch_msg.metadata.clone().unwrap_or_default(), - msg.clone().into(), + msg.clone(), + )? + .fees; + + let required_fee = hook::quote_dispatch( + &deps.querier, + &required_hook, + dispatch_msg.metadata.clone().unwrap_or_default(), + msg.clone(), + )? + .fees; + + // assert gas received is satisfies required gas + let mut total_fee = required_fee.clone().into_iter().try_fold( + Coins::try_from(base_fee.clone())?, + |mut acc, fee| { + acc.add(fee)?; + StdResult::Ok(acc) + }, )?; - let (required_hook_value, hook_value) = ( - required_hook_value.map(|v| vec![v]), - hook_value.map(|v| vec![v]), - ); + for fund in info.funds { + total_fee.sub(fund)?; + } // interaction let hook = dispatch_msg.get_hook_addr(deps.api, config.get_default_hook())?; @@ -190,16 +159,22 @@ pub fn dispatch( required_hook, hook_metadata.clone(), msg.clone(), - required_hook_value, + Some(required_fee), )?, - post_dispatch(hook, hook_metadata, msg.clone(), hook_value)?, + post_dispatch(hook, hook_metadata, msg.clone(), Some(base_fee))?, ]; + let refund_msg = BankMsg::Send { + to_address: info.sender.to_string(), + amount: total_fee.to_vec(), + }; + Ok(Response::new() .add_event(emit_dispatch_id(msg_id.clone())) .add_event(emit_dispatch(msg)) - .set_data(to_binary(&DispatchResponse { message_id: msg_id })?) - .add_messages(post_dispatch_msgs)) + .set_data(to_json_binary(&DispatchResponse { message_id: msg_id })?) + .add_messages(post_dispatch_msgs) + .add_message(refund_msg)) } pub fn process( @@ -232,8 +207,6 @@ pub fn process( let id = decoded_msg.id(); let ism = ism::recipient(&deps.querier, &recipient)?.unwrap_or(config.get_default_ism()); - deps.api.debug(&format!("mailbox::process: ism: {}", &ism)); - ensure!( !DELIVERIES.has(deps.storage, id.to_vec()), ContractError::AlreadyDeliveredMessage {} @@ -279,9 +252,9 @@ pub fn process( #[cfg(test)] mod tests { use cosmwasm_std::{ - from_binary, + coin, from_json, testing::{mock_dependencies, mock_env, mock_info, MockApi, MockQuerier, MockStorage}, - Addr, ContractResult, OwnedDeps, QuerierResult, SystemResult, WasmQuery, + to_json_binary, Addr, ContractResult, OwnedDeps, QuerierResult, SystemResult, WasmQuery, }; use hpl_interface::{ @@ -307,7 +280,7 @@ mod tests { fn mock_query_handler(req: &WasmQuery) -> QuerierResult { let (req, _addr) = match req { - WasmQuery::Smart { msg, contract_addr } => (from_binary(msg).unwrap(), contract_addr), + WasmQuery::Smart { msg, contract_addr } => (from_json(msg).unwrap(), contract_addr), _ => unreachable!("wrong query type"), }; @@ -316,16 +289,19 @@ mod tests { _ => unreachable!("wrong query type"), }; - let mut gas_amount = None; + let mut fees = Coins::default(); if !req.metadata.is_empty() { - let parsed_gas = u32::from_be_bytes(req.metadata.as_slice().try_into().unwrap()); + let parsed_fee = u32::from_be_bytes(req.metadata.as_slice().try_into().unwrap()); - gas_amount = Some(coin(parsed_gas as u128, "utest")); + fees = Coins::from(coin(parsed_fee as u128, "utest")); } - let res = QuoteDispatchResponse { gas_amount }; - let res = cosmwasm_std::to_binary(&res).unwrap(); + let res = QuoteDispatchResponse { + fees: fees.into_vec(), + }; + let res = to_json_binary(&res).unwrap(); + SystemResult::Ok(ContractResult::Ok(res)) } @@ -495,14 +471,13 @@ mod tests { fn test_process_query_handler(query: &WasmQuery) -> QuerierResult { match query { WasmQuery::Smart { contract_addr, msg } => { - if let Ok(req) = cosmwasm_std::from_binary::(msg) - { + if let Ok(req) = cosmwasm_std::from_json::(msg) { match req { hpl_interface::ism::ExpectedIsmSpecifierQueryMsg::IsmSpecifier( ism::IsmSpecifierQueryMsg::InterchainSecurityModule(), ) => { return SystemResult::Ok( - cosmwasm_std::to_binary(&ism::InterchainSecurityModuleResponse { + to_json_binary(&ism::InterchainSecurityModuleResponse { ism: Some(addr("default_ism")), }) .into(), @@ -511,13 +486,13 @@ mod tests { } } - if let Ok(req) = cosmwasm_std::from_binary::(msg) { + if let Ok(req) = cosmwasm_std::from_json::(msg) { assert_eq!(contract_addr, &addr("default_ism")); match req { ism::ExpectedIsmQueryMsg::Ism(IsmQueryMsg::Verify { metadata, .. }) => { return SystemResult::Ok( - cosmwasm_std::to_binary(&ism::VerifyResponse { + to_json_binary(&ism::VerifyResponse { verified: metadata[0] == 1, }) .into(), diff --git a/contracts/core/mailbox/src/query.rs b/contracts/core/mailbox/src/query.rs index c1c0bfaf..e2e0a151 100644 --- a/contracts/core/mailbox/src/query.rs +++ b/contracts/core/mailbox/src/query.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{Deps, HexBinary}; +use cosmwasm_std::{Coins, Deps, HexBinary, StdResult}; use hpl_interface::{ core::mailbox::{ DefaultHookResponse, DefaultIsmResponse, DispatchMsg, HrpResponse, @@ -11,7 +11,7 @@ use hpl_interface::{ use crate::{ state::{CONFIG, DELIVERIES, LATEST_DISPATCHED_ID, NONCE}, - ContractError, + ContractError, MAILBOX_VERSION, }; pub fn get_hrp(deps: Deps) -> Result { @@ -87,36 +87,47 @@ pub fn get_latest_dispatch_id(deps: Deps) -> Result Result { + let sender = deps.api.addr_validate(&sender)?; + let config = CONFIG.load(deps.storage)?; + let nonce = NONCE.load(deps.storage)?; + + let msg = dispatch_msg + .clone() + .to_msg(MAILBOX_VERSION, nonce, config.local_domain, sender)?; - let target_hook = msg.get_hook_addr(deps.api, config.get_default_hook())?; + let default_hook = config.get_default_hook(); let required_hook = config.get_required_hook(); - let mut required_gas = hook::quote_dispatch( + let base_fee = hook::quote_dispatch( &deps.querier, - required_hook, - msg.metadata.clone().unwrap(), - msg.msg_body.clone(), + dispatch_msg.get_hook_addr(deps.api, default_hook)?, + dispatch_msg.metadata.clone().unwrap_or_default(), + msg.clone(), )? - .gas_amount - .expect("failed to quote required gas"); + .fees; - let target_gas = hook::quote_dispatch( + let required_fee = hook::quote_dispatch( &deps.querier, - target_hook, - msg.metadata.clone().unwrap(), - msg.msg_body, + required_hook, + dispatch_msg.metadata.unwrap_or_default(), + msg, )? - .gas_amount; + .fees; - if let Some(gas) = target_gas { - required_gas.amount += gas.amount; - } + let total_fee = + required_fee + .into_iter() + .try_fold(Coins::try_from(base_fee)?, |mut acc, fee| { + acc.add(fee)?; + StdResult::Ok(acc) + })?; Ok(QuoteDispatchResponse { - gas_amount: Some(required_gas), + fees: total_fee.to_vec(), }) } @@ -124,7 +135,7 @@ pub fn quote_dispatch( mod test { use cosmwasm_std::{ - from_binary, + from_json, testing::{mock_dependencies, mock_env}, Addr, }; @@ -141,7 +152,7 @@ mod test { use super::*; fn query(deps: Deps, req: MailboxQueryMsg) -> T { - from_binary(&contract::query(deps, mock_env(), req.wrap()).unwrap()).unwrap() + from_json(contract::query(deps, mock_env(), req.wrap()).unwrap()).unwrap() } fn query_hrp(deps: Deps) -> HrpResponse { diff --git a/contracts/core/va/src/contract.rs b/contracts/core/va/src/contract.rs index 76b567af..69bd6eb5 100644 --- a/contracts/core/va/src/contract.rs +++ b/contracts/core/va/src/contract.rs @@ -10,7 +10,7 @@ use hpl_interface::{ mailbox::{self, MailboxQueryMsg}, va::{ ExecuteMsg, GetAnnounceStorageLocationsResponse, GetAnnouncedValidatorsResponse, - InstantiateMsg, QueryMsg, + InstantiateMsg, LocalDomainResponse, MailboxResponse, QueryMsg, }, }, to_binary, @@ -77,6 +77,8 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result to_binary(get_validators(deps)), + QueryMsg::Mailbox {} => to_binary(get_mailbox(deps)), + QueryMsg::LocalDomain {} => to_binary(get_local_domain(deps)), } } @@ -106,6 +108,18 @@ fn get_validators(deps: Deps) -> Result Result { + Ok(MailboxResponse { + mailbox: HexBinary::from(MAILBOX.load(deps.storage)?).to_hex(), + }) +} + +fn get_local_domain(deps: Deps) -> Result { + Ok(LocalDomainResponse { + local_domain: LOCAL_DOMAIN.load(deps.storage)?, + }) +} + fn replay_hash(validator: &HexBinary, storage_location: &str) -> StdResult { Ok(keccak256_hash( [validator.to_vec(), storage_location.as_bytes().to_vec()] @@ -150,7 +164,7 @@ fn announce( let replay_id = replay_hash(&validator, &storage_location)?; ensure!( !REPLAY_PROTECITONS.has(deps.storage, replay_id.to_vec()), - ContractError::Unauthorized {} + ContractError::unauthorized("replay protection triggered") ); REPLAY_PROTECITONS.save(deps.storage, replay_id.to_vec(), &Empty {})?; @@ -207,7 +221,7 @@ pub fn migrate(_deps: DepsMut, _env: Env, _msg: Empty) -> Result QuerierResult { SystemResult::Ok(ContractResult::Ok( - cosmwasm_std::to_binary(&mailbox::LocalDomainResponse { + to_json_binary(&mailbox::LocalDomainResponse { local_domain: 26657, }) .unwrap(), diff --git a/contracts/core/va/src/error.rs b/contracts/core/va/src/error.rs index 1cd84e7f..2650f6b9 100644 --- a/contracts/core/va/src/error.rs +++ b/contracts/core/va/src/error.rs @@ -9,8 +9,8 @@ pub enum ContractError { #[error("{0}")] RecoverPubkeyError(#[from] RecoverPubkeyError), - #[error("unauthorized")] - Unauthorized {}, + #[error("unauthorized. reason: {0}")] + Unauthorized(String), #[error("invalid address. reason: {0}")] InvalidAddress(String), @@ -20,6 +20,10 @@ pub enum ContractError { } impl ContractError { + pub fn unauthorized(reason: &str) -> Self { + ContractError::Unauthorized(reason.into()) + } + pub fn invalid_addr(reason: &str) -> Self { ContractError::InvalidAddress(reason.into()) } diff --git a/contracts/hooks/aggregate/src/error.rs b/contracts/hooks/aggregate/src/error.rs index babe75a3..ded0227c 100644 --- a/contracts/hooks/aggregate/src/error.rs +++ b/contracts/hooks/aggregate/src/error.rs @@ -8,9 +8,9 @@ pub enum ContractError { #[error("{0}")] PaymentError(#[from] cw_utils::PaymentError), + #[error("{0}")] + CoinsError(#[from] cosmwasm_std::CoinsError), + #[error("unauthorized")] Unauthorized {}, - - #[error("hook paused")] - Paused {}, } diff --git a/contracts/hooks/aggregate/src/lib.rs b/contracts/hooks/aggregate/src/lib.rs index 4ffcb579..dc91e7ca 100644 --- a/contracts/hooks/aggregate/src/lib.rs +++ b/contracts/hooks/aggregate/src/lib.rs @@ -3,7 +3,7 @@ mod error; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - ensure_eq, Addr, Coin, CosmosMsg, Deps, DepsMut, Env, Event, HexBinary, MessageInfo, + ensure_eq, Addr, Coins, CosmosMsg, Deps, DepsMut, Env, Event, HexBinary, MessageInfo, QueryResponse, Response, StdResult, }; use cw_storage_plus::Item; @@ -80,13 +80,9 @@ pub fn execute( metadata.clone(), message.clone(), )?; - let msg = post_dispatch( - v, - metadata.clone(), - message.clone(), - quote.gas_amount.map(|v| vec![v]), - )? - .into(); + let msg = + post_dispatch(v, metadata.clone(), message.clone(), Some(quote.fees))? + .into(); Ok(msg) }) @@ -151,28 +147,26 @@ fn quote_dispatch( ) -> Result { let hooks = HOOKS.load(deps.storage)?; - let mut total: Option = None; - - for hook in hooks { - let res = hpl_interface::hook::quote_dispatch( - &deps.querier, - hook, - metadata.clone(), - message.clone(), - )?; - - if let Some(gas_amount) = res.gas_amount { - total = match total { - Some(mut v) => { - v.amount += gas_amount.amount; - Some(v) - } - None => Some(gas_amount), - }; - } - } + let total = hooks + .into_iter() + .try_fold(Coins::default(), |mut acc, hook| { + let res = hpl_interface::hook::quote_dispatch( + &deps.querier, + hook, + metadata.clone(), + message.clone(), + )?; + + for fee in res.fees { + acc.add(fee)?; + } + + Ok::<_, ContractError>(acc) + })?; - Ok(QuoteDispatchResponse { gas_amount: total }) + Ok(QuoteDispatchResponse { + fees: total.to_vec(), + }) } fn get_hooks(deps: Deps) -> Result { diff --git a/contracts/hooks/merkle/src/lib.rs b/contracts/hooks/merkle/src/lib.rs index 765ed396..e837cb83 100644 --- a/contracts/hooks/merkle/src/lib.rs +++ b/contracts/hooks/merkle/src/lib.rs @@ -23,13 +23,19 @@ pub enum ContractError { #[error("{0}")] PaymentError(#[from] cw_utils::PaymentError), - #[error("unauthorized")] - Unauthorized {}, + #[error("unauthorized. reason: {0}")] + Unauthorized(String), #[error("hook paused")] Paused {}, } +impl ContractError { + pub fn unauthorized(reason: &str) -> Self { + ContractError::Unauthorized(reason.into()) + } +} + // version info for migration info pub const CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -94,7 +100,7 @@ pub fn execute( ensure_eq!( latest_dispatch_id, decoded_msg.id(), - ContractError::Unauthorized {} + ContractError::unauthorized("message is not dispatching") ); let mut tree = MESSAGE_TREE.load(deps.storage)?; @@ -143,7 +149,7 @@ fn get_mailbox(deps: Deps) -> Result { } fn quote_dispatch() -> Result { - Ok(QuoteDispatchResponse { gas_amount: None }) + Ok(QuoteDispatchResponse { fees: vec![] }) } fn get_tree_count(deps: Deps) -> Result { @@ -200,7 +206,7 @@ mod test { use super::*; use cosmwasm_std::{ - from_binary, + from_json, testing::{mock_dependencies, mock_env, mock_info, MockApi, MockQuerier, MockStorage}, HexBinary, OwnedDeps, WasmQuery, }; @@ -267,12 +273,10 @@ mod test { #[case] message: Option, ) { deps.querier.update_wasm(|query| { - use cosmwasm_std::{to_binary, ContractResult, SystemResult}; + use cosmwasm_std::{to_json_binary, ContractResult, SystemResult}; let (_contract_addr, msg) = match query { - WasmQuery::Smart { contract_addr, msg } => { - (contract_addr, from_binary(msg).unwrap()) - } + WasmQuery::Smart { contract_addr, msg } => (contract_addr, from_json(msg).unwrap()), _ => unreachable!("noo"), }; @@ -283,7 +287,7 @@ mod test { "a6d8af738f99da8a0a8a3611e6c777bc9ebf42b1f685a5ff6b1ff1f2b7b70f45", ), }; - SystemResult::Ok(ContractResult::Ok(to_binary(&res).unwrap())) + SystemResult::Ok(ContractResult::Ok(to_json_binary(&res).unwrap())) } _ => unreachable!("unwrap noo"), } @@ -328,7 +332,7 @@ mod test { deps.as_ref(), QueryMsg::Hook(HookQueryMsg::QuoteDispatch(QuoteDispatchMsg::default())), ); - assert_eq!(res.gas_amount, None); + assert_eq!(res.fees, vec![]); let res: merkle::CountResponse = test_query( deps.as_ref(), diff --git a/contracts/hooks/pausable/src/lib.rs b/contracts/hooks/pausable/src/lib.rs index fe80c63c..142a5d09 100644 --- a/contracts/hooks/pausable/src/lib.rs +++ b/contracts/hooks/pausable/src/lib.rs @@ -96,16 +96,16 @@ fn get_mailbox(_deps: Deps) -> Result { } fn quote_dispatch() -> Result { - Ok(QuoteDispatchResponse { gas_amount: None }) + Ok(QuoteDispatchResponse { fees: vec![] }) } #[cfg(test)] mod test { use cosmwasm_schema::serde::{de::DeserializeOwned, Serialize}; use cosmwasm_std::{ - from_binary, + from_json, testing::{mock_dependencies, mock_env, mock_info, MockApi, MockQuerier, MockStorage}, - Addr, HexBinary, OwnedDeps, + to_json_binary, Addr, HexBinary, OwnedDeps, }; use hpl_interface::hook::{PostDispatchMsg, QuoteDispatchMsg}; use hpl_ownable::get_owner; @@ -118,9 +118,9 @@ mod test { type TestDeps = OwnedDeps; fn query(deps: Deps, msg: S) -> T { - let req: QueryMsg = from_binary(&cosmwasm_std::to_binary(&msg).unwrap()).unwrap(); + let req: QueryMsg = from_json(to_json_binary(&msg).unwrap()).unwrap(); let res = crate::query(deps, mock_env(), req).unwrap(); - from_binary(&res).unwrap() + from_json(res).unwrap() } #[fixture] @@ -182,6 +182,6 @@ mod test { deps.as_ref(), QueryMsg::Hook(HookQueryMsg::QuoteDispatch(QuoteDispatchMsg::default())), ); - assert_eq!(res.gas_amount, None); + assert_eq!(res.fees, vec![]); } } diff --git a/contracts/hooks/routing-custom/src/lib.rs b/contracts/hooks/routing-custom/src/lib.rs index 90d93fe5..70a5b03e 100644 --- a/contracts/hooks/routing-custom/src/lib.rs +++ b/contracts/hooks/routing-custom/src/lib.rs @@ -34,6 +34,9 @@ pub enum ContractError { #[error("route not found for {0}")] RouteNotFound(u32), + + #[error("invalid arguments. reason: {reason:?}")] + InvalidArguments { reason: String }, } // version info for migration info @@ -178,6 +181,15 @@ fn register( ); for msg in msgs.clone() { + let recipient = HexBinary::from_hex(&msg.recipient)?; + ensure_eq!( + recipient.len(), + 32, + ContractError::InvalidArguments { + reason: "recipient must be 32 bytes long".into() + } + ); + CUSTOM_HOOKS.save( deps.storage, ( @@ -199,7 +211,11 @@ fn register( .map(|v| format!("{}:{}", v.dest_domain, v.recipient)) .collect::>(), ) - .unwrap(), + .map_err(|e| { + ContractError::Std(StdError::generic_err(format!( + "failed to marshal keys. reason: {e}", + ))) + })?, ), )) } @@ -236,7 +252,11 @@ fn clear( .map(|v| format!("{}:{}", v.dest_domain, v.recipient)) .collect::>(), ) - .unwrap(), + .map_err(|e| { + ContractError::Std(StdError::generic_err(format!( + "failed to marshal keys. reason: {e}", + ))) + })?, ), )) } @@ -295,9 +315,9 @@ fn quote_dispatch( #[cfg(test)] mod test { use cosmwasm_std::{ - coin, from_binary, + coin, from_json, testing::{mock_dependencies, mock_env, mock_info, MockApi, MockQuerier, MockStorage}, - ContractResult, OwnedDeps, QuerierResult, SystemResult, WasmQuery, + to_json_binary, Coins, ContractResult, OwnedDeps, QuerierResult, SystemResult, WasmQuery, }; use hpl_interface::{build_test_querier, hook::ExpectedHookQueryMsg, router::DomainRouteSet}; use hpl_ownable::get_owner; @@ -329,7 +349,7 @@ mod test { fn mock_query_handler(req: &WasmQuery) -> QuerierResult { let (req, _addr) = match req { - WasmQuery::Smart { msg, contract_addr } => (from_binary(msg).unwrap(), contract_addr), + WasmQuery::Smart { msg, contract_addr } => (from_json(msg).unwrap(), contract_addr), _ => unreachable!("wrong query type"), }; @@ -338,16 +358,19 @@ mod test { _ => unreachable!("wrong query type"), }; - let mut gas_amount = None; + let mut fees = Coins::default(); if !req.metadata.is_empty() { - let parsed_gas = u32::from_be_bytes(req.metadata.as_slice().try_into().unwrap()); + let parsed_fee = u32::from_be_bytes(req.metadata.as_slice().try_into().unwrap()); - gas_amount = Some(coin(parsed_gas as u128, "utest")); + fees = Coins::from(coin(parsed_fee as u128, "utest")); } - let res = QuoteDispatchResponse { gas_amount }; - let res = cosmwasm_std::to_binary(&res).unwrap(); + let res = QuoteDispatchResponse { + fees: fees.into_vec(), + }; + let res = to_json_binary(&res).unwrap(); + SystemResult::Ok(ContractResult::Ok(res)) } @@ -594,7 +617,7 @@ mod test { fn test_quote_dispatch( deps_custom_routes: (TestDeps, Routes, CustomRoutes), #[case] test_domain: u32, - #[case] expected_gas: Option, + #[case] expected_fee: Option, ) { let (mut deps, _, _) = deps_custom_routes; @@ -610,6 +633,9 @@ mod test { message: rand_msg.into(), })), ); - assert_eq!(res.gas_amount.map(|v| v.amount.u128() as u32), expected_gas); + assert_eq!( + res.fees.first().map(|v| v.amount.u128() as u32), + expected_fee + ); } } diff --git a/contracts/hooks/routing-fallback/src/lib.rs b/contracts/hooks/routing-fallback/src/lib.rs index ae0bbc16..0fd4ad46 100644 --- a/contracts/hooks/routing-fallback/src/lib.rs +++ b/contracts/hooks/routing-fallback/src/lib.rs @@ -157,9 +157,9 @@ pub fn quote_dispatch( #[cfg(test)] mod test { use cosmwasm_std::{ - coin, from_binary, + coin, from_json, testing::{mock_dependencies, mock_env, mock_info, MockApi, MockQuerier, MockStorage}, - ContractResult, OwnedDeps, QuerierResult, SystemResult, WasmQuery, + to_json_binary, Coins, ContractResult, OwnedDeps, QuerierResult, SystemResult, WasmQuery, }; use hpl_interface::{build_test_querier, hook::ExpectedHookQueryMsg, router::DomainRouteSet}; use hpl_ownable::get_owner; @@ -184,7 +184,7 @@ mod test { fn mock_query_handler(req: &WasmQuery) -> QuerierResult { let (req, addr) = match req { - WasmQuery::Smart { msg, contract_addr } => (from_binary(msg).unwrap(), contract_addr), + WasmQuery::Smart { msg, contract_addr } => (from_json(msg).unwrap(), contract_addr), _ => unreachable!("wrong query type"), }; @@ -193,20 +193,23 @@ mod test { _ => unreachable!("wrong query type"), }; - let mut gas_amount = None; + let mut fees = Coins::default(); if !req.metadata.is_empty() { - let parsed_gas = u32::from_be_bytes(req.metadata.as_slice().try_into().unwrap()); + let parsed_fee = u32::from_be_bytes(req.metadata.as_slice().try_into().unwrap()); - gas_amount = Some(coin(parsed_gas as u128, "utest")); + fees = Coins::from(coin(parsed_fee as u128, "utest")); } if addr == FALLBACK_HOOK { - gas_amount = None; + fees = Coins::default(); } - let res = QuoteDispatchResponse { gas_amount }; - let res = cosmwasm_std::to_binary(&res).unwrap(); + let res = QuoteDispatchResponse { + fees: fees.into_vec(), + }; + let res = to_json_binary(&res).unwrap(); + SystemResult::Ok(ContractResult::Ok(res)) } @@ -315,7 +318,7 @@ mod test { fn test_quote_dispatch( deps_routes: (TestDeps, Routes), #[case] test_domain: u32, - #[case] expected_gas: Option, + #[case] expected_fee: Option, ) { let (mut deps, _) = deps_routes; @@ -331,6 +334,9 @@ mod test { message: rand_msg.into(), })), ); - assert_eq!(res.gas_amount.map(|v| v.amount.u128() as u32), expected_gas); + assert_eq!( + res.fees.first().map(|v| v.amount.u128() as u32), + expected_fee + ); } } diff --git a/contracts/hooks/routing/src/lib.rs b/contracts/hooks/routing/src/lib.rs index 7e97cc82..dd4651f3 100644 --- a/contracts/hooks/routing/src/lib.rs +++ b/contracts/hooks/routing/src/lib.rs @@ -138,9 +138,9 @@ fn post_dispatch( #[cfg(test)] mod test { use cosmwasm_std::{ - coin, from_binary, + coin, from_json, testing::{mock_dependencies, mock_env, mock_info, MockApi, MockQuerier, MockStorage}, - ContractResult, OwnedDeps, QuerierResult, SystemResult, WasmQuery, + to_json_binary, Coins, ContractResult, OwnedDeps, QuerierResult, SystemResult, WasmQuery, }; use hpl_interface::{build_test_querier, hook::ExpectedHookQueryMsg, router::DomainRouteSet}; use hpl_ownable::get_owner; @@ -163,7 +163,7 @@ mod test { fn mock_query_handler(req: &WasmQuery) -> QuerierResult { let (req, _addr) = match req { - WasmQuery::Smart { msg, contract_addr } => (from_binary(msg).unwrap(), contract_addr), + WasmQuery::Smart { msg, contract_addr } => (from_json(msg).unwrap(), contract_addr), _ => unreachable!("wrong query type"), }; @@ -172,16 +172,19 @@ mod test { _ => unreachable!("wrong query type"), }; - let mut gas_amount = None; + let mut fees = Coins::default(); if !req.metadata.is_empty() { - let parsed_gas = u32::from_be_bytes(req.metadata.as_slice().try_into().unwrap()); + let parsed_fee = u32::from_be_bytes(req.metadata.as_slice().try_into().unwrap()); - gas_amount = Some(coin(parsed_gas as u128, "utest")); + fees = Coins::from(coin(parsed_fee as u128, "utest")); } - let res = QuoteDispatchResponse { gas_amount }; - let res = cosmwasm_std::to_binary(&res).unwrap(); + let res = QuoteDispatchResponse { + fees: fees.into_vec(), + }; + let res = to_json_binary(&res).unwrap(); + SystemResult::Ok(ContractResult::Ok(res)) } @@ -287,7 +290,7 @@ mod test { fn test_quote_dispatch( deps_routes: (TestDeps, Routes), #[case] test_domain: u32, - #[case] expected_gas: Option, + #[case] expected_fee: Option, ) { let (mut deps, _) = deps_routes; @@ -303,6 +306,9 @@ mod test { message: rand_msg.into(), })), ); - assert_eq!(res.gas_amount.map(|v| v.amount.u128() as u32), expected_gas); + assert_eq!( + res.fees.first().map(|v| v.amount.u128() as u32), + expected_fee + ); } } diff --git a/contracts/igps/core/Cargo.toml b/contracts/igps/core/Cargo.toml index 738bd5e3..0e4548bc 100644 --- a/contracts/igps/core/Cargo.toml +++ b/contracts/igps/core/Cargo.toml @@ -27,6 +27,8 @@ cw-storage-plus.workspace = true cw2.workspace = true cw-utils.workspace = true +serde.workspace = true +prost.workspace = true schemars.workspace = true thiserror.workspace = true diff --git a/contracts/igps/core/src/contract.rs b/contracts/igps/core/src/contract.rs index 16cfb454..225b794f 100644 --- a/contracts/igps/core/src/contract.rs +++ b/contracts/igps/core/src/contract.rs @@ -1,6 +1,8 @@ #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; -use cosmwasm_std::{Deps, DepsMut, Empty, Env, Event, MessageInfo, QueryResponse, Response}; +use cosmwasm_std::{ + ensure, Deps, DepsMut, Empty, Env, Event, MessageInfo, QueryResponse, Response, +}; use hpl_interface::hook::HookQueryMsg; use hpl_interface::igp::core::{ExecuteMsg, IgpQueryMsg, InstantiateMsg, QueryMsg}; @@ -24,6 +26,17 @@ pub fn instantiate( ) -> Result { cw2::set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + // check hrp is lowercase + ensure!( + msg.hrp.chars().all(|v| v.is_lowercase()), + ContractError::invalid_config("hrp must be lowercase") + ); + + // check gas token exists + deps.querier.query_supply(&msg.gas_token).map_err(|e| { + ContractError::invalid_config(&format!("gas_token {} does not exist: {e}", msg.gas_token,)) + })?; + let owner = deps.api.addr_validate(&msg.owner)?; let beneficiary = deps.api.addr_validate(&msg.beneficiary)?; diff --git a/contracts/igps/core/src/error.rs b/contracts/igps/core/src/error.rs index f1c49455..267149d4 100644 --- a/contracts/igps/core/src/error.rs +++ b/contracts/igps/core/src/error.rs @@ -20,6 +20,17 @@ pub enum ContractError { gas_needed: Uint256, }, + #[error("invalid config. reason: {reason:?}")] + InvalidConfig { reason: String }, + #[error("gas oracle not found for {0}")] GasOracleNotFound(u32), } + +impl ContractError { + pub fn invalid_config(reason: &str) -> Self { + Self::InvalidConfig { + reason: reason.to_string(), + } + } +} diff --git a/contracts/igps/core/src/lib.rs b/contracts/igps/core/src/lib.rs index cedd7a79..c45aa050 100644 --- a/contracts/igps/core/src/lib.rs +++ b/contracts/igps/core/src/lib.rs @@ -2,6 +2,7 @@ pub mod contract; mod error; mod event; pub mod execute; +mod proto; pub mod query; #[cfg(test)] @@ -30,8 +31,8 @@ pub const DEFAULT_GAS_USAGE: Item = Item::new(DEFAULT_GAS_USAGE_KEY); pub const GAS_FOR_DOMAIN_PREFIX: &str = "gas_for_domain"; pub const GAS_FOR_DOMAIN: Map = Map::new(GAS_FOR_DOMAIN_PREFIX); -pub const BENEFICAIRY_KEY: &str = "beneficiary"; -pub const BENEFICIARY: Item = Item::new(BENEFICAIRY_KEY); +pub const BENEFICIARY_KEY: &str = "beneficiary"; +pub const BENEFICIARY: Item = Item::new(BENEFICIARY_KEY); pub fn get_default_gas(storage: &dyn Storage, domain: u32) -> StdResult { let custom_gas = GAS_FOR_DOMAIN.may_load(storage, domain)?; diff --git a/contracts/igps/core/src/proto.rs b/contracts/igps/core/src/proto.rs new file mode 100644 index 00000000..13bd68d0 --- /dev/null +++ b/contracts/igps/core/src/proto.rs @@ -0,0 +1,24 @@ +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(::prost::Message, ::serde::Serialize, ::serde::Deserialize)] +pub struct QuerySupplyOfRequest { + /// denom is the coin denom to query balances for. + #[prost(string, tag = "1")] + pub denom: ::prost::alloc::string::String, +} + +/// QuerySupplyOfResponse is the response type for the Query/SupplyOf RPC method. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(::prost::Message, ::serde::Serialize, ::serde::Deserialize)] +pub struct QuerySupplyOfResponse { + /// amount is the supply of the coin. + #[prost(message, optional, tag = "1")] + pub amount: ::core::option::Option, +} + +#[derive(serde::Serialize, serde::Deserialize, ::prost::Message)] +pub struct Coin { + #[prost(string, tag = "1")] + pub denom: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub amount: ::prost::alloc::string::String, +} diff --git a/contracts/igps/core/src/query.rs b/contracts/igps/core/src/query.rs index 6b672013..2ce30824 100644 --- a/contracts/igps/core/src/query.rs +++ b/contracts/igps/core/src/query.rs @@ -1,7 +1,7 @@ use crate::error::ContractError; use crate::{BENEFICIARY, DEFAULT_GAS_USAGE, GAS_FOR_DOMAIN, GAS_TOKEN, TOKEN_EXCHANGE_RATE_SCALE}; -use cosmwasm_std::{coin, Addr, Deps, QuerierWrapper, StdResult, Storage, Uint256}; +use cosmwasm_std::{coins, Addr, Deps, QuerierWrapper, StdResult, Storage, Uint256}; use hpl_interface::hook::{MailboxResponse, QuoteDispatchMsg, QuoteDispatchResponse}; use hpl_interface::igp::core::{ BeneficiaryResponse, DefaultGasResponse, GasForDomainResponse, QuoteGasPaymentResponse, @@ -51,10 +51,10 @@ pub fn list_gas_for_domains( } pub fn get_beneficiary(deps: Deps) -> Result { - let beneficairy = BENEFICIARY.load(deps.storage)?; + let beneficiary = BENEFICIARY.load(deps.storage)?; Ok(BeneficiaryResponse { - beneficiary: beneficairy.into(), + beneficiary: beneficiary.into(), }) } @@ -62,7 +62,7 @@ pub fn quote_gas_price( storage: &dyn Storage, querier: &QuerierWrapper, dest_domain: u32, - gas_amount: Uint256, + fees: Uint256, ) -> Result { let gas_oracle_set = hpl_router::get_route::(storage, dest_domain)?; let gas_oracle = gas_oracle_set @@ -74,7 +74,7 @@ pub fn quote_gas_price( &oracle::QueryMsg::Oracle(IgpGasOracleQueryMsg::GetExchangeRateAndGasPrice { dest_domain }), )?; - let dest_gas_cost = gas_amount * Uint256::from(gas_price_resp.gas_price); + let dest_gas_cost = fees * Uint256::from(gas_price_resp.gas_price); let gas_needed = (dest_gas_cost * Uint256::from(gas_price_resp.exchange_rate)) / Uint256::from(TOKEN_EXCHANGE_RATE_SCALE); @@ -84,9 +84,9 @@ pub fn quote_gas_price( pub fn quote_gas_payment( deps: Deps, dest_domain: u32, - gas_amount: Uint256, + fees: Uint256, ) -> Result { - let gas_needed = quote_gas_price(deps.storage, &deps.querier, dest_domain, gas_amount)?; + let gas_needed = quote_gas_price(deps.storage, &deps.querier, dest_domain, fees)?; Ok(QuoteGasPaymentResponse { gas_needed }) } @@ -108,17 +108,17 @@ pub fn quote_dispatch( } }; - let gas_amount = quote_gas_payment(deps, igp_message.dest_domain, gas_limit)?.gas_needed; - let gas_amount = if !gas_amount.is_zero() { - Some(coin( - gas_amount.to_string().parse::()?, + let fees = quote_gas_payment(deps, igp_message.dest_domain, gas_limit)?.gas_needed; + let fees = if !fees.is_zero() { + coins( + fees.to_string().parse::()?, GAS_TOKEN.load(deps.storage)?, - )) + ) } else { - None + vec![] }; - Ok(QuoteDispatchResponse { gas_amount }) + Ok(QuoteDispatchResponse { fees }) } pub fn get_exchange_rate_and_gas_price( diff --git a/contracts/igps/core/src/tests/contract.rs b/contracts/igps/core/src/tests/contract.rs index daf61c7a..4b81d8db 100644 --- a/contracts/igps/core/src/tests/contract.rs +++ b/contracts/igps/core/src/tests/contract.rs @@ -1,8 +1,8 @@ use cosmwasm_std::{ - coin, from_binary, + coin, from_json, testing::{mock_dependencies, mock_env, mock_info}, - to_binary, Addr, BankMsg, Coin, ContractResult, HexBinary, Order, QuerierResult, StdResult, - SubMsg, SystemResult, Uint128, Uint256, WasmQuery, + to_json_binary, Addr, BankMsg, Coin, ContractResult, HexBinary, Order, QuerierResult, + StdResult, SubMsg, SystemResult, Uint128, Uint256, WasmQuery, }; use hpl_interface::{ igp::{ @@ -28,7 +28,7 @@ const DEC_9: u128 = 10u128.pow(9); fn test_mock_querier(v: &WasmQuery) -> QuerierResult { let (contract_addr, msg) = match v { - WasmQuery::Smart { contract_addr, msg } => (contract_addr, from_binary(msg).unwrap()), + WasmQuery::Smart { contract_addr, msg } => (contract_addr, from_json(msg).unwrap()), _ => unreachable!("only smart query"), }; @@ -42,7 +42,7 @@ fn test_mock_querier(v: &WasmQuery) -> QuerierResult { let gas_price = split.pop().unwrap().parse::().unwrap(); let exchange_rate = split.pop().unwrap().parse::().unwrap(); - let res = to_binary(&oracle::GetExchangeRateAndGasPriceResponse { + let res = to_json_binary(&oracle::GetExchangeRateAndGasPriceResponse { gas_price: Uint128::new(gas_price * DEC_9), // 150 gwei gas price exchange_rate: Uint128::new(exchange_rate * DEC_9), // 0.2 exchange rate (remote token less valuable) }) diff --git a/contracts/igps/core/src/tests/mod.rs b/contracts/igps/core/src/tests/mod.rs index 29c4cd51..6bb55faf 100644 --- a/contracts/igps/core/src/tests/mod.rs +++ b/contracts/igps/core/src/tests/mod.rs @@ -1,5 +1,5 @@ use cosmwasm_std::{ - from_binary, + from_json, testing::{mock_info, MockApi, MockQuerier, MockStorage}, Addr, Coin, Deps, DepsMut, Empty, Env, HexBinary, MessageInfo, OwnedDeps, Response, }; @@ -65,7 +65,7 @@ impl IGP { fn query(&self, msg: QueryMsg) -> Result { query(self.deps.as_ref(), self.env.clone(), msg) - .map(|v| from_binary::(&v))? + .map(|v| from_json::(&v))? .map_err(|e| e.into()) } diff --git a/contracts/igps/oracle/src/contract.rs b/contracts/igps/oracle/src/contract.rs index c9901d46..f9ef1d5c 100644 --- a/contracts/igps/oracle/src/contract.rs +++ b/contracts/igps/oracle/src/contract.rs @@ -1,7 +1,8 @@ #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - ensure_eq, to_binary, Deps, DepsMut, Env, Event, MessageInfo, QueryResponse, Response, + ensure, ensure_eq, to_json_binary, Deps, DepsMut, Env, Event, MessageInfo, QueryResponse, + Response, }; use hpl_interface::igp::oracle::{ @@ -50,6 +51,11 @@ pub fn execute( let mut domains = vec![]; for config in configs { + ensure!( + !config.token_exchange_rate.is_zero(), + ContractError::invalid_config("exchange rate must be non-zero") + ); + domains.push(config.remote_domain.to_string()); insert_gas_data(deps.storage, config)?; } @@ -84,7 +90,7 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result { let gas_data = REMOTE_GAS_DATA.load(deps.storage, dest_domain)?; - Ok(to_binary(&GetExchangeRateAndGasPriceResponse { + Ok(to_json_binary(&GetExchangeRateAndGasPriceResponse { gas_price: gas_data.gas_price, exchange_rate: gas_data.token_exchange_rate, })?) diff --git a/contracts/igps/oracle/src/error.rs b/contracts/igps/oracle/src/error.rs index dc19f103..1dd46ab6 100644 --- a/contracts/igps/oracle/src/error.rs +++ b/contracts/igps/oracle/src/error.rs @@ -6,6 +6,17 @@ pub enum ContractError { #[error("{0}")] Std(#[from] StdError), - #[error("Unauthorized")] + #[error("unauthorized")] Unauthorized {}, + + #[error("invalid config. reason: {reason:?}")] + InvalidConfig { reason: String }, +} + +impl ContractError { + pub fn invalid_config(reason: &str) -> Self { + Self::InvalidConfig { + reason: reason.to_string(), + } + } } diff --git a/contracts/igps/oracle/src/tests/mod.rs b/contracts/igps/oracle/src/tests/mod.rs index 80a2f821..d1c39c39 100644 --- a/contracts/igps/oracle/src/tests/mod.rs +++ b/contracts/igps/oracle/src/tests/mod.rs @@ -1,5 +1,5 @@ use cosmwasm_std::{ - from_binary, testing::mock_info, Addr, Api, Empty, Env, MessageInfo, OwnedDeps, Querier, + from_json, testing::mock_info, Addr, Api, Empty, Env, MessageInfo, OwnedDeps, Querier, Response, Storage, }; use hpl_interface::igp::oracle::{ @@ -51,7 +51,7 @@ where fn query(&self, msg: QueryMsg) -> Result { query(self.deps.as_ref(), self.env.clone(), msg) - .map(|v| from_binary::(&v))? + .map(|v| from_json::(&v))? .map_err(|e| e.into()) } diff --git a/contracts/isms/aggregate/src/error.rs b/contracts/isms/aggregate/src/error.rs index 6ceb0a7d..6bc64a01 100644 --- a/contracts/isms/aggregate/src/error.rs +++ b/contracts/isms/aggregate/src/error.rs @@ -12,6 +12,6 @@ pub enum ContractError { #[error("unauthorized")] Unauthorized, - #[error("route not found")] - RouteNotFound {}, + #[error("invalid threshold. reason: {0}")] + InvalidThreshold(String), } diff --git a/contracts/isms/aggregate/src/lib.rs b/contracts/isms/aggregate/src/lib.rs index 45d4e34e..7da45373 100644 --- a/contracts/isms/aggregate/src/lib.rs +++ b/contracts/isms/aggregate/src/lib.rs @@ -4,15 +4,15 @@ pub use crate::error::ContractError; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - ensure_eq, Addr, Deps, DepsMut, Empty, Env, Event, HexBinary, MessageInfo, QueryResponse, - Response, StdResult, + ensure, ensure_eq, to_json_binary, Addr, Deps, DepsMut, Empty, Env, Event, HexBinary, + MessageInfo, QueryResponse, Response, StdResult, }; use cw2::set_contract_version; use cw_storage_plus::Item; use hpl_interface::{ ism::{ aggregate::{AggregateIsmQueryMsg, ExecuteMsg, InstantiateMsg, IsmsResponse, QueryMsg}, - IsmQueryMsg, IsmType, ModuleTypeResponse, VerifyInfoResponse, VerifyResponse, + IsmQueryMsg, IsmType, ModuleTypeResponse, ModulesAndThresholdResponse, VerifyResponse, }, to_binary, types::{bech32_decode, AggregateMetadata}, @@ -72,12 +72,22 @@ pub fn execute( ) -> Result { match msg { ExecuteMsg::Ownable(msg) => Ok(hpl_ownable::handle(deps, env, info, msg)?), - ExecuteMsg::SetIsms { isms } => { + ExecuteMsg::SetIsms { isms, threshold } => { ensure_eq!( get_owner(deps.storage)?, info.sender, ContractError::Unauthorized ); + ensure!( + threshold > 0, + ContractError::InvalidThreshold("threshold must not be zero".to_string()) + ); + ensure!( + isms.len() >= threshold as usize, + ContractError::InvalidThreshold( + "threshold should be less than ism count".to_string() + ) + ); let parsed_isms = isms .iter() @@ -85,10 +95,16 @@ pub fn execute( .collect::>()?; ISMS.save(deps.storage, &parsed_isms)?; + THRESHOLD.save(deps.storage, &threshold)?; Ok(Response::new() .add_event(new_event("set_isms").add_attribute("isms", isms.join(",")))) } + ExecuteMsg::SimulateVerify { metadata, message } => { + verify(deps.as_ref(), metadata, message)?; + + Ok(Response::new()) + } } } @@ -106,16 +122,17 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result to_binary(verify(deps, metadata, message)), - VerifyInfo { message } => to_binary(verify_info(deps, message)), + ModulesAndThreshold { message } => to_binary(modules_and_threshold(deps, message)), }, QueryMsg::AggregateIsm(msg) => match msg { - AggregateIsmQueryMsg::Isms {} => Ok(cosmwasm_std::to_binary(&IsmsResponse { + AggregateIsmQueryMsg::Isms {} => Ok(to_json_binary(&IsmsResponse { isms: ISMS .load(deps.storage)? .into_iter() .map(|v| v.into()) .collect(), + threshold: THRESHOLD.load(deps.storage)?, })?), }, } @@ -147,10 +164,13 @@ fn verify( }) } -fn verify_info(deps: Deps, _message: HexBinary) -> Result { - Ok(VerifyInfoResponse { +fn modules_and_threshold( + deps: Deps, + _message: HexBinary, +) -> Result { + Ok(ModulesAndThresholdResponse { threshold: THRESHOLD.load(deps.storage)?, - validators: ISMS + modules: ISMS .load(deps.storage)? .into_iter() .map(|v| Ok(bech32_decode(v.as_str())?.into())) diff --git a/contracts/isms/multisig/src/contract.rs b/contracts/isms/multisig/src/contract.rs index 15a60f11..03016450 100644 --- a/contracts/isms/multisig/src/contract.rs +++ b/contracts/isms/multisig/src/contract.rs @@ -1,6 +1,8 @@ #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; -use cosmwasm_std::{Deps, DepsMut, Empty, Env, MessageInfo, QueryResponse, Response}; +use cosmwasm_std::{ + ensure, ensure_eq, Deps, DepsMut, Empty, Env, Event, MessageInfo, QueryResponse, Response, +}; use cw2::set_contract_version; use hpl_interface::{ ism::{ @@ -11,10 +13,10 @@ use hpl_interface::{ }, to_binary, }; +use hpl_ownable::get_owner; use crate::{ error::ContractError, - execute, state::{THRESHOLD, VALIDATORS}, CONTRACT_NAME, CONTRACT_VERSION, }; @@ -47,14 +49,61 @@ pub fn execute( match msg { Ownable(msg) => Ok(hpl_ownable::handle(deps, env, info, msg)?), - EnrollValidator { set: msg } => execute::enroll_validator(deps, info, msg), - EnrollValidators { set: validators } => execute::enroll_validators(deps, info, validators), - UnenrollValidator { + SetValidators { domain, - validator: vald, - } => execute::unenroll_validator(deps, info, domain, vald), - SetThreshold { set: threshold } => execute::set_threshold(deps, info, threshold), - SetThresholds { set: thresholds } => execute::set_thresholds(deps, info, thresholds), + threshold, + validators, + } => { + ensure_eq!( + info.sender, + get_owner(deps.storage)?, + ContractError::Unauthorized {} + ); + ensure!( + validators.iter().all(|v| v.len() == 20), + ContractError::invalid_addr("length should be 20") + ); + ensure!( + validators.len() > threshold as usize && threshold > 0, + ContractError::invalid_args(&format!( + "threshold not in range. 0 < <= {}", + validators.len(), + )) + ); + + VALIDATORS.save(deps.storage, domain, &validators)?; + THRESHOLD.save(deps.storage, domain, &threshold)?; + + Ok(Response::new().add_event( + Event::new("ism_multisig_set_validators") + .add_attribute("sender", info.sender) + .add_attribute("domain", domain.to_string()) + .add_attribute("validators", validators.len().to_string()) + .add_attribute("threshold", threshold.to_string()), + )) + } + UnsetDomain { domain } => { + ensure_eq!( + info.sender, + get_owner(deps.storage)?, + ContractError::Unauthorized {} + ); + + VALIDATORS.remove(deps.storage, domain); + THRESHOLD.remove(deps.storage, domain); + + Ok(Response::new().add_event( + Event::new("ism_multisig_unset_domain") + .add_attribute("sender", info.sender) + .add_attribute("domain", domain.to_string()), + )) + } + + SimulateVerify { metadata, message } => { + crate::query::verify_message(deps.as_ref(), metadata, message)?; + + Ok(Response::new()) + } } } @@ -72,9 +121,9 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result to_binary(query::verify_message(deps, raw_metadata, raw_message)), - VerifyInfo { + ModulesAndThreshold { message: raw_message, - } => to_binary(query::get_verify_info(deps, raw_message)), + } => to_binary(query::modules_and_threshold(deps, raw_message)), }, QueryMsg::MultisigIsm(msg) => match msg { MultisigIsmQueryMsg::EnrolledValidators { domain } => to_binary({ diff --git a/contracts/isms/multisig/src/error.rs b/contracts/isms/multisig/src/error.rs index 70db89bc..7ccf0159 100644 --- a/contracts/isms/multisig/src/error.rs +++ b/contracts/isms/multisig/src/error.rs @@ -24,6 +24,9 @@ pub enum ContractError { #[error("invalid address. reason: {0}")] InvalidAddress(String), + #[error("invalid arguments. reason: {reason:?}")] + InvalidArguments { reason: String }, + #[error("duplicate validator")] ValidatorDuplicate, @@ -35,4 +38,10 @@ impl ContractError { pub fn invalid_addr(reason: &str) -> Self { ContractError::InvalidAddress(reason.into()) } + + pub fn invalid_args(reason: &str) -> Self { + ContractError::InvalidArguments { + reason: reason.into(), + } + } } diff --git a/contracts/isms/multisig/src/event.rs b/contracts/isms/multisig/src/event.rs deleted file mode 100644 index 17561622..00000000 --- a/contracts/isms/multisig/src/event.rs +++ /dev/null @@ -1,31 +0,0 @@ -use cosmwasm_std::{Addr, Event}; - -pub fn emit_init_transfer_ownership(next_owner: String) -> Event { - Event::new("ism_multisig_init_transfer_ownership").add_attribute("next_owner", next_owner) -} - -pub fn emit_finish_transfer_ownership(owner: Addr) -> Event { - Event::new("ism_multisig_finish_transfer_owner").add_attribute("owner", owner) -} - -pub fn emit_revoke_transfer_ownership() -> Event { - Event::new("ism_multisig_revoke_transfer_ownership") -} - -pub fn emit_enroll_validator(domain: u32, validator: String) -> Event { - Event::new("ism_multisig_enroll_validator") - .add_attribute("domain", domain.to_string()) - .add_attribute("validator", validator) -} - -pub fn emit_unenroll_validator(domain: u32, validator: String) -> Event { - Event::new("ism_multisig_unenroll_validator") - .add_attribute("domain", domain.to_string()) - .add_attribute("validator", validator) -} - -pub fn emit_set_threshold(domain: u32, threshold: u8) -> Event { - Event::new("ism_multisig_set_threshold") - .add_attribute("domain", domain.to_string()) - .add_attribute("threshold", threshold.to_string()) -} diff --git a/contracts/isms/multisig/src/lib.rs b/contracts/isms/multisig/src/lib.rs index aba3b52f..0519c95a 100644 --- a/contracts/isms/multisig/src/lib.rs +++ b/contracts/isms/multisig/src/lib.rs @@ -1,7 +1,5 @@ pub mod contract; mod error; -pub mod event; -pub mod execute; pub mod query; pub mod state; diff --git a/contracts/isms/multisig/src/query.rs b/contracts/isms/multisig/src/query.rs index ac848b91..662c78be 100644 --- a/contracts/isms/multisig/src/query.rs +++ b/contracts/isms/multisig/src/query.rs @@ -1,6 +1,6 @@ use cosmwasm_std::{Deps, HexBinary}; use hpl_interface::{ - ism::{IsmType, ModuleTypeResponse, VerifyInfoResponse, VerifyResponse}, + ism::{IsmType, ModuleTypeResponse, ModulesAndThresholdResponse, VerifyResponse}, types::{eth_addr, eth_hash, Message, MessageIdMultisigIsmMetadata}, }; @@ -21,11 +21,6 @@ pub fn verify_message( raw_metadata: HexBinary, raw_message: HexBinary, ) -> Result { - deps.api.debug(&format!( - "ism_multisig::verify: metadata: {:?}, message: {:?}", - raw_metadata, raw_message - )); - let metadata: MessageIdMultisigIsmMetadata = raw_metadata.into(); let message: Message = raw_message.into(); @@ -65,18 +60,18 @@ pub fn verify_message( }) } -pub fn get_verify_info( +pub fn modules_and_threshold( deps: Deps, raw_message: HexBinary, -) -> Result { +) -> Result { let message: Message = raw_message.into(); let threshold = THRESHOLD.load(deps.storage, message.origin_domain)?; let validators = VALIDATORS.load(deps.storage, message.origin_domain)?; - Ok(VerifyInfoResponse { + Ok(ModulesAndThresholdResponse { threshold, - validators, + modules: validators, }) } @@ -92,7 +87,7 @@ mod test { use k256::{ecdsa::SigningKey, elliptic_curve::rand_core::OsRng}; use rstest::rstest; - use super::{get_module_type, get_verify_info, verify_message}; + use super::{get_module_type, modules_and_threshold, verify_message}; #[test] fn test_get_module_type() { @@ -160,9 +155,9 @@ mod test { .unwrap(); THRESHOLD.save(deps.as_mut().storage, 26658, &1u8).unwrap(); - let info = get_verify_info(deps.as_ref(), raw_message).unwrap(); + let info = modules_and_threshold(deps.as_ref(), raw_message).unwrap(); - assert_eq!(info.validators, vec![addr]); + assert_eq!(info.modules, vec![addr]); assert_eq!(info.threshold, 1); } } diff --git a/contracts/isms/multisig/src/state.rs b/contracts/isms/multisig/src/state.rs index 25c8564b..ddb09d3a 100644 --- a/contracts/isms/multisig/src/state.rs +++ b/contracts/isms/multisig/src/state.rs @@ -1,13 +1,6 @@ -use cosmwasm_schema::cw_serde; -use cosmwasm_std::{Addr, HexBinary}; +use cosmwasm_std::HexBinary; use cw_storage_plus::Map; -#[cw_serde] -pub struct Config { - pub owner: Addr, - pub addr_prefix: String, -} - pub const VALIDATORS_PREFIX: &str = "validators"; pub const VALIDATORS: Map> = Map::new(VALIDATORS_PREFIX); diff --git a/contracts/isms/routing/src/contract.rs b/contracts/isms/routing/src/contract.rs index 3679fb38..b38c2878 100644 --- a/contracts/isms/routing/src/contract.rs +++ b/contracts/isms/routing/src/contract.rs @@ -1,7 +1,7 @@ #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - ensure_eq, to_binary, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response, + ensure_eq, to_json_binary, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response, }; use cw2::set_contract_version; use hpl_interface::{ @@ -13,7 +13,7 @@ use hpl_interface::{ }; use hpl_ownable::get_owner; -use crate::{error::ContractError, state::MODULES, CONTRACT_NAME, CONTRACT_VERSION}; +use crate::{error::ContractError, new_event, state::MODULES, CONTRACT_NAME, CONTRACT_VERSION}; #[cfg_attr(not(feature = "library"), entry_point)] pub fn instantiate( @@ -65,7 +65,49 @@ pub fn execute( &deps.api.addr_validate(&ism.address)?, )?; - Ok(Response::default()) + Ok(Response::default().add_event( + new_event("set") + .add_attribute("sender", info.sender) + .add_attribute("domain", ism.domain.to_string()) + .add_attribute("ism", ism.address), + )) + } + Unset { domains } => { + ensure_eq!( + get_owner(deps.storage)?, + info.sender, + ContractError::Unauthorized {} + ); + + for domain in domains.clone() { + MODULES.remove(deps.storage, domain); + } + + Ok(Response::default().add_event( + new_event("unset") + .add_attribute("sender", info.sender) + .add_attribute( + "domains", + domains + .into_iter() + .map(|v| v.to_string()) + .collect::>() + .join(","), + ), + )) + } + SimulateVerify { metadata, message } => { + let decoded = Message::from(message.clone()); + + let ism = MODULES + .may_load(deps.storage, decoded.origin_domain)? + .ok_or(ContractError::RouteNotFound {})?; + + let _: VerifyResponse = deps + .querier + .query_wasm_smart(ism, &IsmQueryMsg::Verify { metadata, message }.wrap())?; + + Ok(Response::new()) } } } @@ -77,15 +119,10 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result Ok(hpl_ownable::handle_query(deps, env, msg)?), QueryMsg::Ism(msg) => match msg { - ModuleType {} => Ok(to_binary(&ModuleTypeResponse { + ModuleType {} => Ok(to_json_binary(&ModuleTypeResponse { typ: hpl_interface::ism::IsmType::Routing, })?), Verify { metadata, message } => { - deps.api.debug(&format!( - "ism_routing::verify: metadata: {:?}, message: {:?}", - metadata, message - )); - let decoded = Message::from(message.clone()); let ism = MODULES @@ -96,9 +133,9 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result { + ModulesAndThreshold { message } => { let decoded = Message::from(message.clone()); let ism = MODULES @@ -107,9 +144,9 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result match msg { @@ -121,7 +158,7 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result Event { + Event::new(format!("hpl_ism_routing::{}", name)) +} + // version info for migration info pub const CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/contracts/isms/routing/src/tests/contract.rs b/contracts/isms/routing/src/tests/contract.rs index 718e06ee..1c788e45 100644 --- a/contracts/isms/routing/src/tests/contract.rs +++ b/contracts/isms/routing/src/tests/contract.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{to_binary, Addr, ContractResult, HexBinary, SystemResult, WasmQuery}; +use cosmwasm_std::{to_json_binary, Addr, ContractResult, HexBinary, SystemResult, WasmQuery}; use hpl_interface::{ ism::{routing::IsmSet, IsmType, VerifyResponse}, types::Message, @@ -88,7 +88,7 @@ fn test_query() -> anyhow::Result<()> { // register mock handler ism.deps.querier.update_wasm(|v| match v { WasmQuery::Smart { contract_addr, .. } => SystemResult::Ok(ContractResult::Ok( - to_binary(&VerifyResponse { + to_json_binary(&VerifyResponse { verified: contract_addr == "ism1", }) .unwrap(), diff --git a/contracts/isms/routing/src/tests/mod.rs b/contracts/isms/routing/src/tests/mod.rs index daa9a2f8..42f3da73 100644 --- a/contracts/isms/routing/src/tests/mod.rs +++ b/contracts/isms/routing/src/tests/mod.rs @@ -1,5 +1,5 @@ use cosmwasm_std::{ - from_binary, + from_json, testing::{mock_dependencies, mock_env, mock_info, MockApi, MockQuerier, MockStorage}, Addr, Empty, Env, HexBinary, MessageInfo, OwnedDeps, Response, }; @@ -59,7 +59,7 @@ impl IsmRouting { fn query(&self, msg: QueryMsg) -> Result { query(self.deps.as_ref(), self.env.clone(), msg) - .map(|v| from_binary::(&v))? + .map(|v| from_json::(&v))? .map_err(|e| e.into()) } diff --git a/contracts/mocks/mock-hook/src/contract.rs b/contracts/mocks/mock-hook/src/contract.rs index eb1f8f2d..86096802 100644 --- a/contracts/mocks/mock-hook/src/contract.rs +++ b/contracts/mocks/mock-hook/src/contract.rs @@ -2,8 +2,8 @@ use cosmwasm_schema::cw_serde; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - coin, to_binary, Deps, DepsMut, Env, Event, MessageInfo, QueryResponse, Response, StdResult, - Uint256, + coins, to_json_binary, Deps, DepsMut, Env, Event, MessageInfo, QueryResponse, Response, + StdError, StdResult, Uint256, }; use cw2::set_contract_version; use cw_storage_plus::Item; @@ -27,7 +27,7 @@ pub struct InstantiateMsg {} #[cw_serde] pub enum ExecuteMsg { - SetGasAmount { gas: Uint256 }, + SetGasAmount { gas: Option }, PostDispatch(PostDispatchMsg), } @@ -75,7 +75,10 @@ pub fn execute( ), )), ExecuteMsg::SetGasAmount { gas } => { - GAS.save(deps.storage, &gas)?; + match gas { + Some(gas) => GAS.save(deps.storage, &gas)?, + None => GAS.remove(deps.storage), + } Ok(Response::new()) } @@ -88,12 +91,20 @@ pub fn query(deps: Deps, _env: Env, msg: ExpectedHookQueryMsg) -> StdResult match msg { HookQueryMsg::QuoteDispatch(_) => { - let gas = GAS.load(deps.storage)?; + let gas = GAS + .may_load(deps.storage)? + .map(|v| { + v.to_string().parse::().map_err(|e| { + StdError::generic_err(format!( + "failed to parse Uint256 gas. reason: {e}" + )) + }) + }) + .transpose()?; let gas_token = GAS_TOKEN.load(deps.storage)?; + let fees = gas.map(|v| coins(v, &gas_token)).unwrap_or_default(); - Ok(to_binary(&QuoteDispatchResponse { - gas_amount: Some(coin(gas.to_string().parse::().unwrap(), gas_token)), - })?) + Ok(to_json_binary(&QuoteDispatchResponse { fees })?) } HookQueryMsg::Mailbox {} => { unimplemented!("mailbox query not implemented on mock hook") @@ -104,7 +115,7 @@ pub fn query(deps: Deps, _env: Env, msg: ExpectedHookQueryMsg) -> StdResult StdResult match msg { - ModuleType {} => Ok(to_binary(&IsmType::Null)?), - Verify { .. } => Ok(to_binary(&VerifyResponse { verified: true })?), - VerifyInfo { .. } => Ok(to_binary(&VerifyInfoResponse { + ModuleType {} => Ok(to_json_binary(&IsmType::Null)?), + Verify { .. } => Ok(to_json_binary(&VerifyResponse { verified: true })?), + ModulesAndThreshold { .. } => Ok(to_json_binary(&ModulesAndThresholdResponse { threshold: 1u8, - validators: vec![], + modules: vec![], })?), }, } diff --git a/contracts/mocks/mock-msg-receiver/src/contract.rs b/contracts/mocks/mock-msg-receiver/src/contract.rs index b127e108..4f916778 100644 --- a/contracts/mocks/mock-msg-receiver/src/contract.rs +++ b/contracts/mocks/mock-msg-receiver/src/contract.rs @@ -2,7 +2,7 @@ use cosmwasm_schema::cw_serde; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - attr, to_binary, Deps, DepsMut, Empty, Env, Event, MessageInfo, QueryResponse, Response, + attr, to_json_binary, Deps, DepsMut, Empty, Env, Event, MessageInfo, QueryResponse, Response, StdResult, }; use cw2::set_contract_version; @@ -68,7 +68,7 @@ pub fn query( match msg { ism::ExpectedIsmSpecifierQueryMsg::IsmSpecifier( ism::IsmSpecifierQueryMsg::InterchainSecurityModule(), - ) => Ok(to_binary(&ism::InterchainSecurityModuleResponse { + ) => Ok(to_json_binary(&ism::InterchainSecurityModuleResponse { ism: None, })?), } diff --git a/contracts/warp/cw20/src/contract.rs b/contracts/warp/cw20/src/contract.rs index defe13b2..785be875 100644 --- a/contracts/warp/cw20/src/contract.rs +++ b/contracts/warp/cw20/src/contract.rs @@ -1,8 +1,8 @@ #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - ensure_eq, wasm_execute, CosmosMsg, Deps, DepsMut, Env, HexBinary, MessageInfo, QueryResponse, - Reply, Response, SubMsg, Uint128, Uint256, WasmMsg, + ensure_eq, to_json_binary, wasm_execute, CosmosMsg, Deps, DepsMut, Env, HexBinary, MessageInfo, + QueryResponse, Reply, Response, StdError, SubMsg, Uint128, Uint256, WasmMsg, }; use cw20::Cw20ExecuteMsg; @@ -56,7 +56,7 @@ pub fn instantiate( WasmMsg::Instantiate { admin: Some(env.contract.address.to_string()), code_id: token.code_id, - msg: cosmwasm_std::to_binary(&token_init_msg)?, + msg: to_json_binary(&token_init_msg)?, funds: vec![], label: "token warp cw20".to_string(), }, @@ -107,7 +107,12 @@ pub fn execute( pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> Result { match msg.id { REPLY_ID_CREATE_DENOM => { - let reply_data = msg.result.unwrap().data.unwrap(); + let reply_data = msg + .result + .into_result() + .map_err(StdError::generic_err)? + .data + .ok_or(StdError::generic_err("no reply data"))?; let init_resp = cw_utils::parse_instantiate_response_data(&reply_data)?; let init_addr = deps.api.addr_validate(&init_resp.contract_address)?; @@ -240,11 +245,11 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result to_binary(get_token_type(deps)), TokenMode {} => to_binary(get_token_mode(deps)), }, - QueryMsg::IsmSpecifier(IsmSpecifierQueryMsg::InterchainSecurityModule()) => Ok( - cosmwasm_std::to_binary(&InterchainSecurityModuleResponse { + QueryMsg::IsmSpecifier(IsmSpecifierQueryMsg::InterchainSecurityModule()) => { + Ok(to_json_binary(&InterchainSecurityModuleResponse { ism: get_ism(deps.storage)?, - })?, - ), + })?) + } } } @@ -417,7 +422,7 @@ mod test { CosmosMsg::Wasm(WasmMsg::Instantiate { admin: Some(mock_env().contract.address.to_string()), code_id: v.code_id, - msg: cosmwasm_std::to_binary(&v.init_msg).unwrap(), + msg: to_json_binary(&v.init_msg).unwrap(), funds: vec![], label: "token warp cw20".to_string() }) @@ -474,8 +479,8 @@ mod test { match token_mode { TokenModeMsg::Bridged(_) => { assert_eq!( - cosmwasm_std::to_binary(msg).unwrap(), - cosmwasm_std::to_binary(&CosmosMsg::::Wasm( + to_json_binary(msg).unwrap(), + to_json_binary(&CosmosMsg::::Wasm( conv::to_mint_msg( TOKEN, bech32_encode(hrp, warp_msg.recipient.as_slice()).unwrap(), @@ -488,8 +493,8 @@ mod test { } TokenModeMsg::Collateral(_) => { assert_eq!( - cosmwasm_std::to_binary(msg).unwrap(), - cosmwasm_std::to_binary(&CosmosMsg::::Wasm( + to_json_binary(msg).unwrap(), + to_json_binary(&CosmosMsg::::Wasm( conv::to_send_msg( TOKEN, bech32_encode(hrp, warp_msg.recipient.as_slice()).unwrap(), @@ -548,7 +553,7 @@ mod test { .unwrap(); let warp_msg = warp::Message { - recipient: recipient, + recipient, amount: Uint256::from_u128(100), metadata: HexBinary::default(), }; @@ -559,8 +564,8 @@ mod test { match token_mode { TokenModeMsg::Bridged(_) => { assert_eq!( - cosmwasm_std::to_binary(&msgs).unwrap(), - cosmwasm_std::to_binary(&vec![ + to_json_binary(&msgs).unwrap(), + to_json_binary(&vec![ transfer_from_msg.into(), CosmosMsg::from(conv::to_burn_msg(TOKEN, Uint128::new(100)).unwrap()), dispatch_msg, @@ -570,8 +575,8 @@ mod test { } TokenModeMsg::Collateral(_) => { assert_eq!( - cosmwasm_std::to_binary(&msgs).unwrap(), - cosmwasm_std::to_binary(&vec![transfer_from_msg.into(), dispatch_msg]).unwrap(), + to_json_binary(&msgs).unwrap(), + to_json_binary(&vec![transfer_from_msg.into(), dispatch_msg]).unwrap(), ); } } diff --git a/contracts/warp/native/src/contract.rs b/contracts/warp/native/src/contract.rs index da89fa0d..d9181be2 100644 --- a/contracts/warp/native/src/contract.rs +++ b/contracts/warp/native/src/contract.rs @@ -1,8 +1,8 @@ #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - ensure, ensure_eq, CosmosMsg, Deps, DepsMut, Empty, Env, HexBinary, MessageInfo, QueryResponse, - Reply, Response, SubMsg, Uint128, Uint256, + ensure, ensure_eq, to_json_binary, CosmosMsg, Deps, DepsMut, Empty, Env, HexBinary, + MessageInfo, QueryResponse, Reply, Response, StdError, SubMsg, Uint128, Uint256, }; use hpl_connection::{get_hook, get_ism}; use hpl_interface::{ @@ -64,7 +64,10 @@ pub fn instantiate( ))); } - (msgs, token.denom) + ( + msgs, + format!("factory/{}/{}", env.contract.address, token.denom), + ) } // use denom directly if token is native TokenModeMsg::Collateral(token) => { @@ -106,7 +109,12 @@ pub fn execute( #[cfg_attr(not(feature = "library"), entry_point)] pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> Result { - let reply_data = msg.result.unwrap().data.unwrap(); + let reply_data = msg + .result + .into_result() + .map_err(StdError::generic_err)? + .data + .ok_or(StdError::generic_err("no reply data"))?; match msg.id { REPLY_ID_CREATE_DENOM => { @@ -250,11 +258,11 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result to_binary(get_token_type(deps)), TokenMode {} => to_binary(get_token_mode(deps)), }, - QueryMsg::IsmSpecifier(IsmSpecifierQueryMsg::InterchainSecurityModule()) => Ok( - cosmwasm_std::to_binary(&InterchainSecurityModuleResponse { + QueryMsg::IsmSpecifier(IsmSpecifierQueryMsg::InterchainSecurityModule()) => { + Ok(to_json_binary(&InterchainSecurityModuleResponse { ism: get_ism(deps.storage)?, - })?, - ), + })?) + } } } @@ -553,7 +561,7 @@ mod test { .into(), None, None, - vec![ + [ vec![coin(50, DENOM)], funds.into_iter().filter(|v| v.denom != DENOM).collect() ] diff --git a/integration-test/tests/contracts/cw/ism.rs b/integration-test/tests/contracts/cw/ism.rs index 14d4a5ca..2b58e01f 100644 --- a/integration-test/tests/contracts/cw/ism.rs +++ b/integration-test/tests/contracts/cw/ism.rs @@ -1,5 +1,5 @@ -use cosmwasm_std::Empty; -use hpl_interface::ism::multisig::ThresholdSet; +use cosmwasm_std::{Empty, HexBinary, StdResult}; +use hpl_interface::types::pub_to_addr; use osmosis_test_tube::Wasm; use test_tube::{Account, Runner, SigningAccount}; @@ -69,18 +69,18 @@ impl Ism { wasm.execute( &multisig_ism, - &hpl_interface::ism::multisig::ExecuteMsg::EnrollValidators { set: set.to_set() }, - &[], - owner, - )?; - - wasm.execute( - &multisig_ism, - &hpl_interface::ism::multisig::ExecuteMsg::SetThreshold { - set: ThresholdSet { - domain: set.domain, - threshold: set.threshold, - }, + &hpl_interface::ism::multisig::ExecuteMsg::SetValidators { + domain: set.domain, + threshold: set.threshold, + validators: set + .validators + .iter() + .map(|v| { + pub_to_addr(HexBinary::from( + v.pub_key.to_encoded_point(true).as_bytes().to_vec(), + )) + }) + .collect::>>()?, }, &[], owner, diff --git a/integration-test/tests/validator.rs b/integration-test/tests/validator.rs index 05230e41..25cb8dcd 100644 --- a/integration-test/tests/validator.rs +++ b/integration-test/tests/validator.rs @@ -1,11 +1,11 @@ use cosmwasm_std::{ - testing::{mock_dependencies, mock_info}, + testing::{mock_dependencies, mock_env, mock_info}, Binary, HexBinary, }; use ethers::types::{Address, H160}; use ethers::utils::hex::FromHex; use hpl_interface::{ - ism::multisig::{ThresholdSet, ValidatorSet}, + ism::multisig::ValidatorSet, types::{ bech32_encode, eth_addr, eth_hash, pub_to_addr, Message, MessageIdMultisigIsmMetadata, }, @@ -22,6 +22,7 @@ pub struct TestValidator { pub pub_key: VerifyingKey, } +#[allow(dead_code)] impl TestValidator { fn random() -> Self { let priv_key = SigningKey::random(&mut OsRng); @@ -176,19 +177,18 @@ fn test_validator() { hpl_ownable::initialize(deps.as_mut().storage, &owner).unwrap(); - hpl_ism_multisig::execute::enroll_validators( + hpl_ism_multisig::contract::execute( deps.as_mut(), + mock_env(), mock_info(owner.as_str(), &[]), - validators.to_set(), - ) - .unwrap(); - - hpl_ism_multisig::execute::set_threshold( - deps.as_mut(), - mock_info(owner.as_str(), &[]), - ThresholdSet { + hpl_interface::ism::multisig::ExecuteMsg::SetValidators { domain: validators.domain, threshold: validators.threshold, + validators: validators + .to_set() + .iter() + .map(|v| v.validator.clone()) + .collect(), }, ) .unwrap(); diff --git a/packages/connection/src/lib.rs b/packages/connection/src/lib.rs index 5506c9d8..91c7bdbd 100644 --- a/packages/connection/src/lib.rs +++ b/packages/connection/src/lib.rs @@ -1,6 +1,6 @@ use cosmwasm_std::{ - ensure_eq, Addr, CustomQuery, Deps, DepsMut, Env, Event, MessageInfo, QueryResponse, Response, - StdError, StdResult, Storage, + ensure_eq, to_json_binary, Addr, CustomQuery, Deps, DepsMut, Env, Event, MessageInfo, + QueryResponse, Response, StdError, StdResult, Storage, }; use cw_storage_plus::Item; use hpl_interface::connection::{ @@ -75,13 +75,13 @@ pub fn handle_query( msg: ConnectionQueryMsg, ) -> StdResult { match msg { - ConnectionQueryMsg::GetMailbox {} => Ok(cosmwasm_std::to_binary(&MailboxResponse { + ConnectionQueryMsg::GetMailbox {} => Ok(to_json_binary(&MailboxResponse { mailbox: get_mailbox(deps.storage)?.map(|v| v.into()), })?), - ConnectionQueryMsg::GetHook {} => Ok(cosmwasm_std::to_binary(&HookResponse { + ConnectionQueryMsg::GetHook {} => Ok(to_json_binary(&HookResponse { hook: get_hook(deps.storage)?.map(|v| v.into()), })?), - ConnectionQueryMsg::GetIsm {} => Ok(cosmwasm_std::to_binary(&IsmResponse { + ConnectionQueryMsg::GetIsm {} => Ok(to_json_binary(&IsmResponse { ism: get_ism(deps.storage)?.map(|v| v.into()), })?), } diff --git a/packages/interface/src/core/mailbox.rs b/packages/interface/src/core/mailbox.rs index b5aa8c7e..edebe0b1 100644 --- a/packages/interface/src/core/mailbox.rs +++ b/packages/interface/src/core/mailbox.rs @@ -154,7 +154,7 @@ pub enum QueryMsg { #[derive(QueryResponses)] pub enum MailboxHookQueryMsg { #[returns(QuoteDispatchResponse)] - QuoteDispatch(DispatchMsg), + QuoteDispatch { sender: String, msg: DispatchMsg }, } #[cw_serde] diff --git a/packages/interface/src/core/va.rs b/packages/interface/src/core/va.rs index 7a9ad92a..d94661cc 100644 --- a/packages/interface/src/core/va.rs +++ b/packages/interface/src/core/va.rs @@ -24,6 +24,12 @@ pub enum QueryMsg { #[returns(GetAnnouncedValidatorsResponse)] GetAnnouncedValidators {}, + + #[returns(MailboxResponse)] + Mailbox {}, + + #[returns(LocalDomainResponse)] + LocalDomain {}, } #[cw_serde] @@ -35,3 +41,13 @@ pub struct GetAnnounceStorageLocationsResponse { pub struct GetAnnouncedValidatorsResponse { pub validators: Vec, } + +#[cw_serde] +pub struct MailboxResponse { + pub mailbox: String, +} + +#[cw_serde] +pub struct LocalDomainResponse { + pub local_domain: u32, +} diff --git a/packages/interface/src/hook/mod.rs b/packages/interface/src/hook/mod.rs index 9d2a036d..0c368b0b 100644 --- a/packages/interface/src/hook/mod.rs +++ b/packages/interface/src/hook/mod.rs @@ -69,7 +69,7 @@ pub struct MailboxResponse { #[cw_serde] pub struct QuoteDispatchResponse { - pub gas_amount: Option, + pub fees: Vec, } pub fn post_dispatch( diff --git a/packages/interface/src/ism/aggregate.rs b/packages/interface/src/ism/aggregate.rs index fcb48d5c..144f849e 100644 --- a/packages/interface/src/ism/aggregate.rs +++ b/packages/interface/src/ism/aggregate.rs @@ -1,4 +1,5 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::HexBinary; use crate::ownable::{OwnableMsg, OwnableQueryMsg}; @@ -15,7 +16,15 @@ pub struct InstantiateMsg { pub enum ExecuteMsg { Ownable(OwnableMsg), - SetIsms { isms: Vec }, + SimulateVerify { + metadata: HexBinary, + message: HexBinary, + }, + + SetIsms { + isms: Vec, + threshold: u8, + }, } #[cw_serde] @@ -39,6 +48,7 @@ pub enum AggregateIsmQueryMsg { #[cw_serde] pub struct IsmsResponse { pub isms: Vec, + pub threshold: u8, } #[cfg(test)] @@ -46,10 +56,18 @@ mod test { use cosmwasm_std::HexBinary; use super::*; - use crate::{ism::IsmQueryMsg, msg_checker}; + use crate::{ + ism::{ExpectedIsmMsg, IsmQueryMsg}, + msg_checker, + }; #[test] fn test_ism_interface() { + let _checked: ExecuteMsg = msg_checker(ExpectedIsmMsg::SimulateVerify { + metadata: HexBinary::default(), + message: HexBinary::default(), + }); + let _checked: QueryMsg = msg_checker(IsmQueryMsg::ModuleType {}.wrap()); let _checked: QueryMsg = msg_checker( IsmQueryMsg::Verify { @@ -59,7 +77,7 @@ mod test { .wrap(), ); let _checked: QueryMsg = msg_checker( - IsmQueryMsg::VerifyInfo { + IsmQueryMsg::ModulesAndThreshold { message: HexBinary::default(), } .wrap(), diff --git a/packages/interface/src/ism/mod.rs b/packages/interface/src/ism/mod.rs index 13cccbe4..795350ea 100644 --- a/packages/interface/src/ism/mod.rs +++ b/packages/interface/src/ism/mod.rs @@ -18,6 +18,14 @@ pub enum IsmType { CcipRead = 7, } +#[cw_serde] +pub enum ExpectedIsmMsg { + SimulateVerify { + metadata: HexBinary, + message: HexBinary, + }, +} + #[cw_serde] #[derive(QueryResponses)] pub enum IsmQueryMsg { @@ -30,8 +38,8 @@ pub enum IsmQueryMsg { message: HexBinary, }, - #[returns(VerifyInfoResponse)] - VerifyInfo { message: HexBinary }, + #[returns(ModulesAndThresholdResponse)] + ModulesAndThreshold { message: HexBinary }, } impl IsmQueryMsg { @@ -79,9 +87,9 @@ pub struct VerifyResponse { } #[cw_serde] -pub struct VerifyInfoResponse { +pub struct ModulesAndThresholdResponse { pub threshold: u8, - pub validators: Vec, + pub modules: Vec, } #[cw_serde] diff --git a/packages/interface/src/ism/multisig.rs b/packages/interface/src/ism/multisig.rs index 4f91ac67..77f7253d 100644 --- a/packages/interface/src/ism/multisig.rs +++ b/packages/interface/src/ism/multisig.rs @@ -5,7 +5,7 @@ use crate::ownable::{OwnableMsg, OwnableQueryMsg}; use super::IsmQueryMsg; #[allow(unused_imports)] -use super::{ModuleTypeResponse, VerifyInfoResponse, VerifyResponse}; +use super::{ModuleTypeResponse, ModulesAndThresholdResponse, VerifyResponse}; #[cw_serde] pub struct InstantiateMsg { @@ -18,22 +18,23 @@ pub struct ValidatorSet { pub validator: HexBinary, } -#[cw_serde] -pub struct ThresholdSet { - pub domain: u32, - pub threshold: u8, -} - #[cw_serde] pub enum ExecuteMsg { Ownable(OwnableMsg), - EnrollValidator { set: ValidatorSet }, - EnrollValidators { set: Vec }, - UnenrollValidator { domain: u32, validator: HexBinary }, + SimulateVerify { + metadata: HexBinary, + message: HexBinary, + }, - SetThreshold { set: ThresholdSet }, - SetThresholds { set: Vec }, + SetValidators { + domain: u32, + threshold: u8, + validators: Vec, // should be 20 lenghted + }, + UnsetDomain { + domain: u32, + }, } #[cw_serde] @@ -61,10 +62,15 @@ pub struct EnrolledValidatorsResponse { #[cfg(test)] mod test { use super::*; - use crate::msg_checker; + use crate::{ism::ExpectedIsmMsg, msg_checker}; #[test] fn test_ism_interface() { + let _checked: ExecuteMsg = msg_checker(ExpectedIsmMsg::SimulateVerify { + metadata: HexBinary::default(), + message: HexBinary::default(), + }); + let _checked: QueryMsg = msg_checker(IsmQueryMsg::ModuleType {}.wrap()); let _checked: QueryMsg = msg_checker( IsmQueryMsg::Verify { @@ -74,7 +80,7 @@ mod test { .wrap(), ); let _checked: QueryMsg = msg_checker( - IsmQueryMsg::VerifyInfo { + IsmQueryMsg::ModulesAndThreshold { message: HexBinary::default(), } .wrap(), diff --git a/packages/interface/src/ism/routing.rs b/packages/interface/src/ism/routing.rs index a877532e..d722fb97 100644 --- a/packages/interface/src/ism/routing.rs +++ b/packages/interface/src/ism/routing.rs @@ -23,7 +23,17 @@ pub struct InstantiateMsg { pub enum ExecuteMsg { Ownable(OwnableMsg), - Set { ism: IsmSet }, + SimulateVerify { + metadata: HexBinary, + message: HexBinary, + }, + + Set { + ism: IsmSet, + }, + Unset { + domains: Vec, + }, } #[cw_serde] @@ -52,10 +62,18 @@ mod test { use cosmwasm_std::HexBinary; use super::*; - use crate::{ism::IsmQueryMsg, msg_checker}; + use crate::{ + ism::{ExpectedIsmMsg, IsmQueryMsg}, + msg_checker, + }; #[test] fn test_ism_interface() { + let _checked: ExecuteMsg = msg_checker(ExpectedIsmMsg::SimulateVerify { + metadata: HexBinary::default(), + message: HexBinary::default(), + }); + let _checked: QueryMsg = msg_checker(IsmQueryMsg::ModuleType {}.wrap()); let _checked: QueryMsg = msg_checker( IsmQueryMsg::Verify { @@ -65,7 +83,7 @@ mod test { .wrap(), ); let _checked: QueryMsg = msg_checker( - IsmQueryMsg::VerifyInfo { + IsmQueryMsg::ModulesAndThreshold { message: HexBinary::default(), } .wrap(), diff --git a/packages/interface/src/lib.rs b/packages/interface/src/lib.rs index 595fb188..119204ed 100644 --- a/packages/interface/src/lib.rs +++ b/packages/interface/src/lib.rs @@ -1,7 +1,7 @@ use std::error::Error; use cosmwasm_schema::cw_serde; -use cosmwasm_std::{QueryResponse, StdError, StdResult}; +use cosmwasm_std::{to_json_binary, QueryResponse, StdError, StdResult}; use cw_storage_plus::Bound; pub mod connection; @@ -84,19 +84,18 @@ pub fn range_option<'a, T: cw_storage_plus::PrimaryKey<'a>>( pub fn to_binary + From>( data: Result, ) -> Result { - data.map(|v| cosmwasm_std::to_binary(&v))? - .map_err(|err| err.into()) + data.map(|v| to_json_binary(&v))?.map_err(|err| err.into()) } +#[cfg(test)] +pub use test::msg_checker; + #[cfg(test)] mod test { - use cosmwasm_std::{from_binary, to_binary}; + use cosmwasm_std::{from_json, to_json_binary}; use serde::{de::DeserializeOwned, Serialize}; pub fn msg_checker(input: Input) -> Output { - from_binary::(&to_binary(&input).unwrap()).unwrap() + from_json::(to_json_binary(&input).unwrap()).unwrap() } } - -#[cfg(test)] -pub use test::msg_checker; diff --git a/packages/interface/src/macros.rs b/packages/interface/src/macros.rs index 9a7dc8ba..deb93c80 100644 --- a/packages/interface/src/macros.rs +++ b/packages/interface/src/macros.rs @@ -11,11 +11,11 @@ macro_rules! build_test_querier { let res = $handler( deps, cosmwasm_std::testing::mock_env(), - cosmwasm_std::from_binary(&cosmwasm_std::to_binary(&msg).unwrap()).unwrap(), + cosmwasm_std::from_json(cosmwasm_std::to_json_binary(&msg).unwrap()).unwrap(), ) .map_err(|e| e.to_string()) .unwrap(); - cosmwasm_std::from_binary(&res).unwrap() + cosmwasm_std::from_json(&res).unwrap() } }; } @@ -33,7 +33,7 @@ macro_rules! build_test_executor { deps, cosmwasm_std::testing::mock_env(), cosmwasm_std::testing::mock_info(sender.as_str(), &funds), - cosmwasm_std::from_binary(&cosmwasm_std::to_binary(&msg).unwrap()).unwrap(), + cosmwasm_std::from_json(cosmwasm_std::to_json_binary(&msg).unwrap()).unwrap(), ) .map_err(|e| e.to_string()) .unwrap() diff --git a/packages/interface/src/types/merkle.rs b/packages/interface/src/types/merkle.rs index fd7f404a..5d0978f2 100644 --- a/packages/interface/src/types/merkle.rs +++ b/packages/interface/src/types/merkle.rs @@ -8,7 +8,7 @@ pub const TREE_DEPTH: usize = 32; pub const MAX_LEAVES: u128 = (2_u128.pow(TREE_DEPTH as u32)) - 1; pub const ZERO_BYTES: &str = "0000000000000000000000000000000000000000000000000000000000000000"; -pub const ZERO_HASHES: [&str; HASH_LENGTH] = [ +pub const ZERO_HASHES: [&str; TREE_DEPTH] = [ "0000000000000000000000000000000000000000000000000000000000000000", "ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", "b4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", diff --git a/packages/ownable/src/lib.rs b/packages/ownable/src/lib.rs index 8fbcba50..a4d07821 100644 --- a/packages/ownable/src/lib.rs +++ b/packages/ownable/src/lib.rs @@ -2,7 +2,7 @@ mod test; use cosmwasm_std::{ - ensure, ensure_eq, to_binary, Addr, CustomQuery, Deps, DepsMut, Env, Event, MessageInfo, + ensure, ensure_eq, to_json_binary, Addr, CustomQuery, Deps, DepsMut, Env, Event, MessageInfo, QueryResponse, Response, StdError, StdResult, Storage, }; use cw_storage_plus::Item; @@ -123,10 +123,10 @@ pub fn handle_query( msg: OwnableQueryMsg, ) -> StdResult { match msg { - OwnableQueryMsg::GetOwner {} => to_binary(&OwnerResponse { + OwnableQueryMsg::GetOwner {} => to_json_binary(&OwnerResponse { owner: get_owner(deps.storage)?, }), - OwnableQueryMsg::GetPendingOwner {} => to_binary(&PendingOwnerResponse { + OwnableQueryMsg::GetPendingOwner {} => to_json_binary(&PendingOwnerResponse { pending_owner: get_pending_owner(deps.storage)?, }), } diff --git a/packages/ownable/src/test.rs b/packages/ownable/src/test.rs index af74b678..e75c7561 100644 --- a/packages/ownable/src/test.rs +++ b/packages/ownable/src/test.rs @@ -1,5 +1,5 @@ use cosmwasm_std::{ - from_binary, + from_json, testing::{mock_dependencies, mock_env, mock_info, MockApi, MockQuerier, MockStorage}, Addr, CustomQuery, Empty, Env, MessageInfo, OwnedDeps, Response, StdError, StdResult, }; @@ -27,7 +27,7 @@ where } fn query(&self, msg: OwnableQueryMsg) -> StdResult { - from_binary(&handle_query(self.deps.as_ref(), self.env.clone(), msg)?) + from_json(handle_query(self.deps.as_ref(), self.env.clone(), msg)?) } pub fn init(&mut self, sender: &Addr, next_owner: &Addr) -> StdResult { diff --git a/packages/pausable/src/lib.rs b/packages/pausable/src/lib.rs index 99cd56c7..0c95cd4e 100644 --- a/packages/pausable/src/lib.rs +++ b/packages/pausable/src/lib.rs @@ -2,7 +2,7 @@ mod test; use cosmwasm_std::{ - ensure, ensure_eq, to_binary, Addr, CustomQuery, Deps, DepsMut, Env, Event, MessageInfo, + ensure, ensure_eq, to_json_binary, Addr, CustomQuery, Deps, DepsMut, Env, Event, MessageInfo, QueryResponse, Response, StdError, StdResult, Storage, }; use cw_storage_plus::Item; @@ -69,7 +69,7 @@ pub fn handle_query( msg: PausableQueryMsg, ) -> StdResult { match msg { - PausableQueryMsg::PauseInfo {} => to_binary(&PauseInfoResponse { + PausableQueryMsg::PauseInfo {} => to_json_binary(&PauseInfoResponse { paused: get_pause_info(deps.storage)?, }), } diff --git a/packages/pausable/src/test.rs b/packages/pausable/src/test.rs index 84e0f545..17fa189d 100644 --- a/packages/pausable/src/test.rs +++ b/packages/pausable/src/test.rs @@ -1,5 +1,5 @@ use cosmwasm_std::{ - from_binary, + from_json, testing::{mock_dependencies, mock_env, mock_info, MockApi, MockQuerier, MockStorage}, Addr, CustomQuery, Empty, Env, MessageInfo, OwnedDeps, Response, StdError, StdResult, }; @@ -27,7 +27,7 @@ where } fn query(&self, msg: PausableQueryMsg) -> StdResult { - from_binary(&handle_query(self.deps.as_ref(), self.env.clone(), msg)?) + from_json(handle_query(self.deps.as_ref(), self.env.clone(), msg)?) } pub fn set_owner(&mut self, owner: &Addr) -> StdResult<()> { diff --git a/packages/router/src/lib.rs b/packages/router/src/lib.rs index 2d5c9c57..b11de618 100644 --- a/packages/router/src/lib.rs +++ b/packages/router/src/lib.rs @@ -2,8 +2,8 @@ mod test; use cosmwasm_std::{ - ensure_eq, to_binary, Addr, CustomQuery, Deps, DepsMut, Env, Event, MessageInfo, QueryResponse, - Response, StdError, StdResult, Storage, + ensure_eq, to_json_binary, Addr, CustomQuery, Deps, DepsMut, Env, Event, MessageInfo, + QueryResponse, Response, StdError, StdResult, Storage, }; use cw_storage_plus::Map; use hpl_interface::{ @@ -116,17 +116,17 @@ where T: Serialize + DeserializeOwned + Clone + Eq, { match msg { - RouterQuery::Domains {} => to_binary(&DomainsResponse { + RouterQuery::Domains {} => to_json_binary(&DomainsResponse { domains: get_domains::(deps.storage)?, }), - RouterQuery::GetRoute { domain } => to_binary(&RouteResponse:: { + RouterQuery::GetRoute { domain } => to_json_binary(&RouteResponse:: { route: get_route(deps.storage, domain)?, }), RouterQuery::ListRoutes { offset, limit, order, - } => to_binary(&RoutesResponse:: { + } => to_json_binary(&RoutesResponse:: { routes: get_routes(deps.storage, offset, limit, order)?, }), RouterQuery::Placeholder(_) => unreachable!(), diff --git a/packages/router/src/test.rs b/packages/router/src/test.rs index 0557112b..48b3d079 100644 --- a/packages/router/src/test.rs +++ b/packages/router/src/test.rs @@ -1,7 +1,7 @@ use std::marker::PhantomData; use cosmwasm_std::{ - from_binary, + from_json, testing::{mock_dependencies, mock_env, mock_info, MockApi, MockQuerier, MockStorage}, Addr, Binary, Empty, Env, MessageInfo, OwnedDeps, Response, StdResult, }; @@ -61,7 +61,7 @@ where } fn handle_query(&self, msg: RouterQuery) -> StdResult { - from_binary(&handle_query(self.deps.as_ref(), self.env.clone(), msg)?) + from_json(handle_query(self.deps.as_ref(), self.env.clone(), msg)?) } pub fn query_domains(&self) -> StdResult { @@ -94,7 +94,7 @@ where Self { deps: mock_dependencies(), env: mock_env(), - _marker: PhantomData::::default(), + _marker: PhantomData::, } } } diff --git a/scripts/package.json b/scripts/package.json index 8b6796ec..d7699162 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -19,7 +19,7 @@ "@cosmjs/proto-signing": "^0.31.0", "@cosmjs/stargate": "^0.31.0", "@cosmjs/tendermint-rpc": "0.31.0", - "axios": "^1.4.0", + "axios": "^1.6.2", "colors": "^1.4.0", "commander": "^11.1.0", "inversify": "^6.0.1", @@ -34,4 +34,4 @@ "tsx": "^3.13.0", "typescript": "^5.1.6" } -} +} \ No newline at end of file diff --git a/scripts/pnpm-lock.yaml b/scripts/pnpm-lock.yaml index 3ef0d902..66ec77a8 100644 --- a/scripts/pnpm-lock.yaml +++ b/scripts/pnpm-lock.yaml @@ -30,8 +30,8 @@ dependencies: specifier: 0.31.0 version: 0.31.0 axios: - specifier: ^1.4.0 - version: 1.4.0 + specifier: ^1.6.2 + version: 1.6.2 colors: specifier: ^1.4.0 version: 1.4.0 @@ -74,7 +74,7 @@ packages: resolution: {integrity: sha512-wB6uo+3A50m0sW/EWcU64xpV/8wShZ6bMTa7pF8eYsTrSkQA7oLUIJcs/wb8g4y2Oyq701BaGiO6n/ak5WXO1w==} dependencies: '@noble/hashes': 1.3.1 - protobufjs: 6.11.3 + protobufjs: 6.11.4 dev: false /@cosmjs/amino@0.25.6: @@ -275,7 +275,7 @@ packages: '@cosmjs/utils': 0.31.0 cosmjs-types: 0.8.0 long: 4.0.0 - protobufjs: 6.11.3 + protobufjs: 6.11.4 xstream: 11.14.0 transitivePeerDependencies: - bufferutil @@ -660,8 +660,8 @@ packages: - debug dev: false - /axios@1.4.0: - resolution: {integrity: sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==} + /axios@1.6.2: + resolution: {integrity: sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==} dependencies: follow-redirects: 1.15.2 form-data: 4.0.0 @@ -721,7 +721,7 @@ packages: resolution: {integrity: sha512-Q2Mj95Fl0PYMWEhA2LuGEIhipF7mQwd9gTQ85DdP9jjjopeoGaDxvmPa5nakNzsq7FnO1DMTatXTAx6bxMH7Lg==} dependencies: long: 4.0.0 - protobufjs: 6.11.3 + protobufjs: 6.11.4 dev: false /create-require@1.1.1: @@ -999,8 +999,8 @@ packages: resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} dev: false - /protobufjs@6.11.3: - resolution: {integrity: sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==} + /protobufjs@6.11.4: + resolution: {integrity: sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==} hasBin: true requiresBuild: true dependencies: