Langsung ke konten utama

Documentation Index

Fetch the complete documentation index at: https://docs.raydium.io/llms.txt

Use this file to discover all available pages before exploring further.

Halaman ini diterjemahkan secara otomatis oleh AI. Versi bahasa Inggris adalah acuan resmi.Lihat versi bahasa Inggris →

Mengapa ticks ada

Likuiditas CLMM terkonsentrasi ke dalam rentang harga. Untuk membuat rentang dapat dikelola di chain, harga dikuantisasi menjadi integer ticks, di mana setiap tick adalah kelipatan konstan dari yang sebelumnya: price(i)=1.0001i\text{price}(i) = 1.0001^{\,i} Satu tick sesuai dengan pergerakan harga 0,01%, atau ~1 basis point. Pemetaannya adalah:
Indeks tick iPengali harga
01.0000
1001.0100 (≈ +1.00%)
-1000.9900 (≈ −0.99%)
100002.7181 (≈ e)
MAX_TICK = 4436361.84e19
MIN_TICK = -4436365.42e-20
MIN_TICK dan MAX_TICK dipilih sehingga sqrt_price_x64 pas dalam u128 di kedua ujung. Setiap pool menegakkan bahwa tick_lower >= MIN_TICK dan tick_upper <= MAX_TICK. Dalam praktik, UI web membatasi rentang ke sesuatu yang jauh lebih sempit untuk mencegah pengguna mengunci likuiditas ke ticks yang tidak dapat dijangkau.

Spasi tick

AmmConfig pool menetapkan tick spacing — satu-satunya ticks yang diizinkan posisi untuk digunakan sebagai endpoint. Jika tick_spacing = 60, hanya ticks …, −120, −60, 0, 60, 120, … yang valid. Upaya untuk membuka posisi dengan endpoint 31 akan membatalkan dengan InvalidTickIndex. Spasi yang dipublikasikan secara umum:
Tingkat biayatrade_fee_rateSpasi tickLangkah harga paling kasar per posisi tick
0.01%10010.01%
0.05%500100.10%
0.25%2500600.60%
1.00%100001201.21%
Semakin besar spasi, semakin sedikit tick arrays yang perlu diinisialisasi, semakin murah membuka posisi yang luas, dan semakin kabur batas harganya. Pasangan volatil biasanya berada di tier spasi 120; stables berada di tier spasi 1.

Tick arrays

Pool tidak menyimpan state per-tick dalam akun terpisah. Sebaliknya, TICK_ARRAY_SIZE ticks yang berdekatan (60 dalam CLMM Raydium saat ini) dikemas ke dalam satu TickArrayState. Array pertama tick adalah start_tick_index-nya, dan itu mencakup tepat TICK_ARRAY_SIZE * tick_spacing unit integer-tick. Untuk tick_spacing = 60 dan TICK_ARRAY_SIZE = 60:
  • Setiap tick array mencakup 60 × 60 = 3600 integer ticks.
  • start_tick_index adalah kelipatan dari 3600: …, -7200, -3600, 0, 3600, 7200, ….
Endpoint posisi t = 2040 pada tick_spacing = 60 berada di tick array dengan start_tick_index = 0. Endpoint posisi t = 4200 berada di array dengan start_tick_index = 3600.

Ketika array diinisialisasi

Tick array adalah lazy: posisi pertama yang merujuk ke tick apa pun di dalamnya menginisialisasi array, membayar rent. Swap tidak menginisialisasi tick arrays — mereka melewati array yang belum diinisialisasi menggunakan bitmap. Alur open-position SDK memeriksa rentang yang dipilih, menghitung daftar tick arrays yang disentuhnya, dan menambahkan instruksi init_tick_array dalam transaksi yang sama dengan OpenPosition jika ada yang hilang.

Tick arrays tidak ditutup

Setelah tick array telah diinisialisasi, itu persisten untuk seumur hidup pool. Program tidak mengekspos path untuk menutup tick array, bahkan setelah initialized_tick_count kembali ke nol. Tidak ada pemulihan rent untuk tick arrays; rent yang dibayar oleh posisi pertama yang menyentuh array dikunci ke akun tersebut secara permanen. Ini adalah trade-off yang disengaja: menggunakan kembali tick array yang ada adalah gratis untuk setiap posisi berikutnya, jadi pool yang banyak diperdagangkan hanya membayar biaya rent sekali per slot (pool, start_tick_index) terlepas dari pergantian.

Bitmap

Menemukan “tick yang diinisialisasi berikutnya ke kiri/kanan dari tick saat ini” harus cepat — swap dapat melintasi banyak ticks. Pool menyimpan bitmap 1-bit-per-tick-array inline dalam PoolState untuk rentang ±1.024 arrays di sekitar tick 0. Di luar rentang tersebut (posisi full-range, setup eksotis), TickArrayBitmapExtension menyediakan overflow. Swap berjalan di bitmap: lowest_set_bit_above(tick_current_array_index) memberikan array berikutnya dengan tick yang diinisialisasi di sisi yang sedang dilintasi swap. Dalam array tersebut, bit-scan serupa menemukan tick yang diinisialisasi berikutnya.

liquidity_gross dan liquidity_net

Setiap tick yang diinisialisasi menyimpan dua nilai likuiditas:
  • liquidity_gross — jumlah L di semua posisi yang merujuk ke tick ini sebagai endpoint. Ketika liquidity_gross mencapai nol, tick menjadi belum diinisialisasi dan dapat dihapus dari bitmap.
  • liquidity_net — perubahan bertanda ke level-pool liquidity ketika harga melintasi tick ini bergerak ke atas (kiri-ke-kanan dalam ruang tick). Jika tick ini adalah batas bawah posisi dengan ukuran L, itu berkontribusi +L; jika itu adalah batas atas posisi tersebut, itu berkontribusi −L.
Contoh kerja: dua posisi di pool yang sama.
  • Posisi A: tick_lower = -120, tick_upper = 0, likuiditas L_A = 100.
  • Posisi B: tick_lower = -60, tick_upper = 60, likuiditas L_B = 50.
State tick-by-tick:
TickDisentuh olehliquidity_grossliquidity_net
-120A lower100+100
-60B lower50+50
0A upper100−100
60B upper50−50
Level-pool liquidity untuk nilai tick_current yang berbeda:
  • tick_current = -180: liquidity = 0 (sebelum posisi apa pun)
  • tick_current = -90: liquidity = 100 (hanya di dalam A)
  • tick_current = -30: liquidity = 150 (di dalam A dan B)
  • tick_current = 30: liquidity = 50 (hanya di dalam B)
  • tick_current = 90: liquidity = 0 (melewati keduanya)
Pada setiap tick cross selama swap, program menambahkan liquidity_net (mungkin negatif) ke PoolState.liquidity. Ini adalah mekanisme Uniswap-v3 yang tepat.

Posisi sebagai NFTs

Posisi CLMM Raydium adalah NFT. Membuka posisi mencetak mint baru dengan supply 1 ke dalam dompet pemanggil, dan otoritas mint adalah program CLMM. Program menghubungkan kepemilikan posisi ke siapa pun yang memegang saldo dalam ATA mint tersebut pada waktu CPI. Konsekuensi:
  • Posisi dapat ditransfer. Dompet dapat menjual atau airdrop posisi dengan mentransfer NFT. Pemegang baru kemudian dapat memanggil CollectRewards, IncreaseLiquidity, dll.
  • Posisi dapat dialamatkan di luar CLMM. Marketplace dan dompet menampilkan posisi seperti NFT lainnya. SDK menetapkan name/symbol yang masuk akal pada metadata mint.
  • PDA posisi diturunkan dari mint NFT. Anda dapat menemukan PersonalPositionState tanpa mengetahui siapa yang saat ini menahannya.

Posisi Token-2022

Pool CLMM yang lebih baru dapat mencetak posisi di bawah Token-2022 bukan SPL Token klasik. Program mengekspos dua instruksi open paralel — OpenPosition dan OpenPositionWithToken22Nft — dengan semantik identik di luar program token mana yang memiliki mint NFT. Kompatibilitas dompet dan marketplace berbeda; UI Raydium melacak keduanya.

Aturan rentang yang diizinkan

Pada waktu OpenPosition program menegakkan:
  1. tick_lower < tick_upper.
  2. tick_lower % tick_spacing == 0 dan tick_upper % tick_spacing == 0.
  3. MIN_TICK <= tick_lower dan tick_upper <= MAX_TICK.
  4. Pemanggil telah memasok tick arrays yang berisi tick_lower dan tick_upper — baik sudah diinisialisasi atau melalui init_tick_array dalam transaksi yang sama.
  5. Akun bitmap extension, jika posisi ini meluas ke dalam rentang extension.
Jika pemeriksaan apa pun gagal, instruksi membatalkan dengan InvalidTickIndex, NotApproved, atau InsufficientLiquidity tergantung pada kendala mana. Lihat reference/error-codes.

”In-range” vs “out-of-range”

Posisi adalah in range ketika tick_lower <= tick_current < tick_upper. Hanya posisi in-range yang berkontribusi pada PoolState.liquidity dan karena itu hanya mereka yang mendapatkan biaya swap. Posisi out-of-range:
  • Memegang 100% dari satu token (yang rentangnya telah dilalui). Secara spesifik, jika tick_current < tick_lower, posisi hanya memegang token1 (sudah “dijual” oleh harga yang bergerak menjauh); jika tick_current >= tick_upper, itu hanya memegang token0.
  • Tidak mendapatkan biaya swap.
  • Lanjutkan mengakrual rewards jika aliran reward pool memancarkan ke likuiditas out-of-range — tetapi perilaku default Raydium adalah “emit hanya ke in-range”, mencocokkan konvensi Uniswap v3. Lihat products/clmm/fees.
LP yang mengelola posisi CLMM menghabiskan sebagian besar perhatian mereka untuk menjaga posisi tetap in range saat harga bergerak.

Jebakan integrasi umum

  • Endpoint tidak sesuai spasi. Kode yang menghitung tick dari target harga harus snap ke kelipatan tick_spacing sebelum melewatinya ke OpenPosition. Helper SDK (TickUtils.getTickWithPriceAndTickspacing) melakukan ini; matematika home-grown sering kali tidak.
  • Tick arrays yang hilang. Membuka posisi yang luas mungkin memerlukan inisialisasi beberapa tick arrays; lupa melewati mereka sebagai akun writable membatalkan. openPositionFromBase SDK mengembalikan daftar untuk Anda.
  • Tick basi setelah swap. tick_current dapat melintasi banyak ticks dalam satu swap. Jika UX Anda menampilkan “current tick” dari satu panggilan RPC dan kemudian membuka posisi di panggilan yang lebih baru, posisi relatif vs harga live bisa mati puluhan ticks. Re-fetch tepat sebelum menandatangani.
  • Posisi NFTs dengan metadata tambahan. Jika Anda membangun dompet yang mengenali posisi Raydium, deteksi mereka oleh otoritas mint mereka (= PDA program CLMM), bukan oleh bidang metadata hardcode.

Kemana selanjutnya

  • Math — step-through swap dan derivasi fee-growth yang batas tick berpartisipasi.
  • Accounts — tata letak TickArrayState dan PositionState.
  • Biaya dan rewards — bagaimana in-range-ness gerbang akrual biaya.
  • algorithms/clmm-math — derivasi bersama dari rumus concentrated-liquidity.
Sumber: