# 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:**
- Standard ERC20 functionality (transfer, transferFrom, approve)
- Pre-launch transfer restriction: transfers to the PancakeSwap pair are blocked until `launched = true`
- Initialized via `init()` instead of a constructor (proxy pattern)
- BondingCurve has unlimited transfer allowance pre-launch (internal mechanism)
- Fixed total supply: 1,000,000,000 tokens (18 decimals)

---

## 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

```solidity
event Transfer(address indexed from, address indexed to, uint256 value);
```

Emitted on every token transfer including minting (`from = address(0)`).

### Approval

```solidity
event Approval(address indexed owner, address indexed spender, uint256 value);
```

Emitted when `approve()` is called.

---

## Public Functions

### transfer

```solidity
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:**
- `to`: Recipient address
- `amount`: Token amount in wei

**Returns:** `true` on success

---

### transferFrom

```solidity
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:**
- `from`: Token holder address
- `to`: Recipient address
- `amount`: Token amount in wei

**Returns:** `true` on success

---

### approve

```solidity
function approve(address spender, uint256 amount) public returns (bool)
```

Standard ERC20 approve. Sets the allowance for `spender` to `amount`.

**Parameters:**
- `spender`: Address to approve
- `amount`: Allowance amount in wei. Use `type(uint256).max` for unlimited.

**Returns:** `true` on success

---

### launch

```solidity
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

```solidity
function balanceOf(address account) public view returns (uint256)
```

Returns the token balance of `account`.

### allowance

```solidity
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

```javascript
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

```javascript
// 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

```javascript
// 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.
