Skip to content

Commit

Permalink
Add ability to query version of no-cw2 modules (#69)
Browse files Browse the repository at this point in the history
* Changed account id structure

* Corrected tests

* formatting

* Cleanup and test

* Changelog

* Corrected imports

* null for no cw-2 contracts

* save version after register module

* changelog update

* not mut

* query what

* Fixed tests

* improve ChainName construction strictness

* fix tests

* Cleanup and storage key shortening

* fix test

* clippy fix

* standalone return moduleinfos

* remove osmosis remenant

* bump cw-orch

* simplify version

* update changelog v2

* Hot fix for cw-orch 0.16.0

* Moved from_str to trait

* comment changes

* bump cw-orch

* fix tests

* formatting

* apply robin feedback

* rm unused import

* format

* clippy unused exports

* update STANDALONE storage mutations

* fix clippy

---------

Co-authored-by: Kayanski <[email protected]>
Co-authored-by: cyberhoward <[email protected]>
Co-authored-by: CyberHoward <[email protected]>
  • Loading branch information
4 people authored Sep 13, 2023
1 parent 32bca28 commit 6595c5e
Show file tree
Hide file tree
Showing 10 changed files with 120 additions and 33 deletions.
1 change: 1 addition & 0 deletions framework/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Manager governance now changes only after new "owner" claimed ownership.
- Fixed and separated cw-staking and dex adapters for kujira.
- `ExecOnModule` calls now forward any provided funds to the module that is called.
- Manager queries of standalone module versions will now return version of the contract from the Version Control storage instead of error

## [0.17.2] - 2023-07-27

Expand Down
3 changes: 0 additions & 3 deletions framework/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,6 @@ rstest = "0.17.0"
speculoos = "0.11.0"
anyhow = "1"

[patch.crates-io]
cw-orch = { git = "https://github.com/AbstractSDK/cw-orchestrator", branch = "main" }

# Backup release profile, will result in warnings during optimization
[profile.release]
rpath = false
Expand Down
13 changes: 8 additions & 5 deletions framework/contracts/account/manager/src/commands.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{contract::ManagerResult, error::ManagerError, queries::query_module_cw2};
use crate::{contract::ManagerResult, error::ManagerError, queries::query_module_version};
use crate::{validation, versioning};
use abstract_core::manager::state::{
ACCOUNT_FACTORY, MODULE_QUEUE, PENDING_GOVERNANCE, SUB_ACCOUNTS,
Expand Down Expand Up @@ -528,8 +528,12 @@ pub fn set_migrate_msgs_and_context(
migrate_msg: Option<Binary>,
msgs: &mut Vec<CosmosMsg>,
) -> Result<(), ManagerError> {
let config = CONFIG.load(deps.storage)?;
let version_control = VersionControlContract::new(config.version_control_address);

let old_module_addr = load_module_addr(deps.storage, &module_info.id())?;
let old_module_cw2 = query_module_cw2(&deps.as_ref(), old_module_addr.clone())?;
let old_module_cw2 =
query_module_version(deps.as_ref(), old_module_addr.clone(), &version_control)?;
let requested_module = query_module(deps.as_ref(), module_info.clone(), Some(old_module_cw2))?;

let migrate_msgs = match requested_module.module.reference {
Expand Down Expand Up @@ -789,7 +793,7 @@ fn uninstall_ibc_client(deps: DepsMut, proxy: Addr, ibc_client: Addr) -> StdResu
fn query_module(
deps: Deps,
module_info: ModuleInfo,
old_contract_cw2: Option<ContractVersion>,
old_contract_version: Option<ContractVersion>,
) -> Result<ModuleResponse, ManagerError> {
let config = CONFIG.load(deps.storage)?;
// Construct feature object to access registry functions
Expand All @@ -798,7 +802,7 @@ fn query_module(

let module = match &module_info.version {
ModuleVersion::Version(new_version) => {
let old_contract = old_contract_cw2.unwrap();
let old_contract = old_contract_version.unwrap();

let new_version = new_version.parse::<Version>().unwrap();
let old_version = old_contract.version.parse::<Version>().unwrap();
Expand All @@ -809,7 +813,6 @@ fn query_module(
old_version.to_string(),
));
}

Module {
info: module_info.clone(),
reference: version_registry.query_module_reference_raw(&module_info)?,
Expand Down
65 changes: 53 additions & 12 deletions framework/contracts/account/manager/src/queries.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use abstract_core::manager::state::{Config, SUB_ACCOUNTS, SUSPENSION_STATUS};
use abstract_core::manager::SubAccountIdsResponse;
use abstract_core::objects::module::{self, ModuleInfo};
use abstract_sdk::core::manager::state::{AccountInfo, ACCOUNT_ID, ACCOUNT_MODULES, CONFIG, INFO};
use abstract_sdk::core::manager::{
ConfigResponse, InfoResponse, ManagerModuleInfo, ModuleAddressesResponse, ModuleInfosResponse,
ModuleVersionsResponse,
};
use cosmwasm_std::{
to_binary, Addr, Binary, Deps, Env, Order, QueryRequest, StdError, StdResult, WasmQuery,
};
use cw2::{ContractVersion, CONTRACT};
use abstract_sdk::feature_objects::VersionControlContract;
use abstract_sdk::ModuleRegistryInterface;
use cosmwasm_std::{to_binary, Addr, Binary, Deps, Env, Order, StdError, StdResult};
use cw2::ContractVersion;
use cw_storage_plus::Bound;
use std::collections::BTreeMap;

Expand Down Expand Up @@ -62,9 +63,13 @@ pub fn handle_module_info_query(
.collect();

let ids_and_addr = res?;

let config = CONFIG.load(deps.storage)?;
let version_control = VersionControlContract::new(config.version_control_address);

let mut resp_vec: Vec<ManagerModuleInfo> = vec![];
for (id, address) in ids_and_addr.into_iter() {
let version = query_module_cw2(&deps, address.clone())?;
let version = query_module_version(deps, address.clone(), &version_control)?;
resp_vec.push(ManagerModuleInfo {
id,
version,
Expand Down Expand Up @@ -94,12 +99,45 @@ pub fn handle_sub_accounts_query(
}

/// RawQuery the version of an enabled module
pub fn query_module_cw2(deps: &Deps, module_addr: Addr) -> StdResult<ContractVersion> {
let req = QueryRequest::Wasm(WasmQuery::Raw {
contract_addr: module_addr.into(),
key: CONTRACT.as_slice().into(),
});
deps.querier.query::<ContractVersion>(&req)
pub fn query_module_version(
deps: Deps,
module_addr: Addr,
version_control: &VersionControlContract,
) -> StdResult<ContractVersion> {
let module_registry = version_control.module_registry(deps);

if let Ok(info) = cw2::query_contract_info(&deps.querier, module_addr.to_string()) {
// Check if it's abstract format and return now
if ModuleInfo::from_id(
&info.contract,
module::ModuleVersion::Version(info.version.clone()),
)
.is_ok()
{
return Ok(info);
}
}
// Right now we have either
// - failed cw2 query
// - the query succeeded but the cw2 name doesn't adhere to our formatting standards
//
// Which means this contract is a standalone contract. Hence we need to get its information from VersionControl.
let code_id = deps
.querier
.query_wasm_contract_info(module_addr.to_string())?
.code_id;
module_registry
.query_standalone_info(code_id)
.and_then(|module_info| {
let module_info =
module_info.ok_or(abstract_sdk::AbstractSdkError::StandaloneNotFound {
code_id,
registry_addr: version_control.address.clone(),
})?;
let version = ContractVersion::try_from(module_info)?;
Ok(version)
})
.map_err(|e| StdError::generic_err(e.to_string()))
}

/// RawQuery the module versions of the modules part of the Account
Expand All @@ -112,8 +150,11 @@ pub fn query_module_versions(
let addresses: BTreeMap<String, Addr> =
query_module_addresses(deps, manager_addr, module_names)?;
let mut module_versions: BTreeMap<String, ContractVersion> = BTreeMap::new();

let config = CONFIG.load(deps.storage)?;
let version_control = VersionControlContract::new(config.version_control_address);
for (name, address) in addresses.into_iter() {
let result = query_module_cw2(&deps, address)?;
let result = query_module_version(deps, address, &version_control)?;
module_versions.insert(name, result);
}
Ok(module_versions)
Expand Down
19 changes: 9 additions & 10 deletions framework/contracts/account/manager/tests/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use common::{
create_default_account, init_mock_adapter, install_adapter, mock_modules, AResult, TEST_COIN,
};
use cosmwasm_std::{coin, to_binary, wasm_execute, Addr, Coin, CosmosMsg};
use cw2::ContractVersion;
use cw_orch::deploy::Deploy;
use cw_orch::prelude::*;
use module_factory::error::ModuleFactoryError;
Expand Down Expand Up @@ -384,21 +383,21 @@ fn install_multiple_modules() -> AResult {
// Make sure all installed
let account_module_versions = account.manager.module_versions(vec![
String::from("abstract:standalone1"),
// Querying no_cw2 fails
// String::from("abstract:standalone2"),
String::from("abstract:standalone2"),
])?;
assert_eq!(
account_module_versions,
ModuleVersionsResponse {
versions: vec![
ContractVersion {
contract: String::from(mock_modules::standalone_cw2::MOCK_STANDALONE_ID),
version: String::from(mock_modules::V1)
cw2::ContractVersion {
contract: String::from("abstract:standalone1"),
version: String::from(mock_modules::V1),
},
// Second doesn't have cw2
cw2::ContractVersion {
contract: String::from("abstract:standalone2"),
version: String::from(mock_modules::V1),
},
// ContractVersion {
// contract: String::from("abstract:standalone2"),
// version: String::from(mock_modules::V1)
// },
]
}
);
Expand Down
20 changes: 19 additions & 1 deletion framework/contracts/native/version-control/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ pub fn propose_modules(
None,
)?;
REGISTERED_MODULES.save(deps.storage, &module, &mod_ref)?;
// Save module info of standalone contracts,
// helps querying version for cw-2-less or mis-formatted contracts
if let ModuleReference::Standalone(id) = mod_ref {
STANDALONE_INFOS.save(deps.storage, id, &module)?;
}
} else {
PENDING_MODULES.save(deps.storage, &module, &mod_ref)?;
}
Expand Down Expand Up @@ -148,6 +153,12 @@ fn approve_modules(storage: &mut dyn Storage, approves: Vec<ModuleInfo>) -> VCRe
REGISTERED_MODULES.save(storage, module, &mod_ref)?;
// Remove from pending
PENDING_MODULES.remove(storage, module);

// Save module info of standalone contracts,
// helps querying version for cw-2-less or mis-formatted contracts
if let ModuleReference::Standalone(id) = mod_ref {
STANDALONE_INFOS.save(storage, id, module)?;
}
}

let approves: Vec<_> = approves.into_iter().map(|m| m.to_string()).collect();
Expand Down Expand Up @@ -175,15 +186,22 @@ pub fn remove_module(deps: DepsMut, msg_info: MessageInfo, module: ModuleInfo) -
// Only specific versions may be removed
module.assert_version_variant()?;

let module_ref_res = REGISTERED_MODULES.load(deps.storage, &module);

ensure!(
REGISTERED_MODULES.has(deps.storage, &module) || YANKED_MODULES.has(deps.storage, &module),
module_ref_res.is_ok() || YANKED_MODULES.has(deps.storage, &module),
VCError::ModuleNotFound(module)
);

REGISTERED_MODULES.remove(deps.storage, &module);
YANKED_MODULES.remove(deps.storage, &module);
MODULE_CONFIG.remove(deps.storage, &module);

// Remove standalone info
if let Ok(ModuleReference::Standalone(id)) = module_ref_res {
STANDALONE_INFOS.remove(deps.storage, id);
}

// If this module has no more versions, we also remove default configuration
if REGISTERED_MODULES
.prefix((module.namespace.clone(), module.name.clone()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ pub mod state {
pub const PENDING_MODULES: Map<&ModuleInfo, ModuleReference> = Map::new("pendm");
// We can iterate over the map giving just the prefix to get all the versions
pub const REGISTERED_MODULES: Map<&ModuleInfo, ModuleReference> = Map::new("lib");
// Reverse map for module info of standalone modules
pub const STANDALONE_INFOS: Map<u64, ModuleInfo> = Map::new("stli");
// Yanked Modules
pub const YANKED_MODULES: Map<&ModuleInfo, ModuleReference> = Map::new("yknd");
// Modules Configuration
Expand Down
14 changes: 14 additions & 0 deletions framework/packages/abstract-core/src/objects/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,20 @@ pub struct ModuleInfo {
pub version: ModuleVersion,
}

impl TryFrom<ModuleInfo> for ContractVersion {
type Error = AbstractError;

fn try_from(value: ModuleInfo) -> Result<Self, Self::Error> {
let ModuleVersion::Version(version) = value.version else {
return Err(AbstractError::MissingVersion("module".to_owned()));
};
Ok(ContractVersion {
contract: format!("{}:{}", value.namespace, value.name),
version,
})
}
}

const MAX_LENGTH: usize = 64;

/// Validate attributes of a [`ModuleInfo`].
Expand Down
12 changes: 10 additions & 2 deletions framework/packages/abstract-sdk/src/apis/version_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use abstract_core::{
namespace::Namespace,
},
version_control::{
state::REGISTERED_MODULES, ModuleConfiguration, ModuleResponse, ModulesResponse,
NamespaceResponse, QueryMsg,
state::{REGISTERED_MODULES, STANDALONE_INFOS},
ModuleConfiguration, ModuleResponse, ModulesResponse, NamespaceResponse, QueryMsg,
},
};
use cosmwasm_std::Deps;
Expand Down Expand Up @@ -112,4 +112,12 @@ impl<'a, T: ModuleRegistryInterface> ModuleRegistry<'a, T> {
)?)?;
Ok(namespace_response)
}

/// Queries the module info of the standalone code id
pub fn query_standalone_info(&self, code_id: u64) -> AbstractSdkResult<Option<ModuleInfo>> {
let registry_addr = self.base.abstract_registry(self.deps)?.address;

let info = STANDALONE_INFOS.query(&self.deps.querier, registry_addr, code_id)?;
Ok(info)
}
}
4 changes: 4 additions & 0 deletions framework/packages/abstract-sdk/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ pub enum AbstractSdkError {
#[error("Module {module} not found in version registry {registry_addr}.")]
ModuleNotFound { module: String, registry_addr: Addr },

// module not found in version registry
#[error("Standalone {code_id} not found in version registry {registry_addr}.")]
StandaloneNotFound { code_id: u64, registry_addr: Addr },

// callback not called by IBC client
#[error("IBC callback called by {caller} instead of IBC client {client_addr}.")]
CallbackNotCalledByIbcClient {
Expand Down

0 comments on commit 6595c5e

Please sign in to comment.