diff --git a/Cargo.lock b/Cargo.lock index f1838a09b..3dcb3da77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1705,6 +1705,7 @@ dependencies = [ "multisig", "report", "router-api", + "semver 1.0.23", "service-registry-api", "thiserror", "tofn", diff --git a/contracts/coordinator/Cargo.toml b/contracts/coordinator/Cargo.toml index da5220e94..fa49e44bd 100644 --- a/contracts/coordinator/Cargo.toml +++ b/contracts/coordinator/Cargo.toml @@ -44,6 +44,7 @@ msgs-derive = { workspace = true } multisig = { workspace = true, features = ["library"] } report = { workspace = true } router-api = { workspace = true } +semver = { workspace = true } service-registry-api = { workspace = true } thiserror = { workspace = true } diff --git a/contracts/coordinator/src/contract.rs b/contracts/coordinator/src/contract.rs index 71f3573cf..3aaee3f26 100644 --- a/contracts/coordinator/src/contract.rs +++ b/contracts/coordinator/src/contract.rs @@ -7,13 +7,15 @@ use axelar_wasm_std::{address, permission_control, FnExt}; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - to_json_binary, Addr, Binary, Deps, DepsMut, Env, MessageInfo, Response, Storage, + ensure, to_json_binary, Addr, Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response, Storage, }; -use error_stack::{report, ResultExt}; +use cw2::VersionError; +use error_stack::report; use itertools::Itertools; +use semver::Version; use crate::error::ContractError; -use crate::msg::{ExecuteMsg, InstantiateMsg, MigrationMsg, QueryMsg}; +use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; use crate::state::{is_prover_registered, Config, CONFIG}; pub const CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); @@ -23,12 +25,16 @@ pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); pub fn migrate( deps: DepsMut, _env: Env, - msg: MigrationMsg, + _msg: Empty, ) -> Result { - let service_registry = validate_cosmwasm_address(deps.api, &msg.service_registry)?; - - migrations::v1_0_0::migrate(deps.storage, service_registry) - .change_context(ContractError::Migration)?; + let old_version = Version::parse(&cw2::get_contract_version(deps.storage)?.version)?; + ensure!( + old_version.major == 1 && old_version.minor == 1, + report!(VersionError::WrongVersion { + expected: "1.1.x".into(), + found: old_version.to_string() + }) + ); // this needs to be the last thing to do during migration, // because previous migration steps should check the old version @@ -304,4 +310,16 @@ mod tests { .to_string() )); } + + #[test] + fn migrate_sets_contract_version() { + let governance = "governance_for_coordinator"; + let mut test_setup = setup(governance); + + migrate(test_setup.deps.as_mut(), mock_env(), Empty {}).unwrap(); + + let contract_version = cw2::get_contract_version(test_setup.deps.as_mut().storage).unwrap(); + assert_eq!(contract_version.contract, CONTRACT_NAME); + assert_eq!(contract_version.version, CONTRACT_VERSION); + } } diff --git a/contracts/coordinator/src/contract/migrations/mod.rs b/contracts/coordinator/src/contract/migrations/mod.rs index 1d185e9d7..8b1378917 100644 --- a/contracts/coordinator/src/contract/migrations/mod.rs +++ b/contracts/coordinator/src/contract/migrations/mod.rs @@ -1 +1 @@ -pub mod v1_0_0; + diff --git a/contracts/coordinator/src/contract/migrations/v1_0_0.rs b/contracts/coordinator/src/contract/migrations/v1_0_0.rs deleted file mode 100644 index c89703ee8..000000000 --- a/contracts/coordinator/src/contract/migrations/v1_0_0.rs +++ /dev/null @@ -1,115 +0,0 @@ -#![allow(deprecated)] - -use axelar_wasm_std::nonempty; -use cosmwasm_std::{Addr, StdError, Storage}; -use cw2::VersionError; - -use crate::contract::CONTRACT_NAME; - -const BASE_VERSION: &str = "1.0.0"; - -#[derive(thiserror::Error, Debug)] -pub enum Error { - #[error(transparent)] - Std(#[from] StdError), - #[error(transparent)] - Version(#[from] VersionError), - #[error(transparent)] - NonEmpty(#[from] nonempty::Error), -} - -pub fn migrate(storage: &mut dyn Storage, service_registry: Addr) -> Result<(), Error> { - cw2::assert_contract_version(storage, CONTRACT_NAME, BASE_VERSION)?; - - migrate_config(storage, service_registry)?; - Ok(()) -} - -fn migrate_config(storage: &mut dyn Storage, service_registry: Addr) -> Result<(), Error> { - let new_config = crate::state::Config { service_registry }; - crate::state::CONFIG.save(storage, &new_config)?; - Ok(()) -} - -#[cfg(test)] -mod tests { - use axelar_wasm_std::{address, permission_control}; - use cosmwasm_schema::cw_serde; - use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info}; - use cosmwasm_std::{Addr, DepsMut, Env, MessageInfo, Response}; - - use crate::contract::migrations::v1_0_0::{self, BASE_VERSION}; - use crate::contract::CONTRACT_NAME; - - const GOVERNANCE: &str = "governance"; - - #[test] - fn migrate_checks_contract_version() { - let mut deps = mock_dependencies(); - instantiate_contract(deps.as_mut()); - - cw2::set_contract_version(deps.as_mut().storage, CONTRACT_NAME, "something wrong").unwrap(); - - assert!(v1_0_0::migrate(deps.as_mut().storage, Addr::unchecked("random_service")).is_err()); - - cw2::set_contract_version(deps.as_mut().storage, CONTRACT_NAME, BASE_VERSION).unwrap(); - - assert!(v1_0_0::migrate(deps.as_mut().storage, Addr::unchecked("random_service")).is_ok()); - } - - #[test] - fn migrate_config() { - let mut deps = mock_dependencies(); - instantiate( - deps.as_mut(), - mock_env(), - mock_info("admin", &[]), - InstantiateMsg { - governance_address: "governance".to_string(), - }, - ) - .unwrap(); - - let service_registry_address = Addr::unchecked("random_service"); - assert!(v1_0_0::migrate(deps.as_mut().storage, service_registry_address.clone()).is_ok()); - - let config_result = crate::state::CONFIG.load(deps.as_mut().storage); - assert!(config_result.is_ok()); - - let config = config_result.unwrap(); - assert_eq!(config.service_registry, service_registry_address) - } - - fn instantiate_contract(deps: DepsMut) { - instantiate( - deps, - mock_env(), - mock_info("admin", &[]), - InstantiateMsg { - governance_address: GOVERNANCE.to_string(), - }, - ) - .unwrap(); - } - - #[deprecated(since = "1.0.0", note = "only used to test the migration")] - fn instantiate( - deps: DepsMut, - _env: Env, - _info: MessageInfo, - msg: InstantiateMsg, - ) -> Result { - cw2::set_contract_version(deps.storage, CONTRACT_NAME, BASE_VERSION)?; - - let governance = address::validate_cosmwasm_address(deps.api, &msg.governance_address)?; - permission_control::set_governance(deps.storage, &governance)?; - - Ok(Response::default()) - } - - #[cw_serde] - #[deprecated(since = "1.0.0", note = "only used to test the migration")] - struct InstantiateMsg { - pub governance_address: String, - } -} diff --git a/contracts/coordinator/src/msg.rs b/contracts/coordinator/src/msg.rs index e93bc6ad5..e1c3b5f4c 100644 --- a/contracts/coordinator/src/msg.rs +++ b/contracts/coordinator/src/msg.rs @@ -7,11 +7,6 @@ use msgs_derive::EnsurePermissions; use router_api::ChainName; use service_registry_api::Verifier; -#[cw_serde] -pub struct MigrationMsg { - pub service_registry: String, -} - #[cw_serde] pub struct InstantiateMsg { pub governance_address: String,