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.
0 (all state variables are public, auto-generated getters)
Constructor
Function: Doubler()
Constructor function executed once at contract Deployment to initialize the contract owner.
ATTRIBUTE
VALUE
Selector
N/A (constructor)
Parameters
None
Access
Public (called once at deployment)
Payable
No
FLAG
OBSERVATION
☑
Simple owner initialization with no complex setup
☑
Owner cannot be zero address (would revert in later modifier checks)
△
No events emitted, making deployment tracking difficult
STEP
ACTION
1
Set owner to msg.sender (contract deployer)
VARIABLE
CHANGE
owner
Set to msg.sender (0x45ab6108cc41c20f416a98615aa8c349f02a275b)
functionDoubler(){owner=msg.sender;}
User Functions
Function: fallback()
Unnamed Fallback Function that executes when ETH is sent to the contract without function data. Delegates all calls to enter().
ATTRIBUTE
VALUE
Selector
N/A (fallback)
Parameters
None (accepts msg.value)
Access
Public, Payable
FLAG
OBSERVATION
☑
Simplifies UX - users can send ETH directly without function calls
△
No event emitted, making transaction tracking require full trace
☑
All logic delegated to enter(), maintaining single source of truth
STEP
ACTION
1
Call enter() function with current msg.value
function(){enter();}
Function: enter()
Primary entry point for participants to deposit ETH and join the Ponzi Scheme queue. Handles deposits, fee extraction, balance tracking, and automatic payouts when conditions are met.
ATTRIBUTE
VALUE
Selector
0x13af4035
Parameters
None (uses msg.value and msg.sender)
Access
Public, Payable
FLAG
OBSERVATION
△
Minimum deposit 1 ETH enforced, but refund uses send() which can fail silently
☒
First participant (idx=0) pays 100% in fees with no balance credit
△
send() for payouts can fail silently without reverting transaction
☒
balance variable can desync from actual contract balance due to failed sends
△
No event emitted for deposits, queue additions, or payouts
☒
Unbounded array growth - no limit on participants
CONDITION
REQUIREMENT
Minimum Deposit
msg.value >= 1 ether
Gas Available
Sufficient gas for array expansion and potential payout
STEP
ACTION
1
Check if msg.value < 1 ether - if true, refund via send() and return
2
Get current participants array length as idx
3
Expand participants array by 1
4
Store msg.sender as participants[idx].etherAddress
5
Store msg.value as participants[idx].amount
6
Ifidx != 0: Add msg.value / 10 to collectedFees and add msg.value to balance
7
Else (first participant): Add entire msg.value to collectedFees only
8
Ifbalance > participants[payoutIdx].amount * 2: Calculate and send payout
functionenter(){if(msg.value<1ether){msg.sender.send(msg.value);return;}// add a new participant to arrayuintidx=participants.length;participants.length+=1;participants[idx].etherAddress=msg.sender;participants[idx].amount=msg.value;// collect fees and update contract balanceif(idx!=0){collectedFees+=msg.value/10;balance+=msg.value;}else{// first participant has no one above him,// so it goes all to feescollectedFees+=msg.value;}// if there are enough ether on the balance we can pay out to an earlier participantif(balance>participants[payoutIdx].amount*2){uinttransactionAmount=2*(participants[payoutIdx].amount-participants[payoutIdx].amount/10);participants[payoutIdx].etherAddress.send(transactionAmount);balance-=participants[payoutIdx].amount*2;payoutIdx+=1;}}
Admin Functions
Function: collectFees()
Allows the contract owner to withdraw accumulated fees to their address. Fees represent 10% of all participant deposits.
ATTRIBUTE
VALUE
Selector
0x35c1d349
Parameters
None
Access
Owner only (via onlyowner modifier)
Payable
No
FLAG
OBSERVATION
☒
Owner can withdraw fees at any time without restrictions
△
Uses send() which can fail silently if owner is contract with fallback
△
If send fails, collectedFees is still set to 0 - permanent loss
△
No event emitted for fee collection
☑
Early exit if no fees to collect (gas optimization)
CONDITION
REQUIREMENT
Caller
Must be current owner address
Collected Fees
Must be greater than 0 (otherwise early return)
STEP
ACTION
1
Check if msg.sender == owner (via modifier)
2
If collectedFees == 0, return early
3
Send collectedFees amount to owner via send()
4
Set collectedFees = 0
VARIABLE
CHANGE
collectedFees
Set to 0
Owner ETH balance
Increased by collectedFees amount (if send succeeds)
CONDITION
REVERT MESSAGE
Caller is not owner
No revert - modifier prevents function body execution
The onlyownerModifier restricts function access to the contract owner. However, it uses deprecated Solidity syntax that doesn't explicitly Revert on failure.
Code:
modifieronlyowner{if(msg.sender==owner)_}
Behavior:
Ifmsg.sender == owner: Execute function body (represented by _)
Else: Do nothing (function body is not executed, but transaction succeeds with no revert)
Security Concern: In modern Solidity, this modifier would use require(msg.sender == owner, "Not owner"); to explicitly revert unauthorized calls. The deprecated syntax silently succeeds without executing the function, which could be confusing for callers expecting a revert.
Public State Variables (Auto-Generated Getters)
While not explicit functions in the source code, Solidity automatically generates getter functions for all public State Variables:
FUNCTION
RETURN TYPE
PURPOSE
participants(uint256)
(address, uint256)
Returns etherAddress and amount for participant at given index
payoutIdx()
uint256
Returns current payout queue position (currently 118)