205 lines
9.0 KiB
Markdown
205 lines
9.0 KiB
Markdown
# Rapport `0.7.48` — Raydium CPMM event coverage
|
|
|
|
## Scope
|
|
|
|
Tranche : `0.7.48`.
|
|
Decoder local : `raydium_cpmm`.
|
|
Programme : `CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C`.
|
|
|
|
Objectif : couvrir Raydium CPMM au-delà des swaps, avec preuve locale par backfill/replay SQL, sans modifier les règles trade/candle existantes et sans promouvoir de table métier transversale non nécessaire.
|
|
|
|
## Sources utilisées
|
|
|
|
Sources principales :
|
|
|
|
- Carbon `carbon-raydium-cpmm-decoder` ;
|
|
- fnzero `solana-streamer` / `sol-parser-sdk` IDL `raydium_cpmm.json` ;
|
|
- Raydium CP-Swap officiel ;
|
|
- Solscan page programme / Program IDL comme accélérateur de recherche de signatures, notamment via `instruction=<discriminator>`.
|
|
|
|
Règle retenue : Git/IDL/Solscan sont des indices de recherche. La preuve métier reste le corpus local backfillé puis rejoué.
|
|
|
|
## Entrées CPMM inventoriées
|
|
|
|
| Kind | Entrée | Discriminant | État final `0.7.48` |
|
|
|---|---|---|---|
|
|
| instruction | `close_permission_pda` | `9c5420764587467b` | connu upstream, non observé localement |
|
|
| instruction | `collect_creator_fee` | `1416567bc61cdb84` | décodé + matérialisé fee |
|
|
| instruction | `collect_fund_fee` | `a78a4e95dfc2067e` | décodé + matérialisé fee |
|
|
| instruction | `collect_protocol_fee` | `8888fcddc2427e59` | décodé + matérialisé fee |
|
|
| instruction | `create_amm_config` | `8934edd4d7756c68` | décodé + matérialisé admin/config |
|
|
| instruction | `create_permission_pda` | `878802d889a9b5ca` | décodé + matérialisé admin/config |
|
|
| instruction | `deposit` | `f223c68952e1f2b6` | décodé + matérialisé liquidity add |
|
|
| instruction | `initialize` | `afaf6d1f0d989bed` | décodé + matérialisé lifecycle |
|
|
| instruction | `initialize_with_permission` | `3f37fe4131b25979` | décodé + matérialisé lifecycle only |
|
|
| event | `lp_change_event` | `79a3cdc939da753c` | décodé + matérialisé liquidity bidirectionnelle |
|
|
| instruction | `swap_base_input` | `8fbe5adac41e33de` | décodé + trade matérialisé quand transaction OK |
|
|
| instruction | `swap_base_output` | `37d96256a34ab4ad` | décodé + trade matérialisé quand transaction OK |
|
|
| event | `swap_event` | `40c6cde8260871e2` | décodé audit-only, pas trade/candle |
|
|
| instruction | `update_amm_config` | `313cae889a1c74c8` | décodé + matérialisé admin/config |
|
|
| instruction | `update_pool_status` | `82576c062ee0757b` | connu upstream, non observé localement |
|
|
| instruction | `withdraw` | `b712469c946da122` | décodé + matérialisé liquidity remove |
|
|
|
|
## Décodage ajouté ou stabilisé
|
|
|
|
Le decoder spécialisé `raydium_cpmm` couvre maintenant :
|
|
|
|
- les swaps instruction-scoped `swap_base_input` / `swap_base_output` ;
|
|
- les events `Program data:` / Anchor CPI `swap_event` et `lp_change_event` ;
|
|
- les instructions lifecycle `initialize` / `initialize_with_permission` ;
|
|
- les instructions liquidity `deposit` / `withdraw` ;
|
|
- les fees `collect_creator_fee`, `collect_fund_fee`, `collect_protocol_fee` ;
|
|
- les instructions admin/config `create_amm_config`, `create_permission_pda`, `update_amm_config` ;
|
|
- les instructions connues mais non observées `close_permission_pda`, `update_pool_status` restent listées sans promotion métier.
|
|
|
|
Le fallback `upstream_git.instruction_match` ne doit plus apparaître pour les instructions CPMM couvertes localement.
|
|
|
|
## Matérialisation finale validée
|
|
|
|
Rejeu local validé après backfills ciblés Solscan + Demo Pipeline 2 :
|
|
|
|
| Event kind | Decoded | Table métier | Materialized | Trade count | Statut |
|
|
|---|---:|---|---:|---:|---|
|
|
| `raydium_cpmm.collect_creator_fee` | 4 | `k_sol_fee_events` | 4 | 0 | fee materialized |
|
|
| `raydium_cpmm.collect_fund_fee` | 7 | `k_sol_fee_events` | 7 | 0 | fee materialized |
|
|
| `raydium_cpmm.collect_protocol_fee` | 15 | `k_sol_fee_events` | 15 | 0 | fee materialized |
|
|
| `raydium_cpmm.create_amm_config` | 6 | `k_sol_pool_admin_events` | 6 | 0 | admin materialized |
|
|
| `raydium_cpmm.create_permission_pda` | 4 | `k_sol_pool_admin_events` | 4 | 0 | admin materialized |
|
|
| `raydium_cpmm.deposit` | 11 | `k_sol_liquidity_events` | 11 | 0 | liquidity add materialized |
|
|
| `raydium_cpmm.initialize` | 5 | `k_sol_pool_lifecycle_events` | 5 | 0 | lifecycle materialized |
|
|
| `raydium_cpmm.initialize_with_permission` | 4 | `k_sol_pool_lifecycle_events` | 4 | 0 | lifecycle only |
|
|
| `raydium_cpmm.lp_change_event` | 25 | `k_sol_liquidity_events` | 25 | 0 | liquidity materialized, `changeType` bidirectionnel |
|
|
| `raydium_cpmm.swap_base_input` | 750 | `k_sol_trade_events` | 482 | 482 | trade materialized for OK/actionable tx |
|
|
| `raydium_cpmm.swap_base_output` | 25 | `k_sol_trade_events` | 17 | 17 | trade materialized for OK/actionable tx |
|
|
| `raydium_cpmm.swap_event` | 529 | `k_sol_dex_decoded_events_only` | 0 | 0 | audit-only, no duplicate trade |
|
|
| `raydium_cpmm.update_amm_config` | 13 | `k_sol_pool_admin_events` | 13 | 0 | admin materialized |
|
|
| `raydium_cpmm.withdraw` | 14 | `k_sol_liquidity_events` | 14 | 0 | liquidity remove materialized |
|
|
| `raydium_cpmm.instruction_audit` | 3 | `k_sol_dex_decoded_events_only` | 0 | 0 | unknown audit-only |
|
|
|
|
Replay final observé :
|
|
|
|
```text
|
|
1124 replayed
|
|
561 trades
|
|
50 liquidity
|
|
9 lifecycle
|
|
2224 candle upserts
|
|
```
|
|
|
|
Le total liquidity correspond à :
|
|
|
|
```text
|
|
deposit 11
|
|
withdraw 14
|
|
lp_change_event 25
|
|
-------------------
|
|
total 50
|
|
```
|
|
|
|
## `lp_change_event`
|
|
|
|
`lp_change_event` est un event bidirectionnel :
|
|
|
|
- `changeType = 0` : add/deposit liquidity ;
|
|
- `changeType = 1` : remove/withdraw liquidity.
|
|
|
|
La coverage statique utilise donc `event_family = liquidity`, pas `liquidity_add`. La matérialisation résout le sens au niveau payload. Les events qui ne contiennent pas directement les mints sont enrichis via le contexte pool/pair local ou via le sibling `deposit` / `withdraw` déjà matérialisé dans la même transaction/replay.
|
|
|
|
Validation finale :
|
|
|
|
```text
|
|
changeType 0 -> 11 decoded / 11 liquidity / 0 trade
|
|
changeType 1 -> 14 decoded / 14 liquidity / 0 trade
|
|
```
|
|
|
|
## `initialize_with_permission`
|
|
|
|
`initialize_with_permission` est traité comme pool lifecycle only.
|
|
|
|
Validation finale :
|
|
|
|
```text
|
|
raydium_cpmm.initialize 5 decoded / 5 lifecycle / 0 admin / 0 trade
|
|
raydium_cpmm.initialize_with_permission 4 decoded / 4 lifecycle / 0 admin / 0 trade
|
|
```
|
|
|
|
Le cleanup de matérialisation supprime les anciennes lignes admin dérivées si elles existent déjà dans la base.
|
|
|
|
## Entrées non observées
|
|
|
|
Solscan avec filtre `instruction=` n'a pas retourné de transaction locale utile pour :
|
|
|
|
- `close_permission_pda` / `9c5420764587467b` ;
|
|
- `update_pool_status` / `82576c062ee0757b`.
|
|
|
|
Ces entrées restent donc :
|
|
|
|
```text
|
|
upstream_git_mapped_unverified
|
|
```
|
|
|
|
Absence Solscan ne signifie pas absence on-chain absolue, surtout si l'index UI ne couvre pas tout l'historique. Cela suffit cependant pour ne pas les promouvoir sans corpus local.
|
|
|
|
## Instruction audit inconnue
|
|
|
|
Le discriminator suivant a été observé localement :
|
|
|
|
```text
|
|
40f4bc78a7e9690a
|
|
```
|
|
|
|
Il produit actuellement `raydium_cpmm.instruction_audit` avec `tradeCandidate=false` / `candleCandidate=false`. Il n'est pas nommé dans la tranche `0.7.48`, faute de preuve upstream/corpus suffisante.
|
|
|
|
## Recherche Solscan retenue
|
|
|
|
La page programme Solscan et l'onglet Program IDL sont utiles pour accélérer la recherche :
|
|
|
|
```text
|
|
https://solscan.io/account/CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C#programIdl
|
|
```
|
|
|
|
Le filtre `instruction=<discriminator>` est documenté comme méthode pratique de découverte de signatures à backfiller localement, par exemple :
|
|
|
|
```text
|
|
https://solscan.io/account/CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C?instruction=f223c68952e1f2b6&instruction=b712469c946da122&hide_spam=true&hide_failed=true&show_related=false&sort=desc
|
|
```
|
|
|
|
Solscan reste une aide de recherche, pas une source de vérité métier.
|
|
|
|
## Table technique ajoutée
|
|
|
|
`k_sol_instruction_observations` est ajoutée comme table technique d'index local. Elle permet de retrouver les signatures observées par `decoder_code`, `instruction_name` et `discriminator_hex`, sans créer de nouvelle table métier.
|
|
|
|
Exemple :
|
|
|
|
```sql
|
|
SELECT
|
|
instruction_name,
|
|
discriminator_hex,
|
|
COUNT(*) AS observed_count,
|
|
COUNT(DISTINCT signature) AS tx_count
|
|
FROM k_sol_instruction_observations
|
|
WHERE decoder_code = 'raydium_cpmm'
|
|
GROUP BY instruction_name, discriminator_hex
|
|
ORDER BY observed_count DESC;
|
|
```
|
|
|
|
## Invariants validés
|
|
|
|
- `swap_event` ne produit aucun trade/candle.
|
|
- `deposit`, `withdraw`, `lp_change_event`, fees, admin/config et lifecycle gardent `trade_count=0`.
|
|
- Les transactions failed restent non matérialisées en trade/candle.
|
|
- Les side effects SPL Token / Token-2022 (`burn`, `transfer`, `transferChecked`, `closeAccount`) restent hors decoder métier CPMM direct et devront passer par une future table transversale si plusieurs DEX le justifient.
|
|
- Aucun program id n'est promu sans corpus local.
|
|
|
|
## État de clôture
|
|
|
|
`0.7.48 raydium_cpmm` est clôturable avec deux entrées connues mais non observées :
|
|
|
|
```text
|
|
close_permission_pda
|
|
update_pool_status
|
|
```
|
|
|
|
La prochaine tranche fonctionnelle est `0.7.49 raydium_clmm`.
|