diff --git a/contracts/adapters/swap/drop/src/contract.rs b/contracts/adapters/swap/drop/src/contract.rs index 7bf15331..5482d502 100644 --- a/contracts/adapters/swap/drop/src/contract.rs +++ b/contracts/adapters/swap/drop/src/contract.rs @@ -207,7 +207,7 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> ContractResult { match msg { QueryMsg::SimulateSwapExactAssetIn { asset_in, .. } => { let asset_out_denom = - get_opposite_denom(asset_in.denom(), &remote_denom, &bonded_denom); + get_opposite_denom_in(asset_in.denom(), &remote_denom, &bonded_denom)?; let exchange_rate = get_exchange_rate(deps)?; @@ -218,7 +218,7 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> ContractResult { } QueryMsg::SimulateSwapExactAssetOut { asset_out, .. } => { let asset_in_denom = - get_opposite_denom(asset_out.denom(), &remote_denom, &bonded_denom); + get_opposite_denom_out(asset_out.denom(), &remote_denom, &bonded_denom)?; let exchange_rate = get_exchange_rate(deps)?; @@ -233,7 +233,7 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> ContractResult { .. } => { let asset_out_denom = - get_opposite_denom(asset_in.denom(), &remote_denom, &bonded_denom); + get_opposite_denom_in(asset_in.denom(), &remote_denom, &bonded_denom)?; let exchange_rate = get_exchange_rate(deps)?; @@ -257,7 +257,7 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> ContractResult { .. } => { let asset_in_denom = - get_opposite_denom(asset_out.denom(), &remote_denom, &bonded_denom); + get_opposite_denom_out(asset_out.denom(), &remote_denom, &bonded_denom)?; let exchange_rate = get_exchange_rate(deps)?; @@ -277,7 +277,7 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> ContractResult { } QueryMsg::SimulateSmartSwapExactAssetIn { asset_in, .. } => { let asset_out_denom = - get_opposite_denom(asset_in.denom(), &remote_denom, &bonded_denom); + get_opposite_denom_in(asset_in.denom(), &remote_denom, &bonded_denom)?; let exchange_rate = get_exchange_rate(deps)?; @@ -292,7 +292,7 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> ContractResult { .. } => { let asset_out_denom = - get_opposite_denom(asset_in.denom(), &remote_denom, &bonded_denom); + get_opposite_denom_in(asset_in.denom(), &remote_denom, &bonded_denom)?; let exchange_rate = get_exchange_rate(deps)?; @@ -314,10 +314,28 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> ContractResult { .map_err(From::from) } -fn get_opposite_denom(denom: &str, remote_denom: &str, bonded_denom: &str) -> String { - match denom { - denom if denom == remote_denom => bonded_denom.to_string(), - denom if denom == bonded_denom => remote_denom.to_string(), +fn get_opposite_denom_in( + denom_in: &str, + remote_denom: &str, + bonded_denom: &str, +) -> ContractResult { + match denom_in { + // if doing an 'in' query, only allow for simulating putting the remote denom in + denom_in if denom_in == remote_denom => Ok(bonded_denom.to_string()), + denom_in if denom_in == bonded_denom => Err(ContractError::UnsupportedDenom), + _ => unimplemented!(), + } +} + +fn get_opposite_denom_out( + denom_out: &str, + remote_denom: &str, + bonded_denom: &str, +) -> ContractResult { + match denom_out { + // if doing an 'out' query, only allow for simulating getting the bonded denom out + denom_out if denom_out == remote_denom => Err(ContractError::UnsupportedDenom), + denom_out if denom_out == bonded_denom => Ok(remote_denom.to_string()), _ => unimplemented!(), } } diff --git a/contracts/adapters/swap/drop/tests/test_queries.rs b/contracts/adapters/swap/drop/tests/test_queries.rs index 3dbde4f2..3083c595 100644 --- a/contracts/adapters/swap/drop/tests/test_queries.rs +++ b/contracts/adapters/swap/drop/tests/test_queries.rs @@ -6,6 +6,7 @@ use cosmwasm_std::{ // use lido_satellite::msg::ExecuteMsg as LidoSatelliteExecuteMsg; use skip::{asset::Asset, swap::QueryMsg}; use skip_go_swap_adapter_drop::{ + error::ContractError, error::ContractResult, state::{DROP_CORE_CONTRACT_ADDRESS, FACTORY_BONDED_DENOM, IBC_REMOTE_DENOM}, }; @@ -16,9 +17,10 @@ struct Params { query: QueryMsg, response: Binary, exchange_rate: Decimal, + expected_error: Option, } -// Test execute_swap +// Test queries #[test_case( Params { query: QueryMsg::SimulateSwapExactAssetIn { @@ -30,6 +32,7 @@ struct Params { "factory/uatom", ))).unwrap(), exchange_rate: Decimal::one(), + expected_error: None, }; "SimulateSwapExactAssetIn Query")] #[test_case( @@ -43,8 +46,20 @@ struct Params { "factory/uatom", ))).unwrap(), exchange_rate: Decimal::from_atomics(cosmwasm_std::Uint128::new(5), 1).unwrap(), + expected_error: None, }; "SimulateSwapExactAssetIn Query half exchange rate")] +#[test_case( + Params { + query: QueryMsg::SimulateSwapExactAssetOut { + swap_operations: vec![], + asset_out: Asset::Native(Coin::new(100, "ibc/uatom")), + }, + response: Binary([].to_vec()), + exchange_rate: Decimal::one(), + expected_error: Some(ContractError::UnsupportedDenom), + }; + "SimulateSwapExactAssetOut Query - want out remote denom")] #[test_case( Params { query: QueryMsg::SimulateSwapExactAssetOut { @@ -56,8 +71,9 @@ struct Params { "ibc/uatom", ))).unwrap(), exchange_rate: Decimal::one(), + expected_error: None, }; - "SimulateSwapExactAssetOut Query")] + "SimulateSwapExactAssetOut Query - want out factory denom")] #[test_case( Params { query: QueryMsg::SimulateSwapExactAssetOut { @@ -69,8 +85,20 @@ struct Params { "ibc/uatom", ))).unwrap(), exchange_rate: Decimal::from_atomics(cosmwasm_std::Uint128::new(5), 1).unwrap(), + expected_error: None, }; - "SimulateSwapExactAssetOut Query half exchange rate")] + "SimulateSwapExactAssetOut Query half exchange rate - want out factory denom")] +#[test_case( + Params { + query: QueryMsg::SimulateSwapExactAssetOut { + swap_operations: vec![], + asset_out: Asset::Native(Coin::new(100, "ibc/uatom")), + }, + response: Binary([].to_vec()), + exchange_rate: Decimal::from_atomics(cosmwasm_std::Uint128::new(5), 1).unwrap(), + expected_error: Some(ContractError::UnsupportedDenom), + }; + "SimulateSwapExactAssetOut Query half exchange rate - want out remote denom")] #[test_case( Params { query: QueryMsg::SimulateSwapExactAssetInWithMetadata { @@ -86,6 +114,7 @@ struct Params { spot_price: None }).unwrap(), exchange_rate: Decimal::one(), + expected_error: None, }; "SimulateSwapExactAssetInWithMetadata Query")] #[test_case( @@ -103,6 +132,7 @@ struct Params { spot_price: Some(Decimal::from_atomics(cosmwasm_std::Uint128::new(5), 1).unwrap()) }).unwrap(), exchange_rate: Decimal::from_atomics(cosmwasm_std::Uint128::new(5), 1).unwrap(), + expected_error: None, }; "SimulateSwapExactAssetInWithMetadata Query include spot price")] #[test_case( @@ -120,8 +150,33 @@ struct Params { spot_price: None }).unwrap(), exchange_rate: Decimal::one(), + expected_error: None, }; - "SimulateSwapExactAssetOutWithMetadata Query")] + "SimulateSwapExactAssetOutWithMetadata Query - want out factory denom")] +#[test_case( + Params { + query: QueryMsg::SimulateSwapExactAssetOutWithMetadata { + swap_operations: vec![], + asset_out: Asset::Native(Coin::new(100, "ibc/uatom")), + include_spot_price: false, + }, + response: Binary([].to_vec()), + exchange_rate: Decimal::one(), + expected_error: Some(ContractError::UnsupportedDenom), + }; + "SimulateSwapExactAssetOutWithMetadata Query - want out remote denom")] +#[test_case( + Params { + query: QueryMsg::SimulateSwapExactAssetOutWithMetadata { + swap_operations: vec![], + asset_out: Asset::Native(Coin::new(100, "ibc/uatom")), + include_spot_price: true, + }, + response: Binary([].to_vec()), + exchange_rate: Decimal::from_atomics(cosmwasm_std::Uint128::new(5), 1).unwrap(), + expected_error: Some(ContractError::UnsupportedDenom), + }; + "SimulateSwapExactAssetOutWithMetadata Query include spot price - want out remote denom")] #[test_case( Params { query: QueryMsg::SimulateSwapExactAssetOutWithMetadata { @@ -137,8 +192,9 @@ struct Params { spot_price: Some(Decimal::from_atomics(cosmwasm_std::Uint128::new(5), 1).unwrap()) }).unwrap(), exchange_rate: Decimal::from_atomics(cosmwasm_std::Uint128::new(5), 1).unwrap(), + expected_error: None, }; - "SimulateSwapExactAssetOutWithMetadata Query include spot price")] + "SimulateSwapExactAssetOutWithMetadata Query include spot price - want out factory denom")] fn test_queries(params: Params) -> ContractResult<()> { // Create mock dependencies @@ -169,21 +225,42 @@ fn test_queries(params: Params) -> ContractResult<()> { let mut env = mock_env(); env.contract.address = Addr::unchecked("swap_contract_address"); - // Store the lido satellite contract address + // Store the drop contract address DROP_CORE_CONTRACT_ADDRESS.save( deps.as_mut().storage, &Addr::unchecked("drop_core_contract"), )?; - // Store Lido Satellite denoms + // Store drop remote and bonded denoms IBC_REMOTE_DENOM.save(deps.as_mut().storage, &String::from("ibc/uatom"))?; FACTORY_BONDED_DENOM.save(deps.as_mut().storage, &String::from("factory/uatom"))?; // Call execute_swap with the given test parameters - let res = skip_go_swap_adapter_drop::contract::query(deps.as_ref(), env, params.query.clone()) - .unwrap(); + let res = skip_go_swap_adapter_drop::contract::query(deps.as_ref(), env, params.query.clone()); + + match res { + Ok(res) => { + // Assert that we did not want an error + assert!( + params.expected_error.is_none(), + "expected test to error with {:?}, but it succeeded", + params.expected_error + ); - assert_eq!(res, params.response); + // Assert the response is correct + assert_eq!(res, params.response); + } + Err(err) => { + // Asser that we did in fact expect an error + assert!( + params.expected_error.is_some(), + "expected test to succeed, but it errored with {:?}", + err + ); + // Assert the error is correct + assert_eq!(err, params.expected_error.unwrap()); + } + } Ok(()) }