Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor instantiation logic #94

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.lock

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

4 changes: 0 additions & 4 deletions contracts/babylon/benches/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,6 @@ pub fn setup_instance() -> Instance<MockApi, MockStorage, MockQuerier> {
btc_confirmation_depth: 10,
checkpoint_finalization_timeout: 1,
notify_cosmos_zone: false,
btc_staking_code_id: None,
btc_staking_msg: None,
btc_finality_code_id: None,
btc_finality_msg: None,
admin: None,
};
let info = mock_info(CREATOR, &[]);
Expand Down
118 changes: 10 additions & 108 deletions contracts/babylon/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use babylon_bindings::babylon_sdk::{
get_babylon_sdk_params, QueryParamsResponse, QUERY_PARAMS_PATH,
};
use cosmwasm_std::{
to_json_binary, Addr, Binary, Deps, DepsMut, Empty, Env, MessageInfo, QueryResponse, Reply,
Response, SubMsg, SubMsgResponse, WasmMsg,
Expand Down Expand Up @@ -40,56 +43,15 @@ pub fn instantiate(
btc_confirmation_depth: msg.btc_confirmation_depth,
checkpoint_finalization_timeout: msg.checkpoint_finalization_timeout,
notify_cosmos_zone: msg.notify_cosmos_zone,
btc_staking: None, // Will be set in `reply` if `btc_staking_code_id` is provided
btc_finality: None, // Will be set in `reply` if `btc_finality_code_id` is provided
consumer_name: None,
consumer_description: None,
};

let mut res = Response::new().add_attribute("action", "instantiate");

if let Some(btc_staking_code_id) = msg.btc_staking_code_id {
// Update config with consumer information
cfg.consumer_name = msg.consumer_name;
cfg.consumer_description = msg.consumer_description;

// Instantiate BTC staking contract
let init_msg = WasmMsg::Instantiate {
admin: msg.admin.clone(),
code_id: btc_staking_code_id,
msg: msg.btc_staking_msg.unwrap_or(Binary::from(b"{}")),
funds: vec![],
label: "BTC Staking".into(),
};
let init_msg = SubMsg::reply_on_success(init_msg, REPLY_ID_INSTANTIATE_STAKING);

// Test code sets a channel, so that we can better approximate IBC in test code
#[cfg(any(test, all(feature = "library", not(target_arch = "wasm32"))))]
{
let channel = cosmwasm_std::testing::mock_ibc_channel(
"channel-123",
cosmwasm_std::IbcOrder::Ordered,
"babylon",
);
IBC_CHANNEL.save(deps.storage, &channel)?;
}

res = res.add_submessage(init_msg);
}

if let Some(btc_finality_code_id) = msg.btc_finality_code_id {
// Instantiate BTC finality contract
let init_msg = WasmMsg::Instantiate {
admin: msg.admin,
code_id: btc_finality_code_id,
msg: msg.btc_finality_msg.unwrap_or(Binary::from(b"{}")),
funds: vec![],
label: "BTC Finality".into(),
};
let init_msg = SubMsg::reply_on_success(init_msg, REPLY_ID_INSTANTIATE_FINALITY);
let res = Response::new().add_attribute("action", "instantiate");

res = res.add_submessage(init_msg);
}
// Update config with consumer information
cfg.consumer_name = msg.consumer_name;
cfg.consumer_description = msg.consumer_description;

// Save the config after potentially updating it
CONFIG.save(deps.storage, &cfg)?;
Expand All @@ -98,18 +60,6 @@ pub fn instantiate(
Ok(res)
}

pub fn reply(
deps: DepsMut,
_env: Env,
reply: Reply,
) -> Result<Response<BabylonMsg>, ContractError> {
match reply.id {
REPLY_ID_INSTANTIATE_STAKING => reply_init_callback_staking(deps, reply.result.unwrap()),
REPLY_ID_INSTANTIATE_FINALITY => reply_init_finality_callback(deps, reply.result.unwrap()),
_ => Err(ContractError::InvalidReplyId(reply.id)),
}
}

/// Tries to get contract address from events in reply
fn reply_init_get_contract_address(reply: SubMsgResponse) -> Result<Addr, ContractError> {
for event in reply.events {
Expand All @@ -126,47 +76,6 @@ fn reply_init_get_contract_address(reply: SubMsgResponse) -> Result<Addr, Contra
)))
}

/// Store BTC staking address
fn reply_init_callback_staking(
deps: DepsMut,
reply: SubMsgResponse,
) -> Result<Response<BabylonMsg>, ContractError> {
// Try to get contract address from events in reply
let addr = reply_init_get_contract_address(reply)?;
CONFIG.update(deps.storage, |mut cfg| {
cfg.btc_staking = Some(addr);
Ok::<_, ContractError>(cfg)
})?;
Ok(Response::new())
}

/// Store BTC finality address
fn reply_init_finality_callback(
deps: DepsMut,
reply: SubMsgResponse,
) -> Result<Response<BabylonMsg>, ContractError> {
// Try to get contract address from events in reply
let finality_addr = reply_init_get_contract_address(reply)?;
CONFIG.update(deps.storage, |mut cfg| {
cfg.btc_finality = Some(finality_addr.clone());
Ok::<_, ContractError>(cfg)
})?;
// Set the BTC staking contract address to the BTC finality contract
let cfg = CONFIG.load(deps.storage)?;
let msg = finality_api::ExecuteMsg::UpdateStaking {
staking: cfg
.btc_staking
.ok_or(ContractError::BtcStakingNotSet {})?
.to_string(),
};
let wasm_msg = WasmMsg::Execute {
contract_addr: finality_addr.to_string(),
msg: to_json_binary(&msg)?,
funds: vec![],
};
Ok(Response::new().add_message(wasm_msg))
}

pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result<QueryResponse, ContractError> {
match msg {
QueryMsg::Config {} => Ok(to_json_binary(&queries::config(deps)?)?),
Expand Down Expand Up @@ -228,18 +137,15 @@ pub fn execute(
Ok(Response::new())
}
ExecuteMsg::Slashing { evidence } => {
// This is an internal routing message from the `btc_finality` contract
let cfg = CONFIG.load(deps.storage)?;
// Check sender
let btc_finality = cfg
.btc_finality
.ok_or(ContractError::BtcFinalityNotSet {})?;
let params = get_babylon_sdk_params(&deps.querier)?;
let btc_finality = params.btc_finality_contract_address;
if info.sender != btc_finality {
return Err(ContractError::Unauthorized {});
}
// Send to the staking contract for processing
let mut res = Response::new();
let btc_staking = cfg.btc_staking.ok_or(ContractError::BtcStakingNotSet {})?;
let btc_staking = params.btc_staking_contract_address;
// Slashes this finality provider, i.e., sets its slashing height to the block height
// and its power to zero
let msg = btc_staking_api::ExecuteMsg::Slash {
Expand Down Expand Up @@ -298,10 +204,6 @@ mod tests {
btc_confirmation_depth: 10,
checkpoint_finalization_timeout: 100,
notify_cosmos_zone: false,
btc_staking_code_id: None,
btc_staking_msg: None,
btc_finality_code_id: None,
btc_finality_msg: None,
admin: None,
consumer_name: None,
consumer_description: None,
Expand Down
14 changes: 5 additions & 9 deletions contracts/babylon/src/ibc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ pub(crate) mod ibc_packet {
ActiveBtcDelegation, NewFinalityProvider, UnbondedBtcDelegation,
};
use babylon_apis::finality_api::Evidence;
use babylon_bindings::babylon_sdk::{
get_babylon_sdk_params, QueryParamsResponse, QUERY_PARAMS_PATH,
};
use babylon_proto::babylon::btcstaking::v1::BtcStakingIbcPacket;
use babylon_proto::babylon::zoneconcierge::v1::zoneconcierge_packet_data::Packet::ConsumerSlashing;
use babylon_proto::babylon::zoneconcierge::v1::ConsumerSlashingIbcPacket;
Expand Down Expand Up @@ -201,13 +204,10 @@ pub(crate) mod ibc_packet {
_caller: String,
btc_staking: &BtcStakingIbcPacket,
) -> StdResult<IbcReceiveResponse<BabylonMsg>> {
let storage = deps.storage;
let cfg = CONFIG.load(storage)?;
let params = get_babylon_sdk_params(&deps.querier)?;

// Route the packet to the btc-staking contract
let btc_staking_addr = cfg
.btc_staking
.ok_or(StdError::generic_err("btc_staking contract not set"))?;
let btc_staking_addr = params.btc_staking_contract_address;

// Build the message to send to the BTC staking contract
let msg = babylon_apis::btc_staking_api::ExecuteMsg::BtcStaking {
Expand Down Expand Up @@ -331,10 +331,6 @@ mod tests {
btc_confirmation_depth: 10,
checkpoint_finalization_timeout: 100,
notify_cosmos_zone: false,
btc_staking_code_id: None,
btc_staking_msg: None,
btc_finality_code_id: None,
btc_finality_msg: None,
admin: None,
consumer_name: None,
consumer_description: None,
Expand Down
5 changes: 0 additions & 5 deletions contracts/babylon/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,6 @@ pub fn instantiate(
contract::instantiate(deps, env, info, msg)
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn reply(deps: DepsMut, env: Env, reply: Reply) -> Result<Response<BabylonMsg>, ContractError> {
contract::reply(deps, env, reply)
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn query(deps: Deps, env: Env, msg: msg::contract::QueryMsg) -> Result<Binary, ContractError> {
contract::query(deps, env, msg)
Expand Down
31 changes: 0 additions & 31 deletions contracts/babylon/src/msg/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,6 @@ pub struct InstantiateMsg {
/// NOTE: If set to true, then the Cosmos zone needs to integrate the corresponding message handler
/// as well
pub notify_cosmos_zone: bool,
/// If set, this will instantiate a BTC staking contract for BTC re-staking
pub btc_staking_code_id: Option<u64>,
/// If set, this will define the instantiation message for the BTC staking contract.
/// This message is opaque to the Babylon contract, and depends on the specific staking contract
/// being instantiated
pub btc_staking_msg: Option<Binary>,
/// If set, this will instantiate a BTC finality contract
pub btc_finality_code_id: Option<u64>,
/// If set, this will define the instantiation message for the BTC finality contract.
/// This message is opaque to the Babylon contract, and depends on the specific finality contract
/// being instantiated
pub btc_finality_msg: Option<Binary>,
/// If set, this will be the Wasm migration / upgrade admin of the BTC staking contract and the
/// BTC finality contract
pub admin: Option<String>,
Expand All @@ -64,25 +52,6 @@ impl ContractMsg for InstantiateMsg {
}
let _ = self.babylon_tag_to_bytes()?;

if self.btc_staking_code_id.is_some() {
if let (Some(consumer_name), Some(consumer_description)) =
(&self.consumer_name, &self.consumer_description)
{
if consumer_name.trim().is_empty() {
return Err(StdError::generic_err("Consumer name cannot be empty"));
}
if consumer_description.trim().is_empty() {
return Err(StdError::generic_err(
"Consumer description cannot be empty",
));
}
} else {
return Err(StdError::generic_err(
"Consumer name and description are required when btc_staking_code_id is set",
));
}
}

Ok(())
}

Expand Down
23 changes: 4 additions & 19 deletions contracts/babylon/src/multitest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@ mod suite;
use cosmwasm_std::Addr;
use suite::SuiteBuilder;

// Some multi-test default settings
// TODO: Replace these with their address generators
const CONTRACT0_ADDR: &str = "cosmwasm19mfs8tl4s396u7vqw9rrnsmrrtca5r66p7v8jvwdxvjn3shcmllqupdgxu";
const CONTRACT1_ADDR: &str = "cosmwasm14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s8jef58";
const CONTRACT2_ADDR: &str = "cosmwasm1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrqt8utkp";

#[test]
fn initialization() {
let suite = SuiteBuilder::new().build();
Expand All @@ -23,16 +17,8 @@ fn initialization() {
assert_eq!(config.btc_confirmation_depth, 1);
assert_eq!(config.checkpoint_finalization_timeout, 10);
assert!(!config.notify_cosmos_zone);
assert_eq!(config.btc_staking, Some(Addr::unchecked(CONTRACT1_ADDR)));
assert_eq!(config.btc_finality, Some(Addr::unchecked(CONTRACT2_ADDR)));

// Check that the btc-staking contract was initialized correctly
let btc_staking_config = suite.get_btc_staking_config();
assert_eq!(btc_staking_config.babylon, Addr::unchecked(CONTRACT0_ADDR));

// Check that the btc-finality contract was initialized correctly
let btc_finality_config = suite.get_btc_finality_config();
assert_eq!(btc_finality_config.babylon, Addr::unchecked(CONTRACT0_ADDR));
assert!(!suite.btc_staking_contract.to_string().is_empty());
assert!(!suite.btc_finality_contract.to_string().is_empty());
}

mod instantiation {
Expand All @@ -43,10 +29,9 @@ mod instantiation {
let suite = SuiteBuilder::new().build();

// Confirm the btc-staking contract has been instantiated and set
let config = suite.get_config();
assert_eq!(config.btc_staking, Some(Addr::unchecked(CONTRACT1_ADDR)));
assert!(!suite.btc_staking_contract.to_string().is_empty());
// Confirm the btc-finality contract has been instantiated and set
assert_eq!(config.btc_finality, Some(Addr::unchecked(CONTRACT2_ADDR)));
assert!(!suite.btc_finality_contract.to_string().is_empty());
}
}

Expand Down
Loading
Loading