Audit finding: Last SBT IDs Cannot Be Reserved
Project: MantaNetwork
Auditor: Halborn
Location: pallets/manta-sbt/src/lib.rs:369,883
Impact: Low
Vulnerability class (Scout): Error Handling and Validation

4.2 (HAL-02) LAST SBT IDS CANNOT BE RESERVED - LOW (2.5)\nDescription:\nWhen users invoke the reserve_sbt function, it reserves a specific number of IDs - quantified by MintPerReserve. The reserve_sbt function achieves this by repeatedly calling the next_sbt_id_and_increment function - as many times as the MintPerReserve value. This next_sbt_id_and_increment function serves to return the next available ID and concurrently increment the NextSbtId storage value by 1.\nA potential problem arises if the incrementing process results in an overflow, causing the next_sbt_id_and_increment function to throw an overflow exception, which in turn fails the ongoing transaction. In this scenario, previously identified IDs that did not contribute to the overflow situation remain unreserved. This issue presents a concern as it could potentially lead to resource allocation inefficiencies and transaction failures.\nCode Location:\nBody of the reserve_sbt function, where the next zkSBT id is incremented.\nListing 3: pallets/manta-sbt/src/lib.rs (Line 369)\n356 pub fn reserve_sbt ( origin : OriginFor <T >) -> DispatchResult {\nlet who = ensure_signed ( origin ) ?;\n// Charges fee to reserve AssetIds\n<T as pallet :: Config >:: Currency :: transfer (\n& who ,\n& Self :: account_id () ,\nT :: ReservePrice :: get () ,\nExistenceRequirement :: KeepAlive ,\n) ?;\n// Reserves uniques AssetIds to be used later to mint SBTs\n368 let asset_id_range : Vec < StandardAssetId > = (0.. T :: MintsPerReserve :: get () )\n369 . map (| _ | Self :: next_sbt_id_and_increment () )\n370 . collect :: < Result < Vec < StandardAssetId > , _ > >() ?;\nnext_sbt_id_and_increment function will overflow if the max number for u128 is surpassed\nListing 4: pallets/manta-sbt/src/lib.rs (Line 883)\n875 fn next_sbt_id_and_increment () -> Result < StandardAssetId , DispatchError > {\n876 NextSbtId :: <T >:: try_mutate (| maybe_val | {\n877 match maybe_val {\n878 Some ( current ) = > {\n879 let id = * current ;\n880 * maybe_val = Some (\n881 current\n882 . checked_add ( One :: one () )\n883 . ok_or ( ArithmeticError :: Overflow )? ,\n884 );\n885 Ok ( id )\n886 }\n887 // If storage is empty , starts at value of one ( Field cannot be zero )\n888 None = > {\n889 * maybe_val = Some (2) ;\n890 Ok ( One :: one () )\n891 }\n892 }\n893 })\n894 }\nBVSS:\nAO:A/AC:L/AX:L/C:N/I:N/A:L/D:N/Y:N/R:N/S:U (2.5)\nProof Of Concept:\nNote: For this Proof of Concept (PoC), the codebase was modified such that the zkSBT IDs are now u8 instead of u128. This alteration reduces the time needed to demonstrate that the function fails in this edge-case scenario.\nListing 5: pallets/manta-sbt/src/tests.rs\n236 #[ test ]\n237 fn hal02 () {\n238 new_test_ext () . execute_with (|| {\n239 assert_ok! ( Balances :: set_balance (\n240 MockOrigin :: root () ,\n241 ALICE ,\n242 1 _000_000_000_000_000 ,\n243 0\n244 )) ;\n245 for i in (1..51) {\n246 assert_ok! ( MantaSBTPallet :: reserve_sbt_bis ( MockOrigin :: signed ( ALICE )) );\n247 println! (" First id : {} - Last id : {} " , ReservedIdsBis :: < Test >:: get ( ALICE ) . unwrap () .0 , ReservedIdsBis :: < Test >:: get ( ALICE ) . unwrap () .1) ;\n248 }\n250 assert_noop! ( MantaSBTPallet :: reserve_sbt_bis ( MockOrigin :: signed ( ALICE )) , ArithmeticError :: Overflow );\n251 });\n252 }\nIn this test, we reserve all available IDs, excluding the last five. Attempting to reserve the last ID will cause the StandardAssetId value to overflow, resulting in a failure.\nRecommendation:\nTo address this issue, it is recommended to implement a check to determine whether the value of the StandardAssetId has reached the maximum value for u128 can prevent overflow. This measure will stop the occurrence of an exception.

Summary: Overflow in next_sbt_id_and_increment causes unreserved IDs and transaction failure.