Problem
contracts/loyalty_token/src/lib.rs:151-156 - transfer_admin() immediately overwrites the Admin storage key:
env.storage().instance().set(&DataKey::Admin, &new_admin);
A single typo in new_admin permanently locks out the current admin with no recovery path. No confirmation is required from the new admin, no event is emitted, and the ability to mint, burn, and manage the loyalty token contract is permanently lost.
Proposed Solution
Implement a two-step admin transfer:
transfer_admin(env, caller, new_admin) - sets DataKey::PendingAdmin, emits (symbol_short!("admin"), symbol_short!("proposed")). Does NOT change DataKey::Admin.
accept_admin(env, caller) - requires caller == PendingAdmin, promotes to Admin, clears PendingAdmin, emits accepted event
cancel_transfer(env, caller) - requires current admin auth, clears PendingAdmin
Acceptance Criteria
Problem
contracts/loyalty_token/src/lib.rs:151-156-transfer_admin()immediately overwrites theAdminstorage key:A single typo in
new_adminpermanently locks out the current admin with no recovery path. No confirmation is required from the new admin, no event is emitted, and the ability to mint, burn, and manage the loyalty token contract is permanently lost.Proposed Solution
Implement a two-step admin transfer:
transfer_admin(env, caller, new_admin)- setsDataKey::PendingAdmin, emits(symbol_short!("admin"), symbol_short!("proposed")). Does NOT changeDataKey::Admin.accept_admin(env, caller)- requirescaller == PendingAdmin, promotes toAdmin, clearsPendingAdmin, emitsacceptedeventcancel_transfer(env, caller)- requires current admin auth, clearsPendingAdminAcceptance Criteria
transfer_admin()alone does NOT change the active adminaccept_admin()from any address other thanPendingAdminpanics with"not pending admin"PendingAdmincleared, old admin still activeproposedandacceptedevents emitted at the correct step