diff --git a/contracts/compliance/src/allowlist.rs b/contracts/compliance/src/allowlist.rs index cc0e348..620850d 100644 --- a/contracts/compliance/src/allowlist.rs +++ b/contracts/compliance/src/allowlist.rs @@ -15,6 +15,7 @@ pub enum DataKey { AddressIndex, AllowCount, BlockCount, + Tier(Address), } #[contracttype] diff --git a/contracts/compliance/src/lib.rs b/contracts/compliance/src/lib.rs index 444f0fe..5b69362 100644 --- a/contracts/compliance/src/lib.rs +++ b/contracts/compliance/src/lib.rs @@ -119,6 +119,46 @@ impl ComplianceContract { Ok(()) } + /// Allow an address and record its compliance tier. + /// + /// Tier 0 = basic KYC, higher values = enhanced / institutional. + /// The tier is stored independently and does not affect `is_allowed` logic; + /// callers (e.g. the treasury contract) read it via `get_address_tier`. + /// + /// # Errors + /// - [`ContractError::Unauthorized`] if `admin` is not the stored administrator. + /// - [`ContractError::ContractPaused`] if the contract is paused. + pub fn allow_address_with_tier( + env: Env, + admin: Address, + address: Address, + tier: u8, + ) -> Result<(), ContractError> { + Self::require_admin(&env, &admin)?; + Self::require_not_paused(&env)?; + env.storage() + .persistent() + .set(&DataKey::Allowed(address.clone()), &true); + env.storage() + .persistent() + .remove(&DataKey::AllowedUntil(address.clone())); + env.storage() + .persistent() + .set(&DataKey::Tier(address.clone()), &tier); + Self::track_address(&env, &address); + env.events() + .publish((Symbol::new(&env, "address_allowed"),), address); + Ok(()) + } + + /// Returns the stored compliance tier for `address`, or `0` if none has been set. + pub fn get_address_tier(env: Env, address: Address) -> u8 { + env.storage() + .persistent() + .get(&DataKey::Tier(address)) + .unwrap_or(0u8) + } + // Emergency policy: block_address and clear_address are permitted while paused // so the admin can remediate compromised addresses without unpausing first. pub fn block_address(