#48894 [SC-Low] Underflow in index calculation fails remove_item
Submitted on Jul 8th 2025 at 20:29:20 UTC by @uhudo for Audit Comp | Folks Smart Contract Library
Report ID: #48894
Report Type: Smart Contract
Report severity: Low
Target: https://github.com/Folks-Finance/algorand-smart-contract-library/blob/main/contracts/library/UInt64SetLib.py
Impacts:
Permanent denial of service of a smart contract functionality
Temporary denial of service for more than one block
Temporary denial of service (smart contract is made unable to operate for one block, functionality is restored in the next block)
Description
Brief/Intro
Underflow in index calculation in remove_item
causes the subroutine call to fail if items
is an empty dynamic array. As this is a library, the impact can vary depending on use. In worst case, the contract could become blocked.
Vulnerability Details
In subroutine remove_item
, the items
input can be an empty DynamicArray, which has a length of 0. Calculation of last_idx (L33) causes an underflow in this case. As the code description for the library states that the subroutine "Removes an item from the set. Returns whether the item was removed and the new set.", it would be expected that the call succeeds but returns false and the same array.
Impact Details
Impact of this error can vary greatly as this is a library. In the worst case, it could lead to contract being blocked due to unexpected call failure. However, if developers are careful and understand the library inner workings, they can protect against this by checking for empty array before calling the remove_item. However, as the purpose of the library is to simplify development, it would be prudent to include this check in the library and let the developers handle the result based on whether the item was removed or not. Or at least a disclaimer should be added, similar to the maximum number of items supported by the library.
References
Underflow happens at: https://github.com/Folks-Finance/algorand-smart-contract-library/blob/7673a43fa5183af736b65f17d1a297fdea672059/contracts/library/UInt64SetLib.py#L33
Proof of Concept
Proof of Concept
In contract UInt64SetLibExposed, the following method can be added to demonstrate the issue:
@abimethod
def empty_remove_item(self, to_remove: UInt64) -> Tuple[Bool, DynamicArray[ARC4UInt64]]:
items = DynamicArray[ARC4UInt64]()
return UInt64SetLib.remove_item(to_remove, items.copy())
Calling the method produces: Error resolving execution info via simulate in transaction 0: transaction KUA2Y7DHE2LJEDFFZUAHRRZO2MHHJ3WURIGFEKORO7EPRPFMQ75Q: logic eval error: - would result negative. Details: app=28046, pc=584, opcodes=dup; intc_0 // 1; -
Was this helpful?