From 71e4337c2821cf5fe157ed049fb0c84a8825ef05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Wo=C5=BAniak?= Date: Fri, 27 Sep 2024 14:34:51 +0200 Subject: [PATCH 1/3] feat: Add `UpdateAdmin` and `ClearAdmin` constructors in the `Remote` --- sylvia/src/types.rs | 13 ++++ sylvia/tests/remote.rs | 146 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 141 insertions(+), 18 deletions(-) diff --git a/sylvia/src/types.rs b/sylvia/src/types.rs index cbf12d38..86499000 100644 --- a/sylvia/src/types.rs +++ b/sylvia/src/types.rs @@ -434,6 +434,19 @@ impl<'a, Contract: ?Sized> Remote<'a, Contract> { pub fn executor(&self) -> ExecutorBuilder<(EmptyExecutorBuilderState, Contract)> { ExecutorBuilder::<(EmptyExecutorBuilderState, Contract)>::new(&self.addr) } + + pub fn update_admin(&self, new_admin: String) -> WasmMsg { + WasmMsg::UpdateAdmin { + contract_addr: self.addr.to_string(), + admin: new_admin, + } + } + + pub fn clear_admin(&self) -> WasmMsg { + WasmMsg::ClearAdmin { + contract_addr: self.addr.to_string(), + } + } } impl<'a, Contract: ?Sized> AsRef for Remote<'a, Contract> { diff --git a/sylvia/tests/remote.rs b/sylvia/tests/remote.rs index 1c433228..ad47995c 100644 --- a/sylvia/tests/remote.rs +++ b/sylvia/tests/remote.rs @@ -257,12 +257,52 @@ pub mod manager { Ok(count) } + + #[sv::msg(exec)] + fn update_admin( + &self, + ctx: ExecCtx, + new_admin: String, + ) -> Result, StdError> { + let wasm = self + .remote_counter + .load(ctx.deps.storage)? + .interface_remote + .update_admin(new_admin); + let resp = Response::new().add_message(wasm); + Ok(resp) + } + + #[sv::msg(exec)] + fn clear_admin( + &self, + ctx: ExecCtx, + ) -> Result, StdError> { + let wasm = self + .remote_counter + .load(ctx.deps.storage)? + .interface_remote + .clear_admin(); + let resp = Response::new().add_message(wasm); + Ok(resp) + } + + #[sv::msg(query)] + fn counter_contract(&self, ctx: QueryCtx) -> Result { + Ok(self + .remote_counter + .load(ctx.deps.storage)? + .interface_remote + .as_ref() + .clone()) + } } } #[cfg(test)] mod tests { - use cw_multi_test::{BasicApp, IntoBech32}; + use cosmwasm_std::{CosmosMsg, WasmMsg}; + use cw_multi_test::{BasicApp, Executor, IntoAddr}; use sylvia::cw_std::{Addr, StdError}; use sylvia::multitest::{App, Proxy}; use sylvia::types::Remote; @@ -277,7 +317,6 @@ mod tests { use crate::{ExampleMsg, ExampleQuery}; type ExampleApp = BasicApp; - const OWNER: &str = "owner"; #[test] fn remote_generation() { @@ -302,11 +341,12 @@ mod tests { assert_eq!(&addr, borrowed_remote.as_ref()); } - fn setup( - app: &App, + fn setup<'a>( + app: &'a App, + owner: &'a Addr, ) -> ( - Proxy>, - Proxy>, + Proxy<'a, ExampleApp, ManagerContract>, + Proxy<'a, ExampleApp, ManagerContract>, ) { // Manager operating on signed numbers let signed_counter_code_id = SignedCounterCodeId::store_code(app); @@ -314,7 +354,7 @@ mod tests { let signed_counter_contract = signed_counter_code_id .instantiate() .with_label("Signed counter contract") - .call(&OWNER.into_bech32()) + .call(owner) .unwrap(); let manager_code_id = ManagerCodeId::store_code(app); @@ -322,7 +362,7 @@ mod tests { let signed_manager_contract = manager_code_id .instantiate(signed_counter_contract.contract_addr.clone()) .with_label("Manager contract") - .call(&OWNER.into_bech32()) + .call(owner) .unwrap(); // Manager operating on unsigned numbers @@ -331,7 +371,8 @@ mod tests { let unsigned_counter_contract = unsigned_counter_code_id .instantiate() .with_label("Unsigned counter contract") - .call(&OWNER.into_bech32()) + .with_admin(Some(owner.as_str())) + .call(owner) .unwrap(); let manager_code_id = ManagerCodeId::store_code(app); @@ -339,7 +380,18 @@ mod tests { let unsigned_manager_contract = manager_code_id .instantiate(unsigned_counter_contract.contract_addr.clone()) .with_label("Manager contract") - .call(&OWNER.into_bech32()) + .call(owner) + .unwrap(); + + // Set manager contract as an admin of the counter contract + app.app_mut() + .execute( + owner.clone(), + CosmosMsg::Wasm(WasmMsg::UpdateAdmin { + contract_addr: unsigned_counter_contract.contract_addr.to_string(), + admin: unsigned_manager_contract.contract_addr.to_string(), + }), + ) .unwrap(); (signed_manager_contract, unsigned_manager_contract) @@ -347,23 +399,81 @@ mod tests { #[test] fn call_remote() { + let owner = "owner".into_addr(); let app = App::>::custom(|_, _, _| {}); - let (signed_manager_contract, unsigned_manager_contract) = setup(&app); + let (signed_manager_contract, unsigned_manager_contract) = setup(&app, &owner); assert_eq!(signed_manager_contract.count().unwrap(), 0); - signed_manager_contract - .add(5) - .call(&OWNER.into_bech32()) - .unwrap(); + signed_manager_contract.add(5).call(&owner).unwrap(); assert_eq!(signed_manager_contract.count().unwrap(), 5); assert_eq!(unsigned_manager_contract.count().unwrap(), 0); + unsigned_manager_contract.add(5).call(&owner).unwrap(); + assert_eq!(unsigned_manager_contract.count().unwrap(), 5); + } + + #[test] + fn update_admin() { + let owner = "owner".into_addr(); + let app = App::>::custom(|_, _, _| {}); + let (_, unsigned_manager_contract) = setup(&app, &owner); + let new_admin = "new_admin".into_addr(); + + let unsigned_counter_contract_addr = unsigned_manager_contract.counter_contract().unwrap(); + + // Initial admin should be the manager_contract + let contract_info = app + .querier() + .query_wasm_contract_info(unsigned_counter_contract_addr.clone()) + .unwrap(); + assert_eq!( + contract_info.admin, + Some(unsigned_manager_contract.contract_addr.clone()) + ); + + // Add new admin unsigned_manager_contract - .add(5) - .call(&OWNER.into_bech32()) + .update_admin(new_admin.to_string()) + .call(&owner) .unwrap(); - assert_eq!(unsigned_manager_contract.count().unwrap(), 5); + + let contract_info = app + .querier() + .query_wasm_contract_info(unsigned_counter_contract_addr) + .unwrap(); + assert_eq!(contract_info.admin, Some(new_admin.clone())); + } + + #[test] + fn clear_admin() { + let owner = "owner".into_addr(); + let app = App::>::custom(|_, _, _| {}); + let (_, unsigned_manager_contract) = setup(&app, &owner); + + let unsigned_counter_contract_addr = unsigned_manager_contract.counter_contract().unwrap(); + + // Initial admin should be the manager_contract + let contract_info = app + .querier() + .query_wasm_contract_info(unsigned_counter_contract_addr.clone()) + .unwrap(); + assert_eq!( + contract_info.admin, + Some(unsigned_manager_contract.contract_addr.clone()) + ); + + // Clear admin + unsigned_manager_contract + .clear_admin() + .call(&owner) + .unwrap(); + + let contract_info = app + .querier() + .query_wasm_contract_info(unsigned_counter_contract_addr.clone()) + .unwrap(); + assert_eq!(contract_info.admin, None); } } From 1b6c5733b3f27aae039ab91fd672faf2ab5e2d49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Wo=C5=BAniak?= Date: Thu, 3 Oct 2024 11:24:42 +0200 Subject: [PATCH 2/3] chore: Add doc comments and use `&str` in `update_admin` --- sylvia/src/types.rs | 8 ++++++-- sylvia/tests/remote.rs | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/sylvia/src/types.rs b/sylvia/src/types.rs index 86499000..b3999c6e 100644 --- a/sylvia/src/types.rs +++ b/sylvia/src/types.rs @@ -1,4 +1,5 @@ //! Module providing utilities to build and use sylvia contracts. + use cosmwasm_std::{Binary, Coin, Deps, DepsMut, Empty, Env, MessageInfo, WasmMsg}; #[cfg(feature = "sv_replies")] use cosmwasm_std::{Event, MsgResponse}; @@ -431,17 +432,20 @@ impl<'a, Contract: ?Sized> Remote<'a, Contract> { } } + /// Creates a new instance of [ExecutorBuilder] from underlying contract address. pub fn executor(&self) -> ExecutorBuilder<(EmptyExecutorBuilderState, Contract)> { ExecutorBuilder::<(EmptyExecutorBuilderState, Contract)>::new(&self.addr) } - pub fn update_admin(&self, new_admin: String) -> WasmMsg { + /// Creates a new instance of [WasmMsg::UpdateAdmin] from underlying contract address and provided admin address. + pub fn update_admin(&self, new_admin: &str) -> WasmMsg { WasmMsg::UpdateAdmin { contract_addr: self.addr.to_string(), - admin: new_admin, + admin: new_admin.to_string(), } } + /// Creates a new instance of [WasmMsg::ClearAdmin] from underlying contract address. pub fn clear_admin(&self) -> WasmMsg { WasmMsg::ClearAdmin { contract_addr: self.addr.to_string(), diff --git a/sylvia/tests/remote.rs b/sylvia/tests/remote.rs index ad47995c..a5821488 100644 --- a/sylvia/tests/remote.rs +++ b/sylvia/tests/remote.rs @@ -268,7 +268,7 @@ pub mod manager { .remote_counter .load(ctx.deps.storage)? .interface_remote - .update_admin(new_admin); + .update_admin(&new_admin); let resp = Response::new().add_message(wasm); Ok(resp) } From 6fb60497d2777b3262f7f072f412d72b738c4b6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Wo=C5=BAniak?= Date: Wed, 9 Oct 2024 18:22:22 +0200 Subject: [PATCH 3/3] chore: Add comment with more context about ContractStorage --- sylvia/tests/remote.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sylvia/tests/remote.rs b/sylvia/tests/remote.rs index a5821488..f7468e66 100644 --- a/sylvia/tests/remote.rs +++ b/sylvia/tests/remote.rs @@ -156,7 +156,9 @@ pub mod unsigned_contract { } } -// Making sure `Remote` can be stored in `#[cw_serde]` types +// Making sure `Remote` can be stored in `#[cw_serde]` types. +// This is intentionally a dead code. +// https://github.com/CosmWasm/sylvia/issues/181 #[cw_serde] #[allow(dead_code)] pub struct ContractStorage {