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

BAL Hookathon - VolatilityLoyaltyHook #105

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

Conversation

dilawari2008
Copy link

@dilawari2008 dilawari2008 commented Oct 20, 2024

Volatility and Loyalty Hook for Balancer V3 Hackathon

Video explanation - https://www.loom.com/share/4b8b9b2685274af0864ac27887782196?sid=54923331-f288-40d1-9344-387905874e4f

Video demo - https://www.loom.com/share/defa9c16751e401d92daf6d5ed7d6b0d?sid=9a36b6bf-e3a4-4647-a955-71868bae7e78

The Volatility and Loyalty Hook aims to stimulate trading activity in a newly launched pool on Balancer by rewarding users with discounts on swap fees when they hold project tokens for a longer duration. It simultaneously ensures stability by increasing swap fees during periods of high volatility.

Contents

Hook Lifecycle Points

  • onAfterRemoveLiquidity(), onAfterAddLiquidity():
    Updates the new token price in the Volatility Oracle along with the timestamps.

  • onAfterSwap():
    Updates the new token price in the Volatility Oracle along with the timestamps.
    Updates the loyalty index of the user.

  • onComputeDynamicSwapFeePercentage():
    Calculates the swap fee based on the pool's volatility and the user's loyalty index.

Balancer Hook Diagram

Swap Fee Calculation

The swap fee is calculated as the sum of the swapFeeWithLoyaltyDiscount and the volatilityFee.

Swap Fee with Loyalty Discount

This reduces the static swap fee but maintains a minimum fee and a cap on the loyalty discount to prevent exploitation by large holders (whales).

  • Minimum fee that must be paid: 1%
  • Cap on loyalty discount: 1%

Let’s assume MAX_LOYALTY_FEE = 1%. The logic is as follows:

  • If staticSwapFee <= 1%:
    swapFeeWithLoyaltyDiscount = staticSwapFee

  • If 1% < staticSwapFee < 2% (1% + MAX_LOYALTY_FEE):
    swapFeeWithLoyaltyDiscount = 1% + (staticSwapFee - 1%) * (1 - loyaltyPercentage)

  • If staticSwapFee == 2% (1% + MAX_LOYALTY_FEE):
    swapFeeWithLoyaltyDiscount = 1% + MAX_LOYALTY_FEE * (1 - loyaltyPercentage)

  • Else:
    swapFeeWithLoyaltyDiscount = 1% + MAX_LOYALTY_FEE * (1 - loyaltyPercentage) + (staticSwapFee - 1% - MAX_LOYALTY_FEE)

Loyalty Percentage Calculation

We calculate a loyaltyIndex based on the time the tokens have been held, preventing flash loan attacks:

newLoyaltyIndex = previousLoyaltyIndex + (tokens held at the previous transaction) * (current timestamp - previous swap transaction timestamp)

Using this loyaltyIndex, we calculate the loyaltyPercentage through a tier-based system.

The loyalty index is refreshed if the previous transaction occurred more than _LOYALTY_REFRESH_WINDOW (30 days) ago.

Volatility Fee

volatilityFee = MAX_VOLATILITY_FEE * volatilityPercentage

Volatility Percentage Calculation

Note - The price oracle approach using a circular buffer was inspired from the implementation of the same in balancer v2; the code used from that section has been put in a separate folder balancer-v2-oracle.

Reference
  • Implementation of PriceOracle in Balancer V2:
    Etherscan

The volatility percentage is calculated using a circular buffer to maintain a history of price and timestamp objects. The buffer ensures price updates are stored at intervals of, for example, 2 minutes ( a shorter duration for demo purposes). If an update occurs within this interval, the previous entry is overwritten; if it occurs later, a new entry is added.

Once the prices over a span of time are captured, the price 1 hour ago ( a shorter duration for demo purposes) is extracted using binary search from the oracle.

The formula for calculating volatility is:

** correction in the below diagram the inner bracket is to be sqaured (^2).

Screenshot 2024-10-21 at 1 58 47 AM

Where:

  • tf and ti are the final and initial timestamps of the samples collected from the buffer for the last ago seconds.

The unit of volatility is % price change per second. A tier-based system is then used to calculate the volatility fee percent.

DevX

Overall the developer experience was good. The documentation and examples are a good starting point. For more specific issues, the team was proactive on discord.

Copy link

vercel bot commented Oct 20, 2024

Someone is attempting to deploy a commit to the Matt Pereira's projects Team on Vercel.

A member of the Team first needs to authorize it.

@MattPereira MattPereira self-requested a review October 22, 2024 20:21
@dilawari2008
Copy link
Author

Hey @MattPereira would it be possible for you to review the code?

@MattPereira
Copy link
Member

MattPereira commented Oct 29, 2024

Hey @dilawari2008 my apologies but the complexity of this hook is beyond my capacity to confidently evaluate. The way the volatility fee percentage is calculated by the VolatilityOracle contract that leverages the Balancer v2 price oracle code is beyond my current level of understanding.

I can opine that writing a hook this complex without any tests that verify it works as intended makes it more difficult for us review / trust the code.

I have requested that a more experienced dev that was around for v2 take a look

@dilawari2008
Copy link
Author

dilawari2008 commented Oct 31, 2024

Ok, thanks @MattPereira .
Apologies for not writing the tests, actually ran out of time for that.

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