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

feat: Add UpdateAdmin and ClearAdmin constructors in the Remote #438

Merged
merged 3 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
17 changes: 17 additions & 0 deletions sylvia/src/types.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -431,9 +432,25 @@ 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)
}

/// 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.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(),
}
}
}

impl<'a, Contract: ?Sized> AsRef<cosmwasm_std::Addr> for Remote<'a, Contract> {
Expand Down
150 changes: 131 additions & 19 deletions sylvia/tests/remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,9 @@
}
}

// 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<Contract> {
Expand Down Expand Up @@ -257,12 +259,52 @@

Ok(count)
}

#[sv::msg(exec)]
fn update_admin(
&self,
ctx: ExecCtx<ExampleQuery>,
new_admin: String,
) -> Result<Response<ExampleMsg>, 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)

Check warning on line 275 in sylvia/tests/remote.rs

View check run for this annotation

Codecov / codecov/patch

sylvia/tests/remote.rs#L272-L275

Added lines #L272 - L275 were not covered by tests
}

#[sv::msg(exec)]
fn clear_admin(
&self,
ctx: ExecCtx<ExampleQuery>,
) -> Result<Response<ExampleMsg>, StdError> {
let wasm = self
.remote_counter
.load(ctx.deps.storage)?
.interface_remote

Check warning on line 286 in sylvia/tests/remote.rs

View check run for this annotation

Codecov / codecov/patch

sylvia/tests/remote.rs#L286

Added line #L286 was not covered by tests
.clear_admin();
let resp = Response::new().add_message(wasm);
Ok(resp)

Check warning on line 289 in sylvia/tests/remote.rs

View check run for this annotation

Codecov / codecov/patch

sylvia/tests/remote.rs#L288-L289

Added lines #L288 - L289 were not covered by tests
}

#[sv::msg(query)]
fn counter_contract(&self, ctx: QueryCtx<ExampleQuery>) -> Result<Addr, StdError> {
Ok(self
.remote_counter
.load(ctx.deps.storage)?
.interface_remote

Check warning on line 297 in sylvia/tests/remote.rs

View check run for this annotation

Codecov / codecov/patch

sylvia/tests/remote.rs#L297

Added line #L297 was not covered by tests
.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;
Expand All @@ -277,7 +319,6 @@
use crate::{ExampleMsg, ExampleQuery};

type ExampleApp = BasicApp<ExampleMsg, ExampleQuery>;
const OWNER: &str = "owner";

#[test]
fn remote_generation() {
Expand All @@ -302,27 +343,28 @@
assert_eq!(&addr, borrowed_remote.as_ref());
}

fn setup(
app: &App<ExampleApp>,
fn setup<'a>(
app: &'a App<ExampleApp>,
owner: &'a Addr,
) -> (
Proxy<ExampleApp, ManagerContract<i32>>,
Proxy<ExampleApp, ManagerContract<u32>>,
Proxy<'a, ExampleApp, ManagerContract<i32>>,
Proxy<'a, ExampleApp, ManagerContract<u32>>,
) {
// Manager operating on signed numbers
let signed_counter_code_id = SignedCounterCodeId::store_code(app);

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);

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
Expand All @@ -331,39 +373,109 @@
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);

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()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's create a new setup function for the admin scenarios

.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)
}

#[test]
fn call_remote() {
let owner = "owner".into_addr();
jawoznia marked this conversation as resolved.
Show resolved Hide resolved
let app = App::<cw_multi_test::BasicApp<ExampleMsg, ExampleQuery>>::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::<cw_multi_test::BasicApp<ExampleMsg, ExampleQuery>>::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::<cw_multi_test::BasicApp<ExampleMsg, ExampleQuery>>::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);
}
}
Loading