朋友们大家好!今天我们继续UniswapV3代码库中periphery中的NonfungibleTokenPositionDescriptor合约。
这是一个UniswapV3外围体系中负责为仓位NFT生成链上元数据和SVG图像的合约。

合约名字叫NonfungibleTokenPositionDescriptor,继承自INonfungibleTokenPositionDescriptor。
19到23行,硬编码了5个主流代币的主网地址,这些地址后续将应用在tokenRatioPriority函数中,在生成NFT图像时,用于决策哪个代币是基础代币,哪个代币是报价代币。

25行定义了一个immutable的地址叫WETH9,这个地址不可更改,只能在构造函数中初始化,主要用于判断代币是否是原生ETH的包装版本。
27行同样是一个immutable的变量叫nativeCurrencyLabelBytes,这是一个原生代币的标签。
通过构造函数传入,初始化以上两个变量。
函数nativeCurrencyLabel
函数名的意思是“原生代币标签”,主要作用是把27行定义的变量nativeCurrencyLabelBytes从bytes32转换为string类型。

定义了一个len用于记录字符串长度,37行的while循环用于通过逐个字符判断只要nativeCurrencyLabelBytes对应位置不为0且len小于32,长度len就+1。
获得nativeCurrencyLabelBytes字符长度之后,创建一个等长的数组b,逐字节复制nativeCurrencyLabelBytes的有效字符。
最后把数组b转化为string类型,并且返回。
函数tokenURI
这个函数主要用于生成NFT的URI。

函数的入参两个字段分别是positionManager和tokenId,INonfungiblePositionManager是一个接口,所以
positionManager是一个实现了对应接口的合约地址。出参返回一个字符串就是对应的URI。
54行通过传入的tokenId,调用position函数获得仓位的基础信息。

57行在获得池子的地址,使用的方式是通过工厂地址和池子的基础信息计算得出。
65行调用了flipRatio函数给两个token排序,用来决定是否需要翻转显示顺序。flipRatio函数下一个小节就会详细解释。
66和67行分别给quoteTokenAddress和baseTokenAddress赋值,主要基于flipRatio的值,如果flipRatio为0,就是不需要翻转,token1是quote,token0是base。反之就两种代币反过来。quote是引用的意思,base是基础的意思,baseToken就是以它为计价货币的代币,quoteToken就是用baseToken报价的代币。比如两个代币分别为USDC和ETH,代表用USDC计价ETH,多少个USDC可以买一个ETH。
68行,调用pool合约中的slot0,获取当前tick,用于在图片中标注当前的价格位置。

70到92行都是在做返回值,主要逻辑是把必要的参数打包进ConstructTokenURIParams,然后调用NFTDescriptor.constructTokenURI。
函数flipRatio
上文用到了flipRatio函数,这是一个给两个代币排序的函数,如果token0的优先级高于token1,就返回true,否则返回false。具体的逻辑实现在tokenRatioPriority函数中,详见下一小节。

函数tokenRatioPriority
这是一个为代币分配优先级的函数。

针对一系列代币返回了一串TokenRatioSortOrder下的枚举值,具体枚举值的含义可以在TokenRatioSortOrder.sol中找到。

这几个枚举值numerator是分子的意思,期望该代币在报价中做分子;denominator是分母的意思,期望该代币在报价中做分母;后缀有程度的修饰词,most优先级最高其次是more,没有后缀最小。
回到tokenRatioPriority函数中,给代币赋了值,然后调用flipRatio函数比大小。给稳定币的赋值最大,其中USDC>USDT>DAI。所以稳定币会优先填充quoteTokenAddress,作为计价单位。
总结
这是一个基于仓位和池子信息,生成对应NFT图片的函数,所有的内容都可以不依赖中心化服务,全部在链上完成。
朋友们下次再见!
夜雨聆风