Contract Analysis
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
Analysis Date: 2026-02-13
Metadata
Primary Contract
| PROPERTY | VALUE |
|---|---|
| Contract Address | 0xfD2487cc0e5dCe97F08BE1Bc8eF1DCE8D5988B4D (etherscan) |
| Network | Ethereum Mainnet |
| Contract Type | Standalone Ponzi Scheme |
| Deployment Date | 2016-03-13 14:40:17 UTC |
| Deployment Block | 1,143,960 |
| Contract Creator | 0x45ab6108cc41c20f416a98615aa8c349f02a275b (etherscan) |
| Creation TX | 0x61894a6bffbe5f3a9d58674a1241bf2ebe62e6b9c512eea505b17f4148c3df41 (tx) |
| Compiler Version | Solidity v0.2.0-2016-01-15-cc4b4f5 (optimized, 200 runs) |
| Total Functions | 5 (constructor, fallback, enter, collectFees, setOwner) |
| External Contract Dependencies | 0 |
| Upgrade Mechanism | ☒ None - Not Upgradable |
| Verification Status | ☑ Verified - Exact Match |
| Audit Status | ☒ No Audit Available |
Related Addresses
| TYPE | ADDRESS | NOTES |
|---|---|---|
| Owner/Admin | 0x45ab6108cc41c20f416a98615aa8c349f02a275b (etherscan) |
Original deployer - ownership has NEVER changed since deployment (March 2016) |
| Public Tag | etherdoubler.com | Historic Ponzi scheme website (no longer active) |
Attempted Ownership Transfers
Multiple addresses have called setOwner() since 2019 (most recently January 2026), but due to the broken onlyowner modifier, all transactions succeeded while doing nothing. The owner has never changed. See Critical Security Discovery below for details.
Executive Summary
The Doubler contract is a historically significant Ethereum Smart Contract deployed in March 2016 that implements a queue-based Ponzi Scheme. The contract promised to double participants' investments by using funds from new participants to pay earlier participants, while extracting a 10% fee for the owner on each deposit. The mechanics are visible in the verified source code, though the associated website (etherdoubler.com) is no longer available and no archived version of its claims has been found.
Primary Purpose: Accept ETH deposits of 1+ ETH and promise to return 2x the deposited amount (minus 10% fee), funded by subsequent participants' deposits.
Intended Audience: Early Ethereum users. Whether participants understood the Ponzi mechanics is unknown — the website (etherdoubler.com) is no longer available.
Key Mechanisms:
- Queue-based payout system: participants are added to an array and paid out in FIFO order
- Minimum deposit: 1 ETH
- Payout trigger: when contract balance exceeds 2x the next participant's deposit
- Owner fee: 10% of each deposit (except the first participant, who paid 100% in fees)
- No events emitted, making on-chain tracking difficult without storage queries
Significant Trust Assumptions:
- Contract owner could transfer ownership to malicious address
- Participants must trust the Ponzi mechanics will continue (no guarantee of payout)
- No Timelock or Multisig protection on owner functions
- Uses deprecated
send()which can fail silently if recipient has Fallback Function logic
Notable Risks:
- ☒ Guaranteed Losses: Mathematical certainty that late participants lose 100% of deposits
- ☒ Broken Access Control: The
onlyownermodifier silently fails instead of reverting (see Potential Risks) - ☒ Old Solidity Version: Contains multiple known compiler vulnerabilities
- ☒ Failed Sends:
send()returns false on failure but contract doesn't handle it - ☒ Centralization: Single owner can withdraw all accumulated fees at any time
- △ Accounting Mismatch: Contract's internal
balancevariable doesn't match actual ETH balance
Architecture
graph TB
User[Participant] -->|1+ ETH| Fallback[Fallback Function]
Fallback --> Enter[enter Function]
Enter --> Check{msg.value >= 1 ETH?}
Check -->|No| Refund[Refund via send]
Check -->|Yes| AddQueue[Add to participants array]
AddQueue --> CalcFees[Calculate 10% fee]
CalcFees --> UpdateBalance[Update internal balance]
UpdateBalance --> PayoutCheck{Balance > 2x next payout?}
PayoutCheck -->|No| End1[Wait for more deposits]
PayoutCheck -->|Yes| Payout[Send 2x - 10% to participants payoutIdx]
Payout --> IncrementIdx[payoutIdx += 1]
IncrementIdx --> End2[Transaction Complete]
Owner[Contract Owner] -->|onlyowner| CollectFees[collectFees Function]
CollectFees --> SendFees[Send collectedFees to owner]
Owner -->|onlyowner| SetOwner[setOwner Function]
SetOwner --> TransferOwnership[Change owner address]
style Check fill:#fff4cc
style PayoutCheck fill:#fff4cc
style Payout fill:#ccffcc
style CollectFees fill:#ffcccc
style SetOwner fill:#ffcccc
System Overview
The Doubler contract operates as a queue-based Ponzi Scheme where participants are paid from subsequent participants' deposits. The system is entirely self-contained with no external dependencies.
Core Mechanics:
- Deposit: Any address sends 1+ ETH to the contract (via Fallback Function or direct
enter()call) - Queueing: Participant's address and deposit amount are appended to the
participantsarray - Fee Extraction: 10% of each deposit is added to
collectedFees(owner's revenue) - Balance Tracking: 90% of each deposit (or 100% for first participant) is added to internal
balance - Payout Trigger: When
balance > participants[payoutIdx].amount * 2, the next queued participant receives 180% of their deposit (200% minus 10% entry fee) - Owner Withdrawal: Owner can withdraw
collectedFeesat any time viacollectFees()
What This Contract Does:
- Accepts ETH deposits and promises eventual 2x return
- Maintains FIFO queue of participants waiting for payouts
- Extracts 10% fee for contract owner on every deposit
- Attempts to pay earlier participants when sufficient funds accumulate
What This Contract Does Not Do:
- Does NOT generate any revenue or investment returns
- Does NOT guarantee payouts (depends entirely on future deposits)
- Does NOT emit Events (no transparency without direct storage queries)
- Does NOT handle failed
send()calls (silent failures possible) - Does NOT prevent owner from draining fees during active payouts
Design Patterns Used
Ponzi/Pyramid Queue Pattern: Maintains ordered array of participants with FIFO payout logic. This pattern is mathematically guaranteed to fail when new deposits stop, leaving unpaid participants with total losses.
Modifier-Based Access Control: Uses simple onlyowner modifier for privileged functions. However, the modifier uses deprecated syntax (if (msg.sender == owner) _) without explicit require() or revert().
Fallback Delegation: The unnamed fallback function delegates all direct ETH transfers to the enter() function, allowing seamless deposits without function calls.
Fee Extraction Pattern: Separates user deposits from owner revenue via collectedFees accumulator and withdrawal function, allowing owner to extract profits independently of participant payouts.
Access Control
Roles & Permissions
| ROLE | ASSIGNED BY | REVOKABLE | CALL COUNT |
|---|---|---|---|
| Owner | Constructor (set to msg.sender at deployment) |
Yes - via setOwner() |
Owner functions callable unlimited times |
| Participant | Self-assignment (anyone who sends 1+ ETH) | No - permanent queue position | Unlimited participants (array grows unbounded) |
Permission Matrix
| FUNCTION | OWNER | PARTICIPANT | ANYONE |
|---|---|---|---|
Doubler() (constructor) |
N/A | N/A | ☒ |
fallback() |
☑ | ☑ | ☑ |
enter() |
☑ | ☑ | ☑ |
collectFees() |
☑ | ☒ | ☒ |
setOwner() |
☑ | ☒ | ☒ |
Time Locks & Delays
| ACTION | TIME LOCK | CAN CANCEL | PURPOSE |
|---|---|---|---|
| Transfer Ownership | ☒ None - Immediate | ☒ No | △ No protection - owner can be changed instantly |
| Collect Fees | ☒ None - Immediate | ☒ No | △ No protection - fees can be withdrawn at any time |
| Participant Payout | ☒ None - Immediate | ☒ No | ☑ Automatic when balance threshold met |
Economic Model
Ponzi Payout Flow
flowchart TD
Start([Participant Sends 1+ ETH]) --> QueueAdd[Added to participants array at index N]
QueueAdd --> FeeSplit{First Participant?}
FeeSplit -->|Yes idx=0| Fee100[100% → collectedFees]
FeeSplit -->|No idx>0| Fee10[10% → collectedFees<br/>90% → balance]
Fee100 --> WaitInQueue[Wait in Queue Position 0]
Fee10 --> WaitInQueue2[Wait in Queue Position N]
WaitInQueue --> CheckPayout{Enough balance to pay<br/>participant at payoutIdx?}
WaitInQueue2 --> CheckPayout
CheckPayout -->|No| KeepWaiting[Remain in Queue]
CheckPayout -->|Yes| Calculate[Calculate Payout:<br/>2 × deposit × 0.9 = 180%]
Calculate --> SendPayout[Send payout via .send]
SendPayout --> Success{Send Successful?}
Success -->|Yes| UpdateQueue[payoutIdx += 1<br/>balance -= 2 × deposit]
Success -->|No| SilentFail[△ Send failed silently<br/>payoutIdx still incremented]
UpdateQueue --> NextInLine[Next participant in queue]
SilentFail --> NextInLine
KeepWaiting --> MoreDeposits{More deposits arrive?}
MoreDeposits -->|Yes| CheckPayout
MoreDeposits -->|No| StuckForever[☒ Stuck in queue permanently]
style Fee100 fill:#ffcccc
style Fee10 fill:#fff4cc
style StuckForever fill:#ffcccc
style SilentFail fill:#ffcccc
Fee Structure
| FEE TYPE | PERCENTAGE | RECIPIENT | PURPOSE | NOTES |
|---|---|---|---|---|
| Entry Fee (First Participant) | 100% | Owner (via collectedFees) |
Owner revenue | First participant receives nothing, pure fee |
| Entry Fee (All Others) | 10% | Owner (via collectedFees) |
Owner revenue | Reduces effective balance for payouts |
| Payout Amount | 180% of deposit | Earlier participants | Ponzi payout | 200% gross - 10% entry fee = 180% net |
Funding Sources & Sinks
Inflows:
- Participant deposits via fallback function or
enter()(minimum 1 ETH) - No external revenue generation
- System is closed-loop (payouts funded only by new deposits)
Outflows:
- Participant payouts: 180% of original deposit (when queue position reached)
- Owner fee withdrawal: 10% of all deposits (via
collectFees()) - Refunds: Full refund for deposits < 1 ETH
Economic Invariants
Broken Invariants:
-
Balance Accounting Mismatch: The contract's internal
balancevariable (27.44 ETH) does not match the actual ETH balance (32.44 ETH). This 5 ETH discrepancy suggests either:
- Failedsend()calls that didn't revert the transaction
- Accounting errors in the balance update logic
- Direct ETH transfers to the contract that bypassedenter() -
Guaranteed Insolvency: With 321 participants and only 118 paid out, 203 participants remain in queue. The current contract balance (32.44 ETH) is insufficient to pay even the next participant, let alone all 203 remaining. The contract is mathematically insolvent.
-
No New Deposits: The last transaction occurred years ago. With no new deposits, the remaining 203 participants have zero chance of receiving payouts.
Summary of Observations
The Doubler contract is a historically significant artifact from early Ethereum (2016) that implemented a Ponzi scheme with mechanics clearly visible in its verified source code. The code is straightforward in its intent: accept deposits, queue participants, extract 10% fees for the owner, and pay earlier participants 180% when sufficient funds accumulate from later participants.
Primary Purpose: The contract implemented a Ponzi scheme on Ethereum. The mechanics are visible in the verified source code, though how the scheme was marketed to participants via etherdoubler.com is unknown.
Significant Mechanisms:
- FIFO queue with unbounded array growth (321 participants total)
- Simple arithmetic for fee extraction and payout calculation
- No emergency stop, pause, or recovery mechanisms
- Deprecated
send()instead of moderncall{value: x}("")pattern
Significant Financial Observations:
- Total Deposits: Approximately 32.44 ETH currently locked in contract
- Participants Paid: 118 out of 321 (36.8% payout rate)
- Participants Stuck: 203 participants will never receive payouts
- Owner Fees: All collected fees (10% of deposits) have been withdrawn (
collectedFees = 0) - Accounting Error: 5 ETH discrepancy between internal
balanceand actual ETH balance
Significant Concerns:
- Contract is mathematically insolvent and cannot pay remaining participants
- Uses Solidity v0.2.0 which contains numerous known vulnerabilities
- No events make it difficult for participants to track queue position
- Silent send failures could result in payoutIdx incrementing without actual payment
- Owner can change ownership without any delay or governance
Strengths:
- Source code is verified and publicly auditable
- Logic is simple and easy to understand (no obfuscation)
- Ponzi mechanics are visible in verified source code (no obfuscation)
- Immutable code (no upgrade mechanism)
Weaknesses:
- Economically guaranteed to fail (Ponzi mathematics)
- Old Solidity version with known security issues
- Poor error handling (send failures ignored)
- No participant protections or recovery mechanisms
- Centralized owner control over fees and ownership transfer
This contract represents a category of early Ethereum experiments that tested social and economic mechanisms on-chain. While technically functional, it is economically predatory and serves primarily as a historical example of what NOT to build. The 203 remaining participants who deposited approximately 32.44 ETH have lost their funds permanently.
This analysis was performed for educational purposes and should not be considered an official security audit or financial advice. This contract is defunct and should not be interacted with except for academic study.
References
| RESOURCE | NOTES |
|---|---|
| Etherscan Contract Page | Verified source code and transaction history |
| Solidity v0.2.0 Documentation | Legacy compiler version documentation |
| Ethereum Yellow Paper | EVM specification for understanding bytecode |
Change Log
| DATE | AUTHOR | NOTES |
|---|---|---|
| 2026-02-13 | Artificial. | Generated by robots. Gas: 75 tok |
| 2026-02-13 | Denizen. | Reviewed, edited, and curated by humans. |