我正在开发一个anchor/solana程序,该程序为包括saber.so和invariant.app在内的多个池提供流动性。在交换过程中,我需要计算TVL,以便以公平的汇率提供代币。
我的问题是:计算链上TVL的最佳方法是什么?
以下是我心目中的一些方法,每种方法都有其缺点:
(1( 计算链外,并将其作为预言机提供:
我们可以计算出链下的TVL,然后将这个TVL作为预言家提供。缺点是:solana上的chainlink(一个oracle提供程序(似乎不支持自定义数据源,以太坊就是这样。这个解决方案进一步提高了应用程序的集中度,如果能把它挂在链上就好了。此外,还可能存在消耗协议储备的oracle攻击。
(2( 拥有流动性头寸的庞大列表:
另一种方法是跟踪我们作为协议提供流动性的所有流动性头寸。尽管这是可能的,但我相信这将(非常快(达到索拉纳的账户限额。
在这种情况下,我们将有一个巨大的";状态-";帐户,它跟踪每个池的以下变量:
- token1_mint:Pubkey
- token2_mint:公钥
- token1_amount:u64
- token2_amount:u64
- token1_to_current_pyth_feed_address:公钥
- token2_to_current_pyth_feed_address:公钥
- 提供程序:u8
假设我们有4*32+2*64字节+8字节=264字节,我们可以有大约20个池,我们可以在任何给定的时间点存款(因为solana的4KB帐户限制(
第二种选择似乎是可行的,因为第一种是链外的,容易受到预言机攻击。然而,第二种选择似乎仍然有点棘手,因为每当我打算计算总TVL时,我都必须包括这个数据结构。
你有没有其他合适的设计想法出现在你的脑海中或你已经看到了?
我对程序的总体设计不太了解,无法为您提供一个好的解决方案。我也不知道不变量是什么,也许这打破了我下面要描述的内容。
我假设你的程序中有一些指示,cpi调用Saber等并打开流动性头寸。假设该指令在链上创建了一个包含以下信息的帐户:
pool_address,
token_1_mint_address
token_2_mint_address
amount_token_1
amount_token_2
...
一个简单的解决方案是循环浏览所有这些账户,因为你有每个代币的数量和铸币局,所以你可以使用pyth价格预言器之类的东西来计算价值。不过我不会在连锁店里做这件事,因为它很快就会变得很贵!也许最好在客户端进行,并将这些信息写回链中。最近的solana训练营视频实际上有一个将链下信息带回链的教程!https://www.youtube.com/watch?v=GwhRWde3Ckw&t=385s
下面是链上程序运行时限制的演示,如果你使用一些索引和PDA来找到账户地址,并假设你的流动性头寸数量有限,也许你可以在池账户中循环使用!然而,我不会将所有信息硬编码到一个帐户中,这似乎是一种不可持续的方法,可能会导致很多问题。可能会给你带来卓越的表现,但不确定。
https://www.youtube.com/watch?v=5IrfSecDPeA&t=1191s
无论如何GL!