Allocation logic redesign #42
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Allocation Logic Redesign: Linked List Structure with Expiration Normalization
This PR redesigns the allocation storage mechanism in OnChainAllocator to prevent allocation bombing DoS attacks. The previous array-based storage allowed attackers to create unbounded allocations with unique expirations, causing gas exhaustion during traversal operations.
Problem
An attacker could create ~66,000 allocations on behalf of a victim (via
allocateAndRegister), each with a unique expiration. Operations likeattest(),allocate(), andauthorizeClaim()would need to traverse all allocations, exceeding block gas limits and causing permanent DoS.Solution
Linked List Storage Structure
mapping(bytes32 => Allocation[])array with sorted linked list_nextExpirationPointer[tokenHash]→ head pointer to earliest expiration_balancesByExpiration[tokenHash | expiration]→ node with amount and next pointer_allocatedClaims[claimHash]→ maps claims to their normalized expirationExpiration Normalization
< 10 min: No rounding (600 max unique values)< 1 hour 5 min: Round to 10 seconds (330 max)< 1 day: Round to 1 minute (1,375 max)< 1 week 1 hour: Round to 10 minutes (870 max)> 1 week: Round to 1 hour (551 max)Hint System for O(1) Deletion
authorizeClaimacceptsallocatorDataparameter with position hintsgetNormalizedExpirationForClaim()view function to retrieve hintsTechnical Changes
Data Structures
tokenHashchanged frombytes32tobytes28to fit expiration in same keyBalanceExpirationstruct:{uint32 nextExpiration, uint224 amount}tokenHash | expirationcombines both inbytes32Gas-Optimized Assembly
_readAllocatedBalance: Traverses list, cleans expired entries, returns pointers_storeAllocatedBalance: Inserts into sorted position with O(1) for same-expiration_deleteAllocatedBalance: Removes node, updates pointers, supports hintsNew Interface
getNormalizedExpirationForClaim(bytes32 claimHash)→ returns normalized expirationInvalidHinterror for malformed allocatorDataGas Impact
attest()allocate()authorizeClaim()authorizeClaim()with hintLimitation
The previous uint224.max limit per allocated balance now expands to an expiration time.
Testing
Added comprehensive allocation bombing tests that: