Bonding Curve Implementation Issue: Price Calculation Overflow

Problem Description

I’m implementing a bonding curve for pass pricing in my protocol and encountering two issues:

  1. Arithmetic Overflow: The multiplication in the price calculation is causing overflow errors in Move
  • Price Suppression: When fixing the overflow, the resulting prices are too low

Current Implementation

Python Reference (Working as Expected)

def get_price(supply, amount):
    # Constants
    DEFAULT_WEIGHT_A = 30000000  # 0.3 * 10^8
    DEFAULT_WEIGHT_B = 20000000  # 0.2 * 10^8
    DEFAULT_WEIGHT_C = 2
    WAD = 100000000  # 10^8
    INITIAL_PRICE = 1 * WAD

    # Add adjustment factor to supply
    adjusted_supply = supply + DEFAULT_WEIGHT_C
    if adjusted_supply == 0:
        return INITIAL_PRICE

    # Calculate summations
    n1 = adjusted_supply - 1
    sum1 = (n1 * adjusted_supply * (2 * n1 + 1)) // 6
    
    n2 = n1 + amount
    sum2 = (n2 * (adjusted_supply + amount) * (2 * n2 + 1)) // 6
    
    # Calculate final price
    summation = DEFAULT_WEIGHT_A * (sum2 - sum1)
    price = ((DEFAULT_WEIGHT_B * summation) // WAD * INITIAL_PRICE) // WAD
    
    return max(price, INITIAL_PRICE)

MOVE Implementation (Causing Overflow)

public fun calculate_price(supply: u64, amount: u64, is_sell: bool): u64 acquires Config {
    let config = borrow_global<Config>(@podium);

    let adjusted_supply = supply + config.weight_c;
    if (adjusted_supply == 0) {
        return INITIAL_PRICE
    };

    let n1 = adjusted_supply - 1;
    let sum1 = (n1 * adjusted_supply * (2 * n1 + 1)) / 6;
    
    let n2 = n1 + amount;
    let sum2 = (n2 * (adjusted_supply + amount) * (2 * n2 + 1)) / 6;
    
    let summation = config.weight_a * (sum2 - sum1);
    let price = (config.weight_b * summation * INITIAL_PRICE) / (WAD * WAD);
    
    if (price < INITIAL_PRICE) {
        INITIAL_PRICE
    } else {
        price
    }
}

Expected Price Progression
First 10 passes: ~$1-15 range
First 50 passes: ~$15-75 range
First 100 passes: ~$75-200 range
Questions
What’s the best way to handle the multiplication overflow in Move while maintaining the desired price curve?
Should we be using different scaling factors or a different order of operations?
Are there any Move-specific patterns for handling large number calculations in bonding curves?
Additional Context
Using WAD = 100000000 (10^8) for decimal scaling
Initial price is set to 1 MOVE (100000000 in internal units)
The weights are currently:
weight_a = 30000000 (0.3 10^8)
weight_b = 20000000 (0.2 10^8)
weight_c = 2
Any insights on implementing this correctly in Move would be greatly appreciated!

I’ll take a look through the codebase and get back to you but just some initial thoughts:

looks like the summation can get very large very very quickly a u64 holds 2^64 - 1 and your current summation can blow through that before you do your division. This might need some rethinking - maybe if possible doing the division earlier?

This issue I had was that when I did the division earlier it seemed to suppress the price. I will try and find my prior attempt.