This document explains what the admin address recorded by initialize(admin) currently stores, what the admin can do today, and design considerations for future admin powers.
- The contract records the
adminaddress in instance storage under theAdminkey. - It also sets an
Initializedflag soinitialize()can only be called once. - The recorded admin address is required to have signed the
initialize()transaction (the function callsadmin.require_auth()).
- Access: Public, no authorization required.
- Description: Returns the current admin address stored in instance storage.
- State changes: None (read-only).
- Panics: If the contract has not been initialized yet.
- Access: Admin-only.
- Description: Transfers admin privileges from the current admin to a new address.
- Authorization: Must be called by the current admin (requires
admin.require_auth()). - State changes: Updates the
Adminkey in instance storage to the new admin address, emits atransfer_adminevent. - Panics: If the contract has not been initialized, or if the caller is not the current admin.
- Access: Admin-only.
- Description: Activates an emergency pause on the contract. During a pause,
depositandlock_fundsare blocked, butwithdrawandwithdraw_lockremain available so users can always exit. The pause automatically expires afterduration_secsseconds. - Authorization: Must be called by the current admin (requires
admin.require_auth()). - State changes: Sets
PausedtotrueandPauseExpirytocurrent_timestamp + duration_secsin instance storage. Emits apauseevent with the expiry timestamp. - Panics: If the contract has not been initialized, if the caller is not the admin, or if
duration_secsis zero. - Notes: Calling
pausewhile already paused refreshes the expiry (double-pause is allowed).
- Access: Admin-only.
- Description: Immediately deactivates an active pause, re-enabling deposits and locks. Can be called before the pause expires to restore normal operations early.
- Authorization: Must be called by the current admin (requires
admin.require_auth()). - State changes: Sets
PausedtofalseandPauseExpiryto0in instance storage. Emits anunpauseevent. - Panics: If the contract has not been initialized, or if the caller is not the admin.
- Access: Public, no authorization required.
- Description: Returns
trueif the contract is currently paused and the pause has not expired. Returnsfalseif not paused or if the pause has expired. - State changes: None (read-only).
- Panics: If the contract has not been initialized.
- Cannot pause contract execution or halt deposits/withdrawals — RESOLVED: The admin can now pause via
pause(duration_secs), but withdrawals remain open during a pause. - Cannot migrate or sweep funds from user balances.
- Cannot recover or forcibly withdraw user funds.
- Cannot upgrade the contract (no
upgrade()or proxy mechanism is present). - Cannot change user balances or unlock times except via the existing user-authorized functions (which call
require_auth()on the user address). - Cannot pause indefinitely — the pause auto-expires after the specified duration.
- Cannot pause withdrawals — the withdraw-only safety net is a hard guarantee.
- The admin's powers are currently limited to transferring admin rights; they cannot access or modify user funds.
- Users and auditors should review any future changes to the admin's capabilities carefully.
- Multi-signature (multisig) administration is recommended for the admin key to reduce the risk of a single point of failure.
When adding admin capabilities in the future, consider the following best practices:
- Principle of least privilege: give admin only the minimal necessary powers.
- Multi-signature or multisig guardianship: require multiple parties to authorize sensitive admin actions.
- Timelocks and delays: make critical changes subject to delays and on-chain announcements to allow user reaction time.
- Emergency pause vs. recovery: separate a limited emergency pause from powerful recovery/migration privileges.
- On-chain governance: consider decentralizing critical powers to a DAO or governance contract.
- Upgrade patterns: if supporting upgrades, prefer transparent proxy patterns, clearly documented migration steps, and on-chain governance or multisig protection.
- The admin value is stored under
DataKey::Adminincontracts/savings_vault/src/lib.rs. - Admin helper functions:
assert_initialized(),assert_supported_storage_version(),assert_admin(). - Admin functions:
get_admin(),transfer_admin().
- Admin role documentation exists.
- Docs explain what
initialize(admin)stores. - Docs explain current admin capabilities.
- Docs explain what admin cannot do.
- Docs mention future admin design considerations.
If you want, I can expand this file with recommended admin function implementations (pause, migrate, multisig examples) and accompanying tests.