diff --git a/contracts/access_control/admin.rs b/contracts/access_control/admin.rs new file mode 100644 index 0000000..c2a9c76 --- /dev/null +++ b/contracts/access_control/admin.rs @@ -0,0 +1,24 @@ +use soroban_sdk::{Env, Address}; +use super::storage::get_admin; + +/// 🔒 Require admin authentication +pub fn require_admin(env: &Env) -> Address { + let admin = get_admin(env); + + // Enforce authentication + admin.require_auth(); + + admin +} + +/// 🔄 Optional: transfer admin ownership +pub fn transfer_admin(env: &Env, new_admin: Address) { + let current_admin = require_admin(env); + + // Prevent accidental self-transfer (optional safety) + if current_admin == new_admin { + panic!("New admin must be different"); + } + + super::storage::set_admin(env, &new_admin); +} \ No newline at end of file diff --git a/contracts/access_control/mod.rs b/contracts/access_control/mod.rs new file mode 100644 index 0000000..ac83d30 --- /dev/null +++ b/contracts/access_control/mod.rs @@ -0,0 +1,6 @@ +pub mod admin; +pub mod storage; + +// Re-export for easy use +pub use admin::{require_admin, transfer_admin}; +pub use storage::{set_admin, get_admin}; \ No newline at end of file diff --git a/contracts/access_control/storage.rs b/contracts/access_control/storage.rs new file mode 100644 index 0000000..cb2003f --- /dev/null +++ b/contracts/access_control/storage.rs @@ -0,0 +1,14 @@ +use soroban_sdk::{Env, Address, Symbol}; + +const ADMIN_KEY: Symbol = Symbol::short("ADMIN"); + +pub fn set_admin(env: &Env, admin: &Address) { + env.storage().instance().set(&ADMIN_KEY, admin); +} + +pub fn get_admin(env: &Env) -> Address { + env.storage() + .instance() + .get(&ADMIN_KEY) + .expect("Admin not initialized") +} \ No newline at end of file diff --git a/contracts/benchmark/mod.rs b/contracts/benchmark/mod.rs new file mode 100644 index 0000000..2ffb1e2 --- /dev/null +++ b/contracts/benchmark/mod.rs @@ -0,0 +1,15 @@ +pub mod profiler; + +pub use profiler::{GasProfile}; +use soroban_sdk::Env; + +/// Measure gas/footprint for a closure +pub fn profile(env: &Env, f: F) -> GasProfile +where + F: FnOnce(), +{ + let start = GasProfile::new(env); + f(); + let end = GasProfile::new(env); + start.delta(&end) +} \ No newline at end of file diff --git a/contracts/benchmark/profiler.rs b/contracts/benchmark/profiler.rs new file mode 100644 index 0000000..e20b04d --- /dev/null +++ b/contracts/benchmark/profiler.rs @@ -0,0 +1,21 @@ +use soroban_sdk::{Env, BytesN}; + +pub struct GasProfile { + pub cpu_insns: u64, + pub mem_bytes: u64, +} + +impl GasProfile { + pub fn new(env: &Env) -> Self { + let cpu_insns = env.budget().cpu_insns(); + let mem_bytes = env.budget().mem_bytes(); + Self { cpu_insns, mem_bytes } + } + + pub fn delta(&self, after: &GasProfile) -> GasProfile { + GasProfile { + cpu_insns: after.cpu_insns - self.cpu_insns, + mem_bytes: after.mem_bytes - self.mem_bytes, + } + } +} \ No newline at end of file