Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Price Impact Helper #323

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open

Price Impact Helper #323

wants to merge 22 commits into from

Conversation

brunoguerios
Copy link
Member

@brunoguerios brunoguerios commented Feb 26, 2024

Description

This PR aims to create a helper contract to calculate price impact for add liquidity unbalanced operations.

Price impact is currently being done off-chain, within the SDK, through the ABA method (described here)
For most operations (e.g. swaps, remove liquidity single token, etc..) this is ok to be done off-chain, because they contain a respective "reverse" operation and ABA method requires only 2 on-chain queries (A -> B and B -> A) to calculate price impact.
Add Liquidity Unbalanced is the only operation that requires an adapted version of ABA because Remove Liquidity Unbalanced is not available in v3.
More details on the adapted ABA logic can be found here

A few items still open for discussion:

  1. I created a new package called standalone-utils to place this new helper contract. The goal was to have something similar to what we had on monorepo-v2. If there's any better alternative approach, feel free to suggest.
  2. I initially thought of interfacing with the Router, in the same way the SDK does, but after some feedback from @mkflow27, I decided to remove the intermediary and query the vault directly. This has led to some code duplication. Let me know if you think there's a better way of doing this.
  3. I created standalone-utils as a new package by copy/paste from another existing package. It might have some dependencies (or other things) that are not needed. Could use a help on identifying what is ok to remove or not.

Depends on #383.

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Dependency changes
  • Code refactor / cleanup
  • Documentation or wording changes
  • Other

Checklist:

  • The diff is legible and has no extraneous changes
  • Complex code has been commented, including external interfaces
  • Tests have 100% code coverage
  • The base branch is either main, or there's a description of how to merge

Issue Resolution

@brunoguerios brunoguerios added the enhancement New feature or request label Feb 26, 2024
@brunoguerios brunoguerios self-assigned this Feb 26, 2024
Copy link
Contributor

@joaobrunoah joaobrunoah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't check the contract logic, only passed through some patterns that we use as a standard

pkg/standalone-utils/contracts/PriceImpact.sol Outdated Show resolved Hide resolved
pkg/standalone-utils/contracts/PriceImpact.sol Outdated Show resolved Hide resolved
pkg/standalone-utils/contracts/PriceImpact.sol Outdated Show resolved Hide resolved
.gitignore Outdated Show resolved Hide resolved
@jubeira jubeira mentioned this pull request Mar 13, 2024
11 tasks
@jubeira jubeira changed the base branch from main to clean-quote March 13, 2024 19:53
@brunoguerios brunoguerios marked this pull request as ready for review March 22, 2024 20:09
@brunoguerios brunoguerios changed the title Price Impact Helper (WIP) Price Impact Helper Mar 25, 2024
Copy link
Contributor

@joaobrunoah joaobrunoah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some minor comments, but looks good :D
Not sure if it's synched with latest main, the version of pragma changed, but shouldn't affect the code.

pkg/standalone-utils/contracts/PriceImpact.sol Outdated Show resolved Hide resolved
pkg/standalone-utils/contracts/PriceImpact.sol Outdated Show resolved Hide resolved
pkg/standalone-utils/coverage.sh Outdated Show resolved Hide resolved
pkg/standalone-utils/test/foundry/PriceImpact.t.sol Outdated Show resolved Hide resolved
pkg/standalone-utils/contracts/PriceImpact.sol Outdated Show resolved Hide resolved
pkg/standalone-utils/README.md Show resolved Hide resolved
Base automatically changed from clean-quote to main May 24, 2024 19:19
EndymionJkb and others added 7 commits December 9, 2024 08:36
# Conflicts:
#	pkg/interfaces/contracts/vault/IVaultErrors.sol
#	pkg/interfaces/contracts/vault/IVaultExtension.sol
#	pkg/solidity-utils/contracts/helpers/RevertCodec.sol
#	pkg/solidity-utils/test/foundry/RevertCodec.t.sol
#	pkg/vault/.forge-snapshots/vaultSwapSingleTokenExactInWithProtocolFee.snap
#	pkg/vault/contracts/VaultExtension.sol
#	pkg/vault/contracts/test/RouterMock.sol
#	pkg/vault/test/Queries.test.ts
Copy link
Contributor

@jubeira jubeira left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pushing this @elshan-eth !

First pass done. Only a few minor questions and comments; otherwise LGTM!


import { RevertCodec } from "@balancer-labs/v3-solidity-utils/contracts/helpers/RevertCodec.sol";

contract CallAndRevert {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we can make a library out of this? There's no state to save or to access, so a library would seem better suited. Agree about making it a standalone module.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah this is to reuse the hook right? Then I guess it's fine as it is.

// get deltas between exactAmountsIn and proportionalAmountsOut
int256[] memory deltas = new int256[](exactAmountsIn.length);
for (uint256 i = 0; i < exactAmountsIn.length; i++) {
deltas[i] = int(proportionalAmountsOut[i]) - int(exactAmountsIn[i]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: let's use full types.

Suggested change
deltas[i] = int(proportionalAmountsOut[i]) - int(exactAmountsIn[i]);
deltas[i] = int256(proportionalAmountsOut[i]) - int256(exactAmountsIn[i]);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(here and elsewhere)


// calculate price impact ABA with remaining delta and its respective exactAmountIn
// remaining delta is always negative, so by multiplying by -1 we get a positive number
uint256 delta = uint(-deltas[remainingDeltaIndex]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd still just use safe cast here. Everything is static so we don't care about gas, and we have plenty of bytecode to spare.

uint256 tokenIndex,
int256[] memory deltas,
address sender
) internal returns (int256 deltaBPT) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I don't get the back and forth here. Why is this a signed value if we always change the result to be positive?

// calculate expectedPriceImpact for comparison
uint256 expectedPriceImpact = effectivePrice.divDown(spotPrice) - 1e18;

// assert within acceptable bounds of +-1%
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm isn't 1% quite large for this? Does it break with a lower tolerance?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants