Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
284 changes: 147 additions & 137 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ cw2 = { git = "https://github.com/mars-protocol/cw-plus", rev = "4
cw-multi-test = "0.16.1"
cw-storage-plus = "1.0.1"
cw-utils = "1.0.1"
mars-owner = "1.0.0"
mars-owner = { version = "1.0.0", features = ["emergency-owner"] }
osmosis-std = "0.14.0"
osmosis-test-tube = "14.1.1"
prost = { version = "0.11.5", default-features = false, features = ["prost-derive"] }
Expand Down
3 changes: 0 additions & 3 deletions contracts/red-bank/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ pub fn execute(
) -> Result<Response, ContractError> {
match msg {
ExecuteMsg::UpdateOwner(update) => execute::update_owner(deps, info, update),
ExecuteMsg::UpdateEmergencyOwner(update) => {
execute::update_emergency_owner(deps, info, update)
}
ExecuteMsg::UpdateConfig {
config,
} => execute::update_config(deps, info, config),
Expand Down
22 changes: 2 additions & 20 deletions contracts/red-bank/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ use crate::{
apply_accumulated_interests, get_scaled_debt_amount, get_scaled_liquidity_amount,
get_underlying_debt_amount, get_underlying_liquidity_amount, update_interest_rates,
},
state::{
COLLATERALS, CONFIG, DEBTS, EMERGENCY_OWNER, MARKETS, OWNER, UNCOLLATERALIZED_LOAN_LIMITS,
},
state::{COLLATERALS, CONFIG, DEBTS, MARKETS, OWNER, UNCOLLATERALIZED_LOAN_LIMITS},
user::User,
};

Expand Down Expand Up @@ -69,14 +67,6 @@ pub fn instantiate(deps: DepsMut, msg: InstantiateMsg) -> Result<Response, Contr
},
)?;

EMERGENCY_OWNER.initialize(
deps.storage,
deps.api,
SetInitialOwner {
owner: msg.emergency_owner,
},
)?;

Ok(Response::default())
}

Expand All @@ -88,14 +78,6 @@ pub fn update_owner(
Ok(OWNER.update(deps, info, update)?)
}

pub fn update_emergency_owner(
deps: DepsMut,
info: MessageInfo,
update: OwnerUpdate,
) -> Result<Response, ContractError> {
Ok(EMERGENCY_OWNER.update(deps, info, update)?)
}

/// Update config
pub fn update_config(
deps: DepsMut,
Expand Down Expand Up @@ -216,7 +198,7 @@ pub fn update_asset(
) -> Result<Response, ContractError> {
if OWNER.is_owner(deps.storage, &info.sender)? {
update_asset_by_owner(deps, &env, &denom, params)
} else if EMERGENCY_OWNER.is_owner(deps.storage, &info.sender)? {
} else if OWNER.is_emergency_owner(deps.storage, &info.sender)? {
update_asset_by_emergency_owner(deps, &denom, params)
} else {
Err(OwnerError::NotOwner {}.into())
Expand Down
8 changes: 2 additions & 6 deletions contracts/red-bank/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,19 @@ use crate::{
get_scaled_debt_amount, get_scaled_liquidity_amount, get_underlying_debt_amount,
get_underlying_liquidity_amount,
},
state::{
COLLATERALS, CONFIG, DEBTS, EMERGENCY_OWNER, MARKETS, OWNER, UNCOLLATERALIZED_LOAN_LIMITS,
},
state::{COLLATERALS, CONFIG, DEBTS, MARKETS, OWNER, UNCOLLATERALIZED_LOAN_LIMITS},
};

const DEFAULT_LIMIT: u32 = 5;
const MAX_LIMIT: u32 = 10;

pub fn query_config(deps: Deps) -> StdResult<ConfigResponse> {
let owner_state = OWNER.query(deps.storage)?;
let emergency_owner_state = EMERGENCY_OWNER.query(deps.storage)?;
let config = CONFIG.load(deps.storage)?;
Ok(ConfigResponse {
owner: owner_state.owner,
proposed_new_owner: owner_state.proposed,
emergency_owner: emergency_owner_state.owner,
proposed_new_emergency_owner: emergency_owner_state.proposed,
emergency_owner: owner_state.emergency_owner,
address_provider: config.address_provider.to_string(),
close_factor: config.close_factor,
})
Expand Down
1 change: 0 additions & 1 deletion contracts/red-bank/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use mars_owner::Owner;
use mars_red_bank_types::red_bank::{Collateral, Config, Debt, Market};

pub const OWNER: Owner = Owner::new("owner");
pub const EMERGENCY_OWNER: Owner = Owner::new("emergency_owner");
pub const CONFIG: Item<Config<Addr>> = Item::new("config");
pub const MARKETS: Map<&str, Market> = Map::new("markets");
pub const COLLATERALS: Map<(&Addr, &str), Collateral> = Map::new("collaterals");
Expand Down
1 change: 0 additions & 1 deletion contracts/red-bank/tests/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ pub fn th_setup(contract_balances: &[Coin]) -> OwnedDeps<MockStorage, MockApi, M
};
let msg = InstantiateMsg {
owner: "owner".to_string(),
emergency_owner: "emergency_owner".to_string(),
config,
};
instantiate(deps.as_mut(), env, info, msg).unwrap();
Expand Down
20 changes: 11 additions & 9 deletions contracts/red-bank/tests/test_admin.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use cosmwasm_std::{attr, coin, from_binary, testing::mock_info, Addr, Decimal, Event, Uint128};
use mars_owner::OwnerError::NotOwner;
use mars_owner::{OwnerError::NotOwner, OwnerUpdate};
use mars_red_bank::{
contract::{execute, instantiate, query},
error::ContractError,
Expand Down Expand Up @@ -41,7 +41,6 @@ fn proper_initialization() {
};
let msg = InstantiateMsg {
owner: "owner".to_string(),
emergency_owner: "emergency_owner".to_string(),
config: empty_config,
};
let info = mock_info("owner", &[]);
Expand All @@ -58,7 +57,6 @@ fn proper_initialization() {
};
let msg = InstantiateMsg {
owner: "owner".to_string(),
emergency_owner: "emergency_owner".to_string(),
config,
};
let info = mock_info("owner", &[]);
Expand All @@ -83,7 +81,6 @@ fn proper_initialization() {
};
let msg = InstantiateMsg {
owner: "owner".to_string(),
emergency_owner: "emergency_owner".to_string(),
config,
};

Expand Down Expand Up @@ -114,7 +111,6 @@ fn update_config() {
};
let msg = InstantiateMsg {
owner: "owner".to_string(),
emergency_owner: "emergency_owner".to_string(),
config: init_config.clone(),
};
// we can just call .unwrap() to assert this was a success
Expand Down Expand Up @@ -191,7 +187,6 @@ fn init_asset() {
};
let msg = InstantiateMsg {
owner: "owner".to_string(),
emergency_owner: "emergency_owner".to_string(),
config,
};
let info = mock_info("owner", &[]);
Expand Down Expand Up @@ -477,7 +472,6 @@ fn update_asset() {
};
let msg = InstantiateMsg {
owner: "owner".to_string(),
emergency_owner: "emergency_owner".to_string(),
config,
};
let info = mock_info("owner", &[]);
Expand Down Expand Up @@ -731,7 +725,6 @@ fn update_asset_with_new_interest_rate_model_params() {
};
let msg = InstantiateMsg {
owner: "owner".to_string(),
emergency_owner: "emergency_owner".to_string(),
config,
};
let info = mock_info("owner", &[]);
Expand Down Expand Up @@ -951,7 +944,6 @@ fn update_asset_by_emergency_owner() {
};
let msg = InstantiateMsg {
owner: "owner".to_string(),
emergency_owner: "emergency_owner".to_string(),
config,
};
let info = mock_info("owner", &[]);
Expand All @@ -975,6 +967,16 @@ fn update_asset_by_emergency_owner() {
deposit_cap: None,
};

execute(
deps.as_mut(),
env.clone(),
mock_info("owner", &[]),
ExecuteMsg::UpdateOwner(OwnerUpdate::SetEmergencyOwner {
emergency_owner: "emergency_owner".to_string(),
}),
)
.unwrap();

// emergency owner is authorized but can't update asset if not initialized first
{
let msg = ExecuteMsg::UpdateAsset {
Expand Down
16 changes: 2 additions & 14 deletions contracts/red-bank/tests/test_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,10 @@ fn query_collateral() {
let user_addr = Addr::unchecked("user");

// Setup first market
let market_1 = th_init_market(
deps.as_mut(),
"uosmo",
&Market {
..Default::default()
},
);
let market_1 = th_init_market(deps.as_mut(), "uosmo", &Default::default());

// Setup second market
let market_2 = th_init_market(
deps.as_mut(),
"uusd",
&Market {
..Default::default()
},
);
let market_2 = th_init_market(deps.as_mut(), "uusd", &Default::default());

let amount_1 = Uint128::new(12345);
let amount_2 = Uint128::new(54321);
Expand Down
120 changes: 18 additions & 102 deletions contracts/red-bank/tests/test_update_emergency_owner.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
use cosmwasm_std::testing::{mock_env, mock_info};
use mars_owner::{
OwnerError::{NotOwner, NotProposedOwner},
OwnerUpdate,
};
use mars_owner::{OwnerError::NotOwner, OwnerUpdate};
use mars_red_bank::{contract::execute, error::ContractError};
use mars_red_bank_types::red_bank::{ConfigResponse, ExecuteMsg, QueryMsg};

Expand All @@ -15,145 +12,64 @@ fn initialized_state() {
let deps = th_setup(&[]);

let config: ConfigResponse = th_query(deps.as_ref(), QueryMsg::Config {});
assert!(config.emergency_owner.is_some());
assert!(config.proposed_new_emergency_owner.is_none());
assert!(config.emergency_owner.is_none());
}

#[test]
fn propose_new_emergency_owner() {
fn only_owner_can_set_emergency_owner() {
let mut deps = th_setup(&[]);

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

let new_owner = "new_admin";

// only admin can propose new admins
let bad_guy = "bad_guy";
let err = execute(
deps.as_mut(),
mock_env(),
mock_info(bad_guy, &[]),
ExecuteMsg::UpdateEmergencyOwner(OwnerUpdate::ProposeNewOwner {
proposed: bad_guy.to_string(),
ExecuteMsg::UpdateOwner(OwnerUpdate::SetEmergencyOwner {
emergency_owner: "new_emergency_owner".to_string(),
}),
)
.unwrap_err();
assert_eq!(err, ContractError::Owner(NotOwner {}));

execute(
deps.as_mut(),
mock_env(),
mock_info(&original_config.emergency_owner.clone().unwrap(), &[]),
ExecuteMsg::UpdateEmergencyOwner(OwnerUpdate::ProposeNewOwner {
proposed: new_owner.to_string(),
}),
)
.unwrap();

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

assert_eq!(new_config.owner, original_config.owner);
assert_eq!(new_config.proposed_new_owner, original_config.proposed_new_owner);
assert_eq!(new_config.emergency_owner, original_config.emergency_owner);
assert_ne!(
new_config.proposed_new_emergency_owner,
original_config.proposed_new_emergency_owner
);
assert_eq!(new_config.proposed_new_emergency_owner, Some(new_owner.to_string()));
}

#[test]
fn clear_proposed_emergency_owner() {
fn set_and_clear_emergency_owner() {
let mut deps = th_setup(&[]);

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

let new_owner = "new_admin";
let emergency_owner = "new_emergency_owner";

execute(
deps.as_mut(),
mock_env(),
mock_info(&original_config.emergency_owner.clone().unwrap(), &[]),
ExecuteMsg::UpdateEmergencyOwner(OwnerUpdate::ProposeNewOwner {
proposed: new_owner.to_string(),
mock_info(&original_config.owner.clone().unwrap(), &[]),
ExecuteMsg::UpdateOwner(OwnerUpdate::SetEmergencyOwner {
emergency_owner: emergency_owner.to_string(),
}),
)
.unwrap();

let interim_config: ConfigResponse = th_query(deps.as_ref(), QueryMsg::Config {});
assert_eq!(interim_config.proposed_new_emergency_owner, Some(new_owner.to_string()));

// only admin can clear
let bad_guy = "bad_guy";
let err = execute(
deps.as_mut(),
mock_env(),
mock_info(bad_guy, &[]),
ExecuteMsg::UpdateEmergencyOwner(OwnerUpdate::ClearProposed),
)
.unwrap_err();
assert_eq!(err, ContractError::Owner(NotOwner {}));

execute(
deps.as_mut(),
mock_env(),
mock_info(&original_config.emergency_owner.clone().unwrap(), &[]),
ExecuteMsg::UpdateEmergencyOwner(OwnerUpdate::ClearProposed),
)
.unwrap();

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

assert_eq!(latest_config.owner, original_config.owner);
assert_eq!(latest_config.proposed_new_owner, original_config.proposed_new_owner);
assert_eq!(latest_config.emergency_owner, original_config.emergency_owner);
assert_ne!(
latest_config.proposed_new_emergency_owner,
interim_config.proposed_new_emergency_owner
);
assert_eq!(latest_config.proposed_new_emergency_owner, None);
}

#[test]
fn accept_emergency_owner_role() {
let mut deps = th_setup(&[]);

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

let new_owner = "new_admin";
let new_config: ConfigResponse = th_query(deps.as_ref(), QueryMsg::Config {});

execute(
deps.as_mut(),
mock_env(),
mock_info(&original_config.emergency_owner.clone().unwrap(), &[]),
ExecuteMsg::UpdateEmergencyOwner(OwnerUpdate::ProposeNewOwner {
proposed: new_owner.to_string(),
}),
)
.unwrap();
assert_eq!(new_config.owner, original_config.owner);
assert_eq!(new_config.proposed_new_owner, original_config.proposed_new_owner);
assert_eq!(new_config.emergency_owner, Some(emergency_owner.to_string()));

// Only proposed admin can accept
let err = execute(
deps.as_mut(),
mock_env(),
mock_info(&original_config.emergency_owner.unwrap(), &[]),
ExecuteMsg::UpdateEmergencyOwner(OwnerUpdate::AcceptProposed),
)
.unwrap_err();
assert_eq!(err, ContractError::Owner(NotProposedOwner {}));
// clear emergency owner

execute(
deps.as_mut(),
mock_env(),
mock_info(new_owner, &[]),
ExecuteMsg::UpdateEmergencyOwner(OwnerUpdate::AcceptProposed),
mock_info(&original_config.owner.clone().unwrap(), &[]),
ExecuteMsg::UpdateOwner(OwnerUpdate::ClearEmergencyOwner {}),
)
.unwrap();

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

assert_eq!(new_config.owner, original_config.owner);
assert_eq!(new_config.proposed_new_owner, original_config.proposed_new_owner);
assert_eq!(new_config.emergency_owner.unwrap(), new_owner.to_string());
assert_eq!(new_config.proposed_new_emergency_owner, None);
assert_eq!(new_config.emergency_owner, None);
}
Loading