一键导入
share-allocation-fairness
Trigger Pattern SHARE_ALLOCATION flag detected in pattern scan - Inject Into Breadth agents, depth-edge-case
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Trigger Pattern SHARE_ALLOCATION flag detected in pattern scan - Inject Into Breadth agents, depth-edge-case
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | share-allocation-fairness |
| description | Trigger Pattern SHARE_ALLOCATION flag detected in pattern scan - Inject Into Breadth agents, depth-edge-case |
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
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.
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 |
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?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)?Int/Decimal → the choice ABORTS → holders cannot merge → liveness brick.Tag: [BOUNDARY:splitAmount=1 -> child=0], [VARIATION:Decimal truncation favors protocol on every split].
For each allocation entry choice:
start_time/since field compared to getTime), or only THAT it exists at distribution time?| 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.
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:
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.deposit owner amount where owner /= caller create a per-holder contract that captures rewards the owner did not earn?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?
Check that entry and exit use consistent valuation:
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.Mint-authority risks in DAML:
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?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.
For each finding, specify:
Int/Decimal example**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 | 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).
Protocol Type Trigger NAMED_EXTERNAL_PROTOCOL (detected when recon finds import/interface for an identifiable external protocol — not standard libraries). Researches known integration hazards of the target protocol.
Trigger Pattern Always required for DAML audits - Inject Into Breadth agents, depth-state-trace, depth-external
Trigger Pattern Always required for DAML audits - Inject Into Breadth agents, depth-state-trace, depth-edge-case
Trigger Pattern Always required for DAML audits - Inject Into Breadth agents, depth-external, depth-edge-case
Trigger Pattern Always required for DAML audits (self-skips if no template defines a key) - Inject Into Breadth agents, depth-state-trace
Trigger Pattern MONETARY_PARAMETER flag (fee, rate, emission, cap, bps as template fields) - Inject Into Breadth agents (merged via M4 hierarchy)