Build a Custom Bonding Curve for Token Sales with Solidity

Posted By : Tushar

Nov 28, 2024

A bonding curve is a mathematical curve that depicts how pricing and token supply are linked. This bonding curve states that a token's price grows as its supply increases. As numerous individuals become engaged with the initiative and continue to buy tokens, for instance, the cost of each subsequent buyer increases slightly, providing early investors with a chance to profit. If early buyers identify profitable businesses, they may eventually make money if they buy curve-bonded tokens early and then sell them. For more related to crypto exchange, visit our crypto exchange development services

 

Check this blog | Tokenization of RWA (Real-World Assets): A Comprehensive Guide

 

Bonding Curve Design: Key Considerations :

 

  1. Token pricing can be best managed by using unique purchasing and selling curves.
  2. Those who adopt first are often entitled to better benefits to promote early support.
  3. Inspect for any price manipulation and deploy measures to protect the integrity of the token sale.
  4. As the last price system, the bonding curve will ensure that tokens are valued equitably in line with supply and demand.
  5. After a rapid initial development phase, your project will probably follow an S-curve growth pattern, resulting in a more stable maturity phase.
  6. Aim for an enormous increase in the token's value over time. Pre-mining tokens should be carefully considered and backed by the project's specific requirements.
  7. Make sure that token pricing is in line with the project's long-term value proposition and set reasonable fundraising targets.

     

How Bonding Curves Are Used?

 

1. Market Prediction 

 

Bonding curves are used by platforms such as Augur to generate dynamic markets for upcoming events. The price of each share varies according to market demand, and users can buy shares that reflect particular outcomes.

 

2. Crowdfunding and ICOs

 

Fundraising efforts can be streamlined by using bonding curves. For example, during initial coin offerings (ICOs), Bancor's protocol uses a bonding curve to control its token supply. This system ensures liquidity and reduces price volatility by enabling investors to buy tokens at a dynamic pricing.

 

An example of a bonding curve interaction:

 

  • To enable users to mint or purchase a new token (such as the Bonding Curve Token, or BCT) with a designated reserve currency (let's say CWEB), a smart contract is developed.
    The price of BCT is algorithmically calculated in relation to its current circulating supply and shown in its reserve currency, CWEB.

     

  • A smart contract will allow the user to purchase the new BCT token using the reserve currency. The sold CWEB is maintained in the smart contract as collateral and is not distributed to any individual or team.

     

  • After the user completes their purchase, the price of the token will move along the bonding curve per the amount of supply the user has just created (probably increasing the price for future buyers).

     

  • The decision to sell or burn a BCT token back to the curve can be made at any time. After their first purchase, the user will probably sell at a profit (less petrol and fees) if the price keeps rising. Following approval of their sale, the smart contract will return the bonded CWEB to the user.

     

Also, Check | Liquid Democracy | Transforming Governance with Blockchain

 

Bancor Formula 

 

The Bancor Formula calculates the price of a Continuous Token as it changes over time. The Reserve Ratio, which is determined as follows, is a constant used in the formula:


Reserve Token Balance / (Continuous Token Supply x Continuous Token Price) = Reserve Ratio

 

Implementation of Bancor Formula in Solidity :

 

        // SPDX-License-Identifier: UNLICENSED
        pragma solidity ^0.8.27;
        import './SafeMath.sol';
        import './Power.sol';

        contract BancorFormula is Power {
            using SafeMath for uint256;
            uint32 private constant MAX_RESERVE_RATIO = 1000000;
           
            function calculatePurchaseReturn(
            uint256 _supply,
            uint256 _reserveBalance,
            uint32 _reserveRatio,
            uint256 _depositAmount) public view returns (uint256)
            {
            // validate input
            require(_supply > 0 && _reserveBalance > 0 && _reserveRatio > 0 && _reserveRatio <= MAX_RESERVE_RATIO, 'Invalid inputs.');
            // special case for 0 deposit amount
            if (_depositAmount == 0) {
                return 0;
            }
            // special case if the ratio = 100%
            if (_reserveRatio == MAX_RESERVE_RATIO) {
                return _supply.mul(_depositAmount).div(_reserveBalance);
            }
            uint256 result;
            uint8 precision;
            uint256 baseN = _depositAmount.add(_reserveBalance);
            (result, precision) = power(
                baseN, _reserveBalance, _reserveRatio, MAX_RESERVE_RATIO
            );
            uint256 newTokenSupply = _supply.mul(result) >> precision;
            return newTokenSupply.sub(_supply);
            }
           
            function calculateSaleReturn(
            uint256 _supply,
            uint256 _reserveBalance,
            uint32 _reserveRatio,
            uint256 _sellAmount) public view returns (uint256)
            {
            // validate input
            require(_supply > 0 && _reserveBalance > 0 && _reserveRatio > 0 && _reserveRatio <= MAX_RESERVE_RATIO && _sellAmount <= _supply, 'Invalid inputs.');
            // special case for 0 sell amount
            if (_sellAmount == 0) {
                return 0;
            }
            // special case for selling the entire supply
            if (_sellAmount == _supply) {
                return _reserveBalance;
            }
            // special case if the ratio = 100%
            if (_reserveRatio == MAX_RESERVE_RATIO) {
                return _reserveBalance.mul(_sellAmount).div(_supply);
            }
            uint256 result;
            uint8 precision;
            uint256 baseD = _supply.sub(_sellAmount);
            (result, precision) = power(
                _supply, baseD, MAX_RESERVE_RATIO, _reserveRatio
            );
            uint256 oldBalance = _reserveBalance.mul(result);
            uint256 newBalance = _reserveBalance << precision;
            return oldBalance.sub(newBalance).div(result);
            }
        }

 

Implement Interface of IBondingCurve:

 

// SPDX-License-Identifier: UNLICENSED
        pragma solidity ^0.8.27;

        interface IBondingCurve {
           
            function getContinuousMintReward(uint _reserveTokenAmount) external view returns (uint);
            function getContinuousBurnRefund(uint _continuousTokenAmount) external view returns (uint);
        }

 

Implement Bancor Bonding Curve :

 

// SPDX-License-Identifier: UNLICENSED
        pragma solidity ^0.8.27;
        import '../math/BancorFormula.sol';
        import '../interface/IBondingCurve.sol';

        abstract contract BancorBondingCurve is IBondingCurve, BancorFormula {
            uint32 public reserveRatio;
            constructor(uint32 _reserveRatio) {
            reserveRatio = _reserveRatio;
            }
            function getContinuousMintReward(uint _reserveTokenAmount) public view returns (uint) {
            return calculatePurchaseReturn(continuousSupply(), reserveBalance(), reserveRatio, _reserveTokenAmount);
            }
            
            function getContinuousBurnRefund(uint _continuousTokenAmount) public view returns (uint) {
            return calculateSaleReturn(continuousSupply(), reserveBalance(), reserveRatio, _continuousTokenAmount);
            }
            // These functions are unimplemented in this contract, so mark the contract as abstract
            function continuousSupply() public view virtual returns (uint);  
            function reserveBalance() public view virtual returns (uint);
        }

 

Conclusion 

 

We highlighted key considerations for bonding curve design, including the importance of managing token pricing, preventing price manipulation, and aligning the token's value with the long-term goals of the project. By leveraging the Bancor Formula and its implementation in Solidity, we created a model that can adjust token prices dynamically based on supply and demand, while maintaining liquidity and reducing price volatility. 

 

At Oodles , we specialize in advanced blockchain solutions, including bonding curves for token sales and DeFi applications. 

 

Contact our blockchain developers today to bring your token project to life.

Leave a

Comment

Name is required

Invalid Name

Comment is required

Recaptcha is required.

blog-detail

December 21, 2024 at 03:47 pm

Your comment is awaiting moderation.

By using this site, you allow our use of cookies. For more information on the cookies we use and how to delete or block them, please read our cookie notice.

Chat with Us
Telegram Button
Youtube Button

Contact Us

Oodles | Blockchain Development Company

Name is required

Please enter a valid Name

Please enter a valid Phone Number

Please remove URL from text