name: "staking-receipt-tokens" description: "Type Thought-template (instantiate before use) - Research basis Donation attacks via unsolicited token transfers"
Skill: Staking Receipt Token Analysis
Type: Thought-template (instantiate before use) Research basis: Donation attacks via unsolicited token transfers
Trigger Patterns
delegation|staking.*receipt|liquid.*staking|getLiquidRewards|unbond|
stake.*share|validator|deposit.*voucher|withdraw.*voucher|claimReward
Reasoning Template
Step 1: Identify Receipt Tokens
- In {CONTRACTS}, find all external calls that return tokens
- For each, determine:
- What token type is returned? (shares, vouchers, receipts, LP tokens)
- Is the returned token ERC20-compatible?
- Does the protocol hold these tokens?
Step 2: Check Transferability
- For each receipt token {RECEIPT_TOKEN}:
- Can it be acquired externally? (stake directly with {EXTERNAL_STAKING})
- Can it be transferred via standard
transfer()/transferFrom()? - Can anyone transfer it to {PROTOCOL_CONTRACT} unsolicited?
Step 2b: External Token Transferability
For each EXTERNAL staking/delegation token the protocol interacts with (not just the protocol's own receipt token):
- Is it ERC20-transferable? (check if extends IERC20/IERC20Upgradeable)
- Can it be transferred TO the protocol contract unsolicited (without calling deposit/stake)?
- If YES to both:
a. Does the protocol iterate over these tokens or their sources? (gas DoS from many unsolicited transfers)
b. Does
getTotalStake(protocol)or equivalent change? (accounting impact on withdrawal calculations) c. Doestransfer()trigger side effects? (reward auto-claim, delegation state changes) d. Does non-zero balance block any admin/privileged operations? (e.g., entity removal requires balance == 0)
| External Token | ERC20? | Unsolicited Transfer? | Iteration DoS? | Balance Impact? | Side Effects? | Blocks Operations? |
|---|---|---|---|---|---|---|
| {token_name} | YES/NO | YES/NO | YES/NO | YES/NO | YES/NO | YES/NO |
RULE: If ANY external token is ERC20-transferable AND affects protocol state → finding with severity >= MEDIUM.
Step 3: Trace Balance Dependencies
- In {PROTOCOL_CONTRACT}, find all uses of
balanceOf(address(this))for {RECEIPT_TOKEN} - For each usage at {BALANCE_CHECK_LOCATIONS}:
- What calculation depends on this balance?
- Is there a tracked state variable that should match?
- What's the gap risk: tracked vs actual?
Step 4: Model Donation Attack
1. Attacker acquires {RECEIPT_TOKEN} externally via {EXTERNAL_ACQUISITION}
2. Attacker transfers {DONATION_AMOUNT} to {PROTOCOL_CONTRACT}
3. Protocol's balanceOf(this) increases by {DONATION_AMOUNT}
4. Next operation at {AFFECTED_FUNCTION} uses inflated balance
5. Impact: {IMPACT_DESCRIPTION}
Step 5: Assess Severity
- Can attacker profit from this manipulation?
- Can attacker grief other users?
- What's the minimum donation needed for impact?
- Is there a defense (e.g., balance reconciliation)?
Key Questions (must answer all)
- Can {RECEIPT_TOKEN} be acquired without going through {PROTOCOL_CONTRACT}?
- Does {PROTOCOL_CONTRACT} use
balanceOf(this)for {RECEIPT_TOKEN} in any calculation? - Is there a tracked state variable that should equal the actual balance?
- What happens if tracked ≠ actual?
Common False Positives
- Balance reconciliation: If protocol calls
balanceOfand compares to tracked state, donation is detected - Isolated accounting: If receipt tokens are accounted separately per user (not pooled), donation doesn't affect others
- No balance dependency: If protocol never calls
balanceOf(this)for this token, donation has no effect - Burn on transfer: Some receipt tokens are non-transferable or burn on transfer
Multi-Entity Dust Attack Analysis
Step 6: Identify Multi-Entity Patterns
- Does the protocol interact with MULTIPLE staking entities? (validators, pools, vaults)
- Are there separate receipt tokens per entity?
- How does the protocol aggregate across entities?
Step 7: Model Compounding Dust
For protocols with N entities:
Single entity dust: X tokens (below threshold, ignored)
N entities with dust: N × X tokens
Compounding factor: If dust compounds over time → N × X × T
Check: Can attacker spread small amounts across many entities to:
1. Accumulate significant total value?
2. Avoid per-entity dust thresholds?
3. Exploit aggregation rounding?
Step 8: On-Transfer Side Effects
When receipt tokens are transferred:
- Does
transfer()trigger reward claims? - Does
transfer()update internal delegation state? - Does
transfer()call any hooks or callbacks?
Specific checks:
| Token | transfer() Side Effect | Exploitable? |
|---|---|---|
| Staking receipts | May claim rewards | Check if rewards go to sender/receiver/neither |
| stETH | Rebases on transfer | Check exchange rate impact |
| LP tokens | May trigger sync | Check for manipulation window |
| cTokens/aTokens | May accrue interest | Check balance vs shares discrepancy |
Step 9: Cross-Validator Attack Patterns
For protocols managing multiple validators:
Pattern A: Dust Spreading
- Attacker creates dust positions across N validators
- Each position below withdrawal threshold
- Total value: significant
- Impact: locked value, accounting discrepancies
Pattern B: Selective Validator Manipulation
- Attacker identifies validator with exploitable state
- Moves delegation to that specific validator
- Exploits validator-specific vulnerability
- Impact: depends on vulnerability
Pattern C: Aggregation Rounding
- Protocol rounds down per-validator withdrawals
- Attacker exploits: N validators × rounding_error = significant loss/gain
Step 10: External Adverse Events on Pending Operations
When the protocol has multi-step operations (request → wait → claim), check what happens if the external entity (validator, pool, vault, market) experiences an adverse event between steps.
| Multi-Step Operation | External Entity | Adverse Event | Impact on Pending Operation | Recovery Path? |
|---|---|---|---|---|
| {request→claim} | {entity} | Entity paused/frozen | {what happens to pending claim} | YES/NO |
| {request→claim} | {entity} | Entity slashed/penalized | {what happens to pending claim} | YES/NO |
| {request→claim} | {entity} | Entity deprecated/removed | {what happens to pending claim} | YES/NO |
| {request→claim} | {entity} | Entity liquidated/drained | {what happens to pending claim} | YES/NO |
Adverse events to check: pause, slash, penalize, deprecate, remove, liquidate, drain, migrate, upgrade
RULE: If a pending multi-step operation has no recovery path when the external entity experiences an adverse event → apply Rule 9 (stranded asset severity floor).
Instantiation Parameters
{CONTRACTS} - Contracts to analyze
{RECEIPT_TOKEN} - Specific token (stETH, rETH, cToken, aToken, LP token, etc.)
{EXTERNAL_STAKING} - Where token can be acquired externally
{PROTOCOL_CONTRACT} - Contract that holds receipt tokens
{BALANCE_CHECK_LOCATIONS}- Lines where balanceOf(this) is called
{EXTERNAL_ACQUISITION} - How attacker gets tokens (stake directly, buy on DEX)
{DONATION_AMOUNT} - Amount transferred in attack
{AFFECTED_FUNCTION} - Function affected by inflated balance
{IMPACT_DESCRIPTION} - What goes wrong
Output Schema
| Field | Required | Description |
|---|---|---|
| receipt_tokens | yes | List of identified receipt tokens |
| transferable | yes | YES/NO for each token |
| balance_dependencies | yes | Functions using balanceOf(this) |
| donation_impact | yes | What happens if balance is inflated |
| tracked_vs_actual | yes | Gap analysis |
| finding | yes | CONFIRMED / REFUTED / CONTESTED / NEEDS_DEPTH |
| evidence | yes | Code locations with line numbers |
| step_execution | yes | ✓/✗/? for each step |
Step Execution Checklist (MANDATORY)
CRITICAL: You MUST report completion status for ALL steps. Findings with incomplete steps (✗ or ? without valid reason) will be flagged for depth review.
Before finalizing ANY finding, complete this checklist:
| Step | Required | Completed? | Notes |
|---|---|---|---|
| 1. Identify Receipt Tokens | YES | ✓/✗/? | |
| 2. Check Transferability | YES | ✓/✗/? | |
| 2b. External Token Transferability | YES | ✓/✗/? | MANDATORY - never skip |
| 3. Trace Balance Dependencies | YES | ✓/✗/? | |
| 4. Model Donation Attack | YES | ✓/✗/? | |
| 5. Assess Severity | YES | ✓/✗/? | |
| 6. Identify Multi-Entity Patterns | IF N>1 | ✓/✗(N/A)/? | Skip only if protocol has single entity |
| 7. Model Compounding Dust | IF N>1 | ✓/✗(N/A)/? | Skip only if protocol has single entity |
| 8. On-Transfer Side Effects | YES | ✓/✗/? | MANDATORY - never skip |
| 9. Cross-Validator Attack Patterns | IF validators | ✓/✗(N/A)/? | Skip only if no validators |
Cross-Reference Markers
After Step 5 (Assess Severity):
- IF protocol manages multiple entities (validators, pools, vaults) → MUST complete Steps 6-7
- IF protocol has staking receipts → MUST complete Step 8
After Step 8 (On-Transfer Side Effects):
- IF side effects UNKNOWN → mark CONTESTED (not REFUTED)
- IF side effects may exist → assume YES (adversarial default), trace impact
Output Format for Step Execution
**Step Execution**: ✓1,2,3,4,5,8 | ✗6,7(N/A-single validator) | ✗9(N/A-no multi-validator)
OR if incomplete:
**Step Execution**: ✓1,2,3,4,5 | ?6,7(need multi-entity analysis) | ?8(transfer effects unknown)
**FLAG**: Incomplete analysis - requires depth review