Skip to content

Commit

Permalink
Merge pull request #81 from many-things/develop
Browse files Browse the repository at this point in the history
v0.0.6-rc7
  • Loading branch information
byeongsu-hong authored Jan 4, 2024
2 parents 37fea49 + caf8e45 commit b26a6f5
Show file tree
Hide file tree
Showing 65 changed files with 765 additions and 478 deletions.
1 change: 0 additions & 1 deletion .beaker/state.json

This file was deleted.

26 changes: 13 additions & 13 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ panic = "abort"
rpath = false

[workspace.package]
version = "0.0.6-rc6"
version = "0.0.6-rc7"
authors = [
"byeongsu-hong <[email protected]>",
"Eric <[email protected]>",
Expand All @@ -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" }
Expand Down Expand Up @@ -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"] }
Expand Down
1 change: 0 additions & 1 deletion contracts/core/mailbox/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ bech32.workspace = true
thiserror.workspace = true

hpl-ownable.workspace = true
hpl-pausable.workspace = true
hpl-interface.workspace = true

[dev-dependencies]
Expand Down
16 changes: 12 additions & 4 deletions contracts/core/mailbox/src/contract.rs
Original file line number Diff line number Diff line change
@@ -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},
Expand All @@ -23,6 +23,12 @@ pub fn instantiate(
) -> Result<Response, ContractError> {
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,
Expand All @@ -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)))
}
Expand Down Expand Up @@ -71,7 +77,9 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result<QueryResponse, Contr
match msg {
QueryMsg::Ownable(msg) => 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)),
Expand Down
20 changes: 14 additions & 6 deletions contracts/core/mailbox/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use cosmwasm_std::{Coin, StdError};
use cosmwasm_std::StdError;
use thiserror::Error;

#[derive(Error, Debug, PartialEq)]
Expand All @@ -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 },

Expand All @@ -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(),
}
}
}
133 changes: 54 additions & 79 deletions contracts/core/mailbox/src/execute.rs
Original file line number Diff line number Diff line change
@@ -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,
};
Expand All @@ -24,53 +23,6 @@ use crate::{
ContractError, MAILBOX_VERSION,
};

fn get_required_value(
deps: Deps,
info: &MessageInfo,
hook: impl Into<String>,
metadata: HexBinary,
msg_body: HexBinary,
) -> Result<(Option<Coin>, Option<Coin>), 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,
Expand Down Expand Up @@ -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 =
Expand All @@ -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())?;
Expand All @@ -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(
Expand Down Expand Up @@ -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 {}
Expand Down Expand Up @@ -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::{
Expand All @@ -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"),
};

Expand All @@ -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))
}

Expand Down Expand Up @@ -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::<ism::ExpectedIsmSpecifierQueryMsg>(msg)
{
if let Ok(req) = cosmwasm_std::from_json::<ism::ExpectedIsmSpecifierQueryMsg>(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(),
Expand All @@ -511,13 +486,13 @@ mod tests {
}
}

if let Ok(req) = cosmwasm_std::from_binary::<ism::ExpectedIsmQueryMsg>(msg) {
if let Ok(req) = cosmwasm_std::from_json::<ism::ExpectedIsmQueryMsg>(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(),
Expand Down
Loading

0 comments on commit b26a6f5

Please sign in to comment.