Skip to content

Commit

Permalink
Added migration function from xion accounts (#533)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kayanski authored Nov 12, 2024
1 parent d9bf5c3 commit 7413a12
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 9 deletions.
2 changes: 1 addition & 1 deletion framework/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion framework/contracts/account/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "abstract-account"
version = { workspace = true }
version = "0.24.2"
authors = { workspace = true }
edition = { workspace = true }
description = "Abstract Account Contract"
Expand Down
118 changes: 112 additions & 6 deletions framework/contracts/account/src/migrate.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,125 @@
use abstract_sdk::feature_objects::RegistryContract;
use abstract_sdk::std::{account::state::ACCOUNT_ID, ACCOUNT};
use abstract_std::account::ModuleInstallConfig;
use abstract_std::objects::module::ModuleInfo;
use abstract_std::objects::module_version::assert_contract_upgrade;
use abstract_std::{account::MigrateMsg, objects::AccountId};
use abstract_std::{
account::MigrateMsg, objects::module_version::assert_contract_upgrade, ACCOUNT,
account::{
state::{AccountInfo, WhitelistedModules, INFO, SUSPENSION_STATUS, WHITELISTED_MODULES},
UpdateSubAccountAction,
},
objects::{
gov_type::GovernanceDetails,
ownership::{self},
},
registry::state::LOCAL_ACCOUNT_SEQUENCE,
};
use cosmwasm_std::{DepsMut, Env};
use cw2::set_contract_version;
use abstract_std::{AbstractError, IBC_CLIENT};
use cosmwasm_std::{wasm_execute, DepsMut, Env};
use cw2::{get_contract_version, set_contract_version};
use semver::Version;

use crate::{
modules::{_install_modules, MIGRATE_CONTEXT},
msg::ExecuteMsg,
};

use crate::contract::{AccountResponse, AccountResult, CONTRACT_VERSION};

#[cfg_attr(feature = "export", cosmwasm_std::entry_point)]
pub fn migrate(deps: DepsMut, _env: Env, _msg: MigrateMsg) -> AccountResult {
pub fn migrate(mut deps: DepsMut, env: Env, _msg: MigrateMsg) -> AccountResult {
let version: Version = CONTRACT_VERSION.parse().unwrap();

assert_contract_upgrade(deps.storage, ACCOUNT, version)?;
let current_contract_version = get_contract_version(deps.storage)?;
// If we already have an abstract account, we just migrate like normal
if current_contract_version.contract != "abstract::account" {
assert_contract_upgrade(deps.storage, ACCOUNT, version)?;
set_contract_version(deps.storage, ACCOUNT, CONTRACT_VERSION)?;
return Ok(AccountResponse::action("migrate"));
}

// else this means that we are migrating from another contract, we assert it's `account` and create an abstract account
if current_contract_version.contract != "account" {
Err(AbstractError::ContractNameMismatch {
from: current_contract_version.contract,
to: ACCOUNT.to_string(),
})?;
}

// Use CW2 to set the contract version, this is needed for migrations
set_contract_version(deps.storage, ACCOUNT, CONTRACT_VERSION)?;
Ok(AccountResponse::action("migrate"))

let registry = RegistryContract::new(deps.api, &env)?;

let account_id =
AccountId::local(LOCAL_ACCOUNT_SEQUENCE.query(&deps.querier, registry.address.clone())?);

let mut response = AccountResponse::new(
"migrate",
vec![("account_id".to_owned(), account_id.to_string())],
);

ACCOUNT_ID.save(deps.storage, &account_id)?;
WHITELISTED_MODULES.save(deps.storage, &WhitelistedModules(vec![]))?;

let account_info = AccountInfo {
name: None,
description: None,
link: None,
};

if account_info.has_info() {
INFO.save(deps.storage, &account_info)?;
}
MIGRATE_CONTEXT.save(deps.storage, &vec![])?;

let governance = GovernanceDetails::AbstractAccount {
address: env.contract.address.clone(),
};

// Set owner
let cw_gov_owner = ownership::initialize_owner(deps.branch(), governance)?;

SUSPENSION_STATUS.save(deps.storage, &false)?;

response = response.add_attribute("owner".to_owned(), cw_gov_owner.owner.to_string());

response = response.add_message(wasm_execute(
registry.address,
&abstract_std::registry::ExecuteMsg::AddAccount {
namespace: None,
creator: env.contract.address.to_string(),
},
vec![],
)?);

// Register on account if it's sub-account
if let GovernanceDetails::SubAccount { account } = cw_gov_owner.owner {
response = response.add_message(wasm_execute(
account,
&ExecuteMsg::UpdateSubAccount(UpdateSubAccountAction::RegisterSubAccount {
id: ACCOUNT_ID.load(deps.storage)?.seq(),
}),
vec![],
)?);
}

let install_modules = vec![ModuleInstallConfig::new(
ModuleInfo::from_id_latest(IBC_CLIENT)?,
None,
)];

if !install_modules.is_empty() {
// Install modules
let (install_msgs, install_attribute) =
_install_modules(deps, &env, install_modules, vec![])?;
response = response
.add_submessages(install_msgs)
.add_attribute(install_attribute.key, install_attribute.value);
}

Ok(response)
}

#[cfg(test)]
Expand Down
1 change: 1 addition & 0 deletions framework/docs/src/releases/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Added

- Added migration function to migrate from xion accounts
- Added `PfmMemoBuilder` API for building middleware forwarding memo
- Added `HookMemoBuilder` API for building wasm ibc hook memo
- `execute_with_funds` to Executor to attach funds to execution.
Expand Down
17 changes: 16 additions & 1 deletion framework/packages/abstract-interface/src/deployment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ use crate::{
get_ibc_contracts, get_native_contracts, AbstractIbc, AbstractInterfaceError, AccountI,
AnsHost, ModuleFactory, Registry,
};
use abstract_std::{native_addrs, ACCOUNT, ANS_HOST, MODULE_FACTORY, REGISTRY};
use abstract_std::{
native_addrs, objects::module::ModuleInfo, registry::QueryMsgFns, ACCOUNT, ANS_HOST,
MODULE_FACTORY, REGISTRY,
};

const CW_BLOB: &str = "cw:blob";

Expand Down Expand Up @@ -306,6 +309,18 @@ impl<Chain: CwEnv> Abstract<Chain> {
blob: self.blob.clone(),
}
}

pub fn account_code_id(&self) -> Result<u64, AbstractInterfaceError> {
let account_module_info = &self
.registry
.modules(vec![ModuleInfo::from_id_latest(ACCOUNT)?])?
.modules[0];

match account_module_info.module.reference {
abstract_std::objects::module_reference::ModuleReference::Account(code_id) => Ok(code_id),
_ => panic!("Your abstract instance has an account module that is not registered as an account. This is bad"),
}
}
}

// Sender addr means it's mock or CloneTest(which is also mock)
Expand Down
41 changes: 41 additions & 0 deletions interchain/framework-clone-testing/tests/migrate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,44 @@ mod account_factory {
create_one_account_with_namespace_fee(chain)
}
}

mod from_xion {
use super::*;
use abstract_interface::{AccountExecFns, AccountI};
use abstract_std::{account::MigrateMsg, IBC_CLIENT};
use cw_orch::prelude::*;
use networks::XION_TESTNET_1;

pub const XION_ACCOUNT: &str =
"xion1c8lhvl6hun9jfd7rvpjyprnf3c70utlvwvdxk94s43t5qaqcze9q6qz0y4";

#[test]
fn migrate_from_xion_account() -> anyhow::Result<()> {
let (deployment, chain) = common::setup(XION_TESTNET_1)?;

// We need to register the new code id
deployment.migrate_if_version_changed()?;

// This is a XION user action
let addr_contract = Addr::unchecked(XION_ACCOUNT);
let account = AccountI::new("account-xion", chain);
account.set_address(&addr_contract);

account
.call_as(&addr_contract)
.migrate(&MigrateMsg {}, deployment.account_code_id()?)?;

account
.update_info(None, None, Some("brand new abstract account".to_string()))
.unwrap_err();

account.call_as(&addr_contract).update_info(
None,
None,
Some("brand new abstract account".to_string()),
)?;

assert!(account.is_module_installed(IBC_CLIENT)?);
Ok(())
}
}

0 comments on commit 7413a12

Please sign in to comment.