0.7.56
This commit is contained in:
151
docs/reports/FEE_EVENT_AMOUNTS_MODEL_NOTE_0_7_56.md
Normal file
151
docs/reports/FEE_EVENT_AMOUNTS_MODEL_NOTE_0_7_56.md
Normal file
@@ -0,0 +1,151 @@
|
||||
<!-- file: docs/reports/FEE_EVENT_AMOUNTS_MODEL_NOTE_0_7_56.md -->
|
||||
|
||||
# Note technique — `k_sol_fee_event_amounts` et policy fees — `0.7.56`
|
||||
|
||||
## Objectif
|
||||
|
||||
La table `k_sol_fee_events` était suffisante pour un fee mono-montant, mais insuffisante pour les cas multi-mint, multi-destination ou multi-composant. `0.7.56` ajoute donc `k_sol_fee_event_amounts` comme table de legs rattachée au parent fee.
|
||||
|
||||
## Modèle
|
||||
|
||||
```text
|
||||
k_sol_fee_events
|
||||
id
|
||||
transaction_id
|
||||
decoded_event_id
|
||||
fee_token_mint nullable / vide si multi-leg
|
||||
fee_amount_raw nullable / vide si multi-leg
|
||||
payload_json
|
||||
|
||||
k_sol_fee_event_amounts
|
||||
id
|
||||
fee_event_id
|
||||
transaction_id
|
||||
decoded_event_id
|
||||
leg_index
|
||||
fee_component_kind
|
||||
token_mint
|
||||
amount_raw
|
||||
source_account
|
||||
destination_account
|
||||
amount_source
|
||||
payload_json
|
||||
```
|
||||
|
||||
## Règles invariantes
|
||||
|
||||
1. Un parent fee scalaire avec `fee_token_mint + fee_amount_raw` doit toujours avoir un leg `0`.
|
||||
2. Un parent multi-leg ou multi-mint ne doit pas agréger artificiellement ses montants dans le parent.
|
||||
3. Les legs doivent pointer vers le même `transaction_id` et `decoded_event_id` que le parent.
|
||||
4. Les legs doivent être supprimés/remplacés lors du replay/cleanup parent.
|
||||
5. Les transactions failed ne doivent pas créer de parent ou leg fee métier.
|
||||
6. Les bornes d'instruction (`maxAmount`, `minAmount`, `u64::MAX`) ne sont pas des montants exécutés.
|
||||
|
||||
## Sources de montant acceptées
|
||||
|
||||
| `amount_source` | Usage |
|
||||
|---|---|
|
||||
| `parent_fee_event_amount` | Leg généré automatiquement depuis un parent scalaire déjà fiable. |
|
||||
| `fee_event_amounts` | Source explicite reconstruite par un matérialisateur spécialisé. |
|
||||
| `inner_spl_transfer` | CPI SPL vérifié dans un matérialisateur spécialisé. |
|
||||
| `lamport_balance_delta` | Delta lamports prouvé et contextualisé. |
|
||||
| `allowlisted_inner_spl_transfer` | Recovery générique mais strictement allowlistée pour event kinds déjà validés. |
|
||||
|
||||
## Recovery allowlistée
|
||||
|
||||
La recovery `allowlisted_inner_spl_transfer` n'est pas une règle globale. Elle s'applique seulement aux event kinds explicitement autorisés dans le code. Cette restriction protège les futurs décodeurs : une nouvelle surface ne doit jamais créer des legs fee à partir de transferts internes tant que la sémantique n'a pas été inspectée.
|
||||
|
||||
Résultats de validation croisée en `0.7.56` :
|
||||
|
||||
| Base / surface | Effet observé |
|
||||
|---|---|
|
||||
| `meteora_dbc` | Aucun usage de l'allowlist générique ; chemins spécialisés DBC conservés. |
|
||||
| `raydium_launchpad` | `212` parents enrichis en legs : `claim_creator_fee`, `claim_platform_fee`, `claim_platform_fee_from_vault`, `collect_fee`. |
|
||||
| `raydium_cpmm` | `collect_creator_fee` enrichi ; `collect_fund_fee` / `collect_protocol_fee` explicités sans transfert exploitable. |
|
||||
| `pump_swap` | `collect_coin_creator_fee` et un `transfer_creator_fees_to_pump_v2` enrichis ; autres cas zero/no-transfer explicités. |
|
||||
| `pump_fees` | `crank_donation_fee_pda` et `sweep_buyback` enrichis ; events déjà scalaires conservés. |
|
||||
|
||||
## Contrôles SQL obligatoires
|
||||
|
||||
### Parent scalaire sans leg
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
de.protocol_name,
|
||||
de.event_kind,
|
||||
tx.signature,
|
||||
fee.id AS fee_event_id,
|
||||
fee.fee_token_mint,
|
||||
fee.fee_amount_raw,
|
||||
fee.payload_json
|
||||
FROM k_sol_fee_events fee
|
||||
JOIN k_sol_dex_decoded_events de
|
||||
ON de.id = fee.decoded_event_id
|
||||
JOIN k_sol_chain_transactions tx
|
||||
ON tx.id = fee.transaction_id
|
||||
LEFT JOIN k_sol_fee_event_amounts fea
|
||||
ON fea.fee_event_id = fee.id
|
||||
WHERE COALESCE(TRIM(fee.fee_token_mint), '') <> ''
|
||||
AND COALESCE(TRIM(fee.fee_amount_raw), '') <> ''
|
||||
AND fea.id IS NULL
|
||||
ORDER BY
|
||||
de.protocol_name,
|
||||
de.event_kind,
|
||||
tx.signature
|
||||
LIMIT 100;
|
||||
```
|
||||
|
||||
Attendu : vide.
|
||||
|
||||
### Legs orphelins
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
fea.id,
|
||||
fea.fee_event_id,
|
||||
fea.transaction_id,
|
||||
fea.decoded_event_id
|
||||
FROM k_sol_fee_event_amounts fea
|
||||
LEFT JOIN k_sol_fee_events fee
|
||||
ON fee.id = fea.fee_event_id
|
||||
WHERE fee.id IS NULL;
|
||||
```
|
||||
|
||||
Attendu : vide.
|
||||
|
||||
### Résumé parent/legs par event
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
de.protocol_name,
|
||||
de.event_kind,
|
||||
COUNT(DISTINCT fee.id) AS fee_parent_count,
|
||||
COUNT(DISTINCT CASE
|
||||
WHEN COALESCE(TRIM(fee.fee_token_mint), '') <> ''
|
||||
AND COALESCE(TRIM(fee.fee_amount_raw), '') <> ''
|
||||
THEN fee.id
|
||||
ELSE NULL
|
||||
END) AS parent_with_scalar_amount_count,
|
||||
COUNT(DISTINCT fea.id) AS fee_amount_leg_count,
|
||||
MIN(tx.signature) AS sample_signature
|
||||
FROM k_sol_fee_events fee
|
||||
JOIN k_sol_dex_decoded_events de
|
||||
ON de.id = fee.decoded_event_id
|
||||
JOIN k_sol_chain_transactions tx
|
||||
ON tx.id = fee.transaction_id
|
||||
LEFT JOIN k_sol_fee_event_amounts fea
|
||||
ON fea.fee_event_id = fee.id
|
||||
GROUP BY
|
||||
de.protocol_name,
|
||||
de.event_kind
|
||||
ORDER BY
|
||||
de.protocol_name,
|
||||
de.event_kind;
|
||||
```
|
||||
|
||||
## Règles pour `0.7.57 meteora_dlmm`
|
||||
|
||||
- Les instructions `claim_fee`, `claim_fee2`, `withdraw_protocol_fee`, `zap_protocol_fee`, `CompositionFee`, `ClaimFee`, `ClaimFee2` doivent utiliser `k_sol_fee_event_amounts` dès qu'un montant/mint fiable est disponible.
|
||||
- Les rewards (`claim_reward*`, `fund_reward`, `withdraw_ineligible_reward`) vont vers `k_sol_reward_events`, pas vers fees, sauf sémantique contraire prouvée.
|
||||
- Les `composition_fee` de swap/liquidity ne doivent pas être double-comptés si déjà inclus dans le trade/liquidity effectif.
|
||||
- Toute recovery générique doit être déclarée par policy explicite et tests synthétiques ; ne pas ajouter DLMM à l'allowlist sans audit par event kind.
|
||||
161
docs/reports/METEORA_DBC_EVENT_COVERAGE_REPORT.md
Normal file
161
docs/reports/METEORA_DBC_EVENT_COVERAGE_REPORT.md
Normal file
@@ -0,0 +1,161 @@
|
||||
<!-- file: docs/reports/METEORA_DBC_EVENT_COVERAGE_REPORT.md -->
|
||||
|
||||
# Meteora DBC Event Coverage Report — `0.7.56 final`
|
||||
|
||||
## Statut final
|
||||
|
||||
La tranche `0.7.56 meteora_dbc` est clôturée.
|
||||
|
||||
Program id :
|
||||
|
||||
```text
|
||||
dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN
|
||||
```
|
||||
|
||||
Source locale prioritaire :
|
||||
|
||||
```text
|
||||
idls/meteora_dbc.dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN.json
|
||||
```
|
||||
|
||||
Surface IDL : `28` instructions, `23` events Anchor, `9` accounts, `59` types.
|
||||
|
||||
## Résultat build/replay final
|
||||
|
||||
```text
|
||||
cargo test -p kb_lib -> 446 passed / 0 failed
|
||||
cargo clippy -p kb_lib --all-targets -- -D warnings -> OK
|
||||
480 replayed
|
||||
0 decode skipped
|
||||
480 ledger upserts
|
||||
454 unsafe ledger rows
|
||||
264 trades
|
||||
1 liquidity
|
||||
122 lifecycle
|
||||
0 tokenAccount
|
||||
1056 candle upserts
|
||||
instructionObservations = 7167
|
||||
resetDeleted = 3583
|
||||
catalog = 86 tokens / 60 pools / 60 pairs
|
||||
```
|
||||
|
||||
Replay final recommandé pour reproduire :
|
||||
|
||||
```text
|
||||
skipDexDecode=no
|
||||
forceDexDecode=yes
|
||||
deferInstructionObservations=yes
|
||||
```
|
||||
|
||||
## Décisions métier verrouillées
|
||||
|
||||
### Swaps
|
||||
|
||||
- `meteora_dbc.swap` et `meteora_dbc.swap2` sont les seules entrées candidates trade/candle directes.
|
||||
- Les trades/candles ne sont produits que si les montants exécutés et les mints base/quote sont fiables.
|
||||
- Les montants de `swap2` doivent être dérivés du layout et/ou des CPI SPL effectifs ; ne pas utiliser naïvement les bornes d'instruction.
|
||||
- Les events Anchor `EvtSwap` / `EvtSwap2` restent decoded-only s'ils ne portent pas un contexte mint/pair suffisant ou s'ils doublonnent l'instruction matérialisée.
|
||||
|
||||
### Lifecycle / migration / lockers
|
||||
|
||||
- `initialize_virtual_pool_with_spl_token` et `initialize_virtual_pool_with_token2022` alimentent lifecycle/catalog lorsque les comptes pool/base/quote/config sont fiables.
|
||||
- `create_locker`, `migrate_meteora_damm_claim_lp_token`, `migrate_meteora_damm_lock_lp_token`, `migration_damm_v2*` et `migrate_meteora_damm*` sont lifecycle, pas liquidity artificielle.
|
||||
- Les metadata-only restent decoded-only avec raison explicite si elles n'apportent pas de cible métier fiable.
|
||||
|
||||
### Admin/config
|
||||
|
||||
- `create_config`, `create_operator_account`, `close_*operator*`, metadata, `transfer_pool_creator` et events config/admin alimentent `k_sol_pool_admin_events` uniquement si l'acteur et la cible sont fiables.
|
||||
- Les payloads génériques ou incomplets restent audit/decoded-only.
|
||||
|
||||
### Fees
|
||||
|
||||
- Les fees DBC utilisent le modèle parent+legs : `k_sol_fee_events` + `k_sol_fee_event_amounts`.
|
||||
- Les maxima d'instruction (`maxAmount*`, `u64::MAX`, bornes de claim) ne sont pas des montants exécutés.
|
||||
- Les montants fiables proviennent des CPI SPL, des legs explicitement reconstruits ou des lamport balance deltas prouvés.
|
||||
- Les events Anchor fee sans mint restent decoded-only avec `skipFeeReason`.
|
||||
- Les cas sans transfert réel portent `fee_instruction_has_no_actual_transfer` ou `fee_instruction_has_only_zero_amount_transfers`.
|
||||
|
||||
## Matérialisation fee finale
|
||||
|
||||
| Event kind | Fee parents | Parents scalaires | Amount legs | Décision |
|
||||
|---|---:|---:|---:|---|
|
||||
| `meteora_dbc.claim_creator_trading_fee` | 8 | 8 | 8 | Mono-leg fiable. |
|
||||
| `meteora_dbc.claim_partner_pool_creation_fee` | 10 | 10 | 10 | Mono-leg fiable. |
|
||||
| `meteora_dbc.claim_protocol_fee` | 10 | 10 | 10 | Mono-leg fiable. |
|
||||
| `meteora_dbc.claim_protocol_pool_creation_fee` | 10 | 10 | 10 | Mono-leg/lamport delta fiable. |
|
||||
| `meteora_dbc.claim_trading_fee` | 11 | 6 | 18 | Mix mono-leg et multi-leg ; parent non agrégé pour multi-leg. |
|
||||
| `meteora_dbc.creator_withdraw_surplus` | 2 | 2 | 2 | Mono-leg fiable ; résiduels sans transfert réel explicités. |
|
||||
| `meteora_dbc.partner_withdraw_surplus` | 9 | 9 | 9 | Mono-leg fiable. |
|
||||
| `meteora_dbc.withdraw_leftover` | 10 | 10 | 10 | Mono-leg fiable. |
|
||||
| `meteora_dbc.withdraw_migration_fee` | 9 | 9 | 9 | Fee, pas migration target ; mono-leg fiable. |
|
||||
| `meteora_dbc.zap_protocol_fee` | 10 | 10 | 10 | Mono-leg fiable. |
|
||||
| **Total `meteora_dbc`** | **89** | n/a | **96** | Parent+legs validé. |
|
||||
|
||||
## Socle `k_sol_fee_event_amounts`
|
||||
|
||||
La version `0.7.56` ajoute un modèle durable pour les fees composés :
|
||||
|
||||
- `k_sol_fee_events` est le parent logique unique lié au `decoded_event_id` ;
|
||||
- `k_sol_fee_event_amounts` contient les legs de montants, avec `leg_index`, `fee_component_kind`, `token_mint`, `amount_raw`, comptes source/destination et `amount_source` ;
|
||||
- un parent avec `fee_token_mint + fee_amount_raw` crée automatiquement un leg scalaire ;
|
||||
- un parent multi-leg/multi-mint laisse les champs scalaires du parent vides et stocke tout dans les legs ;
|
||||
- les deletes/replays nettoient les legs avant ou avec le parent ;
|
||||
- la requête de contrôle `parent scalar without leg` doit rester vide.
|
||||
|
||||
Sources `amount_source` connues en fin de tranche :
|
||||
|
||||
```text
|
||||
parent_fee_event_amount
|
||||
fee_event_amounts
|
||||
inner_spl_transfer
|
||||
lamport_balance_delta
|
||||
allowlisted_inner_spl_transfer
|
||||
```
|
||||
|
||||
## Recovery fee allowlistée
|
||||
|
||||
La recovery `allowlisted_inner_spl_transfer` est volontairement non globale.
|
||||
|
||||
Elle a été testée sur anciennes bases pour enrichir les surfaces déjà connues :
|
||||
|
||||
| Surface testée | Résultat |
|
||||
|---|---|
|
||||
| `raydium_launchpad` | `claim_creator_fee`, `claim_platform_fee`, `claim_platform_fee_from_vault`, `collect_fee` enrichis en legs depuis CPI SPL. |
|
||||
| `raydium_cpmm` | `collect_creator_fee` enrichi ; `collect_fund_fee` et `collect_protocol_fee` restent sans transfert réel exploitable dans le corpus testé. |
|
||||
| `pump_swap` | `collect_coin_creator_fee` et certains `transfer_creator_fees_to_pump_v2` enrichis ; cas zero/no-transfer explicités. |
|
||||
| `pump_fees` | `crank_donation_fee_pda` et `sweep_buyback` enrichis ; events déjà scalaires conservés. |
|
||||
| `meteora_dbc` | Non concerné par l'allowlist générique ; DBC conserve ses chemins spécifiques. |
|
||||
|
||||
Règle pour les prochaines versions : tout nouveau decoder doit déclarer explicitement sa policy de récupération des montants fee. Aucun futur decoder ne doit hériter automatiquement de la recovery CPI SPL.
|
||||
|
||||
## Checks de fermeture
|
||||
|
||||
Les contrôles de fermeture exigés sont propres :
|
||||
|
||||
- fallback `upstream_git` `meteora_dbc` pour entrées couvertes localement : vide ;
|
||||
- decoded `meteora_dbc` sans coverage : vide ;
|
||||
- successful non-materialized sans `skip*Reason` ou policy explicite : vide ;
|
||||
- failed tx avec materialization métier : vide ;
|
||||
- multi-target materialization : vide ;
|
||||
- non-swap DBC vers trade/candle : vide ;
|
||||
- parent fee scalaire sans leg : vide ;
|
||||
- legs fee orphelins : vide ;
|
||||
- watchlist globale sans backlog dominant `meteora_dbc`.
|
||||
|
||||
## Fichiers de référence
|
||||
|
||||
```text
|
||||
kb_lib/src/dex/meteora_dbc.rs
|
||||
kb_lib/src/non_trade_event_materialization.rs
|
||||
kb_lib/src/db/queries/fee_event_amount.rs
|
||||
kb_lib/src/db/entities/fee_event_amount.rs
|
||||
kb_lib/src/db/dtos/fee_event_amount.rs
|
||||
validation_sql/SQL_VALIDATION_METEORA_DBC_0_7_56.sql
|
||||
docs/reports/FEE_EVENT_AMOUNTS_MODEL_NOTE_0_7_56.md
|
||||
docs/VALIDATION_STATUS_0_7_56_FINAL.md
|
||||
docs/prompts/PROMPT_0_7_57_METEORA_DLMM_FULL_DECODE_MATERIALIZATION.md
|
||||
```
|
||||
|
||||
## Décision
|
||||
|
||||
`0.7.56 meteora_dbc` est clôturé. La prochaine tranche est `0.7.57 meteora_dlmm` en full decode + full materialization.
|
||||
Reference in New Issue
Block a user