# Curve Oralce

Curve Oracle是链上去中心化预言机的典型代表，也是Curve系统中的重要组件。它的报价依赖于Curve Pool。下面我们将针对性的分别介绍Curve v1、Curve v2、LLAMMA Oracle，它们几乎涵盖了所有的预言机应用案例。

Curve v1和v2池并不依赖外部价格预言机。LLAMMA在起初依赖于Chainlink Oracle数据作为参考值，如果 Chainlink 价格与内部预言机价格 (EMA) 偏差太大（+/-1.5%），它将使用 Chainlink 的来源。

{% hint style="info" %}
**Oracle 预言机存在的理由**

如果从一个比较酷的角度去解释，链上和链下分别是一个独立的世界，它们无法直接进行信息和价值的传递。那么如果链上想要获取链下数据就需要预言机。

这是通用型的预言机服务，当然由于链上的协议越来越多，许多协议之间也需要获取信息，这里也会存在链上各协议之间通过预言机调用数据的场景。
{% endhint %}

那么预言机都有哪几种？

1. **推送式预言机 (例如：Chainlink)**\
   \
   推送式预言机采用一个简单的机制，它们会在特定的时间间隔或在不同的偏离阈值下定期"推送"价格数据到链上。\
   Chainlink就是一个著名的推送式预言机的例子。在预定的时间间隔，或者如果某资产的价格自上次更新以来偏离超过0.5%，Chainlink就会将最新的市场价格数据"推送"到区块链上。\
   Chainlink使用一个去中心化的节点网络来收集数据并将数据馈送给智能合约。它基于声誉系统，只有白名单上的节点才能提供数据，这保证了数据的准确性和安全性，但也引发了关于去中心化的问题。\\

2. **低延迟/拉取式预言机 (例如：Pyth Network)**\
   \
   不同于“推送式”预言机主动将数据更新到链上，拉取式预言机则要求用户或者所谓的守护者（keepers）首先主动请求（或拉取）价格数据。当用户或者守护者得到这个价格后，他们会在执行某个交易的同时，将这个价格数据发送到去中心化应用（dAPP）。\
   这意味着这种类型的预言机几乎可以即时地更新数据。对于那些需要实时数据的DeFi产品，例如在高度波动的市场或对于特定的金融工具（如衍生品、保证金交易等），低延迟预言机是非常有用的。\\

3. **时间加权平均价格预言机 (例如：Uniswap v3)**\
   \
   TWAP，或者说时间加权平均价格，提供了一个资产价格在指定时期内的移动平均值。这并不是实时的价格，而是一段时间内价格的平均值。\
   因为TWAP考虑了一个长时间段内的价格，所以它能够确保市场价格与短期操纵或极端波动相比更为稳定和一致。比如应对传统的闪电贷操作价格攻击等。

### <mark style="color:purple;">**1 Curve V2 Oracle**</mark>

我们先从Curve v2池开始，因为它最具有代表性。Curve v2池由具有波动性价格的资产组成，该池不依赖外部预言机，而是根据池内的交易活动内部计算这些资产的价格。

<figure><img src="https://1519527010-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7UJxm1gCnqCpQPPfK1k7%2Fuploads%2F6wWpTadkNQswEFxHuGZR%2Fimage.png?alt=media&#x26;token=a6ce62f3-30ed-461c-a19a-aade6be78abb" alt=""><figcaption></figcaption></figure>

它由两个参数决定：

**价格预言机 (Price Oracle):**

* 定义：这是池对资产价格的预期或估计。它代表了基于池内最近的交易活动，该资产的“公允”或“合理”价格应该是多少。
* 计算方式：价格预言机是近期交易价格的指数移动平均值EMA (Exponential Moving Average)。这意味着最近的交易数据在计算中会得到更高的权重，而较早之前的交易数据则会逐渐衰减其影响。
* 功能：价格预言机允许池在没有外部干预或依赖外部数据源的情况下，内部评估资产的当前价值。这为DeFi应用提供了一个更加安全和自给自足的价格追踪机制。

{% hint style="info" %}
EMA与常用于技术分析的SMA“简单移动平均值”不同，指数移动平均重视近期的数据并对其赋予更大的权重。这意味着它可以更快地对近期的趋势作出反应。
{% endhint %}

<figure><img src="https://1519527010-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7UJxm1gCnqCpQPPfK1k7%2Fuploads%2F1zNaWpMNDsXKnNY9spIc%2Fimage.png?alt=media&#x26;token=98cbb7f4-bab8-4dbd-9de0-9314078266f2" alt=""><figcaption></figcaption></figure>

**价格刻度 (Price Scale):**

* 定义：这反映了池中流动性的实际分布和当前状态，即资产的实际“市场”价格。
* 计算方式：价格刻度是一个根据池的实际流动性集中度计算出来的快照。简单来说，它是基于当前池中各种资产的供需关系来计算的。
* 功能：价格刻度提供了一个即时的、基于当前流动性情况的资产价格。当用户在池中交易时，池会根据这个价格刻度和价格预言机来确定如何有利地重新调整流动性。价格刻度总是尝试向价格预言机的估值移动，但由于实际的买卖操作，它可能会落后于价格预言机的估值。

### **2 Curve V1 Oracle**

Curve v1是基于稳定币或相同类型资产的交易对所构建的流动性池。例如：USDC-USDT-DAI，ETH-stETH。目前有两个版本：

* 旧版本的v1池不具备预言机功能
* 新版本的v1池有预言机功能 (price\_oracle)，但没有价格刻度 (price\_scale)

Curve v1的新版本池使用的仍然是近期价格的移动平均值。这意味着它可以防止用户因剧烈波动而承受损失，同时为外部协议提供信息。

### **3 LLAMMA**

LLAMMA 代表 Lending-Liquidating AMM Algorithm，顾名思义，是一种与借贷和清算相关的 AMM 算法。Curve主要使用该算法来清算抵押品。

AMM代表的是基于LLAMMA算法的Swap Pool，我们暂且称之为LLAMMA Pool。用户可以将抵押品存入 LLAMMA 池并铸造稳定币。我们可以把它跟正常的流动性池一样，但LLAMMA 池中的资产是抵押品和 Curve 稳定币 (crvUSD)。

LLAMMA Pool最显着的特点是，当抵押品价格跌破特定价格时，池中的抵押品将逐渐变成crvUSD。相反，当价格高于特定价格时，crvUSD 将逐渐转变为抵押品(下图以ETH抵押品为例)。

<figure><img src="https://1519527010-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7UJxm1gCnqCpQPPfK1k7%2Fuploads%2FYUmEVmuxlP3KvDwXTKjc%2Fimage.png?alt=media&#x26;token=181bf3f6-3edc-4bfb-a70a-54e841e65021" alt=""><figcaption></figcaption></figure>

在LLAMMA中，还有一个重要的角色，就是Oracle Price。预言机价格是指外部抵押品价格（可以认为是当前市场价格）。LLAMMA 设计了预言机价格角色，以实现抵押品以特定价格进行 ETH <--> crvUSD 转换的行为。

* 当ETH价格高于 P\_UP（黄色范围）时，该范围内的所有资产将转换为ETH。
* 当ETH价格低于 P\_DOWN（绿色范围）时，该区间内的所有资产将转换为crvUSD。
* 当价格在 P\_UP 和 P\_DOWN 之间（白色范围）时，资产将处于部分 ETH 部分 crvUSD 状态，其中 ETH 和 crvUSD 的比例由价格变化决定。

<figure><img src="https://1519527010-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7UJxm1gCnqCpQPPfK1k7%2Fuploads%2Ff1qE3NGvDPFarTV5YlTs%2Fimage.png?alt=media&#x26;token=bd4ef9eb-da53-4a0a-9f45-deb96eaee6e4" alt=""><figcaption></figcaption></figure>

在这里LLAMMA对预言机价格同样应用了指数移动平均线EMA，以防止用户因剧烈波动而承受损失。

简单来说我们可以把LLAMMA池看做一种特殊的AMM流动性池，在最开始的设计中，对于抵押品的定价，LLAMMA选择了外部预言机 Chainlink 的数据源作为参考价格，如果 Chainlink 价格与内部预言机价格 (EMA) 偏差太大（+/-1.5%），它将使用 Chainlink 的来源。

[而在最近2023年8月19号的一项提案中，正在废除Chainlink的预言机数据依赖。](https://gov.curve.fi/t/disable-chainlink-limits-for-price-oracles-in-crvusd/9527?ref=cmdefi.ghost.io)原因也非常简单，我们可以看到在图中michwill打出了在抵押品价格出现剧烈波动时，Chainlink提供的实际上是一种实时的现货价格，而EMA后的价格更加平缓。

对于LLAMMA来说，引入外部预言机的目的本质上是为了增加多方数据源，提升安全性防止被操纵，在这一点上Chainlink的采用是没有问题的。但是按照最初的设计在价格剧烈波动时采用Chainlink的价格进行矫正，在这种情况下让EMA变得暂时失去作用，同时将产生更大的套利空间。所以kill Chainlink在协议层面避免了一些不必要损失。

<figure><img src="https://1519527010-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7UJxm1gCnqCpQPPfK1k7%2Fuploads%2F81gyV0ZZckrAqSiy9OpC%2Fimage.png?alt=media&#x26;token=b594644f-b1ed-45c0-8c28-1e59408ac78b" alt=""><figcaption></figcaption></figure>

从安全性上考虑，引入更多的预言机价格数据源是更有利的，长期来看如果考虑到现货价格和EMA的差异问题，应当在更底层做出优化，比如获取外部预言机的数据后再进行类似EMA的处理。这样既保证了多个预言机数据来源同时也保护协议免受不必要损失。

我在twitter上提到了这个[建议](https://twitter.com/CurveFinance/status/1693652675164864947?ref=cmdefi.ghost.io)，Curve的回复是这种处理目前在技术层面实现起来有一定困难。如果长时间没有活跃交易可能使AMM停止。

<figure><img src="https://1519527010-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7UJxm1gCnqCpQPPfK1k7%2Fuploads%2FmLjfptDyp8KIis7nTU1n%2Fimage.png?alt=media&#x26;token=52b7a224-f1b2-4bfd-9df2-298abd5a8a5b" alt=""><figcaption></figcaption></figure>

### 4 价格操纵

对于预言机来说，最可怕的就是被操纵的风险。历史上许多黑客攻击的案例都与预言机报价被操纵有关。对Curve来说，对价格操纵的防御有以下几点：

1. Curve的价格预言机变量每个区块只更新一次。(防御闪电贷在单个区块内的恶意交易攻击)
2. 由于 `price_oracle` 的变化受到指数移动平均值EMA的抑制，使用EMA来计算价格意味着任何突然的、异常的价格波动都会被平滑处理，从而进一步防范操纵。所以尝试操纵价格可能会成功，但要付出巨大成本，需要在多个区块上进行持续的攻击。

下面是一组数据模拟，在市场快速波动情况下，实际$CVX价格与快速波动期间的CVX-ETH Pool的 `price_oracle price_scale`

<figure><img src="https://1519527010-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7UJxm1gCnqCpQPPfK1k7%2Fuploads%2FlF2seIZLD73x77vKX9zJ%2Fimage.png?alt=media&#x26;token=fe75e4d1-ad56-4906-9125-98b746c2d61e" alt=""><figcaption></figcaption></figure>

需要注意的是，尽管有这些防御措施，在一些流动性较低的池，意味着操纵价格的成本在降低，外部用户仍有可能操纵价格。

使用链上预言机时，最安全的方法是比较多个预言机的数据来源，并在任何一个表现异常时做出应急处理或撤回交易。这是一个风险管理策略，旨在确保获得的价格数据是准确和可靠的。

***

更新<sub>2023.08.22</sub>
