← Docs / API-Documents.25-03-2026.md ⬇ Download

Table of Contents


CHANGES - 25/03/2026

Initial Release


Protocol Contracts

BullshotFactory

Main factory contract. Deploys bonding curves and tokens via ERC1167 minimal proxy cloning. Emits global Buy, Sell, and Created events.

Network: BSC (BNB Smart Chain)

ABI File: BullshotFactory.abi

State Variables

Name Type Visibility Description
FEE_DENOMINATOR uint16 public constant Fee base denominator (1000)
buyFeePercent uint8 public Buy fee as per-mille of amountIn (e.g., 10 = 1%)
sellFeePercent uint8 public Sell fee as per-mille of amountOut
launchFeePercent uint8 public Fee taken from ETH pool at DEX launch
creationFeeAmount uint256 public Fixed BNB fee required to create a token (in wei)
feeRecipient address payable public Address that receives all protocol fees
uniswapV2Router address public PancakeSwap V2 Router address
uniswapV2Factory address public PancakeSwap V2 Factory address
isBondingCurveAddress mapping(address => bool) public Returns true if address is a BondingCurve deployed by this factory
tokens BCToken[] public Array of all tokens created through the factory

Events

Created

Emitted when a new token and bonding curve are deployed.

event Created(
    address indexed bondingCurve,
    address indexed token,
    address indexed pair,
    address creator
);

Parameters:

Buy

Emitted when a user buys tokens on a bonding curve (forwarded from BondingCurve).

event Buy(
    address indexed bc,
    address indexed token,
    address indexed buyer,
    uint amountIn,
    uint amountOut
);

Parameters:

Sell

Emitted when a user sells tokens on a bonding curve (forwarded from BondingCurve).

event Sell(
    address indexed bc,
    address indexed token,
    address indexed seller,
    uint amountIn,
    uint amountOut
);

Parameters:

Methods

createToken

function createToken(
    string memory name,
    string memory ticker,
    uint256 initAmountIn
) external payable

Creates a new token and its bonding curve. Optionally makes an initial buy on behalf of the caller.

Parameters:

msg.value requirement:

msg.value = initAmountIn + (initAmountIn * buyFeePercent / FEE_DENOMINATOR) + creationFeeAmount

getTokensLength

function getTokensLength() external view returns (uint256)

Returns the total number of tokens created through this factory.

getTokensList

function getTokensList(uint256 startIndex, uint256 count) external view returns (BCToken[] memory)

Returns a paginated slice of the tokens array.

Parameters:

setFee

function setFee(
    uint256 creationFeeAmount_,
    uint8 buyFeePercent_,
    uint8 sellFeePercent_,
    uint8 launchFeePercent_,
    address payable feeRecipient_
) public onlyOwner

Updates all fee parameters. Only callable by the contract owner.


BondingCurve

Constant-product AMM (x*y=k) with virtual reserves powering pre-launch token trading. Automatically launches to PancakeSwap when the ETH reserve crosses launchThreshold.

ABI File: BondingCurve.abi

State Variables

Name Type Visibility Description
FEE_DENOMINATOR uint16 public constant 1000
totalSupply uint256 public Total token supply (1,000,000,000 ether)
virtualTokenReserve uint256 public Virtual token reserve used in k=x*y formula
tokenReserve uint256 public Real tokens available for sale (800,000,000 ether initial)
virtualEthReserve uint256 public Virtual ETH reserve used in k=x*y formula (6 ether initial)
ethReserve uint256 public Real BNB held in the bonding curve
correlation uint256 public k constant = virtualEthReserve × virtualTokenReserve
launchThreshold uint256 public BNB ethReserve level at which DEX launch is triggered
buyFeePercent uint8 public Buy fee per-mille
sellFeePercent uint8 public Sell fee per-mille
launchFeePercent uint8 public Launch fee per-mille of eth pool
feeRecipient address payable public Fee recipient address
uniswapV2Factory IUniswapV2Factory public PancakeSwap factory reference
uniswapV2Router IUniswapV2Router02 public PancakeSwap router reference
token BCToken public Associated BCToken
pair address public PancakeSwap pair address (set on first buy or after launch)
factory address public BullshotFactory address

Events

Buy

event Buy(address indexed buyer, uint amountIn, uint amountOut);

Sell

event Sell(address indexed seller, uint amountIn, uint amountOut);

Launch

Emitted when the bonding curve triggers DEX launch.

event Launch(uint tokenAmount, uint ethAmount);

Methods

buy

function buy(
    uint256 amountIn,
    uint256 amountOutMin,
    address to,
    uint256 deadline
) external payable returns (uint256 amountOut)

Buy tokens from the bonding curve. msg.value must equal amountIn + buyFee.

Parameters:

sell

function sell(
    uint256 amountIn,
    uint256 amountOutMin,
    uint256 deadline
) external returns (uint256 amountOut)

Sell tokens back to the bonding curve. Requires prior token.approve(bondingCurve, amountIn).

Parameters:

calcBuyExactIn

function calcBuyExactIn(uint256 amountIn) public view returns (
    uint256 amountOut,
    uint256 amountInMax,
    uint256 amountOutMax
)

Pre-calculates token output when spending a fixed BNB amount.

calcBuyExactOut

function calcBuyExactOut(uint256 amountOut) public view returns (
    uint256 amountIn,
    uint256 amountOutMax
)

Pre-calculates BNB cost to receive a fixed token amount.

calcSellExactIn

function calcSellExactIn(uint256 amountIn) public view returns (
    uint256 amountOut,
    uint256 amountInMax,
    uint256 amountOutMax
)

Pre-calculates BNB output when selling a fixed token amount.

calcSellExactOut

function calcSellExactOut(uint256 amountOut) public view returns (
    uint256 amountIn,
    uint256 amountOutMax
)

Pre-calculates token amount needed to receive a fixed BNB output.

getData

function getData(address account) public view returns (Data memory data)

Returns a snapshot of all bonding curve state variables plus the account's token balance.

struct Data {
    uint256 totalSupply;
    uint256 tokenReserve;
    uint256 virtualTokenReserve;
    uint256 ethReserve;
    uint256 virtualEthReserve;
    uint256 launchThreshold;
    uint8 buyFeePercent;
    uint8 sellFeePercent;
    address pair;
    uint256 balance;
}

getPostLaunchPrice

function getPostLaunchPrice() public view returns (uint256)

Returns the current token price from PancakeSwap reserves after DEX launch.


BCToken

ERC20 token deployed per bonding curve. Transfers to the PancakeSwap pair are blocked until the bonding curve triggers launch().

ABI File: BCToken.abi

State Variables

Name Type Visibility Description
name string public Token name
symbol string public Token symbol
decimals uint8 public constant 18
totalSupply uint256 public Total token supply
launched bool public true after DEX launch; enables free transfers
balanceOf mapping(address => uint256) public ERC20 balances
allowance mapping(address => mapping(address => uint256)) public ERC20 allowances

Methods

Standard ERC20 methods: transfer, transferFrom, approve.

launch

function launch() public

Called exclusively by the BondingCurve to unlock transfers to the PancakeSwap pair. Reverts with Forbidden() if called by any other address.


FAQ

Error Codes

buy Errors

Error Description
! amountIn > 0 amountIn must be greater than zero
! amountOutMin >= tokenReserve amountOutMin exceeds available supply
Wrong value msg.value does not equal amountIn + buyFee
! amountOut >= amountOutMin Slippage: price moved, output below minimum
Expired block.timestamp exceeded deadline

sell Errors

Error Description
! amountOutMin >= ethReserve amountOutMin exceeds available ETH in curve
! amountOut >= amountOutMin Slippage: price moved, output below minimum
! amountOut >= ethReserve ETH reserve insufficient for payout
Expired block.timestamp exceeded deadline
Allowance Insufficient token allowance granted to BondingCurve

createToken Errors

Error Description
Wrong value msg.value must equal initAmountIn + fee + creationFee exactly

How to Identify a Launched Token

On-chain

BCToken token = BCToken(tokenAddress);
bool isLaunched = token.launched();

If launched == true, the token has graduated to PancakeSwap and bonding curve trading is closed.

Off-chain

Check the pair field on the BondingCurve. Once the launch triggers, a PancakeSwap LP pair is created and pair will return a non-zero address, and ethReserve will be 0.

How Bonding Curve Pricing Works

The bonding curve uses a constant-product formula with virtual reserves:

k = virtualEthReserve × virtualTokenReserve
  = 6 ether × 1,000,000,000 ether

Initial parameters:

When ethReserve >= 24 BNB, the token automatically launches to PancakeSwap.