पिछले अध्यायों में, हमने देखा कि प्रोटोकॉल सीधे price को स्टोर करने के बजाय price के square root (वर्गमूल) को स्टोर करता है। इसलिए, ticks को fixed-point Q64.96 फॉर्मेट में price के square root से जोड़ना आवश्यक है।
इस अध्याय में, हम sqrtPriceX96 और ticks के बीच convert (रूपांतरण) करने का तरीका जानेंगे।
प्रोटोकॉल tick indexes स्टोर करता है
एक tick एक discrete price है, जिसे फॉर्मूले द्वारा दिया जाता है, जहाँ को tick index या केवल tick कहा जाता है। Tick index होने पर, tick price को विशिष्ट रूप से निर्धारित करना संभव है, और इसके विपरीत भी। चूँकि tick indexes को स्टोर करने में को स्टोर करने की तुलना में कम बिट्स (bits) लगते हैं, इसलिए प्रोटोकॉल tick prices के बजाय tick indexes को स्टोर करता है।
इस पुस्तक में, हम tick (price) और tick index शब्दों का उपयोग एक-दूसरे के स्थान पर करेंगे। कोडबेस में, tick नामक वेरिएबल्स हमेशा tick index को संदर्भित करते हैं।
sqrtPriceX96 दिए जाने पर tick index की गणना करना
हम price के square root और sqrtPriceX96 वेरिएबल के बीच के संबंध को याद करते हुए शुरुआत करते हैं:
इस प्रकार, price और sqrtPriceX96 के बीच का संबंध दोनों पक्षों का square (वर्ग) करने से प्राप्त होता है।
चूँकि price और tick index के बीच का संबंध है, इसलिए हमारे पास है:
sqrtPriceX96 के संदर्भ में tick index निर्धारित करने के लिए, हम उपरोक्त समीकरण के दोनों पक्षों का logarithm (लघुगणक) लेते हैं।
एक logarithm हमेशा एक आधार (base) के संबंध में लिया जाता है। उदाहरण के लिए, यदि है, तो (log, base b में लिया गया है)। हालाँकि, उपरोक्त समीकरण में logarithm को किसी भी base में लिया जा सकता है। इसका कारण इस अध्याय के अंतिम भाग में समझाया गया है।
tick index एक discrete वैल्यू है
वास्तव में, उपरोक्त फॉर्मूला एक कारण से पूरी तरह से सही नहीं है: sqrtPriceX96 एक continuous वैल्यू है, जबकि tick index i discrete (एक integer) है। इसलिए, वैल्यू को round down (नीचे की ओर पूर्णांकित) करने की आवश्यकता है।
इसे नीचे दिए गए चित्रण (illustration) में देखा जा सकता है, जहाँ हम एक टूल का उपयोग करते हैं जिसे ticks पर हमारे लेख में पाया जा सकता है। ध्यान दें कि जहाँ price लगातार (continuously) बदलता है, वहीं उस price के लिए संबंधित tick हमेशा उसके ठीक नीचे वाला होता है।
इस प्रकार, tick के लिए सटीक फॉर्मूला है:
जहाँ प्रतीक का अर्थ round down करना है, उदाहरण के लिए, ।
tick index दिए जाने पर sqrtPriceX96 की गणना करना
tick index से price के square root की गणना करने के लिए, हम इस फॉर्मूले से शुरू करते हैं:
फिर, दोनों पक्षों का square root लें और से गुणा करें,
कोडबेस में ticks से price और इसके विपरीत (vice-versa)
Solidity में ticks और sqrtPriceX96 के बीच conversion को TickMath library द्वारा हैंडल किया जाता है, जिसका अध्ययन Solidity में log और square root को लागू करने की जटिलता के कारण एक अलग अध्याय में किया जाएगा।
इसमें दो functions हैं: getSqrtRatioAtTick और getTickAtSqrtRatio, जो sqrtPriceX96 और उसके संबंधित tick index के बीच conversion करते हैं, साथ ही इसके विपरीत कार्य भी करते हैं। इसे नीचे देखा जा सकता है।

हमने पिछले भाग में इन फॉर्मूलों का गणित देखा। इस भाग में, हम Python का उपयोग करके यह गणना करेंगे।
getSqrtRatioAtTick function
Python में getSqrtRatioAtTick function को इस प्रकार लिखा जा सकता है:
def getSqrtRatioAtTick(i):
return math.sqrt(1.0001 ** i) * 2**96
एक उदाहरण के रूप में, upper bound price के लिए sqrtPriceX96 की वैल्यू getSqrtRatioAtTick(887272) का उपयोग करके कैलकुलेट की जा सकती है, जिसके परिणामस्वरूप 1.4614467034780703e+48 आता है, जो (लगभग) TickMath लाइब्रेरी के MAX_SQRT_RATIO constant से मेल खाता है।

Decimal लाइब्रेरी का उपयोग करना
अधिक सटीक परिणाम प्राप्त करने के लिए, हम Python में Decimal लाइब्रेरी का उपयोग कर सकते हैं। इस लाइब्रेरी का उपयोग करके वही फॉर्मूला नीचे कोड किया गया है, साथ ही MAX_SQRT_RATIO के लिए कैलकुलेट की गई वैल्यू भी दी गई है।
import math
from decimal import Decimal, getcontext
getcontext().prec = 50
def getSqrtRatioAtTick(i):
base = Decimal("1.0001")
exponent = Decimal(i)
sqrt_value = base ** (exponent / 2)
multiplier = Decimal(2) ** 96
return sqrt_value * multiplier
print(int(getSqrtRatioAtTick(887272))) # 1461446703485210103244672773810124308346321380902
getTickAtSqrtRatio function
Python में getTickAtSqrtRatio function को इस प्रकार लिखा जा सकता है:
def getTickAtSqrtRatio(sqrtPriceX96):
return math.floor(2*math.log(sqrtPriceX96/2**96)/math.log(1.0001))
एक उदाहरण के रूप में, sqrtPriceX96 के lower bound 4295128739 से संबंधित tick की गणना getTickAtSqrtRatio(4295128739) का उपयोग करके की जा सकती है, जिसके परिणामस्वरूप -887272 वैल्यू आती है, जो ticks के lower bound के लिए अपेक्षित (expected) है।
getTickAtSqrtRatio(4295128739) // -887272
Logarithm के base को बदलना
जब हमने फॉर्मूला प्राप्त किया
तो हमने उल्लेख किया था कि logarithm किसी भी base में हो सकता है। Python में फॉर्मूले के इम्प्लीमेंटेशन में, हमने natural logarithm का उपयोग किया, लेकिन हम base 10 या किसी अन्य base में भी logarithm का उपयोग कर सकते हैं, जिससे समान परिणाम प्राप्त होगा।
इसका कारण logarithms का एक बुनियादी गुण (property) है जो विभिन्न bases में logarithms को संबंधित करता है,
जहाँ और दो अलग-अलग bases हैं, और उस logarithm का argument है जिसकी हम गणना करना चाहते हैं। उदाहरण के लिए, एक log को natural base से base 10 में convert करने पर, हमारे पास है:
ध्यान देने वाली बात यह है कि divisor (भाजक), , केवल bases पर निर्भर करता है, argument पर नहीं। मान लीजिए कि हमारे पास एक fraction (भिन्न) है:
यदि हम logarithms को किसी arbitrary (स्वैच्छिक) base b में convert करना चाहते हैं, तो हम numerator (अंश) और denominator (हर) दोनों को से विभाजित करते हैं। हालाँकि, किसी भिन्न के numerator और denominator दोनों को समान वैल्यू से विभाजित करने से अंतिम उत्तर पर कोई प्रभाव नहीं पड़ता है क्योंकि यह कट जाता है (cancels out)।
आइए इस संबंध को tick index के हमारे फॉर्मूले पर लागू करके और natural base से base 10 में convert करके इसे स्पष्ट करें:
जैसा कि हम देख सकते हैं, transformation factor कट जाता है और base कुछ भी होने के बावजूद गणना समान रहती है।
सारांश
- प्रोटोकॉल को
sqrtPriceX96और tick index के बीच convert करने की आवश्यकता होती है। यहgetSqrtRatioAtTickऔरgetTickAtSqrtRatiofunctions का उपयोग करके किया जाता है, जोTickMathलाइब्रेरी में स्थित हैं। sqrtPriceX96से tick index में convert करने के लिए, निम्नलिखित फॉर्मूले का उपयोग किया जाना चाहिए:
- tick index से sqrtPriceX96 में convert करने के लिए, निम्नलिखित फॉर्मूले का उपयोग किया जाना चाहिए:
अभ्यास प्रश्न
पूल एड्रेस खोजने के लिए Uniswap V3 Pools देखें, फिर एड्रेस को ब्लॉक एक्सप्लोरर में खोलें। पब्लिक वेरिएबल slot0 को खोजें और tick को price में और इसके विपरीत (vice versa) convert करें।

जाँचें कि आपकी गणना Uniswap द्वारा प्रदान की जाने वाली वैल्यू के करीब है या नहीं और फिर sqrtPriceX96 को डॉलर्स में convert करें।
निम्नलिखित पूल्स के लिए यह करें:
- USDC/ETH पर
- Base पर ETH/USDC
- mainnet पर WBTC/USDC
हम बाद में जानेंगे कि किसी कॉन्ट्रैक्ट के लिए slot0 से सीधे sqrtPriceX96 (जो हमें price दे सकता है) और tick डेटा को कंज्यूम (consume) करना सुरक्षित क्यों नहीं है, फिलहाल यह केवल अभ्यास के लिए है।