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

Roundrip fee on proportional remove #1010

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

Roundrip fee on proportional remove #1010

wants to merge 8 commits into from

Conversation

jubeira
Copy link
Contributor

@jubeira jubeira commented Sep 25, 2024

Description

Proposal: tax proportional exits whenever liquidity was added in the same transaction.
Every other remove kind charges fees already as it's unbalanced, and there's no way to remove with more than one token close to the existing proportion to avoid fees (unlike add liquidity unbalanced).

This should make roundrips more difficult, and make swap sandwiches economically unfeasible.
For now I'll keep the liquidity approximation tests as they are, effectively clearing up the flag so as not to apply the tax when calling removeLiquidityProportional. In practice, the fee will make indirect swap paths worse than our current fuzz tests, and that's a desirable outcome.

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Dependency changes
  • Code refactor / cleanup
  • Optimization: [ ] gas / [ ] bytecode
  • 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

N/A

@@ -872,6 +873,13 @@ contract Vault is IVaultMain, VaultCommon, Proxy {
_totalSupply(params.pool),
bptAmountIn
);

if (_addLiquidityCalled().tGet(params.pool)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note: if we clear this flag here, it's easy to bypass.

You add a huge amount, make a decoy proportional exit, and then a big exit.
Whenever the flag is set, it'll be set for the rest of the tx. A more correct approach would be to clean it when transient modifier ends, but we would need a transient set for that and I really don't think it's worth the added complexity.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Agree that's probably not worth it for an edge case. Although... maybe aggregators might bundle lots of transactions and come across that, since it just checks the pool, not the pool + user, so this could also get triggered on bundled transactions with multiple unrelated users doing liquidity operations on a popular pool. Maybe worth investigating if that's possible? If one person added and another person removed, the second one would get unexpectedly taxed.

Though even storing the user wouldn't be foolproof, as someone could craft a transaction where the add and remove steps were done from separate addresses controlled by the same account.

@jubeira jubeira marked this pull request as ready for review October 1, 2024 14:16
@jubeira jubeira requested review from EndymionJkb, joaobrunoah and elshan-eth and removed request for EndymionJkb and joaobrunoah October 1, 2024 14:19
Copy link
Collaborator

@EndymionJkb EndymionJkb left a comment

Choose a reason for hiding this comment

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

Looks correct; one more slice of cheese. Just wonder if it might cause issues with aggregators (see comment).

Comment on lines +71 to +72
* @notice Returns `true` if `addLiquidity` was called for the given pool in this transaction.
* @param pool Address of the pool to check.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
* @notice Returns `true` if `addLiquidity` was called for the given pool in this transaction.
* @param pool Address of the pool to check.
* @notice This flag is used to detect and tax "round trip" transactions (adding/removing liquidity in the same pool)
* @param pool Address of the pool to check
* @return liquidityAdded True if liquidity has been added to this pool in the current transaction

Copy link
Collaborator

Choose a reason for hiding this comment

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

Could also add a dev section here with more detail on why this is desirable / improves security, and documenting limitations.

@@ -872,6 +873,13 @@ contract Vault is IVaultMain, VaultCommon, Proxy {
_totalSupply(params.pool),
bptAmountIn
);

if (_addLiquidityCalled().tGet(params.pool)) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Agree that's probably not worth it for an edge case. Although... maybe aggregators might bundle lots of transactions and come across that, since it just checks the pool, not the pool + user, so this could also get triggered on bundled transactions with multiple unrelated users doing liquidity operations on a popular pool. Maybe worth investigating if that's possible? If one person added and another person removed, the second one would get unexpectedly taxed.

Though even storing the user wouldn't be foolproof, as someone could craft a transaction where the add and remove steps were done from separate addresses controlled by the same account.

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

Successfully merging this pull request may close these issues.

2 participants