From 214acfced89f00edf238e3d66b8b8f14f35075a7 Mon Sep 17 00:00:00 2001 From: mootz12 Date: Thu, 23 May 2024 09:47:03 -0400 Subject: [PATCH] fix: transfer admin to current contract during setup --- src/contract.rs | 12 ++++++--- src/test.rs | 70 +++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 74 insertions(+), 8 deletions(-) diff --git a/src/contract.rs b/src/contract.rs index a5fe2e6..f3496d4 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -8,22 +8,28 @@ pub struct AdminTransfer; #[contractimpl] impl AdminTransfer { - /// Set the details for an admin transfer + /// Set the details for an admin transfer. Also sets the admin of the pool to this contract. + /// Must be called by the current admin of the pool. /// /// ### Arguments /// * `pool` - The address of the pool the admin transfer is for - /// * `new_admin` - The deadline ledger sequence number of the distribution + /// * `cur_admin` - The current admin of the pool + /// * `new_admin` - The new admin of the pool /// /// ### Panics /// * `AdminTransferExists` - If the contract has already been initialized - pub fn set_admin_transfer(e: Env, pool: Address, new_admin: Address) { + pub fn set_admin_transfer(e: Env, pool: Address, cur_admin: Address, new_admin: Address) { assert_with_error!( &e, !storage::has_admin_transfer(&e, &pool), ContractError::AdminTransferExists ); + cur_admin.require_auth(); storage::extend_instance(&e); + let pool_client = Client::new(&e, &pool); + pool_client.set_admin(&e.current_contract_address()); + storage::set_admin_transfer(&e, &pool, &new_admin); } diff --git a/src/test.rs b/src/test.rs index a6b374e..3d78a63 100644 --- a/src/test.rs +++ b/src/test.rs @@ -51,19 +51,79 @@ fn test_admin_transfer() { ); // create admin transfer - let pool_client = PoolClient::new(&env, &pool); - pool_client.mock_all_auths().set_admin(&admin_transfer_id); - admin_transfer_client.set_admin_transfer(&pool, &new_admin); + admin_transfer_client + .mock_auths(&[MockAuth { + address: &admin, + invoke: &MockAuthInvoke { + contract: &admin_transfer_id, + fn_name: &"set_admin_transfer", + args: vec![ + &env, + pool.clone().into_val(&env), + admin.clone().into_val(&env), + new_admin.clone().into_val(&env), + ], + sub_invokes: &[MockAuthInvoke { + contract: &pool, + fn_name: &"set_admin", + args: vec![&env, admin_transfer_id.clone().into_val(&env)], + sub_invokes: &[], + }], + }, + }]) + .set_admin_transfer(&pool, &admin, &new_admin); // -> validate auths - assert_eq!(env.auths().len(), 0); + assert_eq!( + env.auths()[0], + ( + admin.clone(), + AuthorizedInvocation { + function: AuthorizedFunction::Contract(( + admin_transfer_id.clone(), + Symbol::new(&env, "set_admin_transfer"), + vec![ + &env, + pool.clone().into_val(&env), + admin.clone().into_val(&env), + new_admin.clone().into_val(&env), + ] + )), + sub_invocations: std::vec![AuthorizedInvocation { + function: AuthorizedFunction::Contract(( + pool.clone(), + Symbol::new(&env, "set_admin"), + vec![&env, admin_transfer_id.clone().into_val(&env),] + )), + sub_invocations: std::vec![] + }] + } + ) + ); // -> validate chain state let result = admin_transfer_client.get_admin_transfer(&pool); assert_eq!(result, Some(new_admin.clone())); + // -> validate admin is no longer the admin + let pool_client = PoolClient::new(&env, &pool); + let result = pool_client + .mock_auths(&[MockAuth { + address: &admin, + invoke: &MockAuthInvoke { + contract: &pool, + fn_name: &"set_status", + args: vec![&env, 4u32.into_val(&env)], + sub_invokes: &[], + }, + }]) + .try_set_status(&4); + assert!(result.is_err()); + // validate another admin transfer cannot be created - let result = admin_transfer_client.try_set_admin_transfer(&pool, &sauron); + let result = admin_transfer_client + .mock_all_auths() + .try_set_admin_transfer(&pool, &admin, &sauron); assert_eq!( result.err(), Some(Ok(Error::from_contract_error(