use abstract_adapter::{
mock::{self, MockError, MockExecMsg, MockInitMsg},
AdapterError,
};
use abstract_integration_tests::{
add_mock_adapter_install_fee, create_default_account, init_mock_adapter, install_adapter,
install_adapter_with_funds, mock_modules,
mock_modules::adapter_1::{MockAdapterI1V1, MockAdapterI1V2},
AResult,
};
use abstract_interface::*;
use abstract_std::{
adapter::{AdapterBaseMsg, AdapterRequestMsg, BaseExecuteMsg, BaseQueryMsgFns},
manager::{ManagerModuleInfo, ModuleInstallConfig},
objects::{
fee::FixedFee,
module::{ModuleInfo, ModuleVersion, Monetization},
AccountId,
},
*,
};
use abstract_testing::prelude::*;
use cosmwasm_std::{coin, coins};
use cw_orch::prelude::*;
use mock_modules::{adapter_1, V1, V2};
use speculoos::{assert_that, result::ResultAssertions, string::StrAssertions};
#[test]
fn installing_one_adapter_should_succeed() -> AResult {
let chain = MockBech32::new("mock");
let sender = chain.sender_addr();
let deployment = Abstract::deploy_on(chain.clone(), sender.to_string())?;
let account = create_default_account(&deployment.account_factory)?;
let staking_adapter = init_mock_adapter(chain.clone(), &deployment, None, account.id()?)?;
install_adapter(&account.manager, TEST_MODULE_ID)?;
let modules = account.expect_modules(vec![staking_adapter.address()?.to_string()])?;
assert_that(&modules[1]).is_equal_to(&ManagerModuleInfo {
address: staking_adapter.address()?,
id: TEST_MODULE_ID.to_string(),
version: cw2::ContractVersion {
contract: TEST_MODULE_ID.into(),
version: TEST_VERSION.into(),
},
});
let adapter_config = staking_adapter.base_config()?;
assert_that!(adapter_config).is_equal_to(adapter::AdapterConfigResponse {
ans_host_address: deployment.ans_host.address()?,
dependencies: vec![],
version_control_address: deployment.version_control.address()?,
});
let authorized = staking_adapter.authorized_addresses(account.proxy.addr_str()?)?;
assert_that!(authorized)
.is_equal_to(adapter::AuthorizedAddressesResponse { addresses: vec![] });
take_storage_snapshot!(chain, "install_one_adapter");
Ok(())
}
#[test]
fn installing_one_adapter_without_fee_should_fail() -> AResult {
let chain = MockBech32::new("mock");
let sender = chain.sender_addr();
chain.set_balance(&sender, coins(12, "ujunox"))?;
let deployment = Abstract::deploy_on(chain.clone(), sender.to_string())?;
let account = create_default_account(&deployment.account_factory)?;
init_mock_adapter(chain.clone(), &deployment, None, account.id()?)?;
add_mock_adapter_install_fee(
&deployment,
Monetization::InstallFee(FixedFee::new(&coin(45, "ujunox"))),
None,
)?;
assert_that!(install_adapter(&account.manager, TEST_MODULE_ID)).is_err();
assert_that!(install_adapter_with_funds(
&account.manager,
TEST_MODULE_ID,
&coins(12, "ujunox")
))
.is_err();
Ok(())
}
#[test]
fn installing_one_adapter_with_fee_should_succeed() -> AResult {
let chain = MockBech32::new("mock");
let sender = chain.sender_addr();
Abstract::deploy_on(chain.clone(), sender.to_string())?;
abstract_integration_tests::manager::installing_one_adapter_with_fee_should_succeed(
chain.clone(),
)?;
take_storage_snapshot!(chain, "install_one_adapter_with_fee");
Ok(())
}
#[test]
fn install_non_existent_adapterid_should_fail() -> AResult {
let chain = MockBech32::new("mock");
let sender = chain.sender_addr();
let deployment = Abstract::deploy_on(chain, sender.to_string())?;
let account = create_default_account(&deployment.account_factory)?;
let res = install_adapter(&account.manager, "lol:no_chance");
assert_that!(res).is_err();
Ok(())
}
#[test]
fn install_non_existent_version_should_fail() -> AResult {
let chain = MockBech32::new("mock");
let sender = chain.sender_addr();
let deployment = Abstract::deploy_on(chain.clone(), sender.to_string())?;
let account = create_default_account(&deployment.account_factory)?;
init_mock_adapter(chain, &deployment, None, account.id()?)?;
let res = account.manager.install_module_version(
TEST_MODULE_ID,
ModuleVersion::Version("1.2.3".to_string()),
Some(&Empty {}),
None,
);
assert_that!(res).is_err();
Ok(())
}
#[test]
fn installation_of_duplicate_adapter_should_fail() -> AResult {
let chain = MockBech32::new("mock");
let sender = chain.sender_addr();
let deployment = Abstract::deploy_on(chain.clone(), sender.to_string())?;
let account = create_default_account(&deployment.account_factory)?;
let staking_adapter = init_mock_adapter(chain, &deployment, None, account.id()?)?;
install_adapter(&account.manager, TEST_MODULE_ID)?;
let modules = account.expect_modules(vec![staking_adapter.address()?.to_string()])?;
assert_that(&modules[1]).is_equal_to(&ManagerModuleInfo {
address: staking_adapter.address()?,
id: TEST_MODULE_ID.to_string(),
version: cw2::ContractVersion {
contract: TEST_MODULE_ID.into(),
version: TEST_VERSION.into(),
},
});
let second_install_res = install_adapter(&account.manager, TEST_MODULE_ID);
assert_that!(second_install_res)
.is_err()
.matches(|e| e.to_string().contains("test-module-id"));
account.expect_modules(vec![staking_adapter.address()?.to_string()])?;
Ok(())
}
#[test]
fn reinstalling_adapter_should_be_allowed() -> AResult {
let chain = MockBech32::new("mock");
let sender = chain.sender_addr();
let deployment = Abstract::deploy_on(chain.clone(), sender.to_string())?;
let account = create_default_account(&deployment.account_factory)?;
let staking_adapter = init_mock_adapter(chain.clone(), &deployment, None, account.id()?)?;
install_adapter(&account.manager, TEST_MODULE_ID)?;
let modules = account.expect_modules(vec![staking_adapter.address()?.to_string()])?;
assert_that(&modules[1]).is_equal_to(&ManagerModuleInfo {
address: staking_adapter.address()?,
id: TEST_MODULE_ID.to_string(),
version: cw2::ContractVersion {
contract: TEST_MODULE_ID.into(),
version: TEST_VERSION.into(),
},
});
account
.manager
.uninstall_module(TEST_MODULE_ID.to_string())?;
account.expect_modules(vec![])?;
install_adapter(&account.manager, TEST_MODULE_ID)?;
account.expect_modules(vec![staking_adapter.address()?.to_string()])?;
take_storage_snapshot!(chain, "reinstalling_adapter_should_be_allowed");
Ok(())
}
#[test]
fn reinstalling_new_version_should_install_latest() -> AResult {
let chain = MockBech32::new("mock");
let sender = chain.sender_addr();
let deployment = Abstract::deploy_on(chain.clone(), sender.to_string())?;
let account = create_default_account(&deployment.account_factory)?;
deployment
.version_control
.claim_namespace(TEST_ACCOUNT_ID, "tester".to_string())?;
let adapter1 = MockAdapterI1V1::new_test(chain.clone());
adapter1
.deploy(V1.parse().unwrap(), MockInitMsg {}, DeployStrategy::Try)
.unwrap();
install_adapter(&account.manager, &adapter1.id())?;
let modules = account.expect_modules(vec![adapter1.address()?.to_string()])?;
assert_that(&modules[1]).is_equal_to(&ManagerModuleInfo {
address: adapter1.address()?,
id: adapter1.id(),
version: cw2::ContractVersion {
contract: adapter1.id(),
version: V1.into(),
},
});
account.manager.uninstall_module(adapter1.id())?;
account.expect_modules(vec![])?;
let old_adapter_addr = adapter1.address()?;
let adapter2 = MockAdapterI1V2::new_test(chain.clone());
adapter2
.deploy(V2.parse().unwrap(), MockInitMsg {}, DeployStrategy::Try)
.unwrap();
let latest_staking = deployment
.version_control
.module(ModuleInfo::from_id_latest(&adapter1.id())?)?;
assert_that!(latest_staking.info.version).is_equal_to(ModuleVersion::Version(V2.to_string()));
install_adapter(&account.manager, &adapter2.id())?;
let modules = account.expect_modules(vec![adapter2.address()?.to_string()])?;
assert_that!(modules[1]).is_equal_to(&ManagerModuleInfo {
address: adapter2.address()?,
id: adapter2.id(),
version: cw2::ContractVersion {
contract: adapter2.id(),
version: V2.to_string(),
},
});
assert_ne!(old_adapter_addr, adapter2.address()?);
assert_that!(modules[1].address).is_equal_to(adapter2.as_instance().address()?);
take_storage_snapshot!(chain, "reinstalling_new_version_should_install_latest");
Ok(())
}
#[test]
fn unauthorized_exec() -> AResult {
let chain = MockBech32::new("mock");
let sender = chain.sender_addr();
let unauthorized = chain.addr_make("unauthorized");
let deployment = Abstract::deploy_on(chain.clone(), sender.to_string())?;
let account = create_default_account(&deployment.account_factory)?;
let staking_adapter = init_mock_adapter(chain.clone(), &deployment, None, account.id()?)?;
install_adapter(&account.manager, TEST_MODULE_ID)?;
let res = staking_adapter
.call_as(&unauthorized)
.execute(&MockExecMsg {}.into(), None)
.unwrap_err();
assert_that!(res.root().to_string()).contains(format!(
"Sender: {} of request to tester:test-module-id is not a Manager or Authorized Address",
unauthorized
));
let res = staking_adapter
.execute(&MockExecMsg {}.into(), None)
.unwrap_err();
assert_that!(&res.root().to_string()).contains(format!(
"Sender: {} of request to tester:test-module-id is not a Manager or Authorized Address",
chain.sender_addr()
));
Ok(())
}
#[test]
fn manager_adapter_exec() -> AResult {
let chain = MockBech32::new("mock");
let sender = chain.sender_addr();
let deployment = Abstract::deploy_on(chain.clone(), sender.to_string())?;
let account = create_default_account(&deployment.account_factory)?;
let _staking_adapter_one = init_mock_adapter(chain.clone(), &deployment, None, account.id()?)?;
install_adapter(&account.manager, TEST_MODULE_ID)?;
chain.set_balance(&account.proxy.address()?, vec![Coin::new(100_000, TTOKEN)])?;
account.manager.execute_on_module(
TEST_MODULE_ID,
Into::<abstract_std::adapter::ExecuteMsg<MockExecMsg>>::into(MockExecMsg {}),
)?;
Ok(())
}
#[test]
fn installing_specific_version_should_install_expected() -> AResult {
let chain = MockBech32::new("mock");
let sender = chain.sender_addr();
let deployment = Abstract::deploy_on(chain.clone(), sender.to_string())?;
let account = create_default_account(&deployment.account_factory)?;
deployment
.version_control
.claim_namespace(TEST_ACCOUNT_ID, "tester".to_string())?;
let adapter1 = MockAdapterI1V1::new_test(chain.clone());
adapter1
.deploy(V1.parse().unwrap(), MockInitMsg {}, DeployStrategy::Try)
.unwrap();
let v1_adapter_addr = adapter1.address()?;
let adapter2 = MockAdapterI1V2::new_test(chain.clone());
adapter2
.deploy(V2.parse().unwrap(), MockInitMsg {}, DeployStrategy::Try)
.unwrap();
let expected_version = "1.0.0".to_string();
account.manager.install_module_version(
&adapter1.id(),
ModuleVersion::Version(expected_version),
Some(&MockInitMsg {}),
None,
)?;
let modules = account.expect_modules(vec![v1_adapter_addr.to_string()])?;
let installed_module: ManagerModuleInfo = modules[1].clone();
assert_that!(installed_module.id).is_equal_to(adapter1.id());
take_storage_snapshot!(chain, "installing_specific_version_should_install_expected");
Ok(())
}
#[test]
fn account_install_adapter() -> AResult {
let chain = MockBech32::new("mock");
let sender = chain.sender_addr();
let deployment = Abstract::deploy_on(chain.clone(), sender.to_string())?;
let account = create_default_account(&deployment.account_factory)?;
deployment
.version_control
.claim_namespace(TEST_ACCOUNT_ID, "tester".to_owned())?;
let adapter = MockAdapterI1V1::new_test(chain.clone());
adapter.deploy(V1.parse().unwrap(), MockInitMsg {}, DeployStrategy::Try)?;
let adapter_addr = account.install_adapter(&adapter, None)?;
let module_addr = account
.manager
.module_info(adapter_1::MOCK_ADAPTER_ID)?
.unwrap()
.address;
assert_that!(adapter_addr).is_equal_to(module_addr);
take_storage_snapshot!(chain, "account_install_adapter");
Ok(())
}
#[test]
fn account_adapter_ownership() -> AResult {
let chain = MockBech32::new("mock");
let sender = chain.sender_addr();
let deployment = Abstract::deploy_on(chain.clone(), sender.to_string())?;
let account = create_default_account(&deployment.account_factory)?;
deployment
.version_control
.claim_namespace(TEST_ACCOUNT_ID, "tester".to_owned())?;
let adapter = MockAdapterI1V1::new_test(chain.clone());
adapter.deploy(V1.parse().unwrap(), MockInitMsg {}, DeployStrategy::Try)?;
account.install_adapter(&adapter, None)?;
let proxy_addr = account.proxy.address()?;
adapter.call_as(&sender).execute(
&mock::ExecuteMsg::Module(AdapterRequestMsg {
proxy_address: Some(proxy_addr.to_string()),
request: MockExecMsg {},
}),
None,
)?;
adapter.call_as(&account.manager.address()?).execute(
&mock::ExecuteMsg::Module(AdapterRequestMsg {
proxy_address: Some(proxy_addr.to_string()),
request: MockExecMsg {},
}),
None,
)?;
let who = chain.addr_make("who");
let err: MockError = adapter
.call_as(&who)
.execute(
&mock::ExecuteMsg::Module(AdapterRequestMsg {
proxy_address: Some(proxy_addr.to_string()),
request: MockExecMsg {},
}),
None,
)
.unwrap_err()
.downcast()
.unwrap();
assert_eq!(
err,
MockError::Adapter(AdapterError::UnauthorizedAddressAdapterRequest {
adapter: adapter_1::MOCK_ADAPTER_ID.to_owned(),
sender: who.to_string()
})
);
adapter.call_as(&sender).execute(
&mock::ExecuteMsg::Base(BaseExecuteMsg {
proxy_address: Some(proxy_addr.to_string()),
msg: AdapterBaseMsg::UpdateAuthorizedAddresses {
to_add: vec![chain.addr_make("123").to_string()],
to_remove: vec![],
},
}),
None,
)?;
adapter.call_as(&account.manager.address()?).execute(
&mock::ExecuteMsg::Base(BaseExecuteMsg {
proxy_address: Some(proxy_addr.to_string()),
msg: AdapterBaseMsg::UpdateAuthorizedAddresses {
to_add: vec![chain.addr_make("234").to_string()],
to_remove: vec![],
},
}),
None,
)?;
let err: MockError = adapter
.call_as(&who)
.execute(
&mock::ExecuteMsg::Base(BaseExecuteMsg {
proxy_address: Some(proxy_addr.to_string()),
msg: AdapterBaseMsg::UpdateAuthorizedAddresses {
to_add: vec![chain.addr_make("345").to_string()],
to_remove: vec![],
},
}),
None,
)
.unwrap_err()
.downcast()
.unwrap();
assert_eq!(
err,
MockError::Adapter(AdapterError::UnauthorizedAdapterRequest {
adapter: adapter_1::MOCK_ADAPTER_ID.to_owned(),
sender: who.to_string()
})
);
Ok(())
}
#[test]
fn subaccount_adapter_ownership() -> AResult {
let chain = MockBech32::new("mock");
let sender = chain.sender_addr();
let deployment = Abstract::deploy_on(chain.clone(), sender.to_string())?;
let account = create_default_account(&deployment.account_factory)?;
deployment
.version_control
.claim_namespace(TEST_ACCOUNT_ID, "tester".to_owned())?;
let adapter = MockAdapterI1V1::new_test(chain.clone());
adapter.deploy(V1.parse().unwrap(), MockInitMsg {}, DeployStrategy::Try)?;
account.manager.create_sub_account(
vec![ModuleInstallConfig::new(
ModuleInfo::from_id_latest(adapter_1::MOCK_ADAPTER_ID).unwrap(),
None,
)],
"My subaccount".to_string(),
None,
None,
None,
None,
None,
&[],
)?;
let sub_account = AbstractAccount::new(&deployment, AccountId::local(2));
let module = sub_account
.manager
.module_info(adapter_1::MOCK_ADAPTER_ID)?
.unwrap();
adapter.set_address(&module.address);
let proxy_addr = sub_account.proxy.address()?;
adapter.call_as(&sender).execute(
&mock::ExecuteMsg::Module(AdapterRequestMsg {
proxy_address: Some(proxy_addr.to_string()),
request: MockExecMsg {},
}),
None,
)?;
adapter.call_as(&sub_account.manager.address()?).execute(
&mock::ExecuteMsg::Module(AdapterRequestMsg {
proxy_address: Some(proxy_addr.to_string()),
request: MockExecMsg {},
}),
None,
)?;
let who = chain.addr_make("who");
let err: MockError = adapter
.call_as(&who)
.execute(
&mock::ExecuteMsg::Module(AdapterRequestMsg {
proxy_address: Some(proxy_addr.to_string()),
request: MockExecMsg {},
}),
None,
)
.unwrap_err()
.downcast()
.unwrap();
assert_eq!(
err,
MockError::Adapter(AdapterError::UnauthorizedAddressAdapterRequest {
adapter: adapter_1::MOCK_ADAPTER_ID.to_owned(),
sender: who.to_string()
})
);
adapter.call_as(&sender).execute(
&mock::ExecuteMsg::Base(BaseExecuteMsg {
proxy_address: Some(proxy_addr.to_string()),
msg: AdapterBaseMsg::UpdateAuthorizedAddresses {
to_add: vec![chain.addr_make("123").to_string()],
to_remove: vec![],
},
}),
None,
)?;
adapter.call_as(&sub_account.manager.address()?).execute(
&mock::ExecuteMsg::Base(BaseExecuteMsg {
proxy_address: Some(proxy_addr.to_string()),
msg: AdapterBaseMsg::UpdateAuthorizedAddresses {
to_add: vec![chain.addr_make("234").to_string()],
to_remove: vec![],
},
}),
None,
)?;
let err: MockError = adapter
.call_as(&who)
.execute(
&mock::ExecuteMsg::Base(BaseExecuteMsg {
proxy_address: Some(proxy_addr.to_string()),
msg: AdapterBaseMsg::UpdateAuthorizedAddresses {
to_add: vec![chain.addr_make("345").to_string()],
to_remove: vec![],
},
}),
None,
)
.unwrap_err()
.downcast()
.unwrap();
assert_eq!(
err,
MockError::Adapter(AdapterError::UnauthorizedAdapterRequest {
adapter: adapter_1::MOCK_ADAPTER_ID.to_owned(),
sender: who.to_string()
})
);
Ok(())
}
mod old_mock {
use super::*;
use abstract_adapter::gen_adapter_old_mock;
use mock_modules::adapter_1::MOCK_ADAPTER_ID;
gen_adapter_old_mock!(OldMockAdapter1V1, MOCK_ADAPTER_ID, "1.0.0", &[]);
#[test]
fn old_adapters_migratable() -> AResult {
let chain = MockBech32::new("mock");
let sender = chain.sender_addr();
let deployment = Abstract::deploy_on(chain.clone(), sender.to_string())?;
let account = create_default_account(&deployment.account_factory)?;
deployment
.version_control
.claim_namespace(TEST_ACCOUNT_ID, "tester".to_owned())?;
let old = OldMockAdapter1V1::new_test(chain.clone());
old.deploy(V1.parse().unwrap(), MockInitMsg {}, DeployStrategy::Try)?;
account.install_adapter(&old, None)?;
let new = MockAdapterI1V2::new_test(chain.clone());
new.deploy(V2.parse().unwrap(), MockInitMsg {}, DeployStrategy::Try)?;
account.manager.upgrade_module(MOCK_ADAPTER_ID, &Empty {})?;
Ok(())
}
}