@@ -76,6 +76,18 @@ pub enum RegistryError {
7676 InvalidHealthFn = 12 ,
7777}
7878
79+ // ── Constants ─────────────────────────────────────────────────────────────────
80+
81+ /// Maximum byte length of a semver constraint string accepted by
82+ /// [`RouterRegistry::get_latest_with_constraint`].
83+ ///
84+ /// `constraint_str_buf` copies the constraint into a fixed-size stack buffer
85+ /// of exactly this size. Both the length guard (`if len > MAX_CONSTRAINT_LEN`)
86+ /// and the buffer declaration (`[0u8; MAX_CONSTRAINT_LEN]`) must use this
87+ /// constant so they stay in sync — a mismatch would cause a panic on
88+ /// out-of-bounds indexing at runtime.
89+ const MAX_CONSTRAINT_LEN : usize = 32 ;
90+
7991// ── Contract ──────────────────────────────────────────────────────────────────
8092
8193#[ contract]
@@ -297,6 +309,27 @@ impl RouterRegistry {
297309 . ok_or ( RegistryError :: NotFound )
298310 }
299311
312+ /// Check whether a specific version of a contract has been deprecated.
313+ ///
314+ /// This is a lightweight view alternative to calling [`get`] and reading
315+ /// `.deprecated` off the full [`ContractEntry`]. Callers who only need to
316+ /// know the deprecation status (e.g. a UI rendering a deprecation badge)
317+ /// can avoid fetching and discarding the rest of the entry.
318+ ///
319+ /// # Arguments
320+ /// * `env` - The Soroban environment.
321+ /// * `name` - The human-readable name of the contract.
322+ /// * `version` - The exact version number to query.
323+ ///
324+ /// # Returns
325+ /// `true` if the entry is deprecated, `false` otherwise.
326+ ///
327+ /// # Errors
328+ /// * [`RegistryError::NotFound`] — if no entry exists for `(name, version)`.
329+ pub fn is_deprecated ( env : Env , name : String , version : u32 ) -> Result < bool , RegistryError > {
330+ Self :: get ( env, name, version) . map ( |entry| entry. deprecated )
331+ }
332+
300333 /// Get the latest (highest version) non-deprecated entry for a name.
301334 ///
302335 /// Iterates registered versions in descending order and returns the first
@@ -794,12 +827,12 @@ impl RouterRegistry {
794827 /// `soroban_sdk::String` doesn't implement `Display`/`ToString` on the wasm
795828 /// target, so constraint strings (which are always short) are read via
796829 /// `copy_into_slice` instead of allocating.
797- fn constraint_str_buf ( constraint : & String ) -> Result < ( [ u8 ; 32 ] , usize ) , RegistryError > {
830+ fn constraint_str_buf ( constraint : & String ) -> Result < ( [ u8 ; MAX_CONSTRAINT_LEN ] , usize ) , RegistryError > {
798831 let len = constraint. len ( ) as usize ;
799- if len > 32 {
832+ if len > MAX_CONSTRAINT_LEN {
800833 return Err ( RegistryError :: InvalidConstraint ) ;
801834 }
802- let mut buf = [ 0u8 ; 32 ] ;
835+ let mut buf = [ 0u8 ; MAX_CONSTRAINT_LEN ] ;
803836 constraint. copy_into_slice ( & mut buf[ ..len] ) ;
804837 Ok ( ( buf, len) )
805838 }
@@ -938,6 +971,36 @@ mod tests {
938971 assert ! ( !entry. deprecated) ;
939972 }
940973
974+ #[ test]
975+ fn test_is_deprecated_returns_false_for_fresh_registration ( ) {
976+ let ( env, admin, client) = setup ( ) ;
977+ let name = String :: from_str ( & env, "oracle" ) ;
978+ let addr = Address :: generate ( & env) ;
979+ client. register ( & admin, & name, & addr, & 1 ) ;
980+ assert ! ( !client. is_deprecated( & name, & 1 ) ) ;
981+ }
982+
983+ #[ test]
984+ fn test_is_deprecated_returns_true_after_deprecate ( ) {
985+ let ( env, admin, client) = setup ( ) ;
986+ let name = String :: from_str ( & env, "oracle" ) ;
987+ let addr = Address :: generate ( & env) ;
988+ client. register ( & admin, & name, & addr, & 1 ) ;
989+ client. deprecate ( & admin, & name, & 1 , & None :: < String > ) ;
990+ assert ! ( client. is_deprecated( & name, & 1 ) ) ;
991+ }
992+
993+ #[ test]
994+ fn test_is_deprecated_returns_not_found_for_unregistered_version ( ) {
995+ let ( env, admin, client) = setup ( ) ;
996+ let name = String :: from_str ( & env, "oracle" ) ;
997+ let addr = Address :: generate ( & env) ;
998+ client. register ( & admin, & name, & addr, & 1 ) ;
999+ // version 99 was never registered
1000+ let result = client. try_is_deprecated ( & name, & 99 ) ;
1001+ assert_eq ! ( result, Err ( Ok ( RegistryError :: NotFound ) ) ) ;
1002+ }
1003+
9411004 #[ test]
9421005 fn test_get_latest ( ) {
9431006 let ( env, admin, client) = setup ( ) ;
0 commit comments