Functions
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 | 0x090D4613473dEE047c3f2706764f49e0821D256e (etherscan) |
| Network | Ethereum Mainnet |
| Analysis Date | 2026-03-19 |
Function Selectors
| SELECTOR | FUNCTION SIGNATURE | CATEGORY |
|---|---|---|
0x2e7ba6ef |
claim(uint256,address,uint256,bytes32[]) |
User |
0x2eb4a7ab |
merkleRoot() |
View |
0x9e34070f |
isClaimed(uint256) |
View |
0xfc0c546a |
token() |
View |
Summary
| CATEGORY | COUNT |
|---|---|
| Total Functions | 5 |
| User Functions | 1 |
| Admin Functions | 0 |
| View Functions | 3 |
| Private Functions | 1 |
User Functions
Function: claim(uint256 index, address account, uint256 amount, bytes32[] calldata merkleProof)
The primary (and only) state-changing function in the contract. Verifies that the caller provides a valid Merkle proof for the given index, account, and amount, then marks the index as claimed and transfers the specified amount of UNI tokens to the account.
Anyone can call this function on behalf of any eligible address — the tokens are always sent to the account parameter, not to msg.sender. This means a third party can submit a claim transaction for someone else and pay the gas.
| ATTRIBUTE | VALUE |
|---|---|
| Selector | 0x2e7ba6ef |
| Parameters | index (uint256), account (address), amount (uint256), merkleProof (bytes32[]) |
| Access | External, anyone with valid proof |
| State-Changing | Yes |
| Payable | No |
| CONDITION | REQUIREMENT |
|---|---|
| Not already claimed | !isClaimed(index) — reverts if the bit for this index is already set |
| Valid Merkle proof | MerkleProof.verify(merkleProof, merkleRoot, node) where node = keccak256(abi.encodePacked(index, account, amount)) |
| Token transfer succeeds | IERC20(token).transfer(account, amount) must return true |
| STEP | ACTION |
|---|---|
| 1 | Check that the index has not been claimed (isClaimed(index) returns false) |
| 2 | Compute the leaf hash: keccak256(abi.encodePacked(index, account, amount)) |
| 3 | Verify the Merkle proof against the immutable merkleRoot |
| 4 | Mark the index as claimed in the bitmap via _setClaimed(index) |
| 5 | Transfer amount UNI tokens from the contract to account |
| 6 | Emit Claimed(index, account, amount) event |
| VARIABLE | CHANGE |
|---|---|
claimedBitMap[index / 256] |
Sets bit at position index % 256 to 1 |
| CONDITION | REVERT MESSAGE |
|---|---|
| Index already claimed | "MerkleDistributor: Drop already claimed." |
| Invalid Merkle proof | "MerkleDistributor: Invalid proof." |
| Token transfer fails | "MerkleDistributor: Transfer failed." |
function claim(
uint256 index,
address account,
uint256 amount,
bytes32[] calldata merkleProof
) external override {
require(!isClaimed(index), 'MerkleDistributor: Drop already claimed.');
// Verify the merkle proof.
bytes32 node = keccak256(abi.encodePacked(index, account, amount));
require(
MerkleProof.verify(merkleProof, merkleRoot, node),
'MerkleDistributor: Invalid proof.'
);
// Mark it claimed and send the token.
_setClaimed(index);
require(
IERC20(token).transfer(account, amount),
'MerkleDistributor: Transfer failed.'
);
emit Claimed(index, account, amount);
}
flowchart TD
A["claim(index, account, amount, proof)"] --> B{"isClaimed(index)?"}
B -->|"Yes"| C["REVERT: Drop already claimed"]
B -->|"No"| D["Compute leaf = keccak256(index, account, amount)"]
D --> E{"MerkleProof.verify(proof, root, leaf)?"}
E -->|"Invalid"| F["REVERT: Invalid proof"]
E -->|"Valid"| G["_setClaimed(index)"]
G --> H["token.transfer(account, amount)"]
H -->|"Returns false"| I["REVERT: Transfer failed"]
H -->|"Returns true"| J["emit Claimed(index, account, amount)"]
Private Functions
Function: _setClaimed(uint256 index)
Internal helper that marks an index as claimed in the packed bitmap. Computes the word index (index / 256) and bit position (index % 256), then sets that bit via bitwise OR.
| ATTRIBUTE | VALUE |
|---|---|
| Selector | N/A (private) |
| Parameters | index (uint256) |
| Access | Private — called only by claim() |
| VARIABLE | CHANGE |
|---|---|
claimedBitMap[index / 256] |
claimedBitMap[index / 256] | (1 << (index % 256)) |
View Functions
Function: isClaimed(uint256 index)
Returns whether a given index has already been claimed. Reads the packed bitmap by computing the word index (index / 256) and checking whether the bit at position (index % 256) is set.
| ATTRIBUTE | VALUE |
|---|---|
| Selector | 0x9e34070f |
| Parameters | index (uint256) |
| Access | Public view |
| Returns | bool — true if claimed, false if unclaimed |
| FLAG | OBSERVATION |
|---|---|
| ☑ | Gas-efficient: reads a single storage slot and performs bitwise operations |
| ◇ | Packing 256 booleans per slot reduces storage reads by 256x compared to a naive mapping |
Function: merkleRoot()
Returns the immutable Merkle root that was set at deployment. This root represents the entire eligibility dataset — all addresses and their claimable amounts.
| ATTRIBUTE | VALUE |
|---|---|
| Selector | 0x2eb4a7ab |
| Parameters | None |
| Access | Public view |
| Returns | bytes32 — 0xc8500f8e2fcf3c9a32880e1b973fb28acc88be35787a8abcf9981b2b65dbdeb5 |
| FLAG | OBSERVATION |
|---|---|
| ☑ | Immutable — stored in contract bytecode, not storage. Cannot be changed after deployment |
| ◇ | The off-chain Merkle tree data must be available for users to generate proofs. Uniswap published this data publicly |
Function: token()
Returns the immutable address of the ERC-20 token being distributed (UNI).
| ATTRIBUTE | VALUE |
|---|---|
| Selector | 0xfc0c546a |
| Parameters | None |
| Access | Public view |
| Returns | address — 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984 (UNI) |
| FLAG | OBSERVATION |
|---|---|
| ☑ | Immutable — cannot be changed after deployment |