diff --git a/smart-contracts/osmosis/contracts/range-middleware/README.md b/smart-contracts/osmosis/contracts/range-middleware/README.md deleted file mode 100644 index 4118b6d83..000000000 --- a/smart-contracts/osmosis/contracts/range-middleware/README.md +++ /dev/null @@ -1 +0,0 @@ -# Some description of this contract \ No newline at end of file diff --git a/smart-contracts/osmosis/contracts/range-middleware/src/error.rs b/smart-contracts/osmosis/contracts/range-middleware/src/error.rs index 894ac0693..a29d9f5ad 100644 --- a/smart-contracts/osmosis/contracts/range-middleware/src/error.rs +++ b/smart-contracts/osmosis/contracts/range-middleware/src/error.rs @@ -1,23 +1,20 @@ use cosmwasm_std::StdError; use thiserror::Error; -#[derive(Error, Debug)] +#[derive(Error, Debug, PartialEq)] pub enum ContractError { #[error("{0}")] Std(#[from] StdError), #[error("Unauthorized")] Unauthorized {}, - // Add any other custom errors you like here. - // Look at https://docs.rs/thiserror/1.0.21/thiserror/ for details. - /// start submission errors + #[error("Invalid contract address {address}")] InvalidContractAddress { address: String }, #[error("Query against cl-contract failed, maybe it isn't a CL contract?")] ClExpectedQueryFailed { address: String }, - // start execution errors #[error("No range exists for contract {address}")] NoRangeExists { address: String }, } diff --git a/smart-contracts/osmosis/contracts/range-middleware/src/msg.rs b/smart-contracts/osmosis/contracts/range-middleware/src/msg.rs index 967735d45..f00ada81d 100644 --- a/smart-contracts/osmosis/contracts/range-middleware/src/msg.rs +++ b/smart-contracts/osmosis/contracts/range-middleware/src/msg.rs @@ -14,19 +14,15 @@ pub struct InstantiateMsg { #[cw_serde] pub enum ExecuteMsg { - /// range operations RangeMsg(RangeExecuteMsg), - /// admin operations AdminMsg(AdminExecuteMsg), } #[cw_serde] #[derive(QueryResponses)] pub enum QueryMsg { - /// range queries #[returns(Empty)] RangeQuery(RangeQueryMsg), - /// admin queries #[returns(Empty)] AdminQuery(AdminQueryMsg), } diff --git a/smart-contracts/osmosis/contracts/range-middleware/src/range/execute.rs b/smart-contracts/osmosis/contracts/range-middleware/src/range/execute.rs index 60e67f902..2dfc66b29 100644 --- a/smart-contracts/osmosis/contracts/range-middleware/src/range/execute.rs +++ b/smart-contracts/osmosis/contracts/range-middleware/src/range/execute.rs @@ -17,7 +17,9 @@ use super::helpers::is_range_submitter_admin; #[cw_serde] pub enum RangeExecuteMsg { /// Submit a range to the range middleware - SubmitNewRange { new_range: NewRange }, + SubmitNewRange { + new_range: NewRange, + }, /// Execute a new range ExecuteNewRange { cl_vault_address: String, @@ -27,6 +29,9 @@ pub enum RangeExecuteMsg { forced_swap_route: Option>, claim_after: Option, }, + RemoveRange { + contract_address: String, + }, } pub struct RangeExecutionParams { @@ -68,9 +73,22 @@ pub fn execute_range_msg( claim_after, }, ), + RangeExecuteMsg::RemoveRange { contract_address } => { + remove_range(deps, info, contract_address) + } } } +pub fn remove_range( + deps: DepsMut, + info: MessageInfo, + contract_address: String, +) -> Result { + is_range_submitter_admin(deps.storage, &info.sender)?; + PENDING_RANGES.remove(deps.storage, deps.api.addr_validate(&contract_address)?); + Ok(Response::default()) +} + pub fn submit_new_range( deps: DepsMut, _env: Env, @@ -163,3 +181,111 @@ pub fn execute_new_range( .add_attribute("range_executor", info.sender) .add_attribute("range_underlying_contract", params.cl_vault_address)) } + +#[cfg(test)] +mod tests { + use cosmwasm_std::{ + testing::{mock_dependencies, mock_env, mock_info}, + Addr, Decimal, + }; + + use crate::{ + contract::{execute, instantiate, query}, + msg::{InstantiateMsg, QueryMsg}, + range::execute::RangeExecuteMsg, + state::{NewRange, PENDING_RANGES}, + ContractError, + }; + + const RANGE_SUBMITTER_ADMIN: &str = "range_submitter_admin"; + const RANGE_EXECUTOR_ADMIN: &str = "range_executor_admin"; + const TEST_CONTRACT: &str = "test_contract"; + + #[test] + fn test_unauthorized_user_can_not_remove_range() { + let mut deps = mock_dependencies(); + let env = mock_env(); + let info = mock_info("sender", &[]); + assert!(instantiate( + deps.as_mut(), + env.clone(), + info.clone(), + InstantiateMsg { + range_executor_admin: RANGE_EXECUTOR_ADMIN.to_string(), + range_submitter_admin: RANGE_SUBMITTER_ADMIN.to_string(), + } + ) + .is_ok()); + + let err = execute( + deps.as_mut(), + env, + info, + crate::msg::ExecuteMsg::RangeMsg(RangeExecuteMsg::RemoveRange { + contract_address: TEST_CONTRACT.to_string(), + }), + ) + .unwrap_err(); + assert_eq!(err, ContractError::Unauthorized {}); + } + + #[test] + fn test_range_admin_can_remove_range() { + let mut deps = mock_dependencies(); + let env = mock_env(); + let info = mock_info("sender", &[]); + let _ = instantiate( + deps.as_mut(), + env.clone(), + info.clone(), + InstantiateMsg { + range_executor_admin: RANGE_EXECUTOR_ADMIN.to_string(), + range_submitter_admin: RANGE_SUBMITTER_ADMIN.to_string(), + }, + ) + .unwrap(); + + PENDING_RANGES + .save( + deps.as_mut().storage, + Addr::unchecked(TEST_CONTRACT), + &NewRange { + cl_vault_address: TEST_CONTRACT.to_string(), + lower_price: Decimal::zero(), + upper_price: Decimal::one(), + }, + ) + .unwrap(); + assert!(query( + deps.as_ref(), + env.clone(), + QueryMsg::RangeQuery( + crate::range::query::RangeQueryMsg::GetQueuedRangeUpdatesForContract { + contract_address: TEST_CONTRACT.to_string() + } + ) + ) + .is_ok()); + + let info = mock_info(RANGE_SUBMITTER_ADMIN, &[]); + let _ = execute( + deps.as_mut(), + env.clone(), + info, + crate::msg::ExecuteMsg::RangeMsg(RangeExecuteMsg::RemoveRange { + contract_address: TEST_CONTRACT.to_string(), + }), + ) + .unwrap(); + assert!(query( + deps.as_ref(), + env.clone(), + QueryMsg::RangeQuery( + crate::range::query::RangeQueryMsg::GetQueuedRangeUpdatesForContract { + contract_address: TEST_CONTRACT.to_string() + } + ) + ) + .is_err()); + } +}