> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/Ge0frey/nullgraph/llms.txt
> Use this file to discover all available pages before exploring further.

# Protocol Fees

> Understand NullGraph's 2.5% settlement fee model, treasury distribution, and how fees sustain the protocol's development and growth.

# Protocol Fees

NullGraph uses a **configurable fee mechanism** to sustain protocol development, incentivize participation, and build a treasury for future ecosystem growth.

<Note>
  The default fee is **2.5% (250 basis points)** deducted from every bounty settlement. Fees are routed to a protocol-controlled treasury wallet.
</Note>

## Fee Model Overview

### When Fees Apply

Fees are **only charged on successful bounty settlements** via the `approve_bounty_submission` instruction.

<CardGroup cols={3}>
  <Card title="NKA Submission" icon="upload">
    **No fee** — researchers submit null results for free
  </Card>

  <Card title="Bounty Creation" icon="plus">
    **No fee** — creating bounties is free (only escrow cost)
  </Card>

  <Card title="Bounty Approval" icon="check">
    **2.5% fee** — deducted from reward on settlement
  </Card>
</CardGroup>

### Fee Calculation

Fees are calculated using **basis points** (1 bp = 0.01%):

```rust theme={null}
let fee_bps = protocol.fee_basis_points as u64;  // 250 = 2.5%
let total = bounty.reward_amount;

let fee = total
    .checked_mul(fee_bps)       // total * 250
    .ok_or(NullGraphError::FeeOverflow)?
    .checked_div(10_000)        // ÷ 10,000 = 2.5%
    .ok_or(NullGraphError::FeeOverflow)?;

let payout = total.checked_sub(fee).ok_or(NullGraphError::FeeOverflow)?;
```

**Example:**

```
Bounty Reward: 100 BIO (100_000_000 base units)
Fee (2.5%):      2.5 BIO (2_500_000 base units)
Researcher Gets: 97.5 BIO (97_500_000 base units)
```

<Info>
  All arithmetic uses **checked operations** (`checked_mul`, `checked_div`, `checked_sub`) to prevent overflow and underflow attacks.
</Info>

## Protocol State Configuration

Fees are stored in the global `ProtocolState` singleton:

```rust theme={null}
pub struct ProtocolState {
    pub authority: Pubkey,        // Protocol admin wallet
    pub nka_counter: u64,         // Auto-incrementing NKA counter
    pub bounty_counter: u64,      // Auto-incrementing bounty counter
    pub fee_basis_points: u16,    // Fee on settlement (250 = 2.5%)
    pub treasury: Pubkey,         // Treasury wallet for collected fees
    pub bump: u8,                 // PDA bump seed
}
```

**Seeds:** `["protocol_state"]`

### Initialization

The protocol is initialized once via `initialize_protocol`:

```rust theme={null}
pub fn initialize_protocol(
    ctx: Context<InitializeProtocol>,
    fee_basis_points: u16,
) -> Result<()> {
    let state = &mut ctx.accounts.protocol_state;
    state.authority = ctx.accounts.authority.key();
    state.nka_counter = 0;
    state.bounty_counter = 0;
    state.fee_basis_points = fee_basis_points;  // Set fee rate
    state.treasury = ctx.accounts.treasury.key();  // Set treasury wallet
    state.bump = ctx.bumps.protocol_state;

    emit!(ProtocolInitialized {
        authority: state.authority,
        fee_basis_points,
    });
    Ok(())
}
```

**One-time setup script:**

```typescript theme={null}
const initProtocol = async (
  program: Program,
  authority: Keypair,
  treasuryAddress: PublicKey
) => {
  const [protocolState] = PublicKey.findProgramAddressSync(
    [Buffer.from('protocol_state')],
    program.programId
  );

  const tx = await program.methods
    .initializeProtocol(
      250  // 2.5% fee
    )
    .accounts({
      authority: authority.publicKey,
      protocolState,
      treasury: treasuryAddress,
    })
    .signers([authority])
    .rpc();

  console.log('Protocol initialized with 2.5% fee');
  console.log(`Treasury: ${treasuryAddress.toBase58()}`);
};
```

<Tip>
  The fee rate is **configurable at initialization** but cannot be changed afterward in the current implementation. Future versions may add governance-controlled fee updates.
</Tip>

## Treasury Distribution

### Fee Collection Flow

When a bounty is approved, the vault transfers fees to the treasury in the same transaction:

```rust theme={null}
// Pay researcher (97.5%)
transfer_checked(
    CpiContext::new_with_signer(
        ctx.accounts.token_program.to_account_info(),
        TransferChecked {
            from: ctx.accounts.vault.to_account_info(),
            mint: ctx.accounts.usdc_mint.to_account_info(),
            to: ctx.accounts.researcher_usdc_ata.to_account_info(),
            authority: ctx.accounts.vault.to_account_info(),
        },
        &[vault_seeds],
    ),
    payout,  // 97.5%
    decimals,
)?;

// Pay treasury fee (2.5%)
if fee > 0 {
    transfer_checked(
        CpiContext::new_with_signer(
            ctx.accounts.token_program.to_account_info(),
            TransferChecked {
                from: ctx.accounts.vault.to_account_info(),
                mint: ctx.accounts.usdc_mint.to_account_info(),
                to: ctx.accounts.treasury_usdc_ata.to_account_info(),
                authority: ctx.accounts.vault.to_account_info(),
            },
            &[vault_seeds],
        ),
        fee,  // 2.5%
        decimals,
    )?;
}
```

<Card title="Atomic Settlement" icon="bolt">
  **Both transfers happen in one transaction** — researcher payout and treasury fee are inseparable. Either both succeed or both fail.
</Card>

### Treasury Account Derivation

The treasury receives BIO via its Associated Token Account (ATA):

```typescript theme={null}
import { getAssociatedTokenAddressSync } from '@solana/spl-token';

const treasuryWallet = new PublicKey('TreasuryWalletAddress...');
const BIO_MINT = new PublicKey('BioTokenMintAddress...');

const treasuryAta = getAssociatedTokenAddressSync(
  BIO_MINT,
  treasuryWallet,
  false,  // allowOwnerOffCurve
  TOKEN_2022_PROGRAM_ID
);

// This ATA receives all protocol fees
```

## Fee Breakdown Example

Let's trace a 1000 BIO bounty settlement:

| Step                    | Amount (BIO) | Base Units       | Recipient        |
| ----------------------- | ------------ | ---------------- | ---------------- |
| **Bounty Reward**       | 1000.00      | 1\_000\_000\_000 | Vault (escrowed) |
| **Fee (2.5%)**          | 25.00        | 25\_000\_000     | Treasury         |
| **Researcher Payout**   | 975.00       | 975\_000\_000    | Researcher       |
| **Vault Balance After** | 0.00         | 0                | —                |

**On-chain event:**

```rust theme={null}
emit!(BountyFulfilled {
    bounty_number: 42,
    specimen_number: 17,
    researcher: researcher_pubkey,
    payout: 975_000_000,  // 975 BIO
    fee: 25_000_000,      // 25 BIO
});
```

## Fee Basis Points Explained

| Basis Points | Percentage | Calculation             |
| ------------ | ---------- | ----------------------- |
| `0`          | 0%         | `0 / 10_000 = 0`        |
| `100`        | 1%         | `100 / 10_000 = 0.01`   |
| `250`        | 2.5%       | `250 / 10_000 = 0.025`  |
| `500`        | 5%         | `500 / 10_000 = 0.05`   |
| `1000`       | 10%        | `1_000 / 10_000 = 0.10` |

<Info>
  Basis points provide **precision** for fractional percentages (like 2.5%) using only integer arithmetic — critical for on-chain programs.
</Info>

## Why 2.5%?

NullGraph's fee model balances sustainability with accessibility:

<CardGroup cols={2}>
  <Card title="Lower than DeFi" icon="chart-line">
    Most DeFi protocols charge 3-5% fees. NullGraph's 2.5% is competitive for a scientific data marketplace.
  </Card>

  <Card title="No Creator Fee" icon="hand-holding-dollar">
    Unlike NFT marketplaces, bounty creators pay **zero fees** — only settlement is taxed, incentivizing bounty creation.
  </Card>

  <Card title="Researcher-Friendly" icon="flask">
    97.5% payout ensures researchers capture most of the value they create.
  </Card>

  <Card title="Sustainable Treasury" icon="piggy-bank">
    Fees accumulate in BIO, building a war chest for grants, development, and ecosystem growth.
  </Card>
</CardGroup>

## Treasury Use Cases

Fees collected in the treasury can fund:

* **Protocol Development** — smart contract upgrades, frontend improvements
* **Community Grants** — funding for researchers and BioDAOs
* **Verification Incentives** — rewards for NKA peer review and validation
* **Marketing & Growth** — ecosystem expansion, conference sponsorships
* **Liquidity Mining** — future token incentives for participation

<Note>
  Treasury governance mechanisms are **not yet implemented**. The current treasury wallet is controlled by the protocol authority. Future versions may introduce DAO governance.
</Note>

## Fee Events & Tracking

Every settlement emits a `BountyFulfilled` event with exact fee amounts:

```rust theme={null}
#[event]
pub struct BountyFulfilled {
    pub bounty_number: u64,
    pub specimen_number: u64,
    pub researcher: Pubkey,
    pub payout: u64,     // Amount sent to researcher
    pub fee: u64,        // Amount sent to treasury
}
```

**Indexing example:**

```typescript theme={null}
const connection = new Connection(RPC_URL);
const program = new Program(IDL, PROGRAM_ID, { connection });

program.addEventListener('BountyFulfilled', (event) => {
  const payout = event.payout.toNumber() / 1_000_000;  // BIO
  const fee = event.fee.toNumber() / 1_000_000;        // BIO
  const total = payout + fee;

  console.log(`Bounty NB-${event.bountyNumber} settled:`);
  console.log(`  Total: ${total} BIO`);
  console.log(`  Researcher: ${payout} BIO (${(payout/total*100).toFixed(2)}%)`);
  console.log(`  Treasury: ${fee} BIO (${(fee/total*100).toFixed(2)}%)`);
});
```

## Security: Safe Math

All fee calculations use **checked arithmetic** to prevent exploits:

```rust theme={null}
// SAFE: Uses checked_mul and checked_div
let fee = total
    .checked_mul(fee_bps)
    .ok_or(NullGraphError::FeeOverflow)?
    .checked_div(10_000)
    .ok_or(NullGraphError::FeeOverflow)?;

// SAFE: Uses checked_sub
let payout = total
    .checked_sub(fee)
    .ok_or(NullGraphError::FeeOverflow)?;
```

**Why this matters:**

<CardGroup cols={2}>
  <Card title="Overflow Protection" icon="shield-halved">
    Prevents attackers from causing integer overflow with massive reward amounts
  </Card>

  <Card title="Underflow Protection" icon="shield-check">
    Ensures `payout = total - fee` never underflows (e.g., if fee > total)
  </Card>

  <Card title="Deterministic Failure" icon="circle-exclamation">
    Returns clear `FeeOverflow` error instead of silent corruption
  </Card>

  <Card title="Auditable" icon="magnifying-glass">
    Explicit error handling makes fee logic easy to audit
  </Card>
</CardGroup>

## Frontend Fee Display

Show fee breakdown before settlement:

```typescript theme={null}
const FeeSummary = ({ rewardAmount }: { rewardAmount: number }) => {
  const FEE_BPS = 250;  // 2.5%
  const fee = (rewardAmount * FEE_BPS) / 10_000;
  const payout = rewardAmount - fee;

  return (
    <div className="fee-summary">
      <div className="line">
        <span>Bounty Reward:</span>
        <span>{rewardAmount.toFixed(2)} BIO</span>
      </div>
      <div className="line fee">
        <span>Protocol Fee (2.5%):</span>
        <span>-{fee.toFixed(2)} BIO</span>
      </div>
      <div className="line total">
        <span>You Receive:</span>
        <span>{payout.toFixed(2)} BIO</span>
      </div>
    </div>
  );
};
```

## Querying Treasury Balance

Check total fees collected:

```typescript theme={null}
const getTreasuryBalance = async (
  connection: Connection,
  treasuryWallet: PublicKey,
  bioMint: PublicKey
) => {
  const treasuryAta = getAssociatedTokenAddressSync(
    bioMint,
    treasuryWallet,
    false,
    TOKEN_2022_PROGRAM_ID
  );

  const account = await connection.getTokenAccountBalance(treasuryAta);
  const balance = parseFloat(account.value.uiAmount || '0');

  console.log(`Treasury Balance: ${balance} BIO`);
  return balance;
};
```

## No Fees on Closed Bounties

When a bounty is **closed** (not approved), the full vault balance returns to the creator:

```rust theme={null}
pub fn close_bounty(ctx: Context<CloseBounty>) -> Result<()> {
    // ...
    let vault_balance = ctx.accounts.vault.amount;

    // Refund creator (100% — no fee)
    if vault_balance > 0 {
        transfer_checked(
            // ... transfer full vault_balance to creator ...
        )?;
    }

    emit!(BountyClosed {
        refunded_amount: vault_balance,  // Full amount
    });
    Ok(())
}
```

<Tip>
  Closing a bounty incurs **zero fees** — creators get 100% of their escrowed BIO back. Fees only apply on successful settlements.
</Tip>

## Fee Rate Immutability

The current implementation sets the fee rate **once at initialization**:

* ✅ **Transparent** — fee rate is public, stored on-chain
* ✅ **Predictable** — users know exact fees before transacting
* ❌ **Not governable** — cannot be changed without program upgrade

**Future governance:**

A future version may add:

```rust theme={null}
pub fn update_fee_rate(
    ctx: Context<UpdateFeeRate>,
    new_fee_bps: u16,
) -> Result<()> {
    // Require DAO governance vote or multisig authority
    let state = &mut ctx.accounts.protocol_state;
    state.fee_basis_points = new_fee_bps;
    emit!(FeeRateUpdated { new_fee_bps });
    Ok(())
}
```

## Comparison with Other Protocols

| Protocol      | Fee Model       | Fee Rate           |
| ------------- | --------------- | ------------------ |
| **NullGraph** | Settlement fee  | 2.5%               |
| Uniswap V3    | Swap fee        | 0.05-1% (per swap) |
| OpenSea       | Marketplace fee | 2.5%               |
| Magic Eden    | Marketplace fee | 2%                 |
| Tensor        | Marketplace fee | 1.5% (dynamic)     |
| Aave          | Borrow fee      | Variable (0-8%)    |

<Info>
  NullGraph's 2.5% is **competitive with Web3 marketplace standards** and lower than most DeFi lending protocols.
</Info>

## Next Steps

<CardGroup cols={2}>
  <Card title="BIO Integration" href="/features/bio-integration" icon="coins">
    Learn how BIO tokens power the bounty economy
  </Card>

  <Card title="Bounty Marketplace" href="/features/bounty-marketplace" icon="store">
    Explore the full bounty lifecycle and escrow mechanics
  </Card>
</CardGroup>
