Agent skill

share-allocation-fairness

Trigger Pattern SHARE_ALLOCATION flag detected in pattern scan - Inject Into Breadth agents, depth-edge-case

Stars 215
Forks 33

Install this agent skill to your Project

npx add-skill https://github.com/PlamenTSV/plamen/tree/main/agents/skills/soroban/share-allocation-fairness

SKILL.md

SHARE_ALLOCATION_FAIRNESS Skill (Soroban)

Trigger Pattern: SHARE_ALLOCATION flag detected in pattern scan Inject Into: Breadth agents, depth-edge-case Finding prefix: [SAF-N] Rules referenced: R5, R10, R13, R14

shares|allocation|distribute|pro_rata|proportional|vest|reward_per_share|
mint|burn|reward_index|cumulative|checkpoint|epoch_reward

Purpose

Analyze fairness of share/token allocation mechanisms on Soroban where users receive shares proportional to deposits, contributions, or participation — checking for late-entry advantages, storage-default manipulation, authorization bypass, and time-weighting omissions.

Soroban arithmetic constraint: ALL share math uses i128 (signed 128-bit integer). There is no floating-point arithmetic. All pro-rata and time-weighted calculations must use multiply-then-divide integer patterns. Division truncates toward zero. Overflow with unchecked * on i128 wraps silently in Rust release mode — use checked_mul.


STEP 1: Classify Allocation Mechanism

Identify which pattern the protocol uses:

Type Soroban Pattern Key Risk
Pro-rata snapshot Shares minted at fixed ratio via mint() on custom SEP-41 token at deposit time Late depositors dilute early depositors' accrued value
Time-weighted Per-user Persistent entry tracks reward_per_share_paid: i128 and accrued_rewards: i128 Checkpoint manipulation, stale reward index
Epoch-based Shares valued per ledger-sequence epoch; epoch tracked in Instance storage Cross-epoch timing arbitrage at epoch transition ledgers
Queue-based Ordered list in Instance/Persistent storage (Vec or linked entries) Queue position gaming, partial processing fairness

STEP 2: Late Entry Attack Model

For each allocation entry function:

  1. Identify accrual source: What generates value for existing share holders? (yield from cross-contract calls, fees collected at contract address, XLM/token rewards)
  2. Trace timing: When does accrued value become claimable vs when can new shares enter? Is there a checkpoint function separate from deposit?
  3. Check for time-weighting: Does allocation account for HOW LONG shares were held, or only THAT shares are held at checkpoint time?
  4. Model attack: Can a depositor enter AFTER value accrues but BEFORE distribution, capturing value they did not earn?
Entry Function Accrual Source Time-Weighted? Late Entry Possible? Impact

Soroban timing: With ~5s ledger close time, timing attacks require multi-ledger execution. However, in high-value situations an attacker can monitor on-chain state and submit a transaction to land in the specific ledger just before a known distribution event.

STEP 2c: Cross-Address Deposit Model

For each entry function accepting a recipient: Address parameter that is NOT verified to be the function caller:

Entry Function Accepts Recipient != Caller? Default State for New Persistent Entry Exploitable? Impact

Check: When a new Persistent entry is created for a recipient address:

  • What are the DEFAULT values? (reward_per_share_paid: i128 = 0? last_deposit_ledger: u32 = 0?)
  • If reward_per_share_paid starts at 0 while the global index is at N, the new entry holder is entitled to ALL historical rewards on their deposit — FINDING (late-entry variant)
  • Can deposit(recipient, amount) where recipient != caller be used to create a new Persistent entry that captures historical rewards the recipient did not earn?
  • Does the function use a new Persistent entry (first call creates with defaults) vs updating an existing one?

STEP 2d: Pre-Setter Timing Model

For each admin-settable reward/rate parameter stored in Instance storage:

Parameter Setter Staked-Before-Set? Retroactive Rewards? Fair?

Model the sequence: user deposits (Persistent entry created with current index) → admin sets reward rate → rewards accrue.

  • Does the user receive retroactive rewards for the period BEFORE the rate was set?
  • Does a depositor AFTER rate-setting receive the same, more, or less?
  • Is the global reward index updated atomically with the rate change (same transaction), or can a window exist?

2e. Pre-Configuration State Analysis

For the allocation mechanism identified in Step 1:

Configuration Step Storage Key Initialized Functions Available Before Init Exploitable Default?
  1. What is the deployment/initialization sequence? List all initialize_* functions in order.
  2. For each step: what functions are callable BEFORE this initialization completes?
  3. Are there reward/share calculations that read Instance storage keys that may not yet exist (returning None)?
  4. Can a user call deposit/stake functions before all Instance storage keys are initialized and receive outsized rewards/shares due to Noneunwrap_or(0) defaults?
  5. Is there an is_initialized flag in Instance storage or an admin check that prevents interaction before configuration completes?

If users can interact during partial initialization AND default storage values create unfair advantage → FINDING (minimum Medium, Rule 13: design gap).


STEP 3: Queue Position and Batch Processing

For protocols with queue-based or batch processing:

  1. Ordering fairness: Is queue order FIFO (append-only Vec in Instance storage), arbitrary (admin-chosen), or manipulable (fee-based ledger ordering)?
  2. Partial processing: Can processing handle some entries but not others within a batch? (Resource metering limits force partial processing — who gets processed first?)
  3. Cross-batch state: Does processing order within a batch affect allocation ratios? (first processed gets better rate if rate changes with each step)
  4. Deposit splitting: Can a user split one large deposit into many small Persistent entries to gain queue advantage or bypass per-entry limits?

Resource-aware batching: If batch processing iterates over a Vec stored in Instance storage:

  • What is the max batch size before exceeding the transaction's CPU instruction or memory budget?
  • Can an attacker bloat the queue with dust deposits to force partial processing?
  • Does partial processing create unfair ordering advantages for early entries?
  • If the Vec grows unboundedly, does Instance storage size (and thus TTL extension fees) scale unboundedly?

STEP 4: Share Redemption Symmetry

Check that entry and exit use consistent valuation:

  1. Mint vs burn ratio: Are shares minted at the same exchange rate they can be burned? (check share price formula in both deposit and withdraw functions)
    • With i128 math: does rounding in deposit vs withdraw consistently favor one party?
    • Example: deposit mints floor(amount * total_shares / total_value) shares; withdraw gives floor(shares * total_value / total_shares) tokens — rounding may always favor the protocol
  2. Pending claims: Can unclaimed reward tokens tracked in Persistent storage dilute active shares' value? (rewards owed to specific users but still counted as TVL)
  3. Withdrawal ordering: Does withdrawal order create unfair priority? (first to withdraw gets full value; later withdrawers face depleted vault if cross-contract positions haven't been unwound)

Token admin risks in Soroban:

  • Custom token mint authority: If the protocol controls a custom SEP-41 token's admin, can it mint additional shares outside the deposit logic? Is minting gated to the deposit function only?
  • SAC freeze/clawback: If the share token is a SAC-wrapped asset, the Stellar issuer can freeze or clawback individual user balances, preventing them from redeeming shares — denial of service on targeted users
  • If SAC freeze authority is active: who controls it? Can it be revoked? FINDING if freeze can target individual users holding shares.

STEP 4b: Aggregate Constraint Coherence (Rule 14)

For independently-settable allocation rates/shares (e.g., per-pool weights, fee splits, distribution percentages stored as separate Instance storage keys):

Rate/Weight Setter Aggregate Constraint Enforced On-Chain? What if Sum Exceeds/Falls Short?

Soroban-specific: If weights are stored as separate Instance storage keys (one per pool), the setter function may update ONE key without reading and summing ALL keys to validate the aggregate. This is especially problematic when each setter only receives its own key as context.

If aggregate constraint NOT enforced and rates independently settable → FINDING (Rule 14).

Also check: Can admin set a weight to 0 for an active pool? What happens to users with deposits in that pool? (Rule 14 setter regression — setting weight below accumulated state causes division-by-zero or zero-allocation for existing depositors)


Output

For each finding, specify:

  • Allocation mechanism type (pro-rata, time-weighted, queue, epoch)
  • Whether time-weighting is present or missing
  • Concrete attack sequence with numerical i128 example (token amounts in smallest unit, e.g., stroops for XLM)
  • Who benefits and who is harmed
  • Whether the attack requires precise ledger ordering (high-fee transaction) or is achievable with normal timing

Finding Template

markdown
**ID**: [SAF-N]
**Verdict**: CONFIRMED / PARTIAL / REFUTED / CONTESTED
**Step Execution**: (see checklist below)
**Rules Applied**: [R5:___, R10:___, R13:___, R14:___]
**Severity**: Critical/High/Medium/Low/Info
**Location**: src/{file}.rs:LineN
**Title**: {fairness violation type}
**Description**: {specific issue with i128 numerical example}
**Impact**: {quantified at worst-state parameters — who loses how much, in stroops or token units}

Step Execution Checklist (MANDATORY)

Step Required Completed? Notes
1. Classify Allocation Mechanism YES
2. Late Entry Attack Model YES
2c. Cross-Address Deposit Model YES Check recipient != caller patterns
2d. Pre-Setter Timing Model YES Model deposit-before-rate-set sequence
2e. Pre-Configuration State Analysis YES Deployment window + uninitialized storage defaults
3. Queue Position and Batch Processing IF queue/batch detected Include resource-aware batch analysis
4. Share Redemption Symmetry YES Include custom token mint + SAC freeze check
4b. Aggregate Constraint Coherence IF multiple settable weights Rule 14 enforcement check

If any step skipped, document valid reason (N/A, no queue, single pool, no settable weights).

Expand your agent's capabilities with these related and highly-rated skills.

Didn't find tool you were looking for?

Be as detailed as possible for better results