Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat: schema generation (wip) #52

Open
wants to merge 33 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
66c39c6
some scripts (#50)
byeongsu-hong Oct 20, 2023
f4027eb
fix: coverage ci (#49)
byeongsu-hong Oct 20, 2023
9cf9ae9
Revert "revert: aggregate"
byeongsu-hong Oct 20, 2023
b7995ad
test(cw20): cw20 init
byeongsu-hong Oct 20, 2023
ee6edd9
test(warp): unit test for cw20
byeongsu-hong Oct 20, 2023
8f2a4f6
test(warp): add query test for cw20
byeongsu-hong Oct 21, 2023
6007674
test(warp): remove existing tests for native
byeongsu-hong Oct 21, 2023
8e158db
feat(warp): add ownable message
byeongsu-hong Oct 21, 2023
ba17746
wip
byeongsu-hong Oct 21, 2023
a37ab9a
test(warp): unit test for native denom
byeongsu-hong Oct 22, 2023
a9a1e8f
test: use u32 directly
byeongsu-hong Oct 22, 2023
e5d60f0
fix!(ism): use parsed u32 merkle index
byeongsu-hong Oct 22, 2023
0a7e408
test: modularize
byeongsu-hong Oct 22, 2023
817c7d7
test: add empty warp
byeongsu-hong Oct 22, 2023
e005671
test: runnable mailbox
byeongsu-hong Oct 22, 2023
f5feba2
test: warp placeholder
byeongsu-hong Oct 22, 2023
8bac2ac
test: deployable
byeongsu-hong Oct 22, 2023
2777239
fix(warp): inject minter to cw20
byeongsu-hong Oct 22, 2023
41a442c
fix(warp): use consistant event name
byeongsu-hong Oct 22, 2023
2e6b36e
test: warp cw20 / native denom creation
byeongsu-hong Oct 22, 2023
aaed6f9
chore: prune
byeongsu-hong Oct 22, 2023
70d8d7c
feat: aggregation
byeongsu-hong Oct 23, 2023
e7c515b
schema
byeongsu-hong Oct 23, 2023
a23afda
fix: evm equivalence
byeongsu-hong Oct 23, 2023
6ea8a39
fix(hook): pass entire metadata
byeongsu-hong Oct 23, 2023
ecaaed5
fix: aggregate works
byeongsu-hong Oct 23, 2023
4432355
chore: remove debugger
byeongsu-hong Oct 23, 2023
1232151
fix: tests
byeongsu-hong Oct 23, 2023
374f958
clippy
byeongsu-hong Oct 23, 2023
40dd0ee
use aggregate ism on integration test
byeongsu-hong Oct 23, 2023
24b2b2e
feat: schema generation - not working
byeongsu-hong Oct 17, 2023
865fccf
feat: add aggregate hook / ism schema
byeongsu-hong Oct 23, 2023
aac5dda
aggregations
byeongsu-hong Oct 23, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 17 additions & 66 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,50 +9,14 @@ on:
- "main"

jobs:
deps:
name: dependencies
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 1

- name: Cache dependencies
uses: actions/cache@v3
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}

- name: Load toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
targets: wasm32-unknown-unknown

- run: cargo fetch --verbose
- run: cargo build
- run: cargo wasm

unit-test:
strategy:
fail-fast: true

needs: deps

name: unit-test
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 1
- uses: actions/checkout@v4

- name: Cache dependencies
uses: actions/cache@v3
Expand All @@ -65,45 +29,32 @@ jobs:
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}

- name: Load toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
targets: wasm32-unknown-unknown
- name: Install Rust
run: rustup update stable

- name: Install target
run: rustup target add wasm32-unknown-unknown

- run: cargo test --workspace --exclude hpl-tests

coverage:
needs: deps

name: coverage
runs-on: ubuntu-latest
container:
image: xd009642/tarpaulin:develop-nightly
options: --security-opt seccomp=unconfined
env:
CARGO_TERM_COLOR: always
steps:
- name: Checkout repository
uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Cache dependencies
uses: actions/cache@v3
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Install Rust
run: rustup update nightly

- name: Install target
run: rustup target add wasm32-unknown-unknown

- run: rustup target add wasm32-unknown-unknown
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov

- name: Generate code coverage
run: |
cargo +nightly tarpaulin \
--verbose \
--workspace --exclude hpl-tests \
--timeout 120 --out Xml
run: cargo llvm-cov --all-features --workspace --exclude hpl-tests --codecov --output-path codecov.json

- name: Upload to codecov.io
uses: codecov/codecov-action@v3
Expand Down
42 changes: 42 additions & 0 deletions contracts/hooks/aggregate/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
[package]
name = "hpl-hook-aggregate"
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
16 changes: 16 additions & 0 deletions contracts/hooks/aggregate/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use cosmwasm_std::StdError;

#[derive(thiserror::Error, Debug, PartialEq)]
pub enum ContractError {
#[error("{0}")]
Std(#[from] StdError),

#[error("{0}")]
PaymentError(#[from] cw_utils::PaymentError),

#[error("unauthorized")]
Unauthorized {},

#[error("hook paused")]
Paused {},
}
186 changes: 186 additions & 0 deletions contracts/hooks/aggregate/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
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,
QueryResponse, Response, StdResult,
};
use cw_storage_plus::Item;
use error::ContractError;
use hpl_interface::{
hook::{
aggregate::{AggregateHookQueryMsg, ExecuteMsg, HooksResponse, InstantiateMsg, QueryMsg},
post_dispatch, HookQueryMsg, MailboxResponse, PostDispatchMsg, QuoteDispatchMsg,
QuoteDispatchResponse,
},
to_binary,
types::Message,
};
use hpl_ownable::get_owner;

// version info for migration info
pub const CONTRACT_NAME: &str = env!("CARGO_PKG_NAME");
pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");

pub const HOOKS_KEY: &str = "hooks";
pub const HOOKS: Item<Vec<Addr>> = Item::new(HOOKS_KEY);

fn new_event(name: &str) -> Event {
Event::new(format!("hpl_hook_aggregate::{}", name))
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
deps: DepsMut,
_env: Env,
info: MessageInfo,
msg: InstantiateMsg,
) -> Result<Response, ContractError> {
cw2::set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;

let owner = deps.api.addr_validate(&msg.owner)?;
let hooks = msg
.hooks
.iter()
.map(|v| deps.api.addr_validate(v))
.collect::<StdResult<_>>()?;

hpl_ownable::initialize(deps.storage, &owner)?;

HOOKS.save(deps.storage, &hooks)?;

Ok(Response::new().add_event(
new_event("initialize")
.add_attribute("sender", info.sender)
.add_attribute("owner", owner)
.add_attribute("hooks", msg.hooks.join(",")),
))
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
deps: DepsMut,
env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> Result<Response, ContractError> {
match msg {
ExecuteMsg::Ownable(msg) => Ok(hpl_ownable::handle(deps, env, info, msg)?),
ExecuteMsg::PostDispatch(PostDispatchMsg { message, metadata }) => {
// aggregate it
let hooks = HOOKS.load(deps.storage)?;

let msgs: Vec<CosmosMsg> = hooks
.into_iter()
.map(|v| {
let quote = hpl_interface::hook::quote_dispatch(
&deps.querier,
&v,
metadata.clone(),
message.clone(),
)?;
let msg = post_dispatch(
v,
metadata.clone(),
message.clone(),
quote.gas_amount.map(|v| vec![v]),
)?
.into();

Ok(msg)
})
.collect::<StdResult<_>>()?;

let decoded_msg: Message = message.into();

// do nothing
Ok(Response::new().add_messages(msgs).add_event(
new_event("post_dispatch").add_attribute("message_id", decoded_msg.id().to_hex()),
))
}
ExecuteMsg::SetHooks { hooks } => {
ensure_eq!(
get_owner(deps.storage)?,
info.sender,
ContractError::Unauthorized {}
);

let parsed_hooks = hooks
.iter()
.map(|v| deps.api.addr_validate(v))
.collect::<StdResult<_>>()?;

HOOKS.save(deps.storage, &parsed_hooks)?;

Ok(Response::new().add_event(
new_event("set_hooks")
.add_attribute("sender", info.sender)
.add_attribute("hooks", hooks.join(",")),
))
}
}
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result<QueryResponse, ContractError> {
match msg {
QueryMsg::Ownable(msg) => Ok(hpl_ownable::handle_query(deps, env, msg)?),
QueryMsg::Hook(msg) => match msg {
HookQueryMsg::Mailbox {} => to_binary(get_mailbox(deps)),
HookQueryMsg::QuoteDispatch(QuoteDispatchMsg { metadata, message }) => {
to_binary(quote_dispatch(deps, metadata, message))
}
},
QueryMsg::AggregateHook(msg) => match msg {
AggregateHookQueryMsg::Hooks {} => to_binary(get_hooks(deps)),
},
}
}

fn get_mailbox(_deps: Deps) -> Result<MailboxResponse, ContractError> {
Ok(MailboxResponse {
mailbox: "unrestricted".to_string(),
})
}

fn quote_dispatch(
deps: Deps,
metadata: HexBinary,
message: HexBinary,
) -> Result<QuoteDispatchResponse, ContractError> {
let hooks = HOOKS.load(deps.storage)?;

let mut total: Option<Coin> = 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),
};
}
}

Ok(QuoteDispatchResponse { gas_amount: total })
}

fn get_hooks(deps: Deps) -> Result<HooksResponse, ContractError> {
Ok(HooksResponse {
hooks: HOOKS
.load(deps.storage)?
.into_iter()
.map(|v| v.into())
.collect(),
})
}
4 changes: 1 addition & 3 deletions contracts/igps/core/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use hpl_interface::igp::core::{ExecuteMsg, IgpQueryMsg, InstantiateMsg, QueryMsg
use hpl_interface::igp::oracle::IgpGasOracleQueryMsg;
use hpl_interface::to_binary;

use crate::{ContractError, BENEFICIARY, CONTRACT_NAME, CONTRACT_VERSION, GAS_TOKEN, HRP, MAILBOX};
use crate::{ContractError, BENEFICIARY, CONTRACT_NAME, CONTRACT_VERSION, GAS_TOKEN, HRP};

fn new_event(name: &str) -> Event {
Event::new(format!("hpl_igp_core::{}", name))
Expand All @@ -23,13 +23,11 @@ pub fn instantiate(
cw2::set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;

let owner = deps.api.addr_validate(&msg.owner)?;
let mailbox = deps.api.addr_validate(&msg.mailbox)?;
let beneficiary = deps.api.addr_validate(&msg.beneficiary)?;

hpl_ownable::initialize(deps.storage, &owner)?;

BENEFICIARY.save(deps.storage, &beneficiary)?;
MAILBOX.save(deps.storage, &mailbox)?;

GAS_TOKEN.save(deps.storage, &msg.gas_token)?;
HRP.save(deps.storage, &msg.hrp)?;
Expand Down
Loading