0

我正在开发一个锚/solana 程序,该程序为多个池提供流动性,包括 saber.so 和 invariant.app。在交换期间,我需要计算 TVL,以公平的汇率提供代币。

我的问题是:计算链上 TVL 的最佳方法是什么?

以下是我想到的一些方法,每种方法都有其缺点:

(1) 计算链下计算,并将其作为预言机提供:

我们可以在链下计算 TVL,然后将该 TVL 作为预言机提供。缺点是:solana 上的 chainlink(一个预言机提供者)似乎不支持自定义数据馈送,就像以太坊一样。此外,该解决方案增加了应用程序的集中化,将它放在链上会很好。也可能存在耗尽协议储备的预言机攻击。

(2) 拥有大量流动性头寸:

另一种方法是跟踪我们作为协议提供流动性的所有流动性头寸。尽管这是可能的,但我相信这会(很快)达到 solana 的账户限制。

在这种情况下,我们将有一个巨大的“状态”帐户,它跟踪每个池的以下变量:

  • token1_mint:公钥
  • token2_mint:公钥
  • token1_amount: u64
  • token2_amount: u64
  • token1_to_currency_pyth_feed_address:公钥
  • token2_to_currency_pyth_feed_address:公钥
  • 提供者:u8

鉴于我们有 4 * 32 + 2 * 64 字节 + 8 字节 = 264 字节,我们可以在任何给定时间点拥有大约 20 个可以存入的池(因为 solana 的帐户限制为 4KB)

第二种选择似乎是要走的路,第一种选择是脱链并且容易受到预言机攻击。然而,第二个选项似乎仍然有点 hacky,因为我必须在任何时候包含这个数据结构来计算总 TVL。

是否有任何其他的设计理念浮现在您的脑海或您已经看到,这将是合适的?

4

1 回答 1

2

我对你的程序的整体设计了解不多,为你提供一个好的解决方案。我也不知道什么是不变量,也许这打破了我将在下面描述的内容。

我假设你的程序中有一些指令,cpi 调用 Sabre 等并打开流动性头寸。假设该指令在链上创建了一个包含以下信息的帐户:

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!

于 2022-01-23T15:33:04.617 回答