Skip to content

Commit

Permalink
simple fee hook (#6)
Browse files Browse the repository at this point in the history
* Implement simple fee hook

* Address pr comments

* Fix unit tests

* Make set fee only owner

* Implement remaining unit tests

* Fix merkle integration test use

---------

Co-authored-by: nambrot <[email protected]>
Co-authored-by: ByeongSu Hong <[email protected]>
  • Loading branch information
3 people authored Jan 19, 2024
1 parent 2cd2bfc commit 05c34f7
Show file tree
Hide file tree
Showing 10 changed files with 430 additions and 70 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ jobs:
uses: taiki-e/install-action@cargo-llvm-cov

- name: Generate code coverage
run: cargo +nightly llvm-cov --all-features --workspace --exclude hpl-tests --codecov --output-path codecov.json
run: cargo llvm-cov --workspace --exclude hpl-tests --codecov --output-path codecov.json

- name: Upload to codecov.io
uses: codecov/codecov-action@v3
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ hpl-mailbox = { path = "./contracts/core/mailbox" }
hpl-validator-announce = { path = "./contracts/core/va" }

hpl-hook-merkle = { path = "./contracts/hooks/merkle" }
hpl-hook-fee = { path = "./contracts/hooks/fee" }
hpl-hook-pausable = { path = "./contracts/hooks/pausable" }
hpl-hook-routing = { path = "./contracts/hooks/routing" }
hpl-hook-routing-custom = { path = "./contracts/hooks/routing-custom" }
Expand Down
74 changes: 24 additions & 50 deletions contracts/core/mailbox/src/execute.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use cosmwasm_std::{
ensure, ensure_eq, to_json_binary, wasm_execute, BankMsg, Coins, DepsMut, Env, HexBinary,
MessageInfo, Response, StdResult,
ensure, ensure_eq, to_json_binary, wasm_execute, Coin, Coins, DepsMut, Env,
HexBinary, MessageInfo, Response,
};
use cw_utils::PaymentError::MissingDenom;
use hpl_interface::{
core::{
mailbox::{DispatchMsg, DispatchResponse},
HandleMsg,
},
hook::{self, post_dispatch},
hook::{post_dispatch, quote_dispatch},
ism,
types::Message,
};
Expand Down Expand Up @@ -107,74 +108,47 @@ pub fn dispatch(
}
);

// calculate gas
let default_hook = config.get_default_hook();
let required_hook = config.get_required_hook();

// build hyperlane message
let msg =
dispatch_msg
.clone()
.to_msg(MAILBOX_VERSION, nonce, config.local_domain, &info.sender)?;
let msg_id = msg.id();
let metadata = dispatch_msg.clone().metadata.unwrap_or_default();
let hook = dispatch_msg.get_hook_addr(deps.api, config.get_default_hook())?;

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(),
)?
.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)
},
)?;
for fund in info.funds {
total_fee.sub(fund)?;
}
// assert gas received satisfies required gas
let required_hook = config.get_required_hook();
let required_hook_fees: Vec<Coin> =
quote_dispatch(&deps.querier, &required_hook, metadata.clone(), msg.clone())?.fees;

// interaction
let hook = dispatch_msg.get_hook_addr(deps.api, config.get_default_hook())?;
let hook_metadata = dispatch_msg.metadata.unwrap_or_default();
let mut funds = Coins::try_from(info.funds)?;
for coin in required_hook_fees.iter() {
if let Err(_) = funds.sub(coin.clone()) {
return Err(ContractError::Payment(MissingDenom(coin.denom.clone())));
}
}

// effects
// commit to message
let msg_id = msg.id();
NONCE.save(deps.storage, &(nonce + 1))?;
LATEST_DISPATCHED_ID.save(deps.storage, &msg_id.to_vec())?;

// make message
// build post dispatch calls
let post_dispatch_msgs = vec![
post_dispatch(
required_hook,
hook_metadata.clone(),
metadata.clone(),
msg.clone(),
Some(required_fee),
Some(required_hook_fees),
)?,
post_dispatch(hook, hook_metadata, msg.clone(), Some(base_fee))?,
post_dispatch(hook, metadata, msg.clone(), Some(funds.to_vec()))?,
];

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_json_binary(&DispatchResponse { message_id: msg_id })?)
.add_messages(post_dispatch_msgs)
.add_message(refund_msg))
.add_messages(post_dispatch_msgs))
}

pub fn process(
Expand Down
42 changes: 42 additions & 0 deletions contracts/hooks/fee/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
[package]
name = "hpl-hook-fee"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
homepage.workspace = true
documentation.workspace = true
keywords.workspace = true

[lib]
crate-type = ["cdylib", "rlib"]

[features]
# for more explicit tests, cargo test --features=backtraces
backtraces = ["cosmwasm-std/backtraces"]
# use library feature to disable all instantiate/execute/query exports
library = []

[dependencies]
cosmwasm-std.workspace = true
cosmwasm-storage.workspace = true
cosmwasm-schema.workspace = true

cw-storage-plus.workspace = true
cw2.workspace = true
cw-utils.workspace = true

schemars.workspace = true
serde-json-wasm.workspace = true

thiserror.workspace = true

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

[dev-dependencies]
rstest.workspace = true
ibcx-test-utils.workspace = true

anyhow.workspace = true
Loading

0 comments on commit 05c34f7

Please sign in to comment.