Skip to content

Commit

Permalink
impl unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki1frsh committed Aug 16, 2023
1 parent f6ad804 commit 1cfbca8
Show file tree
Hide file tree
Showing 4 changed files with 289 additions and 2 deletions.
11 changes: 9 additions & 2 deletions contracts/ibc-denom-resolver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,20 @@ name = "ibc-denom-resolver"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib", "rlib"]

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

[dependencies]
cosmwasm-std = { version = "1.3.1", features = ["stargate"] }
cosmwasm-schema = "1.3.1"
thiserror = "1.0"
cw-storage-plus = "1.1.0"
cw-utils = "1.0.1"
serde-json-wasm = "0.5.1"
serde-json-wasm = "1.0.0"
packet-forward = { path = "../packet-forward" }
77 changes: 77 additions & 0 deletions contracts/ibc-denom-resolver/tests/helpers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use std::time::Duration;

use cosmwasm_schema::serde;

use ibc_denom_resolver::error::ContractError;
use ibc_denom_resolver::msgs::{InstantiateMsg, QueryMsg, UpdateConfigMsg};
use ibc_denom_resolver::execute::update_config::*;
use ibc_denom_resolver::contract::instantiate;
use ibc_denom_resolver::contract::query;

use cosmwasm_std::testing::{
mock_dependencies, mock_env, mock_info, MockApi, MockQuerier, MockStorage,
};
use cosmwasm_std::{
from_binary, Decimal, Deps, OwnedDeps, Uint128,
};

use ibc_denom_resolver::types::{FeeConfig, Route, Destination, };

pub const DEFAULT_TIMEOUT: u64 = 3600; // 1 hour,
pub const CONTRACT_PORT: &str = "ibc:wasm1234567890abcdef";

pub fn setup() -> OwnedDeps<MockStorage, MockApi, MockQuerier> {
let mut deps = mock_dependencies();

// instantiate an empty contract
let routes = vec![
// Cosmos Hub
Route {
src_port: "transfer".to_string(),
src_channel: "channel-0".to_string(),
destination: Destination::PacketForwardContract("osmo1contractaddress".to_string()),
},
// Osmosis
Route {
src_port: "transfer".to_string(),
src_channel: "channel-1".to_string(),
destination: Destination::PacketForwardMiddleware,
},
// Terra
Route {
src_port: "transfer".to_string(),
src_channel: "channel-2".to_string(),
destination: Destination::PacketForwardContract(
"ununifi1contractaddress".to_string(),
),
},
// UnUniFi
Route {
src_port: "transfer".to_string(),
src_channel: "channel-3".to_string(),
destination: Destination::Terminal,
},
// Cosmos Hub
];
let instantiate_msg = InstantiateMsg {
denom: String::from("uguu"), // random leteral
first_forward_contract: String::from("ununifi14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sm5z28e"), // random address
routes: routes,
timeout: Duration::from_secs(DEFAULT_TIMEOUT),
treasury: String::from("ununifi1f5vsnrwe7h9dhhyxkwr4yah5u0cke69h03latc"), // totally random. DONT use on mainnet
fee: FeeConfig {
commission_rate: Decimal::percent(0),
min: Uint128::zero(),
max: Uint128::zero(),
},
};
let info = mock_info(&String::from("anyone"), &[]);
let res = instantiate(deps.as_mut(), mock_env(), info, instantiate_msg).unwrap();
assert_eq!(0, res.messages.len());

deps
}

pub fn th_query<T: serde::de::DeserializeOwned>(deps: Deps, msg: QueryMsg) -> T {
from_binary(&query(deps, mock_env(), msg).unwrap()).unwrap()
}
108 changes: 108 additions & 0 deletions contracts/ibc-denom-resolver/tests/test_swap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
use std::time::Duration;

use cosmwasm_std::{Decimal, Uint128, Coin, CosmosMsg, BankMsg, SubMsg};
use cosmwasm_std::testing::{mock_env, mock_info};
use cw_utils::one_coin;
use helpers::th_query;
use ibc_denom_resolver::error::ContractError;
use ibc_denom_resolver::execute::swap::execute_swap;
use ibc_denom_resolver::execute::update_config::execute_update_config;
use ibc_denom_resolver::msgs::{QueryMsg, UpdateConfigMsg, SwapMsg};
use ibc_denom_resolver::types::{Config, FeeConfig};

use crate::helpers::setup;

mod helpers;

#[test]
pub fn swap() {
let mut deps = setup();
let sender = "anyone";

// Failure case due to the different number of the routes and recerivers
{
let swap_msg = SwapMsg {
receivers: vec![],
};
let info = mock_info(sender, &[Coin{denom: String::from("fail"), amount: Uint128::one()}]);

let err = execute_swap(
deps.as_mut(),
mock_env(),
info.clone(),
one_coin(&info).unwrap(),
swap_msg,
).unwrap_err();

assert_eq!(ContractError::InvalidReceiversLength, err)
}

let receivers = vec![
"osmo1xv9tklw7d82sezh9haa573wufgy59vmwe6xxe5".to_string(),
"terra1xv9tklw7d82sezh9haa573wufgy59vmwe6xxe5".to_string(),
"ununifi1xv9tklw7d82sezh9haa573wufgy59vmwe6xxe5".to_string(),
"cosmos1xv9tklw7d82sezh9haa573wufgy59vmwe6xxe5".to_string(),
];

// Success case and fee rate is 0%
{
let swap_msg = SwapMsg {
receivers: receivers.clone(),
};
let info = mock_info(sender, &[Coin{denom: String::from("uguu"), amount: Uint128::one()}]);

let res = execute_swap(
deps.as_mut(),
mock_env(),
info.clone(),
one_coin(&info).unwrap(),
swap_msg,
).unwrap();

assert_eq!(1, res.messages.len());
}

// Success case and fee rate is not 0%
{
// update config
let new_fee_conf = FeeConfig {
commission_rate: Decimal::one(),
min: Uint128::one(),
max: Uint128::one().checked_add(Uint128::one()).unwrap(),
};
execute_update_config(
deps.as_mut(),
mock_env(),
mock_info(sender, &[]),
UpdateConfigMsg {
owner: None,
treasury: None,
fee: Some(new_fee_conf.clone()),
timeout: None,
},
)
.unwrap();

let swap_msg = SwapMsg {
receivers: receivers.clone(),
};
let info = mock_info(sender, &[Coin{denom: String::from("uguu"), amount: Uint128::from(100 as u32)}]);

let res = execute_swap(
deps.as_mut(),
mock_env(),
info.clone(),
one_coin(&info).unwrap(),
swap_msg,
).unwrap();

assert_eq!(2, res.messages.len());
let config: Config = th_query(deps.as_ref(), QueryMsg::Config {});
let send_msg = SubMsg::new(CosmosMsg::Bank(BankMsg::Send {
to_address: config.treasury.to_string(),
amount: vec![Coin::new(2 as u128, config.denom.clone())],
}));
assert_eq!(res.messages[0], send_msg)
}

}
95 changes: 95 additions & 0 deletions contracts/ibc-denom-resolver/tests/test_update_config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use std::time::Duration;

use cosmwasm_std::{Decimal, Uint128};
use cosmwasm_std::testing::{mock_env, mock_info};
use helpers::th_query;
use ibc_denom_resolver::error::ContractError;
use ibc_denom_resolver::msgs::{QueryMsg, UpdateConfigMsg};
use ibc_denom_resolver::execute::update_config::execute_update_config;
use ibc_denom_resolver::types::{Config, FeeConfig};

use crate::helpers::setup;

mod helpers;

#[test]
fn initialized_state() {
let deps = setup();

let config: Config = th_query(deps.as_ref(), QueryMsg::Config {});
assert_eq!(Decimal::zero(), config.fee.commission_rate);
assert_eq!("uguu", config.denom);
}

#[test]
fn update_config() {
let mut deps = setup();
let sender = "anyone";

// Success case only for the change of owner
{
// Change with other values for further tests
execute_update_config(
deps.as_mut(),
mock_env(),
mock_info(sender, &[]),
UpdateConfigMsg {
owner: Some(String::from("ununifi1v2k8kt24uqes5l5js772eamzahpg53p38jytlj")),
treasury: None,
fee: None,
timeout: None,
},
)
.unwrap();

let config: Config = th_query(deps.as_ref(), QueryMsg::Config {});

assert_eq!("ununifi1v2k8kt24uqes5l5js772eamzahpg53p38jytlj", config.owner);
}

// Success case for the changes of all params
{
// Change with other values for further tests
let new_fee_conf = FeeConfig {
commission_rate: Decimal::one(),
min: Uint128::one(),
max: Uint128::one().checked_add(Uint128::one()).unwrap(),
};
execute_update_config(
deps.as_mut(),
mock_env(),
mock_info("ununifi1v2k8kt24uqes5l5js772eamzahpg53p38jytlj", &[]),
UpdateConfigMsg {
owner: Some(String::from("ununifi13vs27vvzhdljpexf5zc2zs5vs66yywq8gu8g0x")),
treasury: Some(String::from("ununifi13e0tws93sujjg40052a5jew4933saa9qksn7jn")),
fee: Some(new_fee_conf.clone()),
timeout: Some(Duration::from_secs(7200 as u64)),
},
)
.unwrap();

let config: Config = th_query(deps.as_ref(), QueryMsg::Config {});

assert_eq!("ununifi13vs27vvzhdljpexf5zc2zs5vs66yywq8gu8g0x", config.owner);
assert_eq!("ununifi13e0tws93sujjg40052a5jew4933saa9qksn7jn", config.treasury);
assert_eq!(new_fee_conf, config.fee);
assert_eq!(Duration::from_secs(7200 as u64), config.timeout);
}

{
let bad_sender = "bad_sender";
let err = execute_update_config(
deps.as_mut(),
mock_env(),
mock_info(bad_sender, &[]),
UpdateConfigMsg {
owner: None,
treasury: None,
fee: None,
timeout: None,
},
)
.unwrap_err();
assert_eq!(ContractError::Unauthorized {}, err);
}
}

0 comments on commit 1cfbca8

Please sign in to comment.