diff --git a/contracts/oracle/osmosis/Cargo.toml b/contracts/oracle/osmosis/Cargo.toml index 6950a9118..9cb816041 100644 --- a/contracts/oracle/osmosis/Cargo.toml +++ b/contracts/oracle/osmosis/Cargo.toml @@ -19,9 +19,11 @@ doctest = false backtraces = ["cosmwasm-std/backtraces"] [dependencies] +cosmwasm-schema = { workspace = true } cosmwasm-std = { workspace = true } cw2 = { workspace = true } cw-storage-plus = { workspace = true } +mars-owner = { workspace = true } mars-oracle-base = { workspace = true } mars-osmosis = { workspace = true } mars-red-bank-types = { workspace = true } diff --git a/contracts/oracle/osmosis/src/contract.rs b/contracts/oracle/osmosis/src/contract.rs index edf584b39..ab7627d9d 100644 --- a/contracts/oracle/osmosis/src/contract.rs +++ b/contracts/oracle/osmosis/src/contract.rs @@ -48,6 +48,6 @@ pub mod entry { #[entry_point] pub fn migrate(deps: DepsMut, _env: Env, _msg: Empty) -> ContractResult { - migrations::v1_0_0::migrate(deps) + migrations::v1_0_1::migrate(deps) } } diff --git a/contracts/oracle/osmosis/src/migrations.rs b/contracts/oracle/osmosis/src/migrations.rs index 93a88f7b2..67ecd6176 100644 --- a/contracts/oracle/osmosis/src/migrations.rs +++ b/contracts/oracle/osmosis/src/migrations.rs @@ -1,7 +1,8 @@ -/// Migration logic for Oracle contract with version: 1.0.0 -pub mod v1_0_0 { +/// Migration logic for Oracle contract with version: 1.0.1 +pub mod v1_0_1 { use cosmwasm_std::{DepsMut, Response}; use mars_oracle_base::ContractResult; + use mars_owner::{Owner, OwnerInit}; use crate::contract::{CONTRACT_NAME, CONTRACT_VERSION}; @@ -11,6 +12,25 @@ pub mod v1_0_0 { // make sure we're migrating the correct contract and from the correct version cw2::assert_contract_version(deps.as_ref().storage, CONTRACT_NAME, FROM_VERSION)?; + // map old owner struct to new one + let old_owner = old_state::OWNER.load(deps.storage)?; + let owner = match old_owner { + old_state::OwnerState::B(state) => state.owner.to_string(), + old_state::OwnerState::C(state) => state.owner.to_string(), + }; + + // clear old owner state + old_state::OWNER.remove(deps.storage); + + // initalize owner with new struct + Owner::new("owner").initialize( + deps.storage, + deps.api, + OwnerInit::SetInitialOwner { + owner, + }, + )?; + // update contract version cw2::set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; @@ -20,18 +40,60 @@ pub mod v1_0_0 { .add_attribute("to_version", CONTRACT_VERSION)) } + pub mod old_state { + use cosmwasm_schema::cw_serde; + use cosmwasm_std::Addr; + use cw_storage_plus::Item; + + pub const OWNER: Item = Item::new("owner"); + + /// Old OwnerState variants: + /// A(OwnerUninitialized) + /// B(OwnerSetNoneProposed) + /// C(OwnerSetWithProposed) + /// D(OwnerRoleAbolished) + /// + /// Oracle contract can be in B or C state. Emergency owner is not supported for this contract. + /// We can only read `owner` value and omit `proposed` if exist. + #[cw_serde] + pub enum OwnerState { + B(OwnerSetNoneProposed), + C(OwnerSetWithProposed), + } + + #[cw_serde] + pub struct OwnerSetNoneProposed { + pub owner: Addr, + } + + #[cw_serde] + pub struct OwnerSetWithProposed { + pub owner: Addr, + } + } + #[cfg(test)] mod tests { - use cosmwasm_std::{attr, testing::mock_dependencies}; + use cosmwasm_std::{attr, testing::mock_dependencies, Addr}; use super::*; + use crate::migrations::v1_0_1::old_state::{OwnerSetNoneProposed, OwnerSetWithProposed}; #[test] - fn proper_migration() { + fn migration_owner_from_state_b() { let mut deps = mock_dependencies(); cw2::set_contract_version(deps.as_mut().storage, CONTRACT_NAME, FROM_VERSION).unwrap(); + old_state::OWNER + .save( + deps.as_mut().storage, + &old_state::OwnerState::B(OwnerSetNoneProposed { + owner: Addr::unchecked("xyz"), + }), + ) + .unwrap(); + let res = migrate(deps.as_mut()).unwrap(); assert_eq!(res.messages, vec![]); assert_eq!( @@ -42,6 +104,39 @@ pub mod v1_0_0 { attr("to_version", "1.1.0") ] ); + + let new_owner = Owner::new("owner").query(&deps.storage).unwrap(); + assert_eq!(new_owner.owner.unwrap(), "xyz".to_string()); + } + + #[test] + fn migration_owner_from_state_c() { + let mut deps = mock_dependencies(); + + cw2::set_contract_version(deps.as_mut().storage, CONTRACT_NAME, FROM_VERSION).unwrap(); + + old_state::OWNER + .save( + deps.as_mut().storage, + &old_state::OwnerState::C(OwnerSetWithProposed { + owner: Addr::unchecked("xyz"), + }), + ) + .unwrap(); + + let res = migrate(deps.as_mut()).unwrap(); + assert_eq!(res.messages, vec![]); + assert_eq!( + res.attributes, + vec![ + attr("action", "migrate"), + attr("from_version", "1.0.1"), + attr("to_version", "1.1.0") + ] + ); + + let new_owner = Owner::new("owner").query(&deps.storage).unwrap(); + assert_eq!(new_owner.owner.unwrap(), "xyz".to_string()); } } }