Live source from
contracts/config/src/lib.rs (253 lines). Generated from the deployed contract code.// bwick-config: on-chain service registry. Single source of truth for
// contract addresses + endpoint overrides that the wallet extension,
// bridge dApp, launchpad frontend, and relayer all read at runtime.
//
// Anything that might need to rotate post-launch lives here so clients
// never need a code change to follow.
use cosmwasm_schema::{cw_serde, QueryResponses};
use cosmwasm_std::{
entry_point, to_json_binary, Addr, Binary, Deps, DepsMut, Env, MessageInfo,
Response, StdResult,
};
use cw2::set_contract_version;
use cw_storage_plus::Item;
use thiserror::Error;
const CONTRACT_NAME: &str = "crates.io:bwick-config";
const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");
#[cw_serde]
pub struct Config {
/// Schema version. Bumped on incompatible Config-shape changes so
/// frozen extensions can detect mismatches and degrade gracefully.
pub version: u32,
/// Admin authorized to call UpdateConfig. Rotate via UpdateAdmin
/// (admin -> new_admin handoff is single-step; multisig recommended).
pub admin: Addr,
/// CosmWasm contract addresses on bwickchain.
pub amm_contract: String,
pub launchpad_contract: String,
pub oracle_contract: String,
pub vesting_code_id: u64,
pub names_contract: String,
/// Solana side. Bridge program ID also exists in bridge.Params for
/// redundancy; clients may read either. Empty string disables.
pub solana_bridge_program_id: String,
pub solana_bwick_spl_mint: String,
/// Optional Solana RPC override. Empty = clients use their bundled
/// default. Set this if Helius (or whichever provider) ever fails.
pub solana_rpc_url_override: String,
/// Optional BWICK chain endpoint overrides. Empty = clients use
/// their bundled DNS defaults. Set these only in a disaster-recovery
/// scenario where DNS itself fails.
pub bwick_rpc_url_override: String,
pub bwick_rest_url_override: String,
/// Reserved slots for protocols/integrations we haven't built yet.
/// Locking these into the schema today means future additions are
/// `UpdateConfig` calls instead of contract migrations + extension
/// re-submissions. Empty strings ignored by clients.
pub reserved_addr_1: String,
pub reserved_addr_2: String,
pub reserved_addr_3: String,
pub reserved_addr_4: String,
pub reserved_addr_5: String,
pub reserved_int_1: u64,
pub reserved_int_2: u64,
pub reserved_int_3: u64,
pub reserved_int_4: u64,
pub reserved_int_5: u64,
}
pub const SCHEMA_VERSION: u32 = 1;
const CONFIG: Item<Config> = Item::new("config");
#[cw_serde]
pub struct InstantiateMsg {
pub admin: String,
pub amm_contract: String,
pub launchpad_contract: String,
pub oracle_contract: String,
pub vesting_code_id: u64,
pub names_contract: String,
pub solana_bridge_program_id: String,
pub solana_bwick_spl_mint: String,
/// All overrides default to "" — set only when needed.
#[serde(default)]
pub solana_rpc_url_override: String,
#[serde(default)]
pub bwick_rpc_url_override: String,
#[serde(default)]
pub bwick_rest_url_override: String,
}
#[cw_serde]
pub enum ExecuteMsg {
/// Update any subset of fields. None preserves the existing value.
UpdateConfig {
amm_contract: Option<String>,
launchpad_contract: Option<String>,
oracle_contract: Option<String>,
vesting_code_id: Option<u64>,
names_contract: Option<String>,
solana_bridge_program_id: Option<String>,
solana_bwick_spl_mint: Option<String>,
solana_rpc_url_override: Option<String>,
bwick_rpc_url_override: Option<String>,
bwick_rest_url_override: Option<String>,
reserved_addr_1: Option<String>,
reserved_addr_2: Option<String>,
reserved_addr_3: Option<String>,
reserved_addr_4: Option<String>,
reserved_addr_5: Option<String>,
reserved_int_1: Option<u64>,
reserved_int_2: Option<u64>,
reserved_int_3: Option<u64>,
reserved_int_4: Option<u64>,
reserved_int_5: Option<u64>,
},
/// Rotate admin. Single-step; recommend multisig for the new admin.
UpdateAdmin { new_admin: String },
}
#[cw_serde]
#[derive(QueryResponses)]
pub enum QueryMsg {
/// Returns the full Config. Single round-trip for all consumers.
#[returns(Config)]
Config {},
}
#[derive(Error, Debug)]
pub enum ContractError {
#[error("{0}")]
Std(#[from] cosmwasm_std::StdError),
#[error("Unauthorized: caller is not admin")]
Unauthorized,
#[error("Invalid address: {0}")]
InvalidAddress(String),
}
#[entry_point]
pub fn instantiate(
deps: DepsMut,
_env: Env,
_info: MessageInfo,
msg: InstantiateMsg,
) -> Result<Response, ContractError> {
set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
let admin = deps
.api
.addr_validate(&msg.admin)
.map_err(|e| ContractError::InvalidAddress(e.to_string()))?;
let cfg = Config {
version: SCHEMA_VERSION,
admin,
amm_contract: msg.amm_contract,
launchpad_contract: msg.launchpad_contract,
oracle_contract: msg.oracle_contract,
vesting_code_id: msg.vesting_code_id,
names_contract: msg.names_contract,
solana_bridge_program_id: msg.solana_bridge_program_id,
solana_bwick_spl_mint: msg.solana_bwick_spl_mint,
solana_rpc_url_override: msg.solana_rpc_url_override,
bwick_rpc_url_override: msg.bwick_rpc_url_override,
bwick_rest_url_override: msg.bwick_rest_url_override,
reserved_addr_1: String::new(),
reserved_addr_2: String::new(),
reserved_addr_3: String::new(),
reserved_addr_4: String::new(),
reserved_addr_5: String::new(),
reserved_int_1: 0,
reserved_int_2: 0,
reserved_int_3: 0,
reserved_int_4: 0,
reserved_int_5: 0,
};
CONFIG.save(deps.storage, &cfg)?;
Ok(Response::new().add_attribute("action", "instantiate"))
}
#[entry_point]
pub fn execute(
deps: DepsMut,
_env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> Result<Response, ContractError> {
let mut cfg = CONFIG.load(deps.storage)?;
if info.sender != cfg.admin {
return Err(ContractError::Unauthorized);
}
match msg {
ExecuteMsg::UpdateConfig {
amm_contract,
launchpad_contract,
oracle_contract,
vesting_code_id,
names_contract,
solana_bridge_program_id,
solana_bwick_spl_mint,
solana_rpc_url_override,
bwick_rpc_url_override,
bwick_rest_url_override,
reserved_addr_1,
reserved_addr_2,
reserved_addr_3,
reserved_addr_4,
reserved_addr_5,
reserved_int_1,
reserved_int_2,
reserved_int_3,
reserved_int_4,
reserved_int_5,
} => {
if let Some(v) = amm_contract { cfg.amm_contract = v; }
if let Some(v) = launchpad_contract { cfg.launchpad_contract = v; }
if let Some(v) = oracle_contract { cfg.oracle_contract = v; }
if let Some(v) = vesting_code_id { cfg.vesting_code_id = v; }
if let Some(v) = names_contract { cfg.names_contract = v; }
if let Some(v) = solana_bridge_program_id { cfg.solana_bridge_program_id = v; }
if let Some(v) = solana_bwick_spl_mint { cfg.solana_bwick_spl_mint = v; }
if let Some(v) = solana_rpc_url_override { cfg.solana_rpc_url_override = v; }
if let Some(v) = bwick_rpc_url_override { cfg.bwick_rpc_url_override = v; }
if let Some(v) = bwick_rest_url_override { cfg.bwick_rest_url_override = v; }
if let Some(v) = reserved_addr_1 { cfg.reserved_addr_1 = v; }
if let Some(v) = reserved_addr_2 { cfg.reserved_addr_2 = v; }
if let Some(v) = reserved_addr_3 { cfg.reserved_addr_3 = v; }
if let Some(v) = reserved_addr_4 { cfg.reserved_addr_4 = v; }
if let Some(v) = reserved_addr_5 { cfg.reserved_addr_5 = v; }
if let Some(v) = reserved_int_1 { cfg.reserved_int_1 = v; }
if let Some(v) = reserved_int_2 { cfg.reserved_int_2 = v; }
if let Some(v) = reserved_int_3 { cfg.reserved_int_3 = v; }
if let Some(v) = reserved_int_4 { cfg.reserved_int_4 = v; }
if let Some(v) = reserved_int_5 { cfg.reserved_int_5 = v; }
CONFIG.save(deps.storage, &cfg)?;
Ok(Response::new().add_attribute("action", "update_config"))
}
ExecuteMsg::UpdateAdmin { new_admin } => {
let new = deps
.api
.addr_validate(&new_admin)
.map_err(|e| ContractError::InvalidAddress(e.to_string()))?;
cfg.admin = new;
CONFIG.save(deps.storage, &cfg)?;
Ok(Response::new().add_attribute("action", "update_admin"))
}
}
}
#[entry_point]
pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
match msg {
QueryMsg::Config {} => to_json_binary(&CONFIG.load(deps.storage)?),
}
}

