# Grant Application: Manipulation-Resilient Price Oracle for CoW AMM LP Tokens

**URL:** <https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670>\
**Category:** Funded Grants\
**Tags:** complete, grant-funded\
**Created:** [December 4, 2024, 3:26pm UTC](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670 "2024-12-04T15:26:24Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![lumoswiz](https://avatars.discourse-cdn.com/v4/letter/l/85f322/32.png) [@lumoswiz](https://forum.cow.fi/u/lumoswiz)\
**Post date:** [December 4, 2024, 3:26pm UTC](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670/1 "2024-12-04T15:26:24Z")

</div>

# Grant Title

Manipulation-Resilient Price Oracle for CoW AMM LP Tokens

# Author

The implementation of this project will be carried out by:  
[@bh2smith](https://github.com/bh2smith) & [@lumoswiz](https://github.com/lumoswiz)

# About the authors

- bh2smith is an experienced blockchain engineer and former contributor to CoW Protocol.

- lumoswiz is a smart contract developer with experience working with DeFi protocols, including lending and p2p lending protocols.

# Grant Category

Integrations and protocol order flow

# Grant Description

In response to this [RFG](https://forum.cow.fi/t/rfg-development-of-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2646), we aim to develop the manipulation-resistant price oracle for CoW AMM LP tokens. This will require incorporating the following ideas:

- Computing the rebalancing trade that a zero-fee constant function AMM would accept based on its current balance and external price feeds. This will require utilisation of the [CoW helper contract](https://github.com/balancer/cow-amm/blob/main/src/contracts/BCoWHelper.sol) and Chainlink price feeds for the underlying tokens.
- The effect on the price of LP tokens is counteracted since their price is a function of the simulated pool state post-rebalancing.

# Grant Goals and Impact

The use of AMM LP tokens as collateral is a challenge due to their susceptibility to manipulation within price oracles.

The objective of this work is to produce an oracle for LP tokens that guards against an attacker’s ability to capitalise from short-term under-reporting of value or short-term over-reporting of value.

The use of an oracle that guards against these attacks should boost the adoption of LP tokens as collateral in some lending markets.

To demonstrate real-world application, we will create a proof-of-concept integration with Aave V3, showcasing how LP tokens can be used as collateral while utilising our oracle solution.

# Milestones

## Milestone 1

This milestone has three deliverables, including:

- A smart contract implementing the oracle. The oracle must:

- Comprehensive test suite demonstrating the oracle’s manipulation resistance.

- Documentation detailing the oracle’s functionality. The documentation will be supplied in markdown format within the project’s Github repository.

## Milestone 2

An integration example with Aave V3 will be provided where

- LP tokens can be used as collateral.

- The oracle source for these tokens will point to the oracle developed herein.

This will involve:

- Setting up an Anvil mainnet fork.
- Setup scripts to initialise and configure the LP tokens as a reserve.
- Demonstration of user actions against this state, such as supplying LP tokens as collateral.
- Demonstration of oracle resilience to manipulation.

# Timeline

- Milestone 1 aim to ship before 1/1/2025.
- Milestone 2 aim to ship before 15/1/2025.

# Funding Request

Funding request summary:

- 6000 xDAI for milestone 1.
- 1000 xDAI for milestone 2.

# Gnosis Chain Address (to receive the grant)

0x62780bac6b361C703148B7fdeCDE44987C5C69D0

# Referral

[@fleupold](https://forum.cow.fi/u/fleupold/summary)

# Other Information

Foundry will be utilised.

# Terms and Conditions

By submitting this grant application, I acknowledge and agree to be bound by the CoW DAO Participation Agreement and the CoW Grant Terms and Conditions.

---

<div class="post-metadata">

**Author:** ![middleway.eth](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.cow.fi/middleway.eth/32/12_2.png) [@middleway.eth](https://forum.cow.fi/u/middleway.eth)\
**Post date:** [December 5, 2024, 10:18am UTC](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670/2 "2024-12-05T10:18:37Z")

</div>

Having a robust oracle for CoW AMM LP tokens will enable using them as collateral in lending protocols, which can unlock further use cases.  
Signalling my support

---

<div class="post-metadata">

**Author:** ![mfw78](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.cow.fi/mfw78/32/1598_2.png) [@mfw78](https://forum.cow.fi/u/mfw78)\
**Post date:** [December 9, 2024, 4:25pm UTC](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670/3 "2024-12-09T16:25:19Z")

</div>

Hi, thanks for the inclusion of Foundry in the specification of the grant. Tooling and language selection is a large factor when it comes to burden that may be absorbed by the core team if there is some need to provide out-of-grant changes / support later on, significantly easing maintenance.

I signal my support as well for this grant, and think it would be fine to move this to snapshot.

---

<div class="post-metadata">

**Author:** ![netrunner.eth](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.cow.fi/netrunner.eth/32/252_2.png) [@netrunner.eth](https://forum.cow.fi/u/netrunner.eth)\
**Post date:** [December 10, 2024, 5:31am UTC](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670/4 "2024-12-10T05:31:44Z")

</div>

Very interesting proposal. I look forward to seeing this PoC in the real world. Lets get this to snapshot

---

<div class="post-metadata">

**Author:** ![bh2smith](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.cow.fi/bh2smith/32/1242_2.png) [@bh2smith](https://forum.cow.fi/u/bh2smith)\
**Post date:** [December 10, 2024, 12:13pm UTC](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670/5 "2024-12-10T12:13:19Z")

</div>

This proposal has been moved to snapshot:

[https://snapshot.box/#/s:cowgrants.eth/proposal/0x9d729b4ab92b19a78a234aa25bbba019146f00278746c28569ec86563c42ddba](https://snapshot.box/#/s:cowgrants.eth/proposal/0x9d729b4ab92b19a78a234aa25bbba019146f00278746c28569ec86563c42ddba)

cc @middleway.eth, @mfw78 and @netrunner.eth

---

<div class="post-metadata">

**Author:** ![bh2smith](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.cow.fi/bh2smith/32/1242_2.png) [@bh2smith](https://forum.cow.fi/u/bh2smith)\
**Post date:** [December 11, 2024, 9:20pm UTC](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670/6 "2024-12-11T21:20:15Z")

</div>

Votes are in, development will take place here:

> **[GitHub - lumoswiz/cow-amm-lp-oracle](https://github.com/lumoswiz/cow-amm-lp-oracle)**
>
> Contribute to lumoswiz/cow-amm-lp-oracle development by creating an account on GitHub.

---

<div class="post-metadata">

**Author:** ![mfw78](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.cow.fi/mfw78/32/1598_2.png) [@mfw78](https://forum.cow.fi/u/mfw78)\
**Post date:** [December 12, 2024, 4:33am UTC](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670/7 "2024-12-12T04:33:58Z")

</div>

Just as a heads up, votes can be changed on snapshot before the closing of the poll. Not that I think this will be an issue, just an FYI for your own risk mitigation 😁

---

<div class="post-metadata">

**Author:** ![bh2smith](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.cow.fi/bh2smith/32/1242_2.png) [@bh2smith](https://forum.cow.fi/u/bh2smith)\
**Post date:** [December 17, 2024, 4:43pm UTC](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670/8 "2024-12-17T16:43:04Z")

</div>

Update:

Development is well under way. We have established what we believe to be a complete and solid first draft of the `LPOracle` contract as well as an `OracleFactory` (for convenience).

Unit tests are in place and we have begun setting up fork tests.

A couple of points we would like to highlight for discussion/confirmation are:

- [Implementation Decisions](https://github.com/lumoswiz/cow-amm-lp-oracle/wiki/Implementation-Decisions-Log) (there are 3 debatable decisions made).
- [Potential Issue](https://github.com/lumoswiz/cow-amm-lp-oracle/wiki/Potential-Issues) with Large Initial Pool Imbalances

cc @fleupold, @mfw78 , @fedgiac

---

<div class="post-metadata">

**Author:** ![fedgiac](https://avatars.discourse-cdn.com/v4/letter/f/b19c9b/32.png) [@fedgiac](https://forum.cow.fi/u/fedgiac)\
**Post date:** [December 18, 2024, 4:22pm UTC](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670/9 "2024-12-18T16:22:01Z")

</div>

I like how the discussion items are presented, they are all reasonable technical questions.  
An overall point is that we should start with “well-known” tokens and extend the oracle use to less reliable tokens at a later stage.

- **Token Decimals stored immutably as gas savings.** I see that the gas impact can be significant, for example a call to `decimals()` on USDC, somewhat of a worst case, is about ~10k gas. I’ve never seen a token that can change decimals in the wild. So overall it sounds reasonable to have them immutable. Still, it would be good if it were possible to deploy a new oracle for the same two tokens in the case that the decimals change. Then, the occasional meme coin that could change decimals once in a while can still be supported, provided that the new oracle is used.

- **Underlying Pool Assets must have ≤18 decimals.** I read it’s possible but what I don’t see mentioned is the cost of supporting tokens with \>18 decimals, I suppose it’s significant extra smart-contract risk and complexity. I’ve seen a few tokens with 21 decimals, but they are exceedingly rare and it should be ok to not implement support for them at this point if too costly.

- **Cannot rebalance pool reliably.** That’s indeed concerning and I suppose it’s a consequence of the fact that the helper contract isn’t really the right tool here (it’s more or less a mistake that the grant singles out the helper so much, it should focus more on the rebalancing act). Reverting when the imbalance is large would be a fairly big limitation for an oracle, especially at times of high volatility, which is when the oracle is the most critical. A better solution would be to use the oracle code itself to compute the rebalanced price, which shouldn’t add too much complexity. This would also make the overall gas cost smaller.

- **Choice of oracle’s updatedAt.** Overall, it feels wrong to hijack the oracle semantics to include extra data. I see it’s not clear what `updatedAt` should be, technically we’re updating the prices once the _most recently updated_ oracle has been updated, but the _least recently updated_ oracle is a better indication for price trustworthiness, which is usually the point of oracle timestamps. However, the latter might be an issue if for example some oracles rely on `updatedAt` for refreshing some price cache with a price update by backtracking to an earlier block and simulating the transaction at this point.  
A possible idea to have all data included in the oracle and being semantically consistent could be the following:

---

<div class="post-metadata">

**Author:** ![lumoswiz](https://avatars.discourse-cdn.com/v4/letter/l/85f322/32.png) [@lumoswiz](https://forum.cow.fi/u/lumoswiz)\
**Post date:** [December 18, 2024, 6:38pm UTC](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670/10 "2024-12-18T18:38:00Z")

</div>

Thanks for the insights and comments. I wanted to add a few things to this discussion on re-balancing the pool, however, please correct me if my understanding is off on anything.

I don’t think the expectation that the helper contract should produce an order that perfectly balances the pool every time is correct, since the user inputs a prices vector. Its purpose seems to be to produce an order that satisfies the pool invariants given input prices. It is actually possible to get the order function to produce an order that balances the pool by varying the prices. However, this is not the intention for this work.

In this work, we are looking at pricing the LP tokens via simulating an order that:

- satisfies pool invariants
- zero fees
- prices vector constructed using external chainlink price feeds

To achieve the above, the helper contract is great. The order function does a good job of producing simulated reserves that move toward pool rebalancing. Just based on some results I am seeing in unit tests from today, the LP token price is either at, or within 0.1%, of the balanced pool LP token price.

---

<div class="post-metadata">

**Author:** ![AndreaC](https://avatars.discourse-cdn.com/v4/letter/a/d78d45/32.png) [@AndreaC](https://forum.cow.fi/u/AndreaC)\
**Post date:** [December 19, 2024, 5:13pm UTC](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670/11 "2024-12-19T17:13:47Z")

</div>

Hi @lumoswiz ,

you are correct about the helper contract. And in light of the discussion, it may be better to forget about it altogether. The oracle should look at the pool invariant k (calculated by multiplying the two liquidity reserves) and use that to calculate the TVL of a hypothetical AMM with the same invariant k but prices equal to those from Chainlink. If you go through the math, the TVL computed this way should be 2\* sqrt(k p1 \*p2) (but please verify). Then, to get the LP token prices, you just divide that by the number of LP tokens.

The point we were tying to make (and which ended up generating confusion) is that the oracle logic follows more or less that of the helper contract: it looks at the on-chain state and uses some provided prices to compute a different state. But in this case, there is no need to have a separate helper contract.

I hope this helps!

---

<div class="post-metadata">

**Author:** ![lumoswiz](https://avatars.discourse-cdn.com/v4/letter/l/85f322/32.png) [@lumoswiz](https://forum.cow.fi/u/lumoswiz)\
**Post date:** [December 19, 2024, 11:27pm UTC](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670/12 "2024-12-19T23:27:38Z")

</div>

That helps, thanks for the clarification.

---

<div class="post-metadata">

**Author:** ![lumoswiz](https://avatars.discourse-cdn.com/v4/letter/l/85f322/32.png) [@lumoswiz](https://forum.cow.fi/u/lumoswiz)\
**Post date:** [December 20, 2024, 12:07pm UTC](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670/13 "2024-12-20T12:07:41Z")

</div>

I have been looking at this and, as far as I can tell, the math described above works for 2 token pools with equal weights (50/50). Just for reference, here is the 2 token weight pool equations for determining the reserves:

y = √((k \* p\_x \* w\_y)/(p\_y \* w\_x))

x = √((k \* w\_x \* p\_y)/(w\_y \* p\_x))

Weights sum to 1.

---

<div class="post-metadata">

**Author:** ![AndreaC](https://avatars.discourse-cdn.com/v4/letter/a/d78d45/32.png) [@AndreaC](https://forum.cow.fi/u/AndreaC)\
**Post date:** [December 20, 2024, 3:22pm UTC](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670/14 "2024-12-20T15:22:16Z")

</div>

Hi @lumoswiz ,

I get a different result. Let me show you my derivations:

1. first the invariant Q1^a \* Q2^(1-a)=k (for a between 0 and 1), which can be equivalently written as (Q1/Q2)^a \* Q2=k
2. Then the equation for the AMM marginal prices: if p1 and p2 are the chainlink prices, the AMM has the same prices as chainlink if and only if p1 \* Q1/a =p2 \* Q2/(1-a), which can be rewritten as Q1/Q2=(p2/p1)\*(a/1-a)
3. Now you can compute the reserves as: Q1=k \* [(p2/p1)\*(a/(1-a))]^(1-a) ; Q2=k \* [(p1/p2) \* ((1-a)/a)]^a
4. and then TVL is k \*p1^a \* p2^(1-a) \* [(a/(1-a))^(1-a) + ((1-a)/a)^a]

Again, you should double check my calculations, but as you can see, I don’t get a sqrt anywhere (unless of course you set a=1/2)

---

<div class="post-metadata">

**Author:** ![middleway.eth](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.cow.fi/middleway.eth/32/12_2.png) [@middleway.eth](https://forum.cow.fi/u/middleway.eth)\
**Post date:** [December 27, 2024, 10:03am UTC](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670/15 "2024-12-27T10:03:03Z")

</div>

Dear @lumoswiz and @bh2smith,

Milestone 1 is estimated to be completed on 1/1/25, wanted to get an update and make sure we pay it out if it is was indeed completed.  
(Otherwise, no problem to postpone the payment for when the milestone has been completed)

Happy new year 🎄

---

<div class="post-metadata">

**Author:** ![bh2smith](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.cow.fi/bh2smith/32/1242_2.png) [@bh2smith](https://forum.cow.fi/u/bh2smith)\
**Post date:** [December 28, 2024, 4:24pm UTC](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670/16 "2024-12-28T16:24:45Z")

</div>

Hey @middleway.eth

All the core logic has been implemented, and we had already moved on to testing. However, recent discussions have led us to a significant refactor: removing the helper contract dependency and implementing the math directly within the main contract.

We estimate that it will take an additional 2–3 weeks to finalize these changes.

---

<div class="post-metadata">

**Author:** ![bh2smith](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.cow.fi/bh2smith/32/1242_2.png) [@bh2smith](https://forum.cow.fi/u/bh2smith)\
**Post date:** [January 16, 2025, 5:36pm UTC](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670/17 "2025-01-16T17:36:51Z")

</div>

We believe that this project is in shape for Milestone 1 Review. Note that, since the last discussion, we have [removed the BCoWHelper](https://github.com/lumoswiz/cow-amm-lp-oracle/wiki/Implementation-Decisions-Log#4-remove-bcowhelper-in-favour-of-internal-arithmetic) in favour of intrinsic TVL calculation (as a gas optimization).

We highlight the tests demonstrating viability of this mechanism for “ **Short-term over-reporting of value** ” are captured by the assertions [here](https://github.com/lumoswiz/cow-amm-lp-oracle/blob/e7659fc701c84a55f5a6fe83c0591d91e4f2974c/test/fork/LPOracle.t.sol#L81-L87). Unfortunately, we have not yet come up with an example resulting in “ **Short-term under-reporting of value** ”.

There are fork tests for all mainnet pools with ChainLink price oracles. These are all 50:50 pools since none of the all existing X:Y pools with X != Y have at least one token which doesn’t have a ChainLink price feed.

At this stage we consider the project “ready for review” and, during this time, will proceed with milestone 2.

---

<div class="post-metadata">

**Author:** ![bh2smith](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.cow.fi/bh2smith/32/1242_2.png) [@bh2smith](https://forum.cow.fi/u/bh2smith)\
**Post date:** [January 20, 2025, 8:54am UTC](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670/18 "2025-01-20T08:54:49Z")

</div>

Update: Milestone 2 is also ready [feat: add Aave V3 integration test suite by lumoswiz · Pull Request #47 · cowdao-grants/cow-amm-lp-oracle · GitHub](https://github.com/lumoswiz/cow-amm-lp-oracle/pull/47).

Update2:

The final PR has been reviewed and all comments resolved.

> <https://github.com/cowdao-grants/cow-amm-lp-oracle/pull/49>
>
> For context see grant proposal:
> 
> https://forum.cow.fi/t/grant-application-mani…pulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670

There’s only one thing left to do here…

@middleway.eth, @AndreaC and @mfw78

---

<div class="post-metadata">

**Author:** ![lumoswiz](https://avatars.discourse-cdn.com/v4/letter/l/85f322/32.png) [@lumoswiz](https://forum.cow.fi/u/lumoswiz)\
**Post date:** [February 11, 2025, 10:58am UTC](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670/19 "2025-02-11T10:58:15Z")

</div>

Status: Both milestones completed and merged.

> **[GitHub - cowdao-grants/cow-amm-lp-oracle](https://github.com/cowdao-grants/cow-amm-lp-oracle)**
>
> Contribute to cowdao-grants/cow-amm-lp-oracle development by creating an account on GitHub.

---

<div class="post-metadata">

**Author:** ![mfw78](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.cow.fi/mfw78/32/1598_2.png) [@mfw78](https://forum.cow.fi/u/mfw78)\
**Post date:** [February 12, 2025, 5:15am UTC](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670/20 "2025-02-12T05:15:35Z")

</div>

Great work to yourself and @bh2smith. From the committee’s perspective and as reviewer, I confirm that the milestones have been met and final payment can take place. This will occur in accordance with regular end-of-month payment cycles.

[Next page](https://forum.cow.fi/t/grant-application-manipulation-resilient-price-oracle-for-cow-amm-lp-tokens/2670.md?page=2)
