Artifacts
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 | 0x33184cD3E5F9D27C6E102Da6BE33e779528A606D (etherscan) |
| Network | Ethereum Mainnet |
| Analysis Date | 2026-01-23 |
Overview
This document contains raw analysis artifacts including reconstructed source code, function selector mappings, event signatures, verification commands, and supporting data files. All artifacts are preserved for transparency and independent verification.
Artifact Location: /artifacts/33184cd3...8a606d/
Reconstructed Solidity Source
Based on bytecode analysis and transaction patterns, the contract logic appears to follow this structure:
// SPDX-License-Identifier: UNLICENSED
// Solidity Version: ^0.8.33
// WARNING: Reconstructed from bytecode - NOT the original source code
pragma solidity ^0.8.33;
interface IFlexibleAllocation {
function getAllocation(address account) external view returns (uint256);
}
contract ClaimManager {
//////////////////////////////////////////////////////////////
// STORAGE
//////////////////////////////////////////////////////////////
// Slot 0
address public flexibleAllocation;
// Slot 1 - Dual purpose: hasClaimed AND eligibilityStatus
mapping(address => bool) public hasClaimed; // Also used for eligibility
// Slot 2 - Packed storage
address private _owner; // bytes 0-19
bool private _paused; // byte 20
bool private _claimingEnabled; // byte 21
//////////////////////////////////////////////////////////////
// EVENTS
//////////////////////////////////////////////////////////////
event Claimed(address indexed account, uint256 allocation);
event Paused(address account);
event Unpaused(address account);
event ClaimingEnabledUpdated(bool enabled);
event EligibilityStatusUpdated(address indexed account, bool status);
event FlexibleAllocationUpdated(
address indexed oldAddress,
address indexed newAddress
);
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
//////////////////////////////////////////////////////////////
// MODIFIERS
//////////////////////////////////////////////////////////////
modifier onlyOwner() {
require(msg.sender == _owner, "Only owner can call this function");
_;
}
modifier whenNotPaused() {
require(!_paused, "Contract is paused");
_;
}
modifier whenPaused() {
require(_paused, "Contract is not paused");
_;
}
//////////////////////////////////////////////////////////////
// CONSTRUCTOR
//////////////////////////////////////////////////////////////
constructor(address _flexibleAllocation) {
require(
_flexibleAllocation != address(0),
"Invalid FlexibleAllocation address"
);
flexibleAllocation = _flexibleAllocation;
_owner = msg.sender;
_paused = false;
_claimingEnabled = true; // Note: Not enforced in claim()
}
//////////////////////////////////////////////////////////////
// USER FUNCTIONS
//////////////////////////////////////////////////////////////
/// @notice Allows eligible users to claim (marks status as claimed)
/// @dev Does NOT transfer tokens - only tracking mechanism
function claim() external whenNotPaused {
require(
!hasClaimed[msg.sender],
"Already claimed"
);
// External call to allocation contract
uint256 allocation = IFlexibleAllocation(flexibleAllocation)
.getAllocation(msg.sender);
require(
allocation >= 1,
"Insufficient allocation - must have at least 1"
);
// Mark as claimed (permanent)
hasClaimed[msg.sender] = true;
emit Claimed(msg.sender, allocation);
}
//////////////////////////////////////////////////////////////
// VIEW FUNCTIONS
//////////////////////////////////////////////////////////////
/// @notice Check if an address can claim
/// @param account Address to check
/// @return bool True if can claim, false otherwise
function canClaim(address account) external view returns (bool) {
if (hasClaimed[account]) {
return false;
}
uint256 allocation = IFlexibleAllocation(flexibleAllocation)
.getAllocation(account);
return allocation >= 1;
}
/// @notice Returns pause state
function paused() external view returns (bool) {
return _paused;
}
/// @notice Returns current owner
function owner() external view returns (address) {
return _owner;
}
/// @notice Returns claiming enabled state
/// @dev Note: This flag is NOT checked in claim() function
function claimingEnabled() external view returns (bool) {
return _claimingEnabled;
}
/// @notice Returns FlexibleAllocation contract address
function flexibleAllocation() external view returns (address) {
return flexibleAllocation;
}
/// @notice Returns eligibility status (reads same storage as hasClaimed)
/// @param account Address to check
/// @return bool Status from slot 1
function getEligibilityStatus(address account) external view returns (bool) {
return hasClaimed[account]; // Same storage!
}
//////////////////////////////////////////////////////////////
// ADMIN FUNCTIONS
//////////////////////////////////////////////////////////////
/// @notice Pauses the contract
function pause() external onlyOwner whenNotPaused {
_paused = true;
emit Paused(msg.sender);
}
/// @notice Unpauses the contract
function unpause() external onlyOwner whenPaused {
_paused = false;
emit Unpaused(msg.sender);
}
/// @notice Sets claiming enabled flag
/// @param enabled New enabled state
/// @dev Note: This flag is NOT enforced in claim()
function setClaimingEnabled(bool enabled) external onlyOwner {
_claimingEnabled = enabled;
emit ClaimingEnabledUpdated(enabled);
}
/// @notice Changes FlexibleAllocation contract reference
/// @param newAllocation New allocation contract address
function setFlexibleAllocation(address newAllocation) external onlyOwner {
require(
newAllocation != address(0),
"Invalid FlexibleAllocation address"
);
address oldAllocation = flexibleAllocation;
flexibleAllocation = newAllocation;
emit FlexibleAllocationUpdated(oldAllocation, newAllocation);
}
/// @notice Sets eligibility status for single address
/// @param account Address to modify
/// @param status New eligibility status
/// @dev Writes to same storage as hasClaimed
function setEligibilityStatus(address account, bool status) external onlyOwner {
require(account != address(0), "Invalid account address");
hasClaimed[account] = status; // Dual-purpose storage
emit EligibilityStatusUpdated(account, status);
}
/// @notice Sets eligibility status for multiple addresses
/// @param accounts Array of addresses
/// @param statuses Array of statuses
function batchSetEligibilityStatus(
address[] calldata accounts,
bool[] calldata statuses
) external onlyOwner {
require(accounts.length > 0, "Empty accounts array");
require(
accounts.length == statuses.length,
"Arrays length mismatch"
);
for (uint256 i = 0; i < accounts.length; i++) {
require(accounts[i] != address(0), "Invalid account address");
hasClaimed[accounts[i]] = statuses[i];
emit EligibilityStatusUpdated(accounts[i], statuses[i]);
}
}
/// @notice Transfers ownership
/// @param newOwner New owner address
function transferOwnership(address newOwner) external onlyOwner {
require(newOwner != address(0), "Invalid new owner address");
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
Function Selector Mapping
Complete mapping of function selectors to signatures:
0x0fb50c26 => claimingEnabled() view returns (bool)
0x28c30c07 => setClaimingEnabled(bool)
0x2b2b14a4 => setEligibilityStatus(address,bool)
0x360cbe3e => batchSetEligibilityStatus(address[],bool[])
0x3f4ba83a => unpause()
0x4e71d92d => claim()
0x5c975abb => paused() view returns (bool)
0x73b2e80e => hasClaimed(address) view returns (bool)
0x8456cb59 => pause()
0x8da5cb5b => owner() view returns (address)
0x9d97e2bb => flexibleAllocation() view returns (address)
0xa074696a => getEligibilityStatus(address) view returns (bool)
0xba2f0e4c => setFlexibleAllocation(address)
0xf2fde38b => transferOwnership(address)
0xfd32ea70 => canClaim(address) view returns (bool)
Event Signatures
Event topic hashes and their corresponding signatures:
0x106f923f993c2149d49b4255ff723acafa1f2d94393f561d3eda32ae348f7241
=> Claimed(address indexed account, uint256 allocation)
0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258
=> Paused(address account)
0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa
=> Unpaused(address account)
0x8259bcb199fe2662027c78039375d45439569d4d8f3d2a28451581fdf6f45307
=> ClaimingEnabledUpdated(bool enabled)
0x882c8cb812325c2f735789a0a790cc6a8a62fced20c77fe55dd6bcdccac2ffb7
=> EligibilityStatusUpdated(address indexed account, bool status)
0x4bde3f66dadc7c8dd7a250f6c68357730f7dbbc65bf2b8105a8e492896f7bba9
=> FlexibleAllocationUpdated(address indexed oldAddress, address indexed newAddress)
0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0
=> OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
External Contract Interface
The contract depends on this external interface:
// Address: 0xe6c328360439b91727ec854bf2b6caeeaff5dc66
// Status: UNVERIFIED
interface IFlexibleAllocation {
/// @notice Returns allocation amount for an address
/// @param account Address to check
/// @return uint256 Allocation amount (must be >= 1 to claim)
function getAllocation(address account) external view returns (uint256);
}
// Function selector: 0x0e022923
Storage Layout Diagram
┌───────────────────────────────────────────────────────────────────┐
│ SLOT 0 (32 bytes) │
│ ┌────────────────────────────────────┬─────────────────────────┐ │
│ │ flexibleAllocation (address) │ unused (12 bytes) │ │
│ │ 20 bytes │ │ │
│ └────────────────────────────────────┴─────────────────────────┘ │
└───────────────────────────────────────────────────────────────────┘
┌───────────────────────────────────────────────────────────────────┐
│ SLOT 1 (mapping - dynamic addressing) │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ mapping(address => bool) hasClaimed / eligibilityStatus │ │
│ │ Location: keccak256(abi.encodePacked(address, uint256(1))) │ │
│ └──────────────────────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────────────┘
┌───────────────────────────────────────────────────────────────────┐
│ SLOT 2 (32 bytes - PACKED) │
│ ┌─────────────┬─────┬────────────────┬───────────────────────┐ │
│ │ owner │ p │ cE │ unused │ │ │
│ │ (address) │ a │ │ (10 bytes) │ │
│ │ 20 bytes │ u │ │ │ │
│ │ │ s │ │ │ │
│ │ │ e │ │ │ │
│ │ │ d │ │ │ │
│ │ │ │ │ │ │
│ │ │ 1b│ 1b │ │ │
│ └─────────────┴───┴────┴────────────────────────────────────┘ │
│ bytes 0-19 20 21 bytes 22-31 │
└───────────────────────────────────────────────────────────────────┘
Legend:
- p = paused (bool, 1 byte)
- cE = claimingEnabled (bool, 1 byte)
Verification Commands
Basic Contract Info
# Get contract bytecode
cast code 0x33184cD3E5F9D27C6E102Da6BE33e779528A606D
# Get contract bytecode size
cast code 0x33184cD3E5F9D27C6E102Da6BE33e779528A606D | wc -c
# Check if contract exists
cast codesize 0x33184cD3E5F9D27C6E102Da6BE33e779528A606D
Storage Reading
# Read slot 0 (flexibleAllocation)
cast storage 0x33184cD3E5F9D27C6E102Da6BE33e779528A606D 0
# Read slot 2 (owner + flags)
cast storage 0x33184cD3E5F9D27C6E102Da6BE33e779528A606D 2
# Read hasClaimed for specific address
ADDRESS=0x...
cast index address $ADDRESS 1
# Then read from calculated slot
View Function Calls
# Get owner
cast call 0x33184cD3E5F9D27C6E102Da6BE33e779528A606D "owner()"
# Check pause status
cast call 0x33184cD3E5F9D27C6E102Da6BE33e779528A606D "paused()"
# Check claiming enabled
cast call 0x33184cD3E5F9D27C6E102Da6BE33e779528A606D "claimingEnabled()"
# Get FlexibleAllocation address
cast call 0x33184cD3E5F9D27C6E102Da6BE33e779528A606D "flexibleAllocation()"
# Check if address has claimed
cast call 0x33184cD3E5F9D27C6E102Da6BE33e779528A606D "hasClaimed(address)" 0xADDRESS
# Check if address can claim
cast call 0x33184cD3E5F9D27C6E102Da6BE33e779528A606D "canClaim(address)" 0xADDRESS
# Get eligibility status
cast call 0x33184cD3E5F9D27C6E102Da6BE33e779528A606D "getEligibilityStatus(address)" 0xADDRESS
Function Selector Verification
# Verify function selectors
cast sig "claim()" # 0x4e71d92d
cast sig "pause()" # 0x8456cb59
cast sig "unpause()" # 0x3f4ba83a
cast sig "paused()" # 0x5c975abb
cast sig "owner()" # 0x8da5cb5b
cast sig "transferOwnership(address)" # 0xf2fde38b
cast sig "claimingEnabled()" # 0x0fb50c26
cast sig "setClaimingEnabled(bool)" # 0x28c30c07
cast sig "setEligibilityStatus(address,bool)" # 0x2b2b14a4
cast sig "batchSetEligibilityStatus(address[],bool[])" # 0x360cbe3e
cast sig "hasClaimed(address)" # 0x73b2e80e
cast sig "flexibleAllocation()" # 0x9d97e2bb
cast sig "getEligibilityStatus(address)" # 0xa074696a
cast sig "setFlexibleAllocation(address)" # 0xba2f0e4c
cast sig "canClaim(address)" # 0xfd32ea70
Event Topic Verification
# Verify event topics
cast keccak "Claimed(address,uint256)"
# Should return: 0x106f923f993c2149d49b4255ff723acafa1f2d94393f561d3eda32ae348f7241
cast keccak "Paused(address)"
# Should return: 0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258
cast keccak "Unpaused(address)"
# Should return: 0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa
cast keccak "OwnershipTransferred(address,address)"
# Should return: 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0
Transaction Simulation
# Simulate claim (will revert if not eligible or already claimed)
cast call 0x33184cD3E5F9D27C6E102Da6BE33e779528A606D "claim()" --from 0xYOUR_ADDRESS
# Estimate gas for claim
cast estimate 0x33184cD3E5F9D27C6E102Da6BE33e779528A606D "claim()" --from 0xYOUR_ADDRESS
Raw Data Files
The following files are stored in /artifacts/33184cd3...8a606d/:
| FILE | SIZE | DESCRIPTION |
|---|---|---|
| bytecode.txt | 13.3 KB | Full contract bytecode (hex) |
| selectors.txt | 165 B | List of function selectors |
| function-mapping.txt | 2.1 KB | Selector to signature mapping |
| storage-analysis.txt | 3.5 KB | Storage slot analysis notes |
| contract-summary.md | 1.8 KB | Quick reference summary |
| TODO.md | 3.0 KB | Analysis task checklist |
External Links
| RESOURCE | URL |
|---|---|
| Etherscan Contract | https://etherscan.io/address/0x33184cD3E5F9D27C6E102Da6BE33e779528A606D |
| Creation TX | https://etherscan.io/tx/0x9b3eca091ce21a8f3d2f58c5e3b7c8544af48c0d7feb9358e7e15a7a1afaa6d8 |
| FlexibleAllocation | https://etherscan.io/address/0xe6c328360439b91727ec854bf2b6caeeaff5dc66 |
| Owner Address | https://etherscan.io/address/0x2a4a36b59c47f9ed95b562ebeaefa8c19ef04902 |
| Deployer Address | https://etherscan.io/address/0xfcFD812DDE04058EadD91414772b51De14223DBb |
Analysis Metadata
{
"contract_address": "0x33184cD3E5F9D27C6E102Da6BE33e779528A606D",
"network": "ethereum-mainnet",
"analysis_date": "2026-01-23",
"analyst": "Claude Sonnet 4.5",
"analysis_method": "Bytecode decompilation + transaction pattern analysis",
"verification_status": "unverified",
"total_functions": 15,
"admin_functions": 6,
"user_functions": 1,
"view_functions": 7,
"events": 7,
"storage_slots": 3,
"external_dependencies": 1,
"deployment_block": 24140130,
"deployment_timestamp": "2026-01-01T13:38:11Z",
"compiler_version": "0.8.33",
"transaction_count": 620,
"token_cost": "65 tok"
}
Disclaimer
The reconstructed source code and all artifacts in this document are based on bytecode analysis of an unverified contract. They represent our best interpretation of the contract's behavior but may not perfectly match the original source code. Variables names, function logic, and internal structures are inferred and should not be considered authoritative.
For critical operations, always:
1. Request source code verification from the contract owner
2. Perform transaction simulation before execution
3. Consult with blockchain security professionals
4. Verify all findings independently using provided commands