cw_migratable_contract_std/
execute.rs1use cosmwasm_std::{
2 to_binary, Binary, CanonicalAddr, ContractInfo, CosmosMsg, Deps, DepsMut, ReplyOn, Response,
3 StdError, StdResult, Storage, SubMsg, WasmMsg,
4};
5
6use crate::msg::MigrationListenerExecuteMsg;
7use crate::state::{
8 CanonicalContractInfo, MIGRATION_COMPLETE_EVENT_SUBSCRIBERS,
9 REMAINING_MIGRATION_COMPLETE_EVENT_SUB_SLOTS,
10};
11
12pub fn register_to_notify_on_migration_complete(
13 deps: DepsMut,
14 address: String,
15 code_hash: String,
16) -> StdResult<Response> {
17 let validated = deps.api.addr_validate(address.as_str())?;
18 add_migration_complete_event_subscriber(
19 deps.storage,
20 &deps.api.addr_canonicalize(validated.as_str())?,
21 &code_hash,
22 )?;
23 Ok(Response::new())
24}
25
26pub fn create_broadcast_migration_complete_notification_msgs(
27 deps: Deps,
28 reply_on: ReplyOn,
29 reply_id: u64,
30 migrated_to: &ContractInfo,
31 notification_recipients: Vec<ContractInfo>,
32 data: Option<Binary>,
33) -> StdResult<Vec<SubMsg>> {
34 let msg = to_binary(
35 &MigrationListenerExecuteMsg::MigrationCompleteNotification {
36 to: migrated_to.clone(),
37 data,
38 },
39 )?;
40 let sub_msgs = notification_recipients
41 .into_iter()
42 .map(|contract| {
43 let contract_addr = deps
44 .api
45 .addr_validate(contract.address.as_str())?
46 .to_string();
47 Ok(SubMsg {
48 msg: CosmosMsg::Wasm(WasmMsg::Execute {
49 msg: msg.clone(),
50 contract_addr,
51 code_hash: contract.code_hash,
52 funds: vec![],
53 }),
54 id: reply_id,
55 reply_on: reply_on.clone(),
56 gas_limit: None,
57 })
58 })
59 .collect::<StdResult<Vec<SubMsg>>>()?;
60
61 Ok(sub_msgs)
62}
63
64pub fn add_migration_complete_event_subscriber(
65 storage: &mut dyn Storage,
66 address: &CanonicalAddr,
67 code_hash: &str,
68) -> StdResult<()> {
69 if let Some(remaining_slots) = REMAINING_MIGRATION_COMPLETE_EVENT_SUB_SLOTS.may_load(storage)? {
70 if remaining_slots == 0 {
71 return Err(StdError::generic_err(
72 "No migration complete notification slots available",
73 ));
74 }
75 REMAINING_MIGRATION_COMPLETE_EVENT_SUB_SLOTS.save(storage, &(remaining_slots - 1))?
76 }
77 let mut contracts = MIGRATION_COMPLETE_EVENT_SUBSCRIBERS
79 .load(storage)
80 .unwrap_or_default();
81 let mut update = false;
82 let new_contract = CanonicalContractInfo {
83 address: address.clone(),
84 code_hash: code_hash.to_string(),
85 };
86 if !contracts.contains(&new_contract) {
87 contracts.push(new_contract);
88 update = true;
89 }
90
91 if update {
93 MIGRATION_COMPLETE_EVENT_SUBSCRIBERS.save(storage, &contracts)?;
94 }
95 Ok(())
96}
97
98pub fn update_migrated_subscriber(
99 storage: &mut dyn Storage,
100 raw_sender: &CanonicalAddr,
101 raw_migrated_to: &CanonicalContractInfo,
102) -> StdResult<()> {
103 let notify_on_migration_contracts = MIGRATION_COMPLETE_EVENT_SUBSCRIBERS.may_load(storage)?;
104 if let Some(mut notify_on_migration_contracts) = notify_on_migration_contracts {
105 let mut update = false;
106
107 for contract in notify_on_migration_contracts.iter_mut() {
108 if &contract.address == raw_sender {
109 contract.address = raw_migrated_to.address.clone();
110 contract.code_hash = raw_migrated_to.code_hash.clone();
111 update = true;
112 break;
113 }
114 }
115 if update {
116 MIGRATION_COMPLETE_EVENT_SUBSCRIBERS.save(storage, ¬ify_on_migration_contracts)?;
117 }
118 }
119 Ok(())
120}