diff --git a/sylvia-derive/src/message.rs b/sylvia-derive/src/message.rs index 24bbd530..0ed9212d 100644 --- a/sylvia-derive/src/message.rs +++ b/sylvia-derive/src/message.rs @@ -666,6 +666,16 @@ impl<'a> MsgVariant<'a> { .map_err(Into::into) } }, + MsgType::Sudo => quote! { + pub fn #name (&self, #(#params,)* ) -> Result< #sylvia ::cw_multi_test::AppResponse, #error_type> { + let msg = #enum_name :: #name ( #(#arguments),* ); + + (*self.app) + .app_mut() + .wasm_sudo(self.contract_addr.clone(), &msg) + .map_err(|err| err.downcast().unwrap()) + } + }, _ => quote! {}, } } @@ -719,6 +729,16 @@ impl<'a> MsgVariant<'a> { } } } + MsgType::Sudo => quote! { + fn #name (&self, #(#params,)* ) -> Result< #sylvia ::cw_multi_test::AppResponse, #error_type> { + let msg = #interface_api :: #type_name :: #name ( #(#arguments),* ); + + (*self.app) + .app_mut() + .wasm_sudo(self.contract_addr.clone(), &msg) + .map_err(|err| err.downcast().unwrap()) + } + }, _ => quote! {}, } } @@ -757,6 +777,9 @@ impl<'a> MsgVariant<'a> { fn #name (&self, #(#params,)* ) -> Result<#return_type, #error_type>; } } + MsgType::Sudo => quote! { + fn #name (&self, #(#params,)* ) -> Result< #sylvia ::cw_multi_test::AppResponse, #error_type>; + }, _ => quote! {}, } } @@ -1665,20 +1688,25 @@ impl<'a> EntryPoints<'a> { #[cfg(not(tarpaulin_include))] { - let entry_points = [instantiate_variants, exec_variants, query_variants] - .into_iter() - .map( - |variants| match override_entry_points.get_entry_point(variants.msg_ty) { - Some(_) => quote! {}, - None => variants.emit_default_entry_point( - &custom_msg, - &custom_query, - name, - error, - &attrs.generics, - ), - }, - ); + let entry_points = [ + instantiate_variants, + exec_variants, + query_variants, + sudo_variants, + ] + .into_iter() + .map(|variants| { + match override_entry_points.get_entry_point(variants.msg_ty) { + Some(_) => quote! {}, + None => variants.emit_default_entry_point( + &custom_msg, + &custom_query, + name, + error, + &attrs.generics, + ), + } + }); let migrate_not_overridden = override_entry_points .get_entry_point(MsgType::Migrate) @@ -1714,19 +1742,6 @@ impl<'a> EntryPoints<'a> { _ => quote! {}, }); - let sudo = override_entry_points - .get_entry_point(MsgType::Sudo) - .map(|_| quote! {}) - .unwrap_or_else(|| { - sudo_variants.emit_default_entry_point( - &custom_msg, - &custom_query, - name, - error, - &attrs.generics, - ) - }); - quote! { pub mod entry_points { use super::*; @@ -1736,8 +1751,6 @@ impl<'a> EntryPoints<'a> { #migrate #reply_ep - - #sudo } } } diff --git a/sylvia-derive/src/multitest.rs b/sylvia-derive/src/multitest.rs index 5446029e..362952b4 100644 --- a/sylvia-derive/src/multitest.rs +++ b/sylvia-derive/src/multitest.rs @@ -49,6 +49,7 @@ pub struct ContractMtHelpers<'a> { query_variants: MsgVariants<'a, GenericParam>, migrate_variants: MsgVariants<'a, GenericParam>, reply_variants: MsgVariants<'a, GenericParam>, + sudo_variants: MsgVariants<'a, GenericParam>, } impl<'a> ContractMtHelpers<'a> { @@ -89,6 +90,12 @@ impl<'a> ContractMtHelpers<'a> { generic_params, where_clause, ); + let sudo_variants = MsgVariants::new( + source.as_variants(), + MsgType::Sudo, + generic_params, + where_clause, + ); let error_type: Type = if is_trait(source) { let associated_error = source.items.iter().find_map(|item| match item { @@ -123,6 +130,7 @@ impl<'a> ContractMtHelpers<'a> { instantiate_variants, exec_variants, query_variants, + sudo_variants, migrate_variants, reply_variants, } @@ -136,6 +144,7 @@ impl<'a> ContractMtHelpers<'a> { exec_variants, query_variants, migrate_variants, + sudo_variants, generic_params, where_clause, .. @@ -162,6 +171,8 @@ impl<'a> ContractMtHelpers<'a> { exec_variants.emit_multitest_proxy_methods(&custom_msg, &mt_app, error_type); let query_methods = query_variants.emit_multitest_proxy_methods(&custom_msg, &mt_app, error_type); + let sudo_methods = + sudo_variants.emit_multitest_proxy_methods(&custom_msg, &mt_app, error_type); let migrate_methods = migrate_variants.emit_multitest_proxy_methods(&custom_msg, &mt_app, error_type); let where_predicates = where_clause @@ -215,6 +226,7 @@ impl<'a> ContractMtHelpers<'a> { #( #exec_methods )* #( #migrate_methods )* #( #query_methods )* + #( #sudo_methods )* } impl<'app, BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, #(#generic_params,)* > @@ -498,6 +510,7 @@ impl<'a> ContractMtHelpers<'a> { let bracketed_generics = emit_bracketed_generics(generic_params); let full_where_clause = &source.generics.where_clause; + let instantiate_body = override_entry_points .get_entry_point(MsgType::Instantiate) .map(OverrideEntryPoint::emit_multitest_dispatch) @@ -516,20 +529,14 @@ impl<'a> ContractMtHelpers<'a> { let sudo_body = override_entry_points .get_entry_point(MsgType::Sudo) .map(OverrideEntryPoint::emit_multitest_dispatch) - .unwrap_or_else(|| { - quote! { - #sylvia ::anyhow::bail!("sudo not implemented for contract") - } - }); + .unwrap_or_else(|| emit_default_dispatch(&MsgType::Sudo, contract)); let migrate_body = match override_entry_points.get_entry_point(MsgType::Migrate) { Some(entry_point) => entry_point.emit_multitest_dispatch(), None if migrate_variants.get_only_variant().is_some() => { emit_default_dispatch(&MsgType::Migrate, contract) } - None => quote! { - #sylvia ::anyhow::bail!("migrate not implemented for contract") - }, + None => quote! { #sylvia ::anyhow::bail!("migrate not implemented for contract") }, }; let reply_body = match override_entry_points.get_entry_point(MsgType::Reply) { @@ -630,6 +637,7 @@ pub struct ImplMtHelpers<'a> { generic_params: &'a [&'a GenericParam], exec_variants: MsgVariants<'a, GenericParam>, query_variants: MsgVariants<'a, GenericParam>, + sudo_variants: MsgVariants<'a, GenericParam>, where_clause: &'a Option, contract_module: &'a Option<&'a Path>, contract_name: &'a Ident, @@ -656,6 +664,12 @@ impl<'a> ImplMtHelpers<'a> { generic_params, where_clause, ); + let sudo_variants = MsgVariants::new( + source.as_variants(), + MsgType::Sudo, + generic_params, + where_clause, + ); let associated_error = source.items.iter().find_map(|item| match item { ImplItem::Type(ty) if ty.ident == "Error" => Some(&ty.ty), _ => None, @@ -679,6 +693,7 @@ impl<'a> ImplMtHelpers<'a> { interfaces, exec_variants, query_variants, + sudo_variants, contract_module, } } @@ -692,6 +707,7 @@ impl<'a> ImplMtHelpers<'a> { generic_params, exec_variants, query_variants, + sudo_variants, where_clause, contract_module, contract_name, @@ -753,6 +769,13 @@ impl<'a> ImplMtHelpers<'a> { &interface_api, &associated_items, ); + let sudo_methods = sudo_variants.emit_interface_multitest_proxy_methods( + &custom_msg, + &mt_app, + error_type, + &interface_api, + &associated_items, + ); let exec_methods_declarations = exec_variants.emit_proxy_methods_declarations( &custom_msg, error_type, @@ -765,6 +788,12 @@ impl<'a> ImplMtHelpers<'a> { &interface_api, &associated_items, ); + let sudo_methods_declarations = sudo_variants.emit_proxy_methods_declarations( + &custom_msg, + error_type, + &interface_api, + &associated_items, + ); let contract_module = match contract_module { Some(contract_module) => quote! { #contract_module :: }, @@ -785,6 +814,7 @@ impl<'a> ImplMtHelpers<'a> { pub trait #trait_name #where_clause { #(#query_methods_declarations)* #(#exec_methods_declarations)* + #(#sudo_methods_declarations)* } impl #trait_name< #mt_app, #(#generic_params,)* > for #contract_module sv::multitest_utils:: #contract_proxy <'_, #mt_app, #(#generic_params,)* > @@ -811,6 +841,7 @@ impl<'a> ImplMtHelpers<'a> { { #(#query_methods)* #(#exec_methods)* + #(#sudo_methods)* } } } diff --git a/sylvia/tests/custom_msg.rs b/sylvia/tests/custom_msg.rs index 6e40decb..061ea619 100644 --- a/sylvia/tests/custom_msg.rs +++ b/sylvia/tests/custom_msg.rs @@ -2,7 +2,7 @@ use cosmwasm_std::{CustomMsg, Response, StdResult}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use sylvia::contract; -use sylvia::types::{ExecCtx, InstantiateCtx, MigrateCtx, QueryCtx}; +use sylvia::types::{ExecCtx, InstantiateCtx, MigrateCtx, QueryCtx, SudoCtx}; #[derive(Clone, PartialEq, Serialize, Deserialize, Debug, JsonSchema)] pub struct MyMsg; @@ -22,7 +22,7 @@ pub struct SomeResponse; mod some_interface { use cosmwasm_std::{Response, StdError, StdResult}; use sylvia::interface; - use sylvia::types::{ExecCtx, QueryCtx}; + use sylvia::types::{ExecCtx, QueryCtx, SudoCtx}; use crate::{MyMsg, SomeResponse}; @@ -38,13 +38,17 @@ mod some_interface { #[cfg(not(tarpaulin_include))] #[msg(exec)] fn interface_exec(&self, ctx: ExecCtx) -> StdResult>; + + #[cfg(not(tarpaulin_include))] + #[msg(sudo)] + fn interface_sudo(&self, ctx: SudoCtx) -> StdResult>; } } mod impl_some_interface { use cosmwasm_std::{Response, StdError, StdResult}; use sylvia::contract; - use sylvia::types::{ExecCtx, QueryCtx}; + use sylvia::types::{ExecCtx, QueryCtx, SudoCtx}; use crate::some_interface::SomeInterface; use crate::{MyMsg, SomeResponse}; @@ -64,6 +68,11 @@ mod impl_some_interface { fn interface_exec(&self, _ctx: ExecCtx) -> StdResult> { Ok(Response::default()) } + + #[msg(sudo)] + fn interface_sudo(&self, _ctx: SudoCtx) -> StdResult> { + Ok(Response::new()) + } } } @@ -72,7 +81,7 @@ mod interface { use crate::MyMsg; use cosmwasm_std::{CustomMsg, Response, StdError, StdResult}; use sylvia::interface; - use sylvia::types::ExecCtx; + use sylvia::types::{ExecCtx, QueryCtx, SudoCtx}; #[interface] #[sv::custom(msg=MyMsg)] @@ -83,6 +92,14 @@ mod interface { #[cfg(not(tarpaulin_include))] #[msg(exec)] fn exec(&self, ctx: ExecCtx) -> StdResult>; + + #[cfg(not(tarpaulin_include))] + #[msg(query)] + fn query(&self, ctx: QueryCtx) -> StdResult>; + + #[cfg(not(tarpaulin_include))] + #[msg(sudo)] + fn sudo(&self, ctx: SudoCtx) -> StdResult>; } } mod impl_interface { @@ -90,7 +107,7 @@ mod impl_interface { use crate::{MyMsg, OtherMsg}; use cosmwasm_std::{Response, StdError, StdResult}; use sylvia::contract; - use sylvia::types::ExecCtx; + use sylvia::types::{ExecCtx, QueryCtx, SudoCtx}; #[contract(module=crate)] #[messages(crate::interface)] @@ -103,13 +120,24 @@ mod impl_interface { fn exec(&self, _ctx: ExecCtx) -> StdResult> { Ok(Response::default()) } + + #[msg(query)] + fn query(&self, _ctx: QueryCtx) -> StdResult> { + Ok(Response::new()) + } + + #[cfg(not(tarpaulin_include))] + #[msg(sudo)] + fn sudo(&self, _ctx: SudoCtx) -> StdResult> { + Ok(Response::new()) + } } } mod other_interface { use cosmwasm_std::{Response, StdError, StdResult}; use sylvia::interface; - use sylvia::types::ExecCtx; + use sylvia::types::{ExecCtx, QueryCtx, SudoCtx}; #[interface] pub trait OtherInterface { @@ -118,13 +146,21 @@ mod other_interface { #[cfg(not(tarpaulin_include))] #[msg(exec)] fn other_interface_exec(&self, ctx: ExecCtx) -> StdResult; + + #[cfg(not(tarpaulin_include))] + #[msg(sudo)] + fn other_interface_sudo(&self, ctx: SudoCtx) -> StdResult; + + #[cfg(not(tarpaulin_include))] + #[msg(query)] + fn other_interface_query(&self, ctx: QueryCtx) -> StdResult; } } mod impl_other_interface { use crate::other_interface::OtherInterface; use cosmwasm_std::{Response, StdError, StdResult}; use sylvia::contract; - use sylvia::types::ExecCtx; + use sylvia::types::{ExecCtx, QueryCtx, SudoCtx}; #[contract(module=crate)] #[messages(crate::other_interface)] @@ -136,13 +172,26 @@ mod impl_other_interface { fn other_interface_exec(&self, _ctx: ExecCtx) -> StdResult { Ok(Response::default()) } + + #[cfg(not(tarpaulin_include))] + #[msg(sudo)] + fn other_interface_sudo(&self, _ctx: SudoCtx) -> StdResult { + Ok(Response::new()) + } + + #[cfg(not(tarpaulin_include))] + #[msg(query)] + fn other_interface_query(&self, _ctx: QueryCtx) -> StdResult { + Ok(Response::new()) + } } } mod associated_interface { + use crate::SomeResponse; use cosmwasm_std::{CustomMsg, Response, StdError, StdResult}; use sylvia::interface; - use sylvia::types::ExecCtx; + use sylvia::types::{ExecCtx, QueryCtx, SudoCtx}; #[interface] pub trait AssociatedInterface { @@ -152,14 +201,22 @@ mod associated_interface { #[cfg(not(tarpaulin_include))] #[msg(exec)] fn associated_exec(&self, ctx: ExecCtx) -> StdResult>; + + #[cfg(not(tarpaulin_include))] + #[msg(sudo)] + fn associated_sudo(&self, ctx: SudoCtx) -> StdResult>; + + #[cfg(not(tarpaulin_include))] + #[msg(query)] + fn associated_query(&self, ctx: QueryCtx) -> StdResult; } } mod impl_associated_interface { use crate::associated_interface::AssociatedInterface; - use crate::MyMsg; + use crate::{MyMsg, SomeResponse}; use cosmwasm_std::{Response, StdError, StdResult}; use sylvia::contract; - use sylvia::types::ExecCtx; + use sylvia::types::{ExecCtx, QueryCtx, SudoCtx}; #[contract(module=crate)] #[messages(crate::associated_interface)] @@ -172,6 +229,16 @@ mod impl_associated_interface { fn associated_exec(&self, _ctx: ExecCtx) -> StdResult> { Ok(Response::default()) } + + #[msg(sudo)] + fn associated_sudo(&self, _ctx: SudoCtx) -> StdResult> { + Ok(Response::default()) + } + + #[msg(query)] + fn associated_query(&self, _ctx: QueryCtx) -> StdResult { + Ok(SomeResponse {}) + } } } @@ -207,6 +274,12 @@ impl MyContract { pub fn some_migrate(&self, _ctx: MigrateCtx) -> StdResult> { Ok(Response::default()) } + + #[cfg(not(tarpaulin_include))] + #[msg(sudo)] + pub fn some_sudo(&self, _ctx: SudoCtx) -> StdResult> { + Ok(Response::default()) + } } #[cfg(all(test, feature = "mt"))] @@ -230,23 +303,36 @@ mod tests { let contract = code_id .instantiate() .with_label("MyContract") + .with_admin(owner) .call(owner) .unwrap(); contract.some_exec().call(owner).unwrap(); contract.some_query().unwrap(); + contract.some_sudo().unwrap(); + contract + .some_migrate() + .call(owner, code_id.code_id()) + .unwrap(); // Interface messsages contract.interface_query().unwrap(); contract.interface_exec().call(owner).unwrap(); + contract.interface_sudo().unwrap(); // Other interface messages + contract.other_interface_query().unwrap(); contract.other_interface_exec().call(owner).unwrap(); + contract.other_interface_sudo().unwrap(); // Associated interface messages + contract.associated_query().unwrap(); contract.associated_exec().call(owner).unwrap(); + contract.associated_sudo().unwrap(); // Both associated type and custom attr used + contract.query().unwrap(); contract.exec().call(owner).unwrap(); + contract.sudo().unwrap(); } } diff --git a/sylvia/tests/custom_query.rs b/sylvia/tests/custom_query.rs index 6a5ee6db..ffa98cb1 100644 --- a/sylvia/tests/custom_query.rs +++ b/sylvia/tests/custom_query.rs @@ -1,7 +1,7 @@ use cosmwasm_schema::cw_serde; use cosmwasm_std::{CustomQuery, Response, StdResult}; use sylvia::contract; -use sylvia::types::{ExecCtx, InstantiateCtx, MigrateCtx, QueryCtx}; +use sylvia::types::{ExecCtx, InstantiateCtx, MigrateCtx, QueryCtx, SudoCtx}; #[cw_serde] pub struct MyQuery; @@ -19,9 +19,9 @@ pub struct MyContract; pub struct SomeResponse; mod interface { - use cosmwasm_std::{CustomQuery, Response, StdError, StdResult}; + use cosmwasm_std::{Response, StdError, StdResult}; use sylvia::interface; - use sylvia::types::{ExecCtx, QueryCtx}; + use sylvia::types::{CustomQuery, ExecCtx, QueryCtx, SudoCtx}; use crate::{MyQuery, SomeResponse}; @@ -38,12 +38,16 @@ mod interface { #[cfg(not(tarpaulin_include))] #[msg(exec)] fn interface_exec(&self, ctx: ExecCtx) -> StdResult; + + #[cfg(not(tarpaulin_include))] + #[msg(sudo)] + fn interface_sudo(&self, ctx: SudoCtx) -> StdResult; } } mod impl_interface { use cosmwasm_std::{Response, StdError, StdResult}; - use sylvia::types::{ExecCtx, QueryCtx}; + use sylvia::types::{ExecCtx, QueryCtx, SudoCtx}; use sylvia_derive::contract; use crate::{MyQuery, OtherQuery, SomeResponse}; @@ -64,13 +68,18 @@ mod impl_interface { fn interface_exec(&self, _ctx: ExecCtx) -> StdResult { Ok(Response::default()) } + + #[msg(sudo)] + fn interface_sudo(&self, _ctx: SudoCtx) -> StdResult { + Ok(Response::default()) + } } } mod some_interface { use cosmwasm_std::{Response, StdError, StdResult}; use sylvia::interface; - use sylvia::types::{ExecCtx, QueryCtx}; + use sylvia::types::{ExecCtx, QueryCtx, SudoCtx}; use crate::{MyQuery, SomeResponse}; @@ -86,12 +95,16 @@ mod some_interface { #[cfg(not(tarpaulin_include))] #[msg(exec)] fn some_interface_exec(&self, ctx: ExecCtx) -> StdResult; + + #[cfg(not(tarpaulin_include))] + #[msg(sudo)] + fn some_interface_sudo(&self, ctx: SudoCtx) -> StdResult; } } mod impl_some_interface { use cosmwasm_std::{Response, StdError, StdResult}; - use sylvia::types::{ExecCtx, QueryCtx}; + use sylvia::types::{ExecCtx, QueryCtx, SudoCtx}; use sylvia_derive::contract; use crate::{MyQuery, SomeResponse}; @@ -111,13 +124,18 @@ mod impl_some_interface { fn some_interface_exec(&self, _ctx: ExecCtx) -> StdResult { Ok(Response::default()) } + + #[msg(sudo)] + fn some_interface_sudo(&self, _ctx: SudoCtx) -> StdResult { + Ok(Response::default()) + } } } mod associated_type_interface { - use cosmwasm_std::{CustomQuery, Response, StdError, StdResult}; + use cosmwasm_std::{Response, StdError, StdResult}; use sylvia::interface; - use sylvia::types::{ExecCtx, QueryCtx}; + use sylvia::types::{CustomQuery, ExecCtx, QueryCtx, SudoCtx}; use crate::SomeResponse; @@ -133,13 +151,17 @@ mod associated_type_interface { #[cfg(not(tarpaulin_include))] #[msg(exec)] fn associated_exec(&self, ctx: ExecCtx) -> StdResult; + + #[cfg(not(tarpaulin_include))] + #[msg(sudo)] + fn associated_sudo(&self, ctx: SudoCtx) -> StdResult; } } mod impl_associated_type_interface { use crate::{associated_type_interface::AssociatedTypeInterface, MyQuery, SomeResponse}; use cosmwasm_std::{Response, StdError, StdResult}; - use sylvia::types::{ExecCtx, QueryCtx}; + use sylvia::types::{ExecCtx, QueryCtx, SudoCtx}; use sylvia_derive::contract; #[contract(module=crate)] @@ -157,13 +179,18 @@ mod impl_associated_type_interface { fn associated_exec(&self, _ctx: ExecCtx) -> StdResult { Ok(Response::default()) } + + #[msg(sudo)] + fn associated_sudo(&self, _ctx: SudoCtx) -> StdResult { + Ok(Response::default()) + } } } mod default_query_interface { use cosmwasm_std::{Response, StdError, StdResult}; use sylvia::interface; - use sylvia::types::{ExecCtx, QueryCtx}; + use sylvia::types::{ExecCtx, QueryCtx, SudoCtx}; use crate::SomeResponse; @@ -178,13 +205,17 @@ mod default_query_interface { #[cfg(not(tarpaulin_include))] #[msg(exec)] fn default_exec(&self, ctx: ExecCtx) -> StdResult; + + #[cfg(not(tarpaulin_include))] + #[msg(sudo)] + fn default_sudo(&self, ctx: SudoCtx) -> StdResult; } } mod impl_default_query_interface { use crate::{default_query_interface::DefaultQueryInterface, SomeResponse}; use cosmwasm_std::{Response, StdError, StdResult}; - use sylvia::types::{ExecCtx, QueryCtx}; + use sylvia::types::{ExecCtx, QueryCtx, SudoCtx}; use sylvia_derive::contract; #[contract(module=crate)] @@ -202,6 +233,11 @@ mod impl_default_query_interface { fn default_exec(&self, _ctx: ExecCtx) -> StdResult { Ok(Response::default()) } + + #[msg(sudo)] + fn default_sudo(&self, _ctx: SudoCtx) -> StdResult { + Ok(Response::default()) + } } } @@ -232,11 +268,15 @@ impl MyContract { Ok(SomeResponse) } - #[cfg(not(tarpaulin_include))] #[msg(migrate)] pub fn some_migrate(&self, _ctx: MigrateCtx) -> StdResult { Ok(Response::default()) } + + #[msg(sudo)] + pub fn some_sudo(&self, _ctx: SudoCtx) -> StdResult { + Ok(Response::default()) + } } #[cfg(all(test, feature = "mt"))] @@ -261,26 +301,36 @@ mod tests { let contract = code_id .instantiate() .with_label("MyContract") + .with_admin(owner) .call(owner) .unwrap(); contract.some_exec().call(owner).unwrap(); contract.some_query().unwrap(); + contract.some_sudo().unwrap(); + contract + .some_migrate() + .call(owner, code_id.code_id()) + .unwrap(); // `sv::custom` attribute interface contract.some_interface_query().unwrap(); contract.some_interface_exec().call(owner).unwrap(); + contract.some_interface_sudo().unwrap(); // Associated tyoe interface messages contract.associated_query().unwrap(); contract.associated_exec().call(owner).unwrap(); + contract.associated_sudo().unwrap(); // `sv::custom` attribute and associated type interface contract.interface_query().unwrap(); contract.interface_exec().call(owner).unwrap(); + contract.interface_sudo().unwrap(); // Neither `custom` attribute nor associated type contract.default_query().unwrap(); contract.default_exec().call(owner).unwrap(); + contract.default_sudo().unwrap(); } }