#49437 [SC-Insight] `RateLimiter`: incorrect infinite -> finite bucket transition

Submitted on Jul 15th 2025 at 23:42:49 UTC by @ustas for Audit Comp | Folks Smart Contract Library

  • Report ID: #49437

  • Report Type: Smart Contract

  • Report severity: Insight

  • Target: https://github.com/Folks-Finance/algorand-smart-contract-library/blob/main/contracts/library/RateLimiter.py

  • Impacts:

    • 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)

    • Contract fails to deliver promised returns, but doesn't lose value

Description

Description

The documentation for the RateLimiter contract specifies that a bucket with duration = 0 is considered an infinite bucket, meaning it should not be subject to capacity limits. For these buckets, core functions like _update_capacity, _consume_amount, and _fill_amount become no-ops, and has_capacity always returns True, effectively disabling the rate-limiting checks.

However, the transition of a finite bucket to an infinite one will keep the state variables limit and current_capacity without change, preserving the previous state. When an infinite bucket is then transitioned back to finite, the state variables will be simply unfreezed without the imitation of the rate limit change calculations from the infinite to a normal value.

Remediation

Add a special case to the _update_rate_duration function to fully restore the capacity if the previous duration value was 0, as any finite rate limit is always smaller than the infinity.

Proof of Concept

Proof of Concept

A visual example:

Finite bucket A

In storage
    Limit: 100
    Duration: 100
    Current capacity: 77

Effective
    Limit: 100
    Duration: 100
    Current capacity: 77

After the transition to infinity:

Infinite bucket A

In storage
    Limit: 100
    Duration: 0
    Current capacity: 77

Effective
    Limit: infinite
    Duration: 0
    Current capacity: infinite

After the transition back to finite:

Finite bucket A

In storage
    Limit: 100
    Duration: 100
    Current capacity: 77

Effective
    Limit: 100
    Duration: 100
    Current capacity: 77

While the correct values would be:

Finite bucket A

In storage
    Limit: 100
    Duration: 100
    Current capacity: 100

Effective
    Limit: 100
    Duration: 100
    Current capacity: 100

Representing the transition from the infinite limits to the previous limited ones.

Was this helpful?