@@ -91,6 +91,9 @@ pub fn admin_execute(
91
91
) -> AccountResult {
92
92
ownership:: assert_nested_owner ( deps. storage , & deps. querier , & info. sender ) ?;
93
93
94
+ if CALLING_TO_AS_ADMIN . exists ( deps. storage ) {
95
+ return Err ( AccountError :: CantChainAdminCalls { } ) ;
96
+ }
94
97
CALLING_TO_AS_ADMIN . save ( deps. storage , & addr) ?;
95
98
96
99
let msg = SubMsg :: reply_on_success (
@@ -225,9 +228,71 @@ mod test {
225
228
226
229
mod execute_action {
227
230
228
- use cosmwasm_std:: { testing:: MOCK_CONTRACT_ADDR , wasm_execute, CosmosMsg } ;
231
+ use abstract_sdk:: namespaces:: OWNERSHIP_STORAGE_KEY ;
232
+ use abstract_std:: objects:: { gov_type:: GovernanceDetails , ownership:: Ownership } ;
233
+ use cosmwasm_std:: {
234
+ testing:: MOCK_CONTRACT_ADDR , wasm_execute, Addr , Binary , CosmosMsg , DepsMut , Empty ,
235
+ Env , Response , WasmMsg ,
236
+ } ;
237
+ use cw_storage_plus:: Item ;
238
+
239
+ use crate :: contract:: AccountResult ;
229
240
230
241
use super :: * ;
242
+ fn execute_from_res ( deps : DepsMut , env : Env , res : Response ) -> AccountResult < Response > {
243
+ // Execute all messages
244
+ let info = message_info ( & env. contract . address , & [ ] ) ;
245
+ if let CosmosMsg :: Wasm ( WasmMsg :: Execute {
246
+ contract_addr : _,
247
+ msg,
248
+ funds : _,
249
+ } ) = res. messages [ 0 ] . msg . clone ( )
250
+ {
251
+ execute ( deps, env. clone ( ) , info, from_json ( & msg) ?) . map_err ( Into :: into)
252
+ } else {
253
+ panic ! ( "Wrong message received" ) ;
254
+ }
255
+ }
256
+
257
+ #[ coverage_helper:: test]
258
+ fn admin_actions_not_chained ( ) -> anyhow:: Result < ( ) > {
259
+ let mut deps = mock_dependencies ( ) ;
260
+ deps. querier = abstract_mock_querier ( deps. api ) ;
261
+ mock_init ( & mut deps) ?;
262
+ let env = mock_env_validated ( deps. api ) ;
263
+
264
+ // We set the contract as owner.
265
+ // We can't make it through execute msgs, because signatures are too messy to reproduce in tests
266
+ let ownership = Ownership {
267
+ owner : GovernanceDetails :: AbstractAccount {
268
+ address : env. contract . address . clone ( ) ,
269
+ }
270
+ . verify ( deps. as_ref ( ) ) ?,
271
+ pending_owner : None ,
272
+ pending_expiry : None ,
273
+ } ;
274
+
275
+ const OWNERSHIP : Item < Ownership < Addr > > = Item :: new ( OWNERSHIP_STORAGE_KEY ) ;
276
+ OWNERSHIP . save ( deps. as_mut ( ) . storage , & ownership) ?;
277
+
278
+ let msg = ExecuteMsg :: AdminExecute {
279
+ addr : env. contract . address . to_string ( ) ,
280
+ msg : to_json_binary ( & ExecuteMsg :: < Empty > :: AdminExecute {
281
+ addr : env. contract . address . to_string ( ) ,
282
+ msg : Binary :: new ( vec ! [ ] ) ,
283
+ } ) ?,
284
+ } ;
285
+
286
+ let info = message_info ( & env. contract . address , & [ ] ) ;
287
+ let env = mock_env_validated ( deps. api ) ;
288
+
289
+ let res = execute ( deps. as_mut ( ) , env. clone ( ) , info, msg) . unwrap ( ) ;
290
+ // We simulate it's still an admin call
291
+ AUTH_ADMIN . save ( deps. as_mut ( ) . storage , & true ) ?;
292
+ let res = execute_from_res ( deps. as_mut ( ) , env, res) ;
293
+ assert_eq ! ( res, Err ( AccountError :: CantChainAdminCalls { } ) ) ;
294
+ Ok ( ( ) )
295
+ }
231
296
232
297
#[ coverage_helper:: test]
233
298
fn only_whitelisted_can_execute ( ) -> anyhow:: Result < ( ) > {
0 commit comments