Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions contracts/privacy_pool/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Keeps the interface clean and focused on orchestration.
// ============================================================

use soroban_sdk::{contract, contractimpl, Address, BytesN, Env};
use soroban_sdk::{contract, contractimpl, Address, BytesN, Env, String};

use crate::core::{admin, deposit, initialize, view, withdraw};
use crate::types::errors::Error;
Expand Down Expand Up @@ -94,15 +94,27 @@ impl PrivacyPool {
// ──────────────────────────────────────────────────────────

/// Pause the pool (admin only).
pub fn pause(env: Env, admin: Address) -> Result<(), Error> {
admin::pause(env, admin)
/// Records the pause timestamp and reason for audit trail.
pub fn pause(env: Env, admin: Address, reason: String) -> Result<(), Error> {
admin::pause(env, admin, reason)
}

/// Unpause the pool (admin only).
pub fn unpause(env: Env, admin: Address) -> Result<(), Error> {
admin::unpause(env, admin)
}

/// Check if the pool is currently paused.
pub fn is_paused(env: Env) -> bool {
view::is_paused(env)
}

/// Emergency withdrawal — transfers entire token balance to admin.
/// Only available when pool is paused. Admin-only.
pub fn emergency_withdraw(env: Env, admin: Address) -> Result<i128, Error> {
admin::emergency_withdraw(env, admin)
}

/// Update the Groth16 verifying key (admin only).
pub fn set_verifying_key(
env: Env,
Expand Down
56 changes: 46 additions & 10 deletions contracts/privacy_pool/src/core/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Admin Functions - Pool management
// ============================================================

use soroban_sdk::{Address, Env};
use soroban_sdk::{token, Address, Env, String};

use crate::storage::config;
use crate::types::errors::Error;
Expand All @@ -12,34 +12,70 @@ use crate::utils::validation;

/// Pause the pool - blocks deposits and withdrawals.
/// Only callable by admin.
pub fn pause(env: Env, admin: Address) -> Result<(), Error> {
/// Records the pause timestamp and reason for audit trail.
pub fn pause(env: Env, admin: Address, reason: String) -> Result<(), Error> {
admin.require_auth();

let mut pool_config = config::load(&env)?;
validation::require_admin(&admin, &pool_config)?;

let pause_timestamp = env.ledger().sequence() as u64;
pool_config.paused = true;
pool_config.pause_timestamp = pause_timestamp;
pool_config.pause_reason = reason.clone();
config::save(&env, &pool_config);
emit_pool_paused(&env, admin);

emit_pool_paused(&env, admin, pause_timestamp, reason);
Ok(())
}

/// Unpause the pool.
/// Only callable by admin.
pub fn unpause(env: Env, admin: Address) -> Result<(), Error> {
admin.require_auth();

let mut pool_config = config::load(&env)?;
validation::require_admin(&admin, &pool_config)?;

pool_config.paused = false;
config::save(&env, &pool_config);

emit_pool_unpaused(&env, admin);

let unpause_timestamp = env.ledger().sequence() as u64;
emit_pool_unpaused(&env, admin, unpause_timestamp);
Ok(())
}

/// Emergency withdrawal - allows admin to recover funds when pool is paused.
/// Only callable by admin when pool is paused.
/// Transfers the entire token balance to the admin.
pub fn emergency_withdraw(env: Env, admin: Address) -> Result<i128, Error> {
admin.require_auth();

let pool_config = config::load(&env)?;
validation::require_admin(&admin, &pool_config)?;

// Only allow emergency withdraw when pool is paused
if !pool_config.paused {
return Err(Error::PoolNotPaused);
}

let token_client = token::Client::new(&env, &pool_config.token);
let balance = token_client.balance(&env.current_contract_address());

if balance <= 0 {
return Err(Error::NoFundsToWithdraw);
}

// Transfer entire balance to admin
token_client.transfer(
&env.current_contract_address(),
&admin,
&balance,
);

Ok(balance)
}

/// Update the Groth16 verifying key.
/// Only callable by admin. Critical operation - used for circuit upgrades.
pub fn set_verifying_key(
Expand All @@ -48,12 +84,12 @@ pub fn set_verifying_key(
new_vk: VerifyingKey,
) -> Result<(), Error> {
admin.require_auth();

let pool_config = config::load(&env)?;
validation::require_admin(&admin, &pool_config)?;

config::save_verifying_key(&env, &new_vk);

emit_vk_updated(&env, admin);
Ok(())
}
4 changes: 3 additions & 1 deletion contracts/privacy_pool/src/core/initialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Initialization Logic
// ============================================================

use soroban_sdk::{Address, Env};
use soroban_sdk::{Address, Env, String};

use crate::crypto::merkle;
use crate::storage::config;
Expand Down Expand Up @@ -39,6 +39,8 @@ pub fn execute(
tree_depth: merkle::TREE_DEPTH,
root_history_size: merkle::ROOT_HISTORY_SIZE,
paused: false,
pause_timestamp: 0,
pause_reason: String::from_str(&env, ""),
};

// Save configuration and verifying key
Expand Down
8 changes: 8 additions & 0 deletions contracts/privacy_pool/src/core/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ pub fn is_spent(env: Env, nullifier_hash: BytesN<32>) -> bool {
nullifier::is_spent(&env, &nullifier_hash)
}

/// Check if the pool is currently paused.
pub fn is_paused(env: Env) -> bool {
match config::load(&env) {
Ok(cfg) => cfg.paused,
Err(_) => false,
}
}

/// Returns the pool configuration.
pub fn get_config(env: Env) -> Result<PoolConfig, Error> {
config::load(&env)
Expand Down
Loading