Storage Layout
DISCLAIMER // NFA // DYOR
This analysis is based on observations of the contract behavior. We are not smart contract security experts. This document aims to explain what the contract appears to do based on the code. It should not be considered a comprehensive security audit or financial advice. Always verify critical information independently and consult with blockchain security professionals for important decisions.
⊙ generated by robots | curated by humans
| METADATA | |
|---|---|
| Contract Address | 0x99fdbD43eDd7f4ABA1F745dB29705766946217Dd (etherscan) |
| Network | Ethereum Mainnet |
| Analysis Date | 2026-01-13 |
Variables
Based on bytecode analysis and function selector patterns, the contract storage layout appears structured as follows. Note that exact slot assignments cannot be confirmed without verified source code.
| SLOT | VARIABLE NAME | TYPE | ESTIMATED VALUE | PURPOSE |
|---|---|---|---|---|
| 0 | owner | address | 0xc013Bb57...d29d72e76 |
Contract owner with administrative privileges |
| 1 | paused | bool | false | Emergency pause state flag |
| 2 | initialized | bool | true | Initialization completion flag |
| 3 | locked | bool | false | Allocation lock state (one-way when true) |
| 4 | totalAllocations | uint256 | Unknown | Cumulative sum of all allocation amounts |
| 5 | allocations | mapping(address => uint256) | - | Maps recipient addresses to allocation amounts |
| 6 | recipients | address[] | ~Unknown length | Dynamic array of all recipient addresses |
| 7 | exchangeRates | mapping(address => uint256) | - | Optional exchange rates per token address |
| 8+ | Potential additional state | - | - | Reserved for additional contract state |
Storage Estimation
This storage layout is reconstructed from bytecode analysis and observable function behavior. Without verified source code, exact slot assignments and variable names cannot be definitively confirmed. Solidity compiler optimizations may pack multiple variables into single slots or reorder declarations.
Diagrams
%%{init: {'theme': 'base'}}%%
graph TB
subgraph Core["Core Control - Slots 0-3"]
S0["Slot 0: owner<br/>0xc013Bb57...d29d72e76"]
S1["Slot 1: paused<br/>false"]
S2["Slot 2: initialized<br/>true"]
S3["Slot 3: locked<br/>false"]
end
subgraph Counters["Tracking - Slot 4"]
S4["Slot 4: totalAllocations<br/>Sum of all amounts"]
end
subgraph Mappings["Allocation Data - Slots 5+"]
S5["Slot 5: allocations<br/>mapping(address => uint256)"]
S6["Slot 6: recipients<br/>address[] dynamic array"]
S7["Slot 7: exchangeRates<br/>mapping(address => uint256)"]
end
Core --> Counters --> Mappings
style S0 fill:#ffe1e1
style S1 fill:#fff4e1
style S2 fill:#e1ffe1
style S3 fill:#ffe1e1
style S4 fill:#e1f5ff
style S5 fill:#fff4e1
style S6 fill:#e1ffe1
style S7 fill:#e1f5ff
Storage Details
Slot 0: Owner Address
Type: address (20 bytes)
Current Value: 0xc013Bb5798d34997adbeE84f3f3aF42d29d72e76
Purpose: Stores the address with exclusive administrative control over the contract. Modified only through ownership transfer functions.
Access Pattern:
- Read:
owner()view function - Write:
setOwner(),transferOwnership()admin functions
Slot 1: Paused State
Type: bool (1 byte, packed)
Current Value: false
Purpose: Emergency pause flag. When true, allocation modification operations revert. Likely affects setBatchAllocations() and possibly other admin functions.
Access Pattern:
- Read:
paused()view function - Write:
pause(),unpause()admin functions
Slot 2: Initialized State
Type: bool (1 byte, packed)
Current Value: true (set during constructor execution)
Purpose: Prevents re-initialization of contract state after deployment. Despite not being upgradeable, follows initializer pattern for setup protection.
Access Pattern:
- Read:
isInitialized()view function - Write: Constructor or initializer function (one-time)
Slot 3: Locked State
Type: bool (1 byte, packed)
Current Value: false
Purpose: Allocation finalization flag. When set to true, prevents any further allocation modifications. This is a one-way state transition—once locked, cannot be unlocked. Provides immutability guarantee for recipients once distribution data is finalized.
Access Pattern:
- Read: Internal checks in allocation modification functions
- Write:
lockAllocations()admin function (irreversible)
Slot 4: Total Allocations
Type: uint256 (32 bytes)
Current Value: Unknown (sum of all allocation amounts)
Purpose: Maintains cumulative sum of all allocation amounts across all recipients. Updated when setBatchAllocations() modifies or adds allocations. Useful for tracking total distribution commitments.
Access Pattern:
- Read:
getTotalAllocations()view function - Write:
setBatchAllocations()updates on allocation changes
Calculation:
Slot 5+: Allocations Mapping
Type: mapping(address => uint256)
Storage Location: Slot 5 base, with keys hashed for actual storage positions
Purpose: Primary data structure mapping recipient addresses to their allocated token amounts. Standard Solidity mapping uses keccak256(key || slot) to compute storage position for each entry.
Access Pattern:
- Read:
balanceOf(address),getBalance(address)view functions - Write:
setBatchAllocations()admin function
Storage Calculation:
Example Entry:
Address: 0x9fbcc72a6bc74d0060e14fe8b8f4b7ccfa63ea03
Amount: 0x000000000000000000000000000000000000000000533ece4873e573470c0000
= 404,000,000,000,000,000,000,000,000 wei
Slot 6: Recipients Array
Type: address[] (dynamic array)
Storage Location: Slot 6 stores array length, actual elements at keccak256(6) + index
Purpose: Ordered list of all recipient addresses that have received allocations. Allows iteration through all recipients using getAllocations() for count and getRecipient(index) for individual addresses.
Access Pattern:
- Read:
getAllocations()(length),getRecipient(index)(element access),getRecipientsCount()(length) - Write:
setBatchAllocations()appends new recipients,removeRecipient()removes by index
Storage Calculation:
// Array length stored at slot 6
arrayLength = storage[6]
// Element at index i stored at:
slot = keccak256(6) + i
Growth Pattern:
- Slot 6 value increments with each new unique recipient added
- 20 batch allocation transactions suggest multiple recipients loaded
removeRecipient()likely uses swap-and-pop to avoid gaps
Slot 7+: Exchange Rates Mapping
Type: mapping(address => uint256)
Storage Location: Slot 7 base (estimated), with keys hashed for actual storage positions
Purpose: Stores exchange rates or conversion factors for different token addresses. Purpose unclear without verified source—may enable multi-asset distribution tracking or conversion calculations between allocation units and actual token amounts.
Access Pattern:
- Read:
getExchangeRate(address)view function - Write: Unknown setter function (not observed in documented transactions)
Storage Calculation:
Unused Feature
No transactions have been observed setting exchange rates. This may be an unused feature, reserved for future functionality, or set during contract initialization with hardcoded values.
State Variable Packing
Solidity compiler automatically packs sequential variables smaller than 32 bytes into single storage slots when possible. Based on the estimated layout:
// Likely packed into Slot 1 (32 bytes total)
bool paused; // 1 byte
bool initialized; // 1 byte
bool locked; // 1 byte
// Remaining 29 bytes unused or occupied by additional flags
This packing optimization reduces gas costs for storage operations on these frequently accessed state flags.
Storage Growth Analysis
Static Storage (Slots 0-4)
Fixed-size variables that occupy constant space regardless of contract usage:
- Control variables: owner, paused, initialized, locked
- Counter: totalAllocations
Estimated Gas Cost: ~20,000 gas per SSTORE on cold slots, 5,000 on warm slots
Dynamic Storage (Slots 5+)
Unbounded growth potential based on number of recipients:
Allocations Mapping:
- Each new recipient adds one mapping entry
- Storage cost: ~20,000 gas for new entry, 5,000 for updates
Recipients Array:
- Each new recipient appends to array
- Array length increment: 5,000 gas
- New element storage: 20,000 gas
Worst Case Growth:
N recipients:
- Allocations mapping: N entries × 32 bytes each (sparse storage)
- Recipients array: 32 bytes (length) + N × 20 bytes (addresses)
- Exchange rates: M token addresses × 32 bytes (if used)
Storage Access Patterns
Read Operations (View Functions)
Gas Cost: ~100-2,100 gas depending on whether storage is warm or cold
Most frequent read patterns:
- balanceOf(address): Single mapping read
- getAllocations(): Single array length read
- getTotalAllocations(): Single uint256 read
Write Operations (Admin Functions)
setBatchAllocations(address[], uint256[]):
For N new recipients:
- N × mapping writes: N × 20,000 gas
- N × array appends: N × 20,000 gas
- Total accumulation updates: 5,000 gas
- Transaction observed: ~41,446 gas for 1 recipient
removeRecipient(uint256):
- Array element swap: 5,000 gas
- Array pop: 5,000 gas
- Mapping delete (optional): 5,000 gas refund
Storage Security Considerations
| CONSIDERATION | IMPACT | MITIGATION |
|---|---|---|
| Unbounded array growth | Gas costs increase with recipients count | None observed; consider pagination in future versions |
| Mapping key collision | Extremely low probability (2^256 keyspace) | ☑ Inherent Solidity protection |
| Storage slot collision | Only relevant for proxy contracts | ☑ N/A (not upgradeable) |
| Lock permanence | Irreversible state change | △ No confirmation mechanism |
| Owner single point of failure | Storage fully controlled by one address | △ No multisig or timelock |