Trigger Pattern SHARE_ALLOCATION flag detected in pattern scan - Inject Into Breadth agents, depth-edge-case
Scanned 9/6/2026
Install to Claude Code
npx -y skills add PlamenTSV/plamen --skill share-allocation-fairness --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Share Allocation Fairness?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/plamentsv-share-allocation-fairness-plamen)More formats (shields.io, HTML) on the badges page.
---
name: "share-allocation-fairness"
description: "Trigger Pattern SHARE_ALLOCATION flag detected in pattern scan - Inject Into Breadth agents, depth-edge-case"
---
# SHARE_ALLOCATION_FAIRNESS Skill (DAML)
> **Trigger Pattern**: SHARE_ALLOCATION flag detected in pattern scan
> **Inject Into**: Breadth agents, depth-edge-case
> **Finding prefix**: `[DML-SAF-N]`
> **Rules referenced**: R5, R10, R13, R14
```
shares|allocation|distribute|pro_rata|proportional|split|merge|vest|
reward|cumulative|epoch|mint|burn|holding|units
```
## Purpose
Analyze fairness of share/asset allocation mechanisms on DAML where holders receive units proportional to deposits, contributions, or participation — checking for split/merge rounding loss, late-entry advantages, first/last-holder edge cases, and missing time-weighting. Pairs with LOCKING_SEMANTICS (a locked holding that can still be split/merged is both a fairness and a lock-bypass bug).
**DAML arithmetic constraint**: all share math uses `Int` or `Decimal` (fixed-point, 10 fractional digits) on template **fields**. No floating-point. Pro-rata and split/merge use multiply-then-divide integer/decimal patterns; division truncates toward zero. `Int`/`Decimal` THROW on overflow (a liveness brick, never a silent wrap). A "share" is a holding contract; minting = a choice that creates a holding, burning = a consuming choice that archives one.
---
## STEP 1: Classify Allocation Mechanism
Identify which pattern the protocol uses:
| Type | DAML Pattern | Key Risk |
|------|--------------|----------|
| Split / Merge | A consuming choice archives a holding and creates two (Split) or archives two and creates one (Merge) | Rounding loss or gain breaking value conservation; locked holding still splittable |
| Pro-rata snapshot | A holding created at a fixed ratio at deposit time | Late holders dilute earlier holders' accrued value |
| Time-weighted | A holding/per-holder contract tracks a `reward_index`/`accrued` field | Stale index, checkpoint manipulation across choices |
| Epoch-based | Allocation valued per ledger-time epoch field | Cross-epoch timing arbitrage at epoch boundaries |
---
## STEP 2: Split / Merge Value Conservation (PRIMARY DAML LANE)
For each split/merge/transfer choice:
| Choice | In Amount(s) | Out Amount(s) Formula | Conservation: out == in? | Rounding Direction | Finding? |
|--------|--------------|------------------------|--------------------------|--------------------|----------|
**Methodology — substitute and trace**:
- `Split` with `splitAmount`: do the two children sum EXACTLY to the parent (`child.amount + remainder.amount == parent.amount`)? With `Decimal` truncation, a formula like `parent * ratio` for one child and `parent - (parent * ratio)` for the other can drop or duplicate a unit.
- `Merge`: does the merged child equal the sum of inputs, or does a re-normalization lose value?
- **First-holder / zero-state**: split a holding of the minimum unit (1, or smallest `Decimal`). Does one child get 0 (truncation) while the parent is consumed → value destroyed? Does a zero-amount child even create (cross-reference ENSURE_INVARIANTS — is there `ensure amount > 0`)?
- **Last-holder / dust**: repeated splits leaving dust — does dust round to the protocol, to the holder, or get destroyed?
- **Max boundary**: a merge whose sum overflows `Int`/`Decimal` → the choice ABORTS → holders cannot merge → liveness brick.
Tag: `[BOUNDARY:splitAmount=1 -> child=0]`, `[VARIATION:Decimal truncation favors protocol on every split]`.
---
## STEP 3: Late Entry & Cross-Holder Attack Model
For each allocation entry choice:
1. **Identify accrual source**: what generates value for existing holders (fees collected into a pool contract, rewards distributed by a choice)?
2. **Trace timing**: when does accrued value become claimable vs when can a new holding enter? Is there a separate checkpoint choice?
3. **Time-weighting**: does allocation account for HOW LONG a holding was held (a `start_time`/`since` field compared to `getTime`), or only THAT it exists at distribution time?
4. **Model attack**: can a party create a holding AFTER value accrues but BEFORE distribution, capturing value it did not earn?
| Entry Choice | Accrual Source | Time-Weighted? | Late Entry Possible? | Impact |
|--------------|----------------|----------------|----------------------|--------|
**DAML timing**: ledger-time ordered; a timing attack requires landing a transaction in the ledger just before a known distribution choice.
### STEP 3c: Cross-Party Allocation Model
For each entry choice accepting an `owner`/`recipient : Party` that is NOT verified to be a `controller`/`signatory`:
| Entry Choice | Accepts recipient /= caller? | Default Field State for New Holding | Exploitable? | Impact |
|--------------|------------------------------|--------------------------------------|--------------|--------|
**Check**: when a new holding/per-holder contract is created for a recipient party:
- What are the DEFAULT field values (e.g. `reward_index = 0` while the global index is at N)? A new holder whose `reward_index` starts at 0 may be entitled to ALL historical rewards → late-entry variant → FINDING.
- Can `deposit owner amount` where `owner /= caller` create a per-holder contract that captures rewards the owner did not earn?
- Does the choice create a fresh contract (default fields) vs archive+recreate an existing one?
### STEP 3d: Pre-Setter Timing Model
For each admin-settable reward/rate field (a config template field changed by a choice):
| Setting Choice | Holding-Before-Set? | Retroactive Rewards? | Fair? |
|----------------|---------------------|----------------------|-------|
Model the sequence: holder created (with current index) → role sets reward rate → rewards accrue. Does the holder receive retroactive rewards for the period BEFORE the rate was set? Is the global index re-created atomically with the rate change (same transaction), or can a window exist?
---
## STEP 4: Redemption / Burn Symmetry
Check that entry and exit use consistent valuation:
1. **Mint vs burn ratio**: are units created at the same exchange rate they can be burned? Check the formula in both the create-holding choice and the redeem/burn choice.
- With `Int`/`Decimal` math: does rounding in mint vs burn consistently favor one party? E.g. mint creates `floor(amount * total_units / total_value)` units; burn returns `floor(units * total_value / total_units)` — truncation may always favor the protocol.
2. **Pending claims**: can unclaimed reward holdings dilute active holders' value (rewards owed but still counted in a total)?
3. **Withdrawal ordering**: does redemption order create unfair priority (first to redeem gets full value; later redeemers face a depleted pool contract)?
**Mint-authority risks in DAML**:
- **Issuer over-mint**: if a holding's `signatory` is the issuer, the issuer can create additional holdings outside the deposit logic. Is minting gated to a single controlled choice, or can the issuer freely `createCmd`?
- **Archive/clawback**: can a privileged party archive (claw back) an individual holder's contract, denying redemption? FINDING if archival can target an individual holder without their authorization (cross-reference AUTHORIZATION_MODEL — a consuming/archive choice should require the holder's authority).
### STEP 4b: Aggregate Constraint Coherence (Rule 14)
For independently-settable allocation rates/weights (per-pool weight fields, fee splits, distribution percentages set by separate choices):
| Rate/Weight Setting Choice | Aggregate Constraint | Enforced On-Chain? | What if Sum Exceeds/Falls Short? |
|----------------------------|----------------------|--------------------|----------------------------------|
**DAML-specific**: if each weight is a separate contract field set by its own choice, the setting choice may archive+recreate ONE weight contract without reading and summing ALL of them to validate the aggregate. If the aggregate is not enforced and weights are independently settable → FINDING (Rule 14).
**Also check**: can a choice set a weight to 0 for an active pool? What happens to holders with deposits there (division-by-zero abort / zero allocation)? — Rule 14 setter regression.
---
## Output
For each finding, specify:
- Allocation mechanism type (split/merge, pro-rata, time-weighted, epoch)
- Whether time-weighting is present or missing
- Concrete attack sequence with a numerical `Int`/`Decimal` example
- Who benefits and who is harmed
- Whether the attack requires precise ledger ordering or is achievable with normal timing
---
## Finding Template
```markdown
**ID**: [DML-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**: {Module}.daml:LineN (template X, choice Y)
**Title**: {fairness / conservation / late-entry violation type}
**Description**: {specific issue with an Int/Decimal numerical example}
**Impact**: {quantified at worst-state parameters — who loses how much}
**PoC steer**: split/merge Script asserting `out1 + out2 == parent.amount` (conservation), or a boundary Script splitting the minimum unit to show a 0-value child / destroyed dust, or a late-entry Script where a recipient created after accrual captures historical rewards.
```
---
## Step Execution Checklist (MANDATORY)
| Step | Required | Completed? | Notes |
|------|----------|------------|-------|
| 1. Classify Allocation Mechanism | YES | | |
| 2. Split / Merge Value Conservation | YES | | Primary DAML lane — first/last/dust boundaries |
| 3. Late Entry & Cross-Holder Attack Model | YES | | |
| 3c. Cross-Party Allocation Model | YES | | Check recipient /= caller defaults |
| 3d. Pre-Setter Timing Model | YES | | Model deposit-before-rate-set |
| 4. Redemption / Burn Symmetry | YES | | Include issuer over-mint + archive/clawback check |
| 4b. Aggregate Constraint Coherence | IF multiple settable weights | | Rule 14 enforcement check |
If any step skipped, document a valid reason (N/A, no split/merge, single pool, no settable weights).
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!