From f3ec59d51d816ef575ec99d6df7c9f1aaed22552 Mon Sep 17 00:00:00 2001 From: Connor Barr Date: Thu, 2 Jan 2025 13:55:17 +0000 Subject: [PATCH] feat: kernel environment variables (#738) Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- CHANGELOG.md | 1 + Cargo.lock | 3 +- Cargo.toml | 3 +- .../src/contract.rs | 10 +- contracts/os/andromeda-kernel/Cargo.toml | 3 +- contracts/os/andromeda-kernel/src/contract.rs | 4 +- contracts/os/andromeda-kernel/src/execute.rs | 173 +++++++++++++----- contracts/os/andromeda-kernel/src/query.rs | 11 +- contracts/os/andromeda-kernel/src/state.rs | 2 +- .../os/andromeda-kernel/src/testing/tests.rs | 122 +++++++++++- contracts/os/andromeda-vfs/src/execute.rs | 6 +- ibc-tests/Cargo.toml | 3 +- packages/std/src/error.rs | 6 + packages/std/src/os/aos_querier.rs | 10 + packages/std/src/os/kernel.rs | 19 ++ packages/std/src/testing/mock_querier.rs | 16 ++ tests-integration/Cargo.toml | 2 +- 17 files changed, 336 insertions(+), 58 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 913cb15c8..5a2ecc540 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Rates: Handle cross-chain recipients [(#671)](https://github.com/andromedaprotocol/andromeda-core/pull/671) - Permissions: Permissioned Actors in AndromedaQuery [(#717)](https://github.com/andromedaprotocol/andromeda-core/pull/717) - Added Schema and Form ADOs [(#591)](https://github.com/andromedaprotocol/andromeda-core/pull/591) +- feat: kernel environment variables [#738](https://github.com/andromedaprotocol/andromeda-core/pull/738) - Flat Rate denom can be a VFS path [(#727)](https://github.com/andromedaprotocol/andromeda-core/pull/727) - Auction ADO: Added buy_now_price option in Update Auction [(#730)](https://github.com/andromedaprotocol/andromeda-core/pull/730) diff --git a/Cargo.lock b/Cargo.lock index faa66e102..ba65e03c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -605,7 +605,7 @@ dependencies = [ [[package]] name = "andromeda-kernel" -version = "1.2.0-b.1" +version = "1.2.0-b.2" dependencies = [ "andromeda-std", "cosmwasm-schema", @@ -618,6 +618,7 @@ dependencies = [ "osmosis-std", "osmosis-std-derive 0.15.3", "prost 0.11.9", + "rstest", "schemars", "serde", "serde-json-wasm 1.0.1", diff --git a/Cargo.toml b/Cargo.toml index c3cf8c1fd..bfd9175a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,5 +67,6 @@ cw-multi-test = { version = "1.0.0", features = ["cosmwasm_1_2"] } serde = { version = "1.0.217" } test-case = { version = "3.3.1" } cw-orch = "=0.24.1" -jsonschema-valid = { version = "0.5.2"} +jsonschema-valid = { version = "0.5.2" } serde_json = { version = "1.0.134" } +rstest = "0.23.0" diff --git a/contracts/finance/andromeda-validator-staking/src/contract.rs b/contracts/finance/andromeda-validator-staking/src/contract.rs index 02fc878db..572bde9e0 100644 --- a/contracts/finance/andromeda-validator-staking/src/contract.rs +++ b/contracts/finance/andromeda-validator-staking/src/contract.rs @@ -325,9 +325,15 @@ fn execute_claim( ); let kernel_addr = ADOContract::default().get_kernel_address(deps.storage)?; - let curr_chain = AOSQuerier::get_current_chain(&deps.querier, &kernel_addr)?; - let withdraw_msg: CosmosMsg = if curr_chain == "andromeda" { + let is_andromeda_distribution = AOSQuerier::get_env_variable::( + &deps.querier, + &kernel_addr, + "andromeda_distribution", + )? + .unwrap_or(false); + + let withdraw_msg: CosmosMsg = if is_andromeda_distribution { MsgWithdrawDelegatorReward { delegator_address: delegator.to_string(), validator_address: validator.to_string(), diff --git a/contracts/os/andromeda-kernel/Cargo.toml b/contracts/os/andromeda-kernel/Cargo.toml index 651933c6d..5d0662234 100644 --- a/contracts/os/andromeda-kernel/Cargo.toml +++ b/contracts/os/andromeda-kernel/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "andromeda-kernel" -version = "1.2.0-b.1" +version = "1.2.0-b.2" authors = ["Connor Barr "] edition = "2021" rust-version = "1.65.0" @@ -47,3 +47,4 @@ cw-orch = { workspace = true } [dev-dependencies] # andromeda-testing = { workspace = true, optional = true } +rstest = { workspace = true } diff --git a/contracts/os/andromeda-kernel/src/contract.rs b/contracts/os/andromeda-kernel/src/contract.rs index 7846a8034..a8db17cbb 100644 --- a/contracts/os/andromeda-kernel/src/contract.rs +++ b/contracts/os/andromeda-kernel/src/contract.rs @@ -127,8 +127,9 @@ pub fn execute( ExecuteMsg::UpdateChainName { chain_name } => { execute::update_chain_name(execute_env, chain_name) } + ExecuteMsg::SetEnv { variable, value } => execute::set_env(execute_env, variable, value), + ExecuteMsg::UnsetEnv { variable } => execute::unset_env(execute_env, variable), ExecuteMsg::Internal(msg) => execute::internal(execute_env, msg), - // Base message ExecuteMsg::Ownership(ownership_message) => ADOContract::default().execute_ownership( execute_env.deps, execute_env.env, @@ -175,5 +176,6 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result { encode_binary(&query::chain_name_by_channel(deps, channel)?) } + QueryMsg::GetEnv { variable } => encode_binary(&query::get_env(deps, variable)?), } } diff --git a/contracts/os/andromeda-kernel/src/execute.rs b/contracts/os/andromeda-kernel/src/execute.rs index 586ce4f8e..892c8ca8d 100644 --- a/contracts/os/andromeda-kernel/src/execute.rs +++ b/contracts/os/andromeda-kernel/src/execute.rs @@ -20,7 +20,7 @@ use cosmwasm_std::{ use crate::query; use crate::state::{ ADO_OWNER, CHAIN_TO_CHANNEL, CHANNEL_TO_CHAIN, CHANNEL_TO_EXECUTE_MSG, CURR_CHAIN, - IBC_FUND_RECOVERY, KERNEL_ADDRESSES, PENDING_MSG_AND_FUNDS, TRIGGER_KEY, + ENV_VARIABLES, IBC_FUND_RECOVERY, KERNEL_ADDRESSES, PENDING_MSG_AND_FUNDS, TRIGGER_KEY, }; pub fn send(ctx: ExecuteContext, message: AMPMsg) -> Result { @@ -256,42 +256,49 @@ pub fn create( chain.is_none() || owner.is_some(), ContractError::Unauthorized {} ); - if let Some(_chain) = chain { - Err(ContractError::CrossChainComponentsCurrentlyDisabled {}) - // let channel_info = if let Some(channel_info) = - // CHAIN_TO_CHANNEL.may_load(execute_ctx.deps.storage, &chain)? - // { - // Ok::(channel_info) - // } else { - // return Err(ContractError::InvalidPacket { - // error: Some(format!("Channel not found for chain {chain}")), - // }); - // }?; - // let kernel_msg = IbcExecuteMsg::CreateADO { - // instantiation_msg: msg.clone(), - // owner: owner.clone().unwrap(), - // ado_type: ado_type.clone(), - // }; - // let ibc_msg = IbcMsg::SendPacket { - // channel_id: channel_info.direct_channel_id.clone().unwrap(), - // data: to_json_binary(&kernel_msg)?, - // timeout: execute_ctx - // .env - // .block - // .time - // .plus_seconds(PACKET_LIFETIME) - // .into(), - // }; - // Ok(Response::default() - // .add_message(ibc_msg) - // .add_attributes(vec![ - // attr("action", "execute_create"), - // attr("ado_type", ado_type), - // attr("owner", owner.unwrap().to_string()), - // attr("chain", chain), - // attr("receiving_kernel_address", channel_info.kernel_address), - // attr("msg", msg.to_string()), - // ])) + if let Some(chain) = chain { + let cross_chain_components_enabled = ENV_VARIABLES + .may_load(execute_ctx.deps.storage, "cross_chain_components_enabled")? + .unwrap_or("false".to_string()); + ensure!( + cross_chain_components_enabled == "true", + ContractError::CrossChainComponentsCurrentlyDisabled {} + ); + + let channel_info = if let Some(channel_info) = + CHAIN_TO_CHANNEL.may_load(execute_ctx.deps.storage, &chain)? + { + Ok::(channel_info) + } else { + return Err(ContractError::InvalidPacket { + error: Some(format!("Channel not found for chain {chain}")), + }); + }?; + let kernel_msg = IbcExecuteMsg::CreateADO { + instantiation_msg: msg.clone(), + owner: owner.clone().unwrap(), + ado_type: ado_type.clone(), + }; + let ibc_msg = IbcMsg::SendPacket { + channel_id: channel_info.direct_channel_id.clone().unwrap(), + data: to_json_binary(&kernel_msg)?, + timeout: execute_ctx + .env + .block + .time + .plus_seconds(PACKET_LIFETIME) + .into(), + }; + Ok(Response::default() + .add_message(ibc_msg) + .add_attributes(vec![ + attr("action", "execute_create"), + attr("ado_type", ado_type), + attr("owner", owner.unwrap().to_string()), + attr("chain", chain), + attr("receiving_kernel_address", channel_info.kernel_address), + attr("msg", msg.to_string()), + ])) } else { let vfs_addr = KERNEL_ADDRESSES.load(execute_ctx.deps.storage, VFS_KEY)?; let adodb_addr = KERNEL_ADDRESSES.load(execute_ctx.deps.storage, ADO_DB_KEY)?; @@ -473,6 +480,86 @@ pub fn update_chain_name( .add_attribute("chain_name", chain_name)) } +pub fn set_env( + execute_ctx: ExecuteContext, + variable: String, + value: String, +) -> Result { + let contract = ADOContract::default(); + ensure!( + contract.is_contract_owner(execute_ctx.deps.storage, execute_ctx.info.sender.as_str())?, + ContractError::Unauthorized {} + ); + + ensure!( + !variable.is_empty(), + ContractError::InvalidEnvironmentVariable { + msg: "Environment variable name cannot be empty".to_string() + } + ); + + ensure!( + variable + .chars() + .all(|c| c.is_ascii_alphanumeric() || c == '_'), + ContractError::InvalidEnvironmentVariable { + msg: + "Environment variable name can only contain alphanumeric characters and underscores" + .to_string() + } + ); + + ensure!( + variable.len() <= 100, + ContractError::InvalidEnvironmentVariable { + msg: "Environment variable name length exceeds the maximum allowed length of 100 characters".to_string() + } + ); + + ensure!( + !value.is_empty(), + ContractError::InvalidEnvironmentVariable { + msg: "Environment variable value cannot be empty".to_string() + } + ); + + ensure!( + value.len() <= 100, + ContractError::InvalidEnvironmentVariable { + msg: "Environment variable value length exceeds the maximum allowed length of 100 characters".to_string() + } + ); + + ENV_VARIABLES.save( + execute_ctx.deps.storage, + &variable.to_ascii_uppercase(), + &value, + )?; + Ok(Response::default() + .add_attribute("action", "set_env") + .add_attribute("variable", variable) + .add_attribute("value", value)) +} + +pub fn unset_env(execute_ctx: ExecuteContext, variable: String) -> Result { + let contract = ADOContract::default(); + ensure!( + contract.is_contract_owner(execute_ctx.deps.storage, execute_ctx.info.sender.as_str())?, + ContractError::Unauthorized {} + ); + + ensure!( + ENV_VARIABLES + .may_load(execute_ctx.deps.storage, &variable.to_ascii_uppercase())? + .is_some(), + ContractError::EnvironmentVariableNotFound { variable } + ); + ENV_VARIABLES.remove(execute_ctx.deps.storage, &variable.to_ascii_uppercase()); + Ok(Response::default() + .add_attribute("action", "unset_env") + .add_attribute("variable", variable)) +} + /// Handles a given AMP message and returns a response /// /// Separated due to common functionality across multiple messages @@ -547,9 +634,9 @@ impl MsgHandler { } = original_msg; let recipient_addr = recipient.get_raw_address(&deps.as_ref())?; - + let adodb_addr = KERNEL_ADDRESSES.load(deps.storage, ADO_DB_KEY)?; - + if Binary::default() == message.clone() { ensure!( !funds.is_empty(), @@ -557,18 +644,18 @@ impl MsgHandler { error: Some("No message or funds supplied".to_string()) } ); - + let sub_msg = BankMsg::Send { to_address: recipient_addr.to_string(), amount: funds.clone(), }; - + let mut attrs = vec![]; for (idx, fund) in funds.iter().enumerate() { attrs.push(attr(format!("funds:{sequence}:{idx}"), fund.to_string())); } attrs.push(attr(format!("recipient:{sequence}"), recipient_addr)); - + res = res .add_submessage(SubMsg::reply_on_error( CosmosMsg::Bank(sub_msg), @@ -613,7 +700,7 @@ impl MsgHandler { ReplyId::AMPMsg.repr(), )? }; - + res = res .add_submessage(sub_msg) .add_attributes(vec![attr(format!("recipient:{sequence}"), recipient_addr)]); diff --git a/contracts/os/andromeda-kernel/src/query.rs b/contracts/os/andromeda-kernel/src/query.rs index 18cab3472..683a4e2aa 100644 --- a/contracts/os/andromeda-kernel/src/query.rs +++ b/contracts/os/andromeda-kernel/src/query.rs @@ -3,13 +3,14 @@ use andromeda_std::{ error::ContractError, os::{ aos_querier::AOSQuerier, - kernel::{ChainNameResponse, ChannelInfoResponse, VerifyAddressResponse}, + kernel::{ChainNameResponse, ChannelInfoResponse, EnvResponse, VerifyAddressResponse}, }, }; use cosmwasm_std::{Addr, Coin, Deps}; use crate::state::{ - CHAIN_TO_CHANNEL, CHANNEL_TO_CHAIN, CURR_CHAIN, IBC_FUND_RECOVERY, KERNEL_ADDRESSES, + CHAIN_TO_CHANNEL, CHANNEL_TO_CHAIN, CURR_CHAIN, ENV_VARIABLES, IBC_FUND_RECOVERY, + KERNEL_ADDRESSES, }; pub fn key_address(deps: Deps, key: String) -> Result { @@ -68,3 +69,9 @@ pub fn chain_name(deps: Deps) -> Result { chain_name: CURR_CHAIN.may_load(deps.storage)?.unwrap_or_default(), }) } + +pub fn get_env(deps: Deps, variable: String) -> Result { + Ok(EnvResponse { + value: ENV_VARIABLES.may_load(deps.storage, &variable.to_ascii_uppercase())?, + }) +} diff --git a/contracts/os/andromeda-kernel/src/state.rs b/contracts/os/andromeda-kernel/src/state.rs index 80cb58164..e3f4c80b8 100644 --- a/contracts/os/andromeda-kernel/src/state.rs +++ b/contracts/os/andromeda-kernel/src/state.rs @@ -19,7 +19,7 @@ pub struct OutgoingPacket { } pub const KERNEL_ADDRESSES: Map<&str, Addr> = Map::new("kernel_addresses"); -pub const _ENV_VARIABLES: Map<&str, String> = Map::new("kernel_env_variables"); +pub const ENV_VARIABLES: Map<&str, String> = Map::new("kernel_env_variables"); pub const CURR_CHAIN: Item = Item::new("kernel_curr_chain"); //Temporary storage for creating a new ADO to assign a new owner diff --git a/contracts/os/andromeda-kernel/src/testing/tests.rs b/contracts/os/andromeda-kernel/src/testing/tests.rs index fdeda9a6e..af356b016 100644 --- a/contracts/os/andromeda-kernel/src/testing/tests.rs +++ b/contracts/os/andromeda-kernel/src/testing/tests.rs @@ -1,7 +1,9 @@ use crate::{ contract::{execute, instantiate}, ibc::PACKET_LIFETIME, - state::{ADO_OWNER, CHAIN_TO_CHANNEL, CHANNEL_TO_CHAIN, CURR_CHAIN, KERNEL_ADDRESSES}, + state::{ + ADO_OWNER, CHAIN_TO_CHANNEL, CHANNEL_TO_CHAIN, CURR_CHAIN, ENV_VARIABLES, KERNEL_ADDRESSES, + }, }; use andromeda_std::{ amp::{ @@ -19,6 +21,7 @@ use cosmwasm_std::{ testing::{mock_dependencies, mock_env, mock_info}, to_json_binary, Addr, Binary, CosmosMsg, IbcMsg, }; +use rstest::rstest; #[test] fn proper_initialization() { @@ -390,3 +393,120 @@ fn test_handle_ibc_direct() { // * message fails even though it is a non-default binary message assert!(res.is_ok()); } + +const CREATOR: &str = "creator"; +const REALLY_LONG_VALUE: &str = "reallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallylongvalue"; + +fn invalid_env_variable(msg: &str) -> ContractError { + ContractError::InvalidEnvironmentVariable { + msg: msg.to_string(), + } +} + +#[rstest] +#[case::valid("test_var", Some("test_value"), CREATOR, None, None)] +#[case::not_found("test_var", None, CREATOR, None, Some(ContractError::EnvironmentVariableNotFound { variable: "test_var".to_string() }))] +#[case::unauthorized("test_var", Some("test_value"), "attacker", Some(ContractError::Unauthorized {}), None)] +#[case::long_value( + "test_var", + Some(REALLY_LONG_VALUE), + CREATOR, + Some(invalid_env_variable( + "Environment variable value length exceeds the maximum allowed length of 100 characters" + )), + None +)] +#[case::long_name( + REALLY_LONG_VALUE, + Some("test_val"), + CREATOR, + Some(invalid_env_variable( + "Environment variable name length exceeds the maximum allowed length of 100 characters" + )), + None +)] +#[case::empty_name( + "", + Some("test_value"), + CREATOR, + Some(invalid_env_variable("Environment variable name cannot be empty")), + None +)] +#[case::empty_value( + "test_var", + Some(""), + CREATOR, + Some(invalid_env_variable("Environment variable value cannot be empty")), + None +)] +#[case::nonalphanumeric( + "test-var", + Some("test_value"), + CREATOR, + Some(invalid_env_variable( + "Environment variable name can only contain alphanumeric characters and underscores" + )), + None +)] +fn test_set_unset_env( + #[case] variable: &str, + #[case] value: Option<&str>, + #[case] sender: &str, + #[case] expected_set_error: Option, + #[case] expected_unset_error: Option, +) { + let mut deps = mock_dependencies_custom(&[]); + let info = mock_info(CREATOR, &[]); + let env = mock_env(); + instantiate( + deps.as_mut(), + env.clone(), + info.clone(), + InstantiateMsg { + owner: None, + chain_name: "test".to_string(), + }, + ) + .unwrap(); + + let send_info = mock_info(sender, &[]); + + if let Some(value) = value { + // Set environment variable + let set_env_msg = ExecuteMsg::SetEnv { + variable: variable.to_string(), + value: value.to_string(), + }; + let res = execute(deps.as_mut(), env.clone(), send_info.clone(), set_env_msg); + if let Some(expected_error) = expected_set_error { + assert_eq!(res.unwrap_err(), expected_error); + return; + } else { + assert_eq!(res.unwrap().attributes[0].value, "set_env"); + } + + // Check if the variable is set + let stored_value = ENV_VARIABLES + .load(&deps.storage, &variable.to_ascii_uppercase()) + .unwrap(); + assert_eq!(stored_value, value); + } + + // Unset environment variable + let unset_env_msg = ExecuteMsg::UnsetEnv { + variable: variable.to_string(), + }; + let res = execute(deps.as_mut(), env, send_info, unset_env_msg); + if let Some(expected_error) = expected_unset_error { + assert_eq!(res.unwrap_err(), expected_error); + return; + } else { + assert_eq!(res.unwrap().attributes[0].value, "unset_env"); + } + + // Check if the variable is unset + let stored_value = ENV_VARIABLES + .may_load(&deps.storage, &variable.to_ascii_uppercase()) + .unwrap(); + assert!(stored_value.is_none()); +} diff --git a/contracts/os/andromeda-vfs/src/execute.rs b/contracts/os/andromeda-vfs/src/execute.rs index 508a4d1fe..93feb9c30 100644 --- a/contracts/os/andromeda-vfs/src/execute.rs +++ b/contracts/os/andromeda-vfs/src/execute.rs @@ -167,10 +167,12 @@ pub fn register_user( ); let username = username.to_lowercase(); let kernel = &ADOContract::default().get_kernel_address(env.deps.storage)?; - let curr_chain = AOSQuerier::get_current_chain(&env.deps.querier, kernel)?; + let is_registration_enabled = + AOSQuerier::get_env_variable::(&env.deps.querier, kernel, "username_registration")? + .unwrap_or(false); // Can only register username directly on Andromeda chain ensure!( - curr_chain == "andromeda" || env.info.sender == kernel, + is_registration_enabled || env.info.sender == kernel, ContractError::Unauthorized {} ); // If address is provided sender must be Kernel diff --git a/ibc-tests/Cargo.toml b/ibc-tests/Cargo.toml index 536df46eb..e8f5336f6 100644 --- a/ibc-tests/Cargo.toml +++ b/ibc-tests/Cargo.toml @@ -16,7 +16,7 @@ serde.workspace = true tokio = "1.42.0" cw-orch = { workspace = true } cw-orch-daemon = "0.24.2" -rstest = "0.23.0" +rstest = { workspace = true } andromeda-testing-e2e = { workspace = true } @@ -52,4 +52,3 @@ andromeda-non-fungible-tokens = { workspace = true } cosmwasm-std = { workspace = true, features = ["staking"] } cw20.workspace = true cw721.workspace = true - diff --git a/packages/std/src/error.rs b/packages/std/src/error.rs index c76346399..4982c4d63 100644 --- a/packages/std/src/error.rs +++ b/packages/std/src/error.rs @@ -752,6 +752,12 @@ pub enum ContractError { #[error("Invalid tier for {operation} operation: {msg} ")] InvalidTier { operation: String, msg: String }, + + #[error("Environment variable not found: {variable}")] + EnvironmentVariableNotFound { variable: String }, + + #[error("Invalid environment variable length: {msg}")] + InvalidEnvironmentVariable { msg: String }, } impl ContractError { diff --git a/packages/std/src/os/aos_querier.rs b/packages/std/src/os/aos_querier.rs index f4fbd8a77..0ab695402 100644 --- a/packages/std/src/os/aos_querier.rs +++ b/packages/std/src/os/aos_querier.rs @@ -322,4 +322,14 @@ impl AOSQuerier { }; Ok((new_denom_trace.get_ibc_denom(), new_denom_trace)) } + + pub fn get_env_variable( + querier: &QuerierWrapper, + kernel_addr: &Addr, + variable: &str, + ) -> Result, ContractError> { + let key = AOSQuerier::get_map_storage_key("kernel_env_variables", &[variable.as_bytes()])?; + let verify: Option = AOSQuerier::query_storage(querier, kernel_addr, &key)?; + Ok(verify) + } } diff --git a/packages/std/src/os/kernel.rs b/packages/std/src/os/kernel.rs index 2ee342136..f8756f8c1 100644 --- a/packages/std/src/os/kernel.rs +++ b/packages/std/src/os/kernel.rs @@ -73,6 +73,18 @@ pub enum ExecuteMsg { UpdateChainName { chain_name: String, }, + /// Sets an environment variable with the given name and value. + /// The variable name must be uppercase and can only contain letters, numbers, and underscores. + /// The value must be a valid UTF-8 string. + SetEnv { + variable: String, + value: String, + }, + /// Removes an environment variable with the given name. + /// Returns success even if the variable doesn't exist. + UnsetEnv { + variable: String, + }, // Only accessible to key contracts Internal(InternalMsg), // Base message @@ -102,6 +114,11 @@ pub struct ChainNameResponse { pub chain_name: String, } +#[cw_serde] +pub struct EnvResponse { + pub value: Option, +} + #[cw_serde] #[cfg_attr(not(target_arch = "wasm32"), derive(cw_orch::QueryFns))] #[derive(QueryResponses)] @@ -126,6 +143,8 @@ pub enum QueryMsg { AdoType {}, #[returns(crate::ado_base::ownership::ContractOwnerResponse)] Owner {}, + #[returns(EnvResponse)] + GetEnv { variable: String }, } #[cw_serde] diff --git a/packages/std/src/testing/mock_querier.rs b/packages/std/src/testing/mock_querier.rs index b1684489c..0aff538ee 100644 --- a/packages/std/src/testing/mock_querier.rs +++ b/packages/std/src/testing/mock_querier.rs @@ -504,6 +504,22 @@ impl MockAndromedaQuerier { "andromeda".to_string() }; SystemResult::Ok(ContractResult::Ok(to_json_binary(&res).unwrap())) + } else if key_str.contains("kernel_env_variables") { + let split = key_str.split("kernel_env_variables"); + let key = split.last(); + if let Some(key) = key { + match key { + "username_registration" => { + SystemResult::Ok(ContractResult::Ok(to_json_binary(&!fake).unwrap())) + } + "andromeda_distribution" => { + SystemResult::Ok(ContractResult::Ok(to_json_binary(&!fake).unwrap())) + } + _ => panic!("Invalid Kernel Address Key"), + } + } else { + panic!("Invalid Kernel Address Raw Query") + } } else if key_str.contains("channel") { SystemResult::Ok(ContractResult::Ok( to_json_binary(&ChannelInfo { diff --git a/tests-integration/Cargo.toml b/tests-integration/Cargo.toml index 50940b47d..d81c29190 100644 --- a/tests-integration/Cargo.toml +++ b/tests-integration/Cargo.toml @@ -165,7 +165,7 @@ name = "validator_staking" name = "shunting" [dependencies] -rstest = "0.23.0" +rstest = { workspace = true } # [[test]] # name = "cw20_staking_app"