← Docs / API-Contract-BCToken.md ⬇ Download

BCToken Contract API Documentation

Overview

BCToken is the ERC20 token contract deployed for every token created through the Bullshot Protocol. Each BCToken is a minimal proxy clone (ERC1167) of a master implementation, making deployment extremely gas-efficient. Token transfers to the PancakeSwap pair address are restricted until the associated BondingCurve triggers the launch() function — preventing sniping before DEX liquidity is added.

Key Features:


State Variables

Name Type Visibility Description
name string public Token name (e.g., "Bullshot")
symbol string public Token ticker symbol (e.g., "BULL")
decimals uint8 public constant Always 18
totalSupply uint256 public Total minted supply (set at init, equals BondingCurve's totalSupply)
launched bool public false until BondingCurve calls launch(). When false, transfers to the PancakeSwap pair are blocked
balanceOf mapping(address => uint256) public ERC20 token balances
allowance mapping(address => mapping(address => uint256)) public ERC20 spending allowances

Events

Transfer

event Transfer(address indexed from, address indexed to, uint256 value);

Emitted on every token transfer including minting (from = address(0)).

Approval

event Approval(address indexed owner, address indexed spender, uint256 value);

Emitted when approve() is called.


Public Functions

transfer

function transfer(address to, uint256 amount) public returns (bool)

Standard ERC20 transfer. Will revert with Forbidden() if launched == false and to is the PancakeSwap pair address.

Parameters:

Returns: true on success


transferFrom

function transferFrom(
    address from,
    address to,
    uint256 amount
) public returns (bool)

Standard ERC20 transferFrom. Same anti-snipe restriction applies.

Special case: If launched == false and the caller is the bondingCurve address, the allowance check is bypassed (unlimited internal allowance).

Parameters:

Returns: true on success


approve

function approve(address spender, uint256 amount) public returns (bool)

Standard ERC20 approve. Sets the allowance for spender to amount.

Parameters:

Returns: true on success


launch

function launch() public

Unlocks transfers to the PancakeSwap pair. Sets launched = true.

Access control: Can only be called by the associated bondingCurve address. Reverts with Forbidden() if called by anyone else.

When called: This is called internally by the BondingCurve's buy() function when ethReserve >= launchThreshold.


View Functions

balanceOf

function balanceOf(address account) public view returns (uint256)

Returns the token balance of account.

allowance

function allowance(address owner, address spender) public view returns (uint256)

Returns the remaining allowance that spender is permitted to spend on behalf of owner.


Error Types

Error Description
Forbidden() Thrown when transfer/transferFrom targets the PancakeSwap pair before launch, or when launch() is called by an address other than the bonding curve

Example Usage

Check Token Info

const token = new ethers.Contract(tokenAddress, BCTokenABI, provider);

const name         = await token.name();
const symbol       = await token.symbol();
const totalSupply  = await token.totalSupply();
const launched     = await token.launched();
const userBalance  = await token.balanceOf(userAddress);

console.log(`${name} (${symbol})`);
console.log(`Total Supply: ${ethers.utils.formatEther(totalSupply)}`);
console.log(`Launched: ${launched}`);
console.log(`User Balance: ${ethers.utils.formatEther(userBalance)}`);

Approve BondingCurve for Sell

// Before calling bondingCurve.sell(), approve it to spend your tokens
const amountToSell = ethers.utils.parseEther("500000"); // 500,000 tokens
await token.approve(bondingCurveAddress, amountToSell);
// Then call bondingCurve.sell(...)

Monitor Launch Status

// Poll or use events on the BondingCurve
const bondingCurve = new ethers.Contract(bcAddress, BondingCurveABI, provider);
bondingCurve.on("Launch", (tokenAmount, ethAmount) => {
    console.log("Token has launched to PancakeSwap!");
    console.log("LP Token Amount:", ethers.utils.formatEther(tokenAmount));
    console.log("LP ETH Amount:", ethers.utils.formatEther(ethAmount));
});

Important Notes

  1. Anti-Snipe Mechanism: Before launched = true, any transfer whose to address equals the PancakeSwap pair will revert with Forbidden(). The pair address is lazily resolved from the PancakeSwap factory inside the notRestricted modifier.

  2. Init instead of Constructor: Because BCToken is deployed as an ERC1167 proxy, the init() function acts as the constructor. It can only be called once (guarded by require(bondingCurve == address(0), 'Inited')).

  3. Minting: All tokens are minted in init() directly to the bondingCurve address. No additional minting is possible after initialization.

  4. BondingCurve Unlimited Allowance: The BondingCurve contract has an implicit unlimited allowance on all holders' balances pre-launch, implemented inside transferFrom. This allows the curve to move tokens freely during the pre-launch trading phase without requiring separate approve calls.

  5. Fixed Supply: Total supply is always 1,000,000,000 tokens (1 billion, 18 decimals). 800M are sold on the bonding curve; 200M go to the PancakeSwap LP at launch.