# Overview

KUB is a rapid, secure, and high-performance Layer 1 blockchain network designed to be the foundation for the new era of the internet. KUB functions as an EVM-compatible blockchain network, improving throughput while significantly reducing gas costs and transaction fees.

## Blockchain Network for the New Era of the Internet

KUB aims to democratize blockchain access and build a more inclusive future through innovation. KUB was developed to support real-world applications from developers worldwide, promote the creation of blockchain knowledge, and encourage participation from all sectors of the ecosystem while enhancing the economic value of Southeast Asia. It aims to empower all sectors to develop, innovate, and distribute opportunities through blockchain technology. KUB enables individuals and businesses to:

* Resolve business challenges by forming a network that enables small and large enterprises to operate together
* Convert assets into tokens and non-fungible tokens (NFTs)
* Increase liquidity for illiquid assets with market support
* Provide easily accessible infrastructure for everyone to use the KUB network for real-world applications across business sectors
* Simplify the process of developing smart contracts or applications on the blockchain
* Maintain a balance between permissioned and permissionless networks
* Support developers with both tools and funding to create growth opportunities within the KUB ecosystem

## KUB for Users

| Resource                                            | Description                                                                              |
| --------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| [KUB Ecosystem](https://www.kubchain.com/ecosystem) | A directory of dApps on KUB                                                              |
| [KUB Bridge](/tools/token-bridge)                   | Allows you to move tokens between the selected network and the KUB network               |
| [Delegate KUB Coin](/governance/delegate-kub-coin)  | Delegate KUB Coin to reliable and high-performing validators to promote decentralization |

## KUB for Developers

| Resource                                                             | Description                                                                            |
| -------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| [KUB Developer Center](/build-on-kub/developer-center)               | Access development resources and connect your dApp to KUB                              |
| [Libraries & SDKs](/build-on-kub/libraries-and-sdks)                 | Discover the libraries and SDKs provided by KUB to assist developers                   |
| [KUB Improvement Proposal](/governance/kub-improvement-proposal-kip) | Standardize documentation for the KUB network itself and the conventions built upon it |

## KUB for Node Runners

| Resource                                                     | Description                                                                                      |
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ |
| [Run a Validator Node](/run-a-kub-node/run-a-validator-node) | Propose new blocks and verify transactions following the KUB Proof-of-Stake mechanism            |
| [Run a Full Node](/run-a-kub-node/run-a-full-node)           | Run the latest part of the blockchain state to ensure the stability and operation of the network |
| [Run an Archive Node](/run-a-kub-node/run-an-archive-node)   | Run a node that retains the complete block history of the KUB network                            |


# Connect to KUB

## KUB Wallet

By default, the [KUB Wallet](https://www.kubwallet.com/) supports the KUB Mainnet. With native support for the KUB Mainnet, you can browse dApps directly in your KUB Wallet application.

{% hint style="info" %}
If you are a developer and want to integrate KUB Wallet into your dApp, follow the guide for the [NEXT SDK](/build-on-kub/libraries-and-sdks/next-sdk).
{% endhint %}

## Other wallets

KUB networks can be added as a custom network to any EVM-compatible wallet (i.e., [MetaMask](https://metamask.io/)).

### MetaMask

To add KUB networks as a custom network to MetaMask:

1. Open the MetaMask browser extension.
2. Open the network selection dropdown menu by clicking the dropdown button at the top of the extension.
3. Click the **Add network** button.
4. Click **Add a network manually**.
5. In the **Add a network manually** dialog that appears, enter the following information for the KUB networks:

{% tabs %}
{% tab title="Mainnet" %}

| Name               | Value                     |
| ------------------ | ------------------------- |
| Network Name       | KUB Mainnet               |
| RPC URL            | <https://rpc.kubchain.io> |
| Chain ID           | 96                        |
| Currency Symbol    | KUB                       |
| Block Explorer URL | <https://kubscan.com>     |
| {% endtab %}       |                           |

{% tab title="Testnet" %}

| Name               | Value                             |
| ------------------ | --------------------------------- |
| Network Name       | KUB Testnet                       |
| RPC URL            | <https://rpc-testnet.kubchain.io> |
| Chain ID           | 25925                             |
| Currency Symbol    | tKUB                              |
| Block Explorer URL | <https://testnet.kubscan.com>     |
| {% endtab %}       |                                   |

{% tab title="Layer 2 Mainnet" %}

| Name               | Value                           |
| ------------------ | ------------------------------- |
| Network Name       | KUB Layer 2 Mainnet             |
| RPC URL            | <https://kublayer2.kubchain.io> |
| Chain ID           | 9601                            |
| Currency Symbol    | KUB                             |
| Block Explorer URL | <https://kublayer2.kubscan.com> |
| {% endtab %}       |                                 |

{% tab title="Layer 2 Testnet" %}

| Name               | Value                                   |
| ------------------ | --------------------------------------- |
| Network Name       | KUB Layer 2 Testnet                     |
| RPC URL            | <https://kublayer2.testnet.kubchain.io> |
| Chain ID           | 259251                                  |
| Currency Symbol    | tKUB                                    |
| Block Explorer URL | <https://kublayer2.testnet.kubscan.com> |
| {% endtab %}       |                                         |
| {% endtabs %}      |                                         |

6. Tap the **Save** button to save KUB networks as a network.

You should now be able to connect to the KUB networks by selecting them from the network selection dropdown menu.


# Glossary

This glossary collects key terms used across the KUB Docs.

## A

### Archive node

A node that stores the full block history of the KUB network

## B

### Block explorer

A tool for viewing blocks, transactions, accounts, tokens, and smart contracts on-chain

## C

### Chain ID

A unique network identifier that wallets and apps use to connect to the correct blockchain

## D

### dApp

A decentralized application that runs on a blockchain network

### Delegator

A participant who delegates KUB Coin to a validator or pool node

## E

### ERC

Ethereum Request for Comments. A standard used by Ethereum for tokens and smart contract interfaces

## F

### Fork

A protocol change that updates the rules of the network

### Full node

A node that validates network activity and serves chain data without producing blocks

## G

### Governance

The process used by the KUB community to discuss, approve, and adopt protocol and community changes

## H

### Hard fork

A protocol upgrade that is not backward-compatible with earlier node versions

## K

### KAP

KUB Application Protocol. A standard built for applications and tokens on the KUB network

### KAP-20

A fungible token standard on KUB. It supports features such as `adminTransfer`

### KAP-721

A non-fungible token standard on KUB for unique digital assets

### KAP-1155

A multi-token standard on KUB that supports fungible and non-fungible tokens in one contract

### KIP

KUB Improvement Proposal. A design document used to propose features, standards, and process changes for KUB

### KKUB

Wrapped KUB Coin. Used in wallet and token flows on the KUB network

### KUB

A rapid, secure, and high-performance Layer 1 blockchain network that is EVM-compatible

### KUB Bridge

The native bridge used to move supported assets between KUB and selected networks

### KUB Coin

The native coin of the KUB network. It is used for staking, fees, and network operations

### KUB Developer Center

A platform for submitting dApps to the KUB ecosystem and accessing developer resources

### KUB Faucet

A tool that dispenses free `tKUB` for testing on KUB Testnet

### KUB Layer 2

A Layer 2 network built on top of KUB to increase throughput and reduce costs

### KUB Mainnet

The live production network for KUB

### KUB Scan

The block explorer for KUB Mainnet and KUB Testnet

### KUB Testnet

The public testing network for KUB

### KUB Wallet

A wallet with native support for the KUB network

## L

### Layer 1

The base blockchain that provides the main consensus and settlement layer

### Layer 2

A secondary network built on top of a Layer 1 blockchain to improve scalability

## M

### Mainnet

A live blockchain environment that uses real assets

### MetaMask

An EVM-compatible wallet that can connect to KUB as a custom network

## N

### NEXT SDK

An SDK for integrating dApps with KUB Wallet for authentication, user data access, and blockchain transactions

### NFT

A non-fungible token that represents a unique digital asset

## O

### Official node

A node that steps in to create a block and trigger slashing when a validator misses its duties

### Optimistic rollup

A rollup model that assumes bundled transactions are valid unless challenged with a fraud proof

## P

### Pool node

A validator node that allows other users to delegate KUB Coin to it

### Proof-of-Authority (PoA)

A blockchain consensus mechanism that leverages validator reputation—rather than computational power or financial stake—to secure the network

### Proof-of-Stake (PoS)

KUB's consensus mechanism, where validators and delegators stake KUB Coin to help secure the network

### Proof-of-Stake-Authority (PoSA)

A hybrid blockchain consensus mechanism combining Proof of Stake (PoS) and Proof of Authority (PoA)

## R

### Rollup

A scaling method that bundles many transactions into one compressed transaction submitted to Layer 1

### RPC URL

The endpoint that wallets and apps use to connect to a blockchain network

## S

### Slashing

A penalty applied to validators that fail to perform their duties

### Slashing epoch

The tracking period used to measure validator performance for slashing

### Smart contract

Code deployed on the blockchain that runs automatically when called

### Soft fork

A backward-compatible protocol upgrade

### Span

A unit used by the KUB network to measure validator activity windows

### StakeManager

The core staking contract used for staking, unstaking, rewards, and validator configuration

### Staking

Depositing KUB Coin to activate a validator or participate in network validation

## T

### Testnet

A blockchain environment used for testing without real assets

### tKUB

The testnet version of KUB used on KUB test networks

## V

### Validator

A node or participant that validates transactions and helps secure the KUB network

### ValidatorShare

A contract that manages delegation, undelegation, and delegator rewards for a validator node

## W

### Web3 wallet

A wallet that can connect to blockchain networks and sign transactions

## Z

### ZK rollup

A rollup model that uses cryptographic proofs to verify bundled transactions


# Deploy Smart Contracts on KUB

This walkthrough helps you set up your environment, deploy a smart contract to KUB Testnet, and verify it on [KUB Scan](https://www.kubscan.com/).

## What You'll Achieve

By the end of this quickstart, you'll be able to:

* Set up your development environment to deploy on the KUB Testnet
* Deploy your smart contracts to the KUB Testnet
* Verify your contract on KUB Scan

## Set Up Your Development Environment

Create a new project directory

```bash
mkdir my-kub-project && cd my-kub-project
```

Install Foundry

```bash
curl -L https://foundry.paradigm.xyz | bash
foundryup
```

{% hint style="info" %}
If `curl | bash` installs are blocked in your environment; install via Homebrew instead: `brew install foundry`.
{% endhint %}

Initialize a new Solidity project

```bash
forge init
```

Your Foundry project is now ready. You'll find an example contract below, which we'll use for the rest of this guide.

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

contract Counter {
    uint256 public number;

    function setNumber(uint256 newNumber) public {
        number = newNumber;
    }

    function increment() public {
        number++;
    }
}
```

## Configure Foundry with KUB

To deploy to the KUB network, you need three things: an EVM version setting, a node connection, and a funded private key.

### Target the correct EVM version

The KUB EVM predates the Shanghai upgrade, so it rejects the `PUSH0` opcode that solc 0.8.20 and later emit by default. Without this setting, deployment fails with the cryptic error `invalid opcode: opcode 0x5f not defined`. Add the following to your `foundry.toml` under `[profile.default]`:

```toml
# foundry.toml
evm_version = "paris"
```

{% hint style="info" %}
This compiles your contracts without `PUSH0` while keeping the latest Solidity language features. It applies to every `forge` command in this guide, including verification, so the verified bytecode matches what you deployed.
{% endhint %}

### Set up your node connection

Create a `.env` file in your project root

```bash
KUB_RPC_URL="https://rpc.kubchain.io"
KUB_TESTNET_RPC_URL="https://rpc-testnet.kubchain.io"
```

Load your environment variables

```bash
source .env
```

{% hint style="info" %}
KUB Testnet is the test network we'll use for the rest of this guide. Get free tKUB from the [KUB Faucet](https://faucet.kubchain.com/); it dispenses 5 tKUB to your address every 24 hours. If you wish to deploy to other KUB networks, refer to this [guide](/about-kub/connect-to-kub).
{% endhint %}

### Secure your private key

Store your private key in Foundry's encrypted keystore

```bash
cast wallet import deployer --interactive
```

When prompted, enter your private key and a password. The key is stored in `~/.foundry/keystores`, which is not tracked by git.

{% hint style="warning" %}
Never share or commit your private key. Always keep it secure and handle it with care.
{% endhint %}

### Deploy Your Contracts

Compile and deploy the Counter contract to the KUB Testnet

```bash
forge create ./src/Counter.sol:Counter --rpc-url $KUB_TESTNET_RPC_URL --account deployer --broadcast --legacy
```

{% hint style="info" %}
The `--legacy` flag is required. KUB does not support EIP-1559 fee estimation, so `forge create` without it fails with "Failed to estimate EIP1559 fees". `--legacy` sends a pre-EIP-1559 transaction with a plain gas price instead.
{% endhint %}

After a successful deployment, the transaction hash and contract address are printed to the console. Add the address to your `.env`

```bash
COUNTER_CONTRACT_ADDRESS="0x..."
```

Reload the environment

```bash
source .env
```

### Verify Your Deployment

Check the transaction on [KUB Testnet](https://testnet.kubscan.com/) and read the initial counter value from the command line

```bash
cast call $COUNTER_CONTRACT_ADDRESS "number()(uint256)" --rpc-url $KUB_TESTNET_RPC_URL
```

This should return `0`, the initial value of the Counter's `number` storage variable.

## Verify the Source Code on KUB Scan

Verify the source code on KUB Scan with Foundry using the following command line

```bash
forge verify-contract $COUNTER_CONTRACT_ADDRESS ./src/Counter.sol:Counter \
  --verifier blockscout \
  --verifier-url https://testnet.kubscan.com/api \
  --rpc-url $KUB_TESTNET_RPC_URL
```

{% hint style="info" %}
For KUB Mainnet, swap the verifier URL to `https://www.kubscan.com/api`.
{% endhint %}

{% hint style="warning" %}
The KUB Scan API enforces a rate limit of 12 requests per minute per IP. Exceeding it blocks the IP for 1 minute.
{% endhint %}

Congratulations! You've deployed and verified a smart contract on KUB Testnet.

## Next Steps

* Use [wagmi](https://wagmi.sh) or [viem](https://viem.sh) to connect your frontend to your contracts (see this guide).
* Launch a token with the KAP standard (see this guide).
* Submit your app to the [KUB Developer Center](https://developers.kubchain.com/) to be showcased in the KUB Ecosystem.


# Build an App on KUB

This guide walks you through building an on-chain demo Tally app on the KUB Testnet: connecting wallets, reading and writing to a deployed counter contract, and understanding when to reach for the KUB SDK instead of standard wallet connectors.

## What you will build

* A [Next.js](https://nextjs.org/) app that connects EVM wallets (MetaMask and other injected wallets)
* Contract reads and writes
* An understanding of the two wallets on KUB: standard Web3 wallets and KUB Wallet

## Start Building

### Set up your project

```bash
npx create-next-app@latest my-kub-app --typescript --tailwind --app
cd my-kub-app
npm install wagmi viem @tanstack/react-query
```

### Define the KUB networks and configure Wagmi

[viem](https://github.com/wagmi-dev/viem/tree/main/src/chains/index.ts) ships chain definitions for KUB (exported as `bitkub` / `bitkubTestnet` in `viem/chains`Check your installed version. Defining the chains explicitly with `defineChain` also works on any version and makes the config self-documenting:

```typescript
// config/chains.ts
import { defineChain } from 'viem'

export const kubTestnet = defineChain({
  id: 25925,
  name: 'KUB Testnet',
  nativeCurrency: { name: 'tKUB', symbol: 'tKUB', decimals: 18 },
  rpcUrls: {
    default: { http: ['https://rpc-testnet.kubchain.io'] },
  },
  blockExplorers: {
    default: { name: 'KUB Scan Testnet', url: 'https://testnet.kubscan.com' },
  },
  testnet: true,
})

export const kubMainnet = defineChain({
  id: 96,
  name: 'KUB Mainnet',
  nativeCurrency: { name: 'KUB', symbol: 'KUB', decimals: 18 },
  rpcUrls: {
    default: { http: ['https://rpc.kubchain.io'] },
  },
  blockExplorers: {
    default: { name: 'KUB Scan', url: 'https://kubscan.com' },
  },
})
```

```typescript
// config/wagmi.ts
import { http, createConfig, createStorage, cookieStorage } from 'wagmi'
import { injected } from 'wagmi/connectors'
import { kubTestnet } from './chains'

export const config = createConfig({
  chains: [kubTestnet],
  connectors: [injected()],
  storage: createStorage({ storage: cookieStorage }),
  ssr: true,
  transports: {
    [kubTestnet.id]: http('https://rpc-testnet.kubchain.io'),
  },
})

declare module 'wagmi' {
  interface Register {
    config: typeof config
  }
}
```

{% hint style="info" %}
`ssr: true` combined with `cookieStorage` prevents Next.js hydration mismatches. This pairs with the `cookieToInitialState` call in the root layout below, which restores the connection state on the server so it does not flash on load. The injected connector handles browser extension wallets like MetaMask, which connect to KUB as a custom network.
{% endhint %}

### Wrap your app in the providers

The providers component accepts an `initialState` prop so the layout can pass in the connection state recovered from cookies:

```typescript
// app/providers.tsx
'use client'

import { WagmiProvider, type State } from 'wagmi'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { type ReactNode } from 'react'
import { config } from '@/config/wagmi'

const queryClient = new QueryClient()

export function Providers({
  children,
  initialState,
}: {
  children: ReactNode
  initialState?: State
}) {
  return (
    <WagmiProvider config={config} initialState={initialState}>
      <QueryClientProvider client={queryClient}>
        {children}
      </QueryClientProvider>
    </WagmiProvider>
  )
}
```

### Wire the providers into the root layout

Wrap `{children}` with `Providers` in `app/layout.tsx`. This step is required: any component calling a wagmi hook outside `WagmiProvider` crashes at runtime with `useConfig must be used within WagmiProvider`. Reading the cookie here and converting it with `cookieToInitialState` completes the SSR setup, so a returning user's connection state is already correct on first render instead of flashing through `Reconnecting...`:

```typescript
// app/layout.tsx
import type { Metadata } from 'next'
import { headers } from 'next/headers'
import { cookieToInitialState } from 'wagmi'
import { config } from '@/config/wagmi'
import { Providers } from './providers'
import './globals.css'

export const metadata: Metadata = {
  title: 'Onchain Tally',
}

export default async function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  const initialState = cookieToInitialState(
    config,
    (await headers()).get('cookie')
  )

  return (
    <html lang="en">
      <body>
        <Providers initialState={initialState}>{children}</Providers>
      </body>
    </html>
  )
}
```

{% hint style="info" %}
`headers()` is asynchronous in recent Next.js versions, so the root layout is declared `async` and the call is awaited. If you are on an older Next.js where `headers()` is synchronous, drop the `await`.
{% endhint %}

### Connect wallets

```typescript
// components/ConnectWallet.tsx
'use client'

import { useAccount, useConnect, useDisconnect } from 'wagmi'

export function ConnectWallet() {
  const { address, isConnected, isConnecting, isReconnecting } = useAccount()
  const { connect, connectors } = useConnect()
  const { disconnect } = useDisconnect()

  if (isReconnecting) return <div>Reconnecting...</div>

  if (!isConnected) {
    return (
      <div className="flex flex-col gap-2">
        {connectors.map((connector) => (
          <button
            key={connector.uid}
            onClick={() => connect({ connector })}
            disabled={isConnecting}
          >
            Connect {connector.name}
          </button>
        ))}
      </div>
    )
  }

  return (
    <div className="flex items-center gap-3">
      <span className="font-mono text-sm">
        {address?.slice(0, 6)}...{address?.slice(-4)}
      </span>
      <button onClick={() => disconnect()}>Disconnect</button>
    </div>
  )
}
```

{% hint style="info" %}
`useAccount` exposes four states: `isConnecting`, `isReconnecting`, `isConnected`, and `isDisconnected`. Checking only `isConnected` causes UI flashes on page load. Ensure you handle all four states.
{% endhint %}

### Deploy the contract

Follow this guide to deploy `Counter.sol` to KUB Testnet with Foundry, funded by the [KUB Faucet](https://faucet.kubchain.com/). Please take note of the deployed address.

{% hint style="warning" %}
Fund the account you will connect with in the browser too. The deployer key pays for the contract deployment, but clicking **Increment** later spends gas from your MetaMask account, which starts empty. Request tKUB from the [KUB Faucet](https://faucet.kubchain.com/) for that address as well — the faucet dispenses 5 tKUB per address every 24 hours.
{% endhint %}

### Read contract data

```typescript
// config/counter.ts
export const COUNTER_ADDRESS = '0x...' as const

export const counterAbi = [
  {
    type: 'function',
    name: 'number',
    inputs: [],
    outputs: [{ name: '', type: 'uint256' }],
    stateMutability: 'view',
  },
  {
    type: 'function',
    name: 'increment',
    inputs: [],
    outputs: [],
    stateMutability: 'nonpayable',
  },
] as const
```

{% hint style="info" %}
`as const` is required. Without it, wagmi cannot infer function names, argument types, or return types from the ABI.
{% endhint %}

```typescript
// components/CounterDisplay.tsx
'use client'

import { useReadContract } from 'wagmi'
import { kubTestnet } from '@/config/chains'
import { COUNTER_ADDRESS, counterAbi } from '@/config/counter'

export function CounterDisplay() {
  const { data: count, isLoading, isError } = useReadContract({
    address: COUNTER_ADDRESS,
    abi: counterAbi,
    functionName: 'number',
    chainId: kubTestnet.id,
  })

  if (isLoading && count === undefined) return <p>Loading...</p>
  if (isError && count === undefined) return <p>Failed to read contract</p>

  return <p className="text-5xl font-bold">{count?.toString()}</p>
}
```

### Write to the contract

```typescript
// components/IncrementButton.tsx
'use client'

import { useEffect } from 'react'
import {
  useWriteContract,
  useWaitForTransactionReceipt,
  useChainId,
  useSwitchChain,
} from 'wagmi'
import { readContractQueryOptions } from 'wagmi/query'
import { useQueryClient } from '@tanstack/react-query'
import { config } from '@/config/wagmi'
import { kubTestnet } from '@/config/chains'
import { COUNTER_ADDRESS, counterAbi } from '@/config/counter'

export function IncrementButton() {
  const chainId = useChainId()
  const { switchChain, isPending: isSwitching } = useSwitchChain()
  const { data: hash, isPending, writeContract } = useWriteContract()
  const { isLoading: isConfirming, isSuccess } =
    useWaitForTransactionReceipt({ hash })
  const queryClient = useQueryClient()

  useEffect(() => {
    if (isSuccess) {
      queryClient.invalidateQueries({
        queryKey: readContractQueryOptions(config, {
          address: COUNTER_ADDRESS,
          abi: counterAbi,
          functionName: 'number',
          chainId: kubTestnet.id,
        }).queryKey,
      })
    }
  }, [isSuccess, queryClient])

  if (chainId !== kubTestnet.id) {
    return (
      <button onClick={() => switchChain({ chainId: kubTestnet.id })}>
        {isSwitching ? 'Switching...' : 'Switch to KUB Testnet'}
      </button>
    )
  }

  return (
    <div>
      <button
        onClick={() =>
          writeContract({
            address: COUNTER_ADDRESS,
            abi: counterAbi,
            functionName: 'increment',
            chainId: kubTestnet.id,
          })
        }
        disabled={isPending || isConfirming}
      >
        {isPending
          ? 'Confirm in Wallet...'
          : isConfirming
          ? 'Confirming...'
          : 'Increment'}
      </button>
      {isSuccess && <p>Confirmed!</p>}
      {hash && (
        <a href={`https://testnet.kubscan.com/tx/${hash}`} target="_blank">
          View on KUB Scan
        </a>
      )}
    </div>
  )
}
```

{% hint style="info" %}
Without `useSwitchChain`, calling `writeContract` while the wallet is on the wrong network causes wagmi to attempt a background chain switch. If the user misses the wallet popup, the button stays at "Confirm in Wallet..." indefinitely with no error and no recovery path. Since KUB is a custom network in MetaMask, users landing on your app for the first time are very often on the wrong chain; handle this state.
{% endhint %}

### Assemble the page

```typescript
// app/page.tsx
import { ConnectWallet } from '@/components/ConnectWallet'
import { CounterDisplay } from '@/components/CounterDisplay'
import { IncrementButton } from '@/components/IncrementButton'

export default function Home() {
  return (
    <main className="min-h-screen flex flex-col items-center justify-center gap-8 p-8">
      <h1 className="text-3xl font-bold">Onchain Tally</h1>
      <ConnectWallet />
      <CounterDisplay />
      <IncrementButton />
    </main>
  )
}
```

```bash
npm run dev
```

### Optional: Reach KUB Wallet users with the NEXT SDK

The integration differs from the wagmi flow in two important ways:

1. Install `@bitkub-chain/sdk.js`, initialize it with a Client ID and Project ID (from the [KUB Playground](https://playground.kubchain.com/) for KUB Testnet), and authenticate users via OAuth rather than a wallet popup

```typescript
import { initializeSDK, Network } from '@bitkub-chain/sdk.js'

const sdk = initializeSDK(clientID, projectID, Network.BKC_TESTNET, {
  loginRedirectPath: '/oauth/callback',
})

await sdk.loginWithBitkubNext()
const address = await sdk.getUserWalletAddress()
```

2. KUB Wallet users transact through the CallHelper router, so any write function they call needs an extra trailing `address _bitkubNext` parameter and a guard restricting the caller to the SDK CallHelper Router

```solidity
function increment(address _bitkubNext) external onlySdkCallHelperRouter {
    number++;
}

modifier onlySdkCallHelperRouter() {
    require(msg.sender == sdkCallHelperRouter, "Authorization: restricted only SDK CallHelper Router");
    _;
}
```

Transactions then go through `sdk.sendCustomTx(toAddress, functionReadableABI, methodParams)` rather than `writeContract`. A production KUB app typically supports both paths: wagmi/injected for MetaMask users, NEXT SDK for KUB Wallet users. See the [NEXT SDK](https://docs.kubchain.com/build-on-kub/libraries-and-sdks/next-sdk) and the [Code Cookbook](https://docs.kubchain.com/build-on-kub/libraries-and-sdks/next-sdk/code-cookbook) for working examples.

## Next Steps

* **Go to KUB Mainnet:** add `kubMainnet` to your `chains` array and transports, redeploy your contract, and update `COUNTER_ADDRESS`.
* **Scale on KUB Layer 2:** the rollup-based L2 (chain ID 9601 mainnet / 259251 testnet) offers lower costs for high-frequency apps; bridge tKUB from the faucet flow to the L2 testnet to experiment.
* **Bridge assets in:** [KUB Bridge](https://bridge.kubchain.com/en) supports Ethereum, BNB Smart Chain, and JFIN Chain, so users can bring assets to your app.
* **Get listed:** submit your dApp via the [KUB Developer Center](https://developers.kubchain.com/) to appear in the KUB Ecosystem directory.


# Launching a Token on KUB

When launching a token on KUB, you can choose between two standards: KAP-20 or ERC-20. This guide will help you decide which option suits your needs and provide a step-by-step process for deploying a KAP-20 token.

## Choosing Your Launch Path

### KAP-20

KAP-20 is the fungible token standard specific to KUB, based on the ERC-20 model but tailored with unique KUB features. Opt for KAP-20 if you require:

* **KUB Wallet Compatibility** - Utilize KYC-aware processes to seamlessly integrate KUB Wallet into your project.
* **Asset Recovery** - This feature allows the token's governance committee to reverse fraudulent transactions (e.g., following a legal directive), giving token developers control over recovery actions.
* **Ecosystem Alignment** - Tokens such as kKUB, kBTC, kETH, and others in the KUB ecosystem use the KAP-20 standard.

KAP-20 operates at the contract level: you’ll deploy the official version from [kub-chain/kub-contracts](https://www.npmjs.com/package/@kub-chain/contracts) and connect it to a shared set of contracts (including the KYC registry, AdminProjectRouter, and TransferRouter).

### ERC-20

The KUB network also supports ERC standard tokens. Use a standard [OpenZeppelin ERC-20](https://docs.openzeppelin.com/contracts/5.x/api/token/erc20) token if you need:

* **Consistency with Other EVM Chains** - Ensure your token functions identically to those deployed on different EVM networks.
* **No Admin Recovery or KYC Functions** - Keep your contract simpler without these additional complexities.
* **Minimal Constructor Surface** - Reduce the number of parameters required for deployment.

Deploying an ERC-20 token follows the same process as on any EVM chain: just adhere to the typical deployment guidelines with your OpenZeppelin contract.


# Launch a KAP Token

Use this guide to launch a KAP standard token on KUB with the published [@kub-chain/contracts](https://www.npmjs.com/package/@kub-chain/contracts) package. It helps you choose the right KAP token standard, prepare the required KUB network inputs, and import the official KAP implementations into your project. Use the table below to map each KAP standard to its package path before you build or deploy.

| Standard | Package Path                                     |
| -------- | ------------------------------------------------ |
| KAP-20   | `@kub-chain/contracts/contracts/token/KAP-20/`   |
| KAP-22   | `@kub-chain/contracts/contracts/token/KAP-22/`   |
| KAP-721  | `@kub-chain/contracts/contracts/token/KAP-721/`  |
| KAP-1155 | `@kub-chain/contracts/contracts/token/KAP-1155/` |

{% hint style="info" %}
Deploy to KUB Testnet first. Move to KUB Mainnet only after you validate deployment, transfers, access control, and admin behavior.
{% endhint %}

## Prerequisites

Prepare these before you deploy:

* A wallet with `tKUB` for KUB Testnet from the [KUB Faucet](/tools/testnet-faucet) (or `KUB` for KUB Mainnet)
* Node.js and a package manager such as `npm`, `pnpm`, or `yarn`
* A development environment such as [Hardhat](https://hardhat.org/), [Foundry](https://www.getfoundry.sh/), or [Remix IDE](https://remix.ethereum.org/)
* KAP contracts from [@kub-chain/contracts](https://www.npmjs.com/package/@kub-chain/contracts)
* [KAP infrastructure contract addresses](#kap-infrastructure-contract-addresses)
* KUB network details from [Connect to KUB](/about-kub/connect-to-kub)

### KAP Infrastructure Contract Addresses

Use these values when preparing deployment inputs.

{% tabs %}
{% tab title="KUB Mainnet" %}

| Property             | Value                                        |
| -------------------- | -------------------------------------------- |
| `projectName`        | `kap20-token`                                |
| `kyc`                | `0x409CF41ee862Df7024f289E9F2Ea2F5d0D7f3eb4` |
| `adminProjectRouter` | `0x15122c945763da4435b45E082234108361B64eBA` |
| `committee`          | `0x5106ffca7cC44E6cFfEE9bD016A0934130b0322f` |
| `transferRouter`     | `0xFbf5b70ef07AE6F64D3796f8a0fE83A3579FAb6f` |
| `acceptedKYCLevel`   | `4`                                          |
| {% endtab %}         |                                              |

{% tab title="KUB Testnet" %}

| Property             | Value                                        |
| -------------------- | -------------------------------------------- |
| `projectName`        | `kap20-token`                                |
| `kyc`                | `0x988bC9c05f0e0fBC198a5DB0Bd62ca90DC3e1b05` |
| `adminProjectRouter` | `0x6F0f1CAfE5560d9658833490eE999fa731708346` |
| `committee`          | `Your Developer Address`                     |
| `transferRouter`     | `0x4d61aFc68520E0f0Ccbd1A599dd0dC97E2B3B04B` |
| `acceptedKYCLevel`   | `4`                                          |
| {% endtab %}         |                                              |
| {% endtabs %}        |                                              |

## Example: Deploying KAP-20 Token

This example provides step-by-step instructions for deploying a KAP-20 token. For other token standards, you may follow the same deployment pattern. Make sure to review the [KAP token interfaces](/quickstart/launching-a-token-on-kub/kap-token-interfaces) before deploying your token.

### Step-by-Step Deployment for KUB Testnet

#### Step 1: Configure the network

**Example Hardhat Network Configuration**

```javascript
module.exports = {
  solidity: "0.8.20",
  networks: {
    kubTestnet: {
      url: "https://rpc-testnet.kubchain.io",
      chainId: 25925,
      accounts: [process.env.PRIVATE_KEY]
    },
    kubMainnet: {
      url: "https://rpc.kubchain.io",
      chainId: 96,
      accounts: [process.env.PRIVATE_KEY]
    }
  }
};
```

**Example Foundry RPC Configuration**

```toml
[rpc_endpoints]
kub_testnet = "https://rpc-testnet.kubchain.io"
kub_mainnet = "https://rpc.kubchain.io"
```

If you use the [Remix IDE](https://remix.ethereum.org/), switch the environment to **Injected Provider - MetaMask** and connect to the KUB Testnet as described in this [guide](/about-kub/connect-to-kub).

#### Step 2: Install the package

Install the published contracts package in your project.

{% tabs %}
{% tab title="npm" %}

```bash
npm install @kub-chain/contracts
```

{% endtab %}

{% tab title="pnpm" %}

```bash
pnpm add @kub-chain/contracts
```

{% endtab %}

{% tab title="yarn" %}

```bash
yarn add @kub-chain/contracts
```

{% endtab %}
{% endtabs %}

Import the KAP-20 base contract into your token contract.

```solidity
import "@kub-chain/contracts/contracts/token/KAP-20/KAP20.sol";
```

If you build with Foundry, add a remapping by creating or editing `remappings.txt` at the project root.

```
@kub-chain/contracts/=node_modules/@kub-chain/contracts/
```

Then use the same import path in your Solidity files.

{% hint style="info" %}
Run your package manager install before `forge build`, so Foundry can resolve `node_modules`.
{% endhint %}

If you use Remix IDE, work from a local project that already has `@kub-chain/contracts` installed, then compile the same import path there.

#### Step 3: Compile the contract

Compile using the Solidity version required by the KAP contract you imported.

**Example Hardhat Command**

```bash
npx hardhat compile
```

**Example Foundry Command**

```bash
forge build
```

In Remix IDE, open the **Solidity Compiler** tab, set the version to `0.8.20` and compile.

{% hint style="warning" %}
Set the Solidity version to ^0.8.0 (e.g., 0.8.20). A version mismatch results in a compilation failure.
{% endhint %}

#### Step 4: Set the constructor and mint inputs

Prepare these values before deployment. Review the token interface definitions in the [KAP Token Interfaces](/quickstart/launching-a-token-on-kub/kap-token-interfaces) section.

* `name`
* `symbol`
* `decimals`
* `initialSupply`
* `projectName`
* `kyc`
* `adminProjectRouter`
* `committee`
* `transferRouter`
* `acceptedKYCLevel`

#### Step 5: Deploy to KUB Testnet

**Example Hardhat Deployment Call**

```bash
npx hardhat run scripts/deploy.js --network kubTestnet
```

**Example Hardhat Deployment Script**

```javascript
async function main() {
  const Token = await ethers.getContractFactory("MyKAP20Token");
  const token = await Token.deploy(
    "0x988bC9c05f0e0fBC198a5DB0Bd62ca90DC3e1b05",
    "0x6F0f1CAfE5560d9658833490eE999fa731708346",
    "0xYourDeveloperAddress",
    "0x4d61aFc68520E0f0Ccbd1A599dd0dC97E2B3B04B"
  );
  await token.waitForDeployment();
  console.log(await token.getAddress());
}

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});
```

**Example Foundry Deployment Call**

```bash
forge create src/MyKAP20Token.sol:MyKAP20Token \
  --rpc-url kub_testnet \
  --private-key $PRIVATE_KEY \
  --broadcast \
  --constructor-args \
  0x988bC9c05f0e0fBC198a5DB0Bd62ca90DC3e1b05 \
  0x6F0f1CAfE5560d9658833490eE999fa731708346 \
  0xYourDeveloperAddress \
  0x4d61aFc68520E0f0Ccbd1A599dd0dC97E2B3B04B
```

**For Remix IDE**

1. Open **Deploy & Run Transactions**.
2. Set **Environment** to **Injected Provider - MetaMask**.
3. Select your compiled token contract.
4. Enter the constructor arguments for KUB Testnet.
5. Confirm that MetaMask is connected to **KUB Testnet**.
6. Click **Deploy**, then confirm the transaction in your wallet.
7. Copy the deployed contract address from **Deployed Contracts** or the Remix terminal.
8. Save the deployment transaction hash for later verification.

#### Step 6: Validate on KUB Testnet

Check the deployed token before deploying to the KUB Mainnet.

```solidity
token.name()
token.symbol()
token.decimals()
token.totalSupply()
token.balanceOf(deployer)
```

Then test the following:

* `transfer`
* `approve`
* `transferFrom`
* `adminTransfer`

If your contract integrates KYC-gated flows, also test

* `internalTransfer`
* `externalTransfer`

Keep the deployed address and constructor values. You will need them again for verification.

#### Step 7: Deploy to KUB Mainnet

After testnet validation, update your deployment inputs for KUB Mainnet and redeploy.

**Example Hardhat Command**

```bash
npx hardhat run scripts/deploy.js --network kubMainnet
```

**Example Foundry Command**

```bash
forge create src/MyKAP20Token.sol:MyKAP20Token \
  --rpc-url kub_mainnet \
  --private-key $PRIVATE_KEY \
  --broadcast \
  --constructor-args \
  0x409CF41ee862Df7024f289E9F2Ea2F5d0D7f3eb4 \
  0x15122c945763da4435b45E082234108361B64eBA \
  0x5106ffca7cC44E6cFfEE9bD016A0934130b0322f \
  0xFbf5b70ef07AE6F64D3796f8a0fE83A3579FAb6f
```

**For Remix IDE**

1. Switch MetaMask to **KUB Mainnet**.
2. Update the constructor arguments to the KUB Mainnet values.
3. Open **Deploy & Run Transactions** and confirm the **Environment** is still **Injected Provider - MetaMask**.
4. Select the same compiled contract used on testnet.
5. Deploy again from **Deploy & Run Transactions**.
6. Confirm the transaction in MetaMask.
7. Save the new contract address from the Remix terminal, **Deployed Contracts**, or MetaMask activity.

#### Step 8: Verify on KUB Scan

Verify the deployed contract on KUB Scan after deployment. If you deployed with Remix IDE, use the same compiler version and optimization settings that you used in the **Solidity Compiler** tab. KUB Scan supports viewing, verifying, and interacting with contract source code. See [Block Explorer](/tools/block-explorer) for more information.

**Explorers:**

* [KUB Mainnet](https://kubscan.com/)
* [KUB Testnet](https://testnet.kubscan.com/)

**Keep these values ready:**

* Contract Address
* Compiler Version
* Exact Source Files
* Constructor Arguments

### Post-Deployment

After deployment and verification, it is essential to confirm the token metadata in the block explorer. Be sure to record important details such as the contract address, deployment transaction hash, ABI, and source version. Once these details are documented, import the token into your wallet for testing purposes. It is crucial to test user-facing transfers and allowances to ensure everything functions correctly. Additionally, monitoring relevant `Transfer` and `Approval` events will help ensure that the token operates as intended.


# KAP Token Interfaces

Smart contract token interfaces define the external surface of a token contract. They tell wallets, dApps, explorers, and other contracts which functions and events they can rely on. An interface does not describe internal storage or implementation details. It defines the public contract between your token and every integration around it.

On KUB, token interfaces are commonly defined through [KUB Application Protocol (KAP)](/build-on-kub/kub-application-protocol-kap) standards. KAP extends familiar ERC patterns with KUB-specific roles, KYC-aware transfer flows, and admin-controlled recovery functions where required.

## What Token Interface Includes

A token interface usually defines:

* Read functions such as `balanceOf`, `name`, and `symbol`
* Write functions such as `transfer`, `approve`, and `transferFrom`
* Events such as `Transfer` and `Approval`
* Expected behavior for approvals, transfers, and ownership

## Why It Matters

Interfaces make integrations predictable. They let wallets display balances and metadata. They let dApps request approvals and submit transfers. They let developers verify whether a token supports the behavior they need before integrating it. On KUB, interfaces also help clarify KUB-specific token behavior. KAP standards add functions such as `adminTransfer`, `internalTransfer`, and `externalTransfer`. These functions are not part of standard ERC token interfaces.

## KAP Token Interfaces

Use these KAP interface pages when you need the exact function and event definitions for a token standard on KUB:

* [KAP-20](/quickstart/launching-a-token-on-kub/kap-token-interfaces/kap-20) - Fungible token interface for KUB with KYC-aware transfer flows and `adminTransfer`
* [KAP-721](/quickstart/launching-a-token-on-kub/kap-token-interfaces/kap-721) - Non-fungible token interface for unique assets on KUB
* [KAP-1155](/quickstart/launching-a-token-on-kub/kap-token-interfaces/kap-1155) - Multi-token interface for fungible and non-fungible assets in one contract
* [KAP-22](/quickstart/launching-a-token-on-kub/kap-token-interfaces/kap-22) - Loyalty points token interface built on KAP-20 with periods and token expiration

## How To Use the Interface Pages

Use the interface page when you need to:

* Check supported functions and events
* Review token behavior before integration
* Compare standards before choosing one

Choose the token standard that matches your use case, then review its interface in detail before you deploy or integrate it.


# KAP-20

The following standard outlines a smart contract interface and logic for fungible tokens on KUB that supports an `adminTransfer` function designed to create transactions on behalf of token holders if they have been a victim of a fraudulent transaction. It is proposed by deriving the ERC-20 standard of Ethereum with additional functions related to `adminTransfer`.

## Token Interface

### IAdminProjectRouter

#### isSuperAdmin

Check whether `_addr` is the Super Admin role in `_project`.

```solidity
function isSuperAdmin(address _addr, string calldata _project) external view returns (bool)
```

#### isAdmin

Check whether `_addr` is the Admin role in `_project`.

```solidity
function isAdmin(address _addr, string calldata _project) external view returns (bool)
```

### IKYCBitkubChain

#### kycsLevel

Returns the KYC Level of `_addr`

```solidity
function kycsLevel(address _addr) external view returns (uint256)
```

### IKAP20

#### totalSupply

Returns the total token supply.

```solidity
function totalSupply() external view returns (uint256)
```

#### decimals

Returns the number of decimals the token uses - e.g. `8`, means to divide the token amount by `100000000` to get its user representation.

```solidity
function decimals() external view returns (uint8)
```

{% hint style="info" %}
NOTE: This method is optional in ERC-20. In KAP-20, this is a required method.
{% endhint %}

#### symbol

Returns the symbol of the token. E.g. "HIX".

```solidity
function symbol() external view returns (string memory)
```

{% hint style="info" %}
NOTE: This method is optional in ERC-20. In KAP-20, this is a required method.
{% endhint %}

#### name

Returns the name of the token - e.g.`"MyToken"`.

```solidity
function name() external view returns (string memory)
```

{% hint style="info" %}
NOTE: This method is optional in ERC-20. In KAP-20, this is a required method.
{% endhint %}

#### balanceOf

Returns the account balance of another account with address `account`.

```solidity
function balanceOf(address account) external view returns (uint256)
```

{% hint style="info" %}
NOTE: This method is optional in ERC-20. In KAP-20, this is a required method.
{% endhint %}

#### transfer

Transfers `amount` amount of tokens to address `recipient`, and MUST fire the `Transfer` event. The function SHOULD `throw` if the message caller's account balance does not have enough tokens to spend.

```solidity
function transfer(address recipient, uint256 amount) external returns (bool)
```

{% hint style="info" %}
NOTE: Transfers of 0 values MUST be treated as normal transfers and fire the `Transfer` event.
{% endhint %}

#### allowance

Returns the amount which `spender` is still allowed to withdraw from `owner`.

```solidity
function allowance(address owner, address spender) external view returns (uint256)
```

#### approve

Allows `spender` to withdraw from your account multiple times, up to the `amount` amount. If this function is called again, it overwrites the current allowance with `amount`.

```solidity
function approve(address spender, uint256 amount) external returns (bool)
```

{% hint style="info" %}
NOTE: To prevent attack vectors, clients SHOULD make sure to create user interfaces in such a way that they set the allowance first to 0 before setting it to another value for the same spender. THOUGH The contract itself shouldn't enforce it, to allow backwards compatibility with contracts deployed before
{% endhint %}

#### adminApprove

Allows `spender` to withdraw from `owner` account multiple times, up to the `amount` amount. If this function is called again it overwrites the current allowance with `amount`. This method works similarly to the `approve` method.

```solidity
function adminApprove(address owner, address spender, uint256 amount) external returns (bool)
```

{% hint style="info" %}
NOTE: This function can only be called by the Admin and Super Admin. This function is designed to create transactions automatically on behalf of token holders if they have been a victim of a fraudulent transaction.
{% endhint %}

#### transferFrom

Transfers `amount` amount of tokens from address `sender` to address `recipient`, and MUST fire the Transfer event.

The `transferFrom` method is used for a withdraw workflow, allowing contracts to transfer tokens on your behalf. This can be used for example, to allow a contract to transfer tokens on your behalf and/or to charge fees in sub-currencies. The function SHOULD `throw` unless the `sender` account has deliberately authorized the sender of the message via some mechanism.

```solidity
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool)
```

{% hint style="info" %}
NOTE: Transfers of 0 values MUST be treated as normal transfers and fire the `Transfer` event.
{% endhint %}

#### adminTransfer

Transfers `amount` amount of tokens from address `sender` to address `recipient`, and MUST fire the Transfer event.

```solidity
function adminTransfer(address sender, address recipient, uint256 amount) external returns (bool)
```

{% hint style="info" %}
NOTE: This function can only be called by the Committee address required in the constructor. This function is designed to create transactions automatically on behalf of token holders if they have been victims of a fraudulent transaction. This method works similarly to the `transferFrom` method.
{% endhint %}

### Events

#### Transfer

MUST trigger when tokens are transferred, including zero value transfers.

A token contract which creates new tokens SHOULD trigger a Transfer event with the `from` address set to `0x0` when tokens are created.

```solidity
event Transfer(address indexed from, address indexed to, uint256 value)
```

#### Approval

MUST trigger on any successful call to `approve(address spender, uint256 value)`.

```solidity
event Approval(address indexed owner, address indexed spender, uint256 value)
```

### IKToken

#### internalTransfer

Transfers `amount` amount of tokens to address `recipient` internally from `sender`, and MUST fire the `Transfer` event. The function SHOULD `throw` if the message caller's account balance does not have enough tokens to spend. Tokens can be transferred between internal addresses that have completed KYC for both the sender and the recipient using the internalTransfer function.

```solidity
function internalTransfer(address sender, address recipient, uint256 amount) external returns (bool)
```

{% hint style="info" %}
NOTE: This function can only be called by the Super Admin and the Transfer Router.
{% endhint %}

#### externalTransfer

Transfers `amount` amount of tokens to address `recipient` externally from `sender`, and MUST fire the `Transfer` event. The function SHOULD `throw` if the message caller's account balance does not have enough tokens to spend. The function externalTransfer allows tokens to be transferred between addresses that have only passed the sender's KYC verification process.

```solidity
function externalTransfer(address sender, address recipient, uint256 amount) external returns (bool)
```

{% hint style="info" %}
NOTE: This function can only be called by the Super Admin and the Transfer Router.
{% endhint %}


# KAP-721

The following standard outlines a smart contract interface and logic for non-fungible tokens on KUB that supports an `adminTransfer` function designed to create transactions on behalf of NFT holders if they have been a victim of a fraudulent transaction. It is proposed by deriving the ERC-721 standard of Ethereum with additional functions related to `adminTransfer`.

## Token Interface

### IAdminProjectRouter

#### isSuperAdmin

Check whether `_addr` is the Super Admin role in `_project`.

```solidity
function isSuperAdmin(address _addr, string calldata _project) external view returns (bool)
```

#### isAdmin

Check whether `_addr` is the Admin role in `_project`.

```solidity
function isAdmin(address _addr, string calldata _project) external view returns (bool)
```

### IKYCBitkubChain

#### kycsLevel

Returns the KYC Level of `_addr`.

```solidity
function kycsLevel(address _addr) external view returns (uint256)
```

### IKAP165

#### supportsInterface

Check whether the contract implements `interfaceID` and the `interfaceID` is not `0xffffffff`.

```solidity
function supportsInterface(bytes4 interfaceId) external view returns (bool)
```

{% hint style="info" %}
NOTE: Query if the contract implements an interface
{% endhint %}

### IKAP721

#### balanceOf

Returns the number of NFTs owned by the address `owner`, possibly zero.

```solidity
function balanceOf(address owner) external view returns (uint256 balance)
```

{% hint style="info" %}
NOTE: NFTs assigned to the zero address are considered invalid, and this function `throw` for queries about the zero address.
{% endhint %}

#### ownerOf

Returns the address `owner` of the owner of the NFT `tokenID`.

```solidity
function ownerOf(uint256 tokenId) external view returns (address owner);
```

{% hint style="info" %}
NOTE: NFTs assigned to the zero address are considered invalid, and this function `throw` for queries about the zero address.
{% endhint %}

#### safeTransferFrom

Transfers the ownership of NFT `tokenID` from address `from` to address `to`.

* `throw` unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT `tokenID`.
* `throw` if `from` is not the current owner.
* `throw` if `to` is the zero address.
* `throw` if `tokenID` is not a valid NFT.

When the transfer is complete, this function checks if `to` is a smart contract (code size > 0). If so, it calls `onKAP721Received` on `to` and `throw` if the return value is not `bytes4(keccak256("onKAP721Received(address,address,uint256,bytes)"))`.

```solidity
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external
```

#### transferFrom

Transfers the ownership of NFT `tokenID` from address `from` to address `to`.

* `throw` unless ‘msg.sender‘ is the current owner, an authorized operator, or the approved address for this NFT `tokenID`.
* `throw` if `from` is not the current owner.
* `throw` if `to` is the zero address.
* `throw` if `tokenID` is not a valid NFT.

```solidity
function transferFrom(address from, address to, uint256 tokenId) external
```

{% hint style="info" %}
NOTE: The caller is responsible to confirm that `to` address is capable of receiving NFTs, or else they may be permanently lost.
{% endhint %}

#### adminTransfer

Transfers NFT `tokenID` from address `from` to address `to`, and MUST fire the `Transfer` event.

```solidity
function adminTransfer(address from, address to, uint256 tokenId) external
```

{% hint style="info" %}
NOTE: This function can only be called by the Committee address required in the constructor. This function is designed to create transactions automatically on behalf of NFT holders if they have been a victim of a fraudulent transaction. This method works similarly to the `transferFrom` method.
{% endhint %}

#### internalTransfer

Transfers NFT `tokenID` to address `to` internally from address `from`, and MUST fire the `Transfer` event. The function SHOULD `throw` if the message caller’s account balance does not have the specify NFT `tokenID`. NFTs can be transferred between internal addresses that have completed KYC for both the address `from` and the address `to` using the `internalTransfer` function.

```solidity
function internalTransfer(address from, address to, uint256 tokenId) external returns (bool)
```

{% hint style="info" %}
NOTE: This function can only be called by the Super Admin and the Transfer Router.
{% endhint %}

#### externalTransfer

Transfers NFT `tokenID` to address `to` externally from address `from`, and MUST fire the `Transfer` event. The function SHOULD `throw` if the message caller’s account balance does not have the specified NFT `tokenID`. The function `externalTransfer` allows NFTs to be transferred between addresses that have only passed the sender’s KYC verification process.

```solidity
function externalTransfer(address from, address to, uint256 tokenId) external returns (bool)
```

{% hint style="info" %}
NOTE: This function can only be called by the Super Admin and the Transfer Router.
{% endhint %}

#### approve

Change or reaffirm the approved address for an NFT `tokenID` to the address `to`. The zero address indicates there is no approved address.

`throw` unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.

```solidity
function approve(address to, uint256 tokenId) external
```

#### getApproved

Returns the approved address `operator` for this NFT `tokenID`, or the zero address if there is none.

`throw` if `tokenID` is not a valid NFT.

```solidity
function getApproved(uint256 tokenId) external view returns (address operator)
```

#### setApprovalForAll

Enable or disable approval for a third party `operator` to manage all of `msg.sender`'s assets.

`approve` true if the `operator` is approved, false to revoke approval.

Emits the `ApprovalForAll` event. The contract MUST allow multiple operators per owner.

```solidity
function setApprovalForAll(address operator, bool approved) external
```

#### isApprovedForAll

Check whether `operator` is an approved operator for `owner`.

```solidity
function isApprovedForAll(address owner, address operator) external view returns (bool)
```

{% hint style="info" %}
NOTE: Query if an address `operator` is an authorized operator for another address `owner`.
{% endhint %}

#### safeTransferFrom

Transfers the ownership of NFT `tokenID` from address `from` to address `to`. This works identically to the other function with an extra data parameter, except this function sets data to “”.

```solidity
function safeTransferFrom(address from, address to, uint256 tokenId) external
```

### Events

#### Transfer

This event emits when ownership of any NFT `tokenID` changes by any mechanism, when NFTs are created (`from` == `0`), and when NFTs are destroyed (`to` == `0`).

```solidity
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)
```

{% hint style="info" %}
EXCEPTION: During contract creation, any number of NFTs may be created and assigned without emitting `Transfer`. At the time of any transfer, the approved address for that NFT (if any) is reset to none.
{% endhint %}

#### Approval

This event emits when the `approved` address for an NFT `tokenID` is changed or reaffirmed. The zero address indicates there is no approved address. When a transfer event emits, this also indicates that the approved address for that NFT (if any) is reset to none.

```solidity
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId)
```

#### ApprovalForAll

This event emits when `operator` is enabled or disabled for `owner`. The `operator` can manage all NFTs of the `owner`.

```solidity
event ApprovalForAll(address indexed owner, address indexed operator, bool approved)
```

### IKAP721V2

#### tokenOfOwnerByPage

Returns the list of token identifier for the NFT from `page` to `limit` assigned to `owner`, (sort order not specified).

* `throw` if `limit` is greater than or equals to `balanceOf(owner)`
* `throw` if `page` is less than `0`&#x20;
* `throw` if `limit` is less than `0`
* `throw` if `owner` is the zero address, representing invalid NFTs.

```solidity
function tokenOfOwnerByPage(address owner, uint256 page, uint256 limit) external view returns (uint256[] memory)
```

#### tokenOfOwnerAll

Returns the array of all token identifiers for the NFT assigned to `owner`, (sort order not specified).

```solidity
function tokenOfOwnerAll(address owner) external view returns (uint256[] memory)
```

#### adminApprove

Change or reaffirm the approved address for an NFT `tokenID` to the address `to`. The zero address indicates there is no approved address. This method works similarly to the `approve` method.

`throw` unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.

```solidity
function adminApprove(address to, uint256 tokenId) external
```

{% hint style="info" %}
NOTE: This function can only be called by the Admin and Super Admin. This function is designed to create transactions automatically on behalf of token holders if they have been victims of a fraudulent transaction.
{% endhint %}

#### adminSetApprovalForAll

Enable or disable approval for a third party `operator` to manage all of `msg.sender` assets. `approve` true if the `operator` is approved, false to revoke approval. This method works similarly to the `setApprovalForAll` method.

Emits the `ApprovalForAll` event. The contract MUST allow multiple operators per owner.

```solidity
function adminSetApprovalForAll(address owner, address operator, bool approved) external
```

{% hint style="info" %}
NOTE: This function can only be called by the Admin and Super Admin. This function is designed to create transactions automatically on behalf of token holders if they have been victims of a fraudulent transaction.
{% endhint %}

### IKAP721Metadata

#### name

A descriptive name for a collection of NFTs in this contract.

```solidity
function name() external view returns (string memory)
```

#### symbol

An abbreviated name for NFTs in this contract

```solidity
function symbol() external view returns (string memory)
```

#### tokenURI

A distinct Uniform Resource Identifier (URI) for a given asset.

`throw` if `tokenID` is not a valid NFT. URIs are defined in RFC 3986. The URI may point to a JSON file that conforms to the “KAP721 Metadata JSON Schema”.

```solidity
function tokenURI(uint256 tokenId) external view returns (string memory)
```

### IKAP721Enumerable

#### totalSupply

Returns a count of valid NFTs tracked by this contract, where each one of them has an assigned and queryable owner not equal to the zero address.

```solidity
function totalSupply() external view returns (uint256)
```

#### tokenOfOwnerByIndex

Returns the token identifier for the `index` NFT assigned to `owner`, (sort order not specified).

`throw` if `index` is greater than or equal to `balanceOf(owner)` or if `owner` is the zero address, representing invalid NFTs.

```solidity
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId)
```

#### tokenByIndex

Returns the token identifier for the `index` NFT, (sort order not specified).

`throw` if `index` is greater than or equal to `totalSupply()`

```solidity
function tokenByIndex(uint256 index) external view returns (uint256)
```

### IKAP721Receiver

#### onKAP721Received

The KAP721 smart contract calls this function on the recipient after a `Transfer`. This function MAY `throw` to revert and reject the transfer. Return of other than the magic value `bytes4(keccak256("onKAP721Received(address,address,uint256,bytes)"))` MUST result in the transaction being reverted.

```solidity
function onKAP721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4)
```

{% hint style="info" %}
NOTE: The contract address should always be the message sender.
{% endhint %}


# KAP-1155

The following standard outlines a smart contract interface that can represent any number of fungible and non-fungible token types on KUB. This multi-token standard supports an `adminTransfer` function designed to create transactions on behalf of NFT holders if they have been a victim of a fraudulent transaction. It is proposed by deriving the ERC-1155 standard of Ethereum with additional functions related to `adminTransfer`.

{% hint style="info" %}
The `id` argument contained in each function's argument set indicates a specific token or token type in a transaction.
{% endhint %}

## Token Interface

### IAdminProjectRouter

#### isSuperAdmin

Check whether `_addr` is the Super Admin role in `_project`.

```solidity
function isSuperAdmin(address _addr, string calldata _project) external view returns (bool)
```

#### isAdmin

Check whether `_addr` is the Admin role in `_project`.

```solidity
function isAdmin(address _addr, string calldata _project) external view returns (bool)
```

### IKYCBitkubChain

#### kycsLevel

Returns the KYC Level of `_addr`.

```solidity
function kycsLevel(address _addr) external view returns (uint256)
```

#### setKycCompleted

Set the KYC Level `_level` of `_addr`.

```solidity
function setKycCompleted(address _addr, uint256 _level) external
```

### IKAP165

#### supportsInterface

Check whether the contract implements `interfaceID`, and `interfaceID` is not `0xffffffff`.

* MUST return the constant value `true` if `0x01ffc9a7` is passed through the `interfaceID` argument. This signifies KAP-165 support.
* MUST return the constant value `true` if `0x4e2312e0` is passed through the `interfaceID` argument. This signifies KAP-1155 `IKAP1155Receiver` support.

```solidity
function supportsInterface(bytes4 interfaceId) external view returns (bool)
```

### IKAP1155

#### balanceOf

Return the balance of `account` by `id` token ID.

```solidity
function balanceOf(address account, uint256 id) external view returns (uint256)
```

#### balanceOfBatch

Returns multiple balances of `accounts` by `id` token ID.

```solidity
function balanceOfBatch(address[] calldata accounts, uint256[] calldata id) external view returns (uint256[] memory)
```

#### setApprovalForAll

Enable or disable approval for a third party `operator` to manage all of `msg.sender`'s assets.

`approve` true if the `operator` is approved, false to revoke approval.

Emits the `ApprovalForAll` event. The contract MUST allow multiple operators per owner.

```solidity
function setApprovalForAll(address operator, bool approved) external
```

#### isApprovedForAll

Check whether `operator` is an approved operator for `owner`.

```solidity
function isApprovedForAll(address account, address operator) external view returns (bool)
```

{% hint style="info" %}
NOTE: Query if an address `operator` is an authorized operator for another address `owner`.
{% endhint %}

#### adminTransfer

Transfers `amount` amount of `id` token ID from the `sender` address to the `recipient` address specified, and MUST fire the `TransferSingle` event to reflect the balance change.

```solidity
function adminTransfer(address sender, address recipient, uint256 id, uint256 amount) external
```

{% hint style="info" %}
NOTE: This function can only be called by the Committee address required in the constructor. This function is designed to create transactions automatically on behalf of token holders if they have been a victim of a fraudulent transaction. This method works similarly to the `safeTransferFrom` method.
{% endhint %}

#### internalTransfer

Transfers `amount` amount of `id` token ID from the `sender` address to the `recipient` address internally and MUST fire the `TransferSingle` event to reflect the balance change.

The function SHOULD `throw` if the message caller's account balance for token `id` is lower than the `amount` sent. Tokens can be transferred between internal addresses that have completed KYC for both the address `sender` and the address `recipient` using the `internalTransfer` function.

```solidity
function internalTransfer(address sender, address recipient, uint256 id, uint256 amount) external returns (bool)
```

{% hint style="info" %}
NOTE: This function can only be called by the Super Admin and the Transfer Router.
{% endhint %}

#### externalTransfer

Transfers `amount` amount of `id` token ID from the `sender` address to the `recipient` address externally and MUST fire the `TransferSingle` event to reflect the balance change.

The function SHOULD `throw` if the message caller’s account balance for token `id` is lower than the `amount` sent. Tokens can be transferred between internal addresses that have completed KYC for both the address `sender` and the address `recipient` using the `internalTransfer` function.

```solidity
function externalTransfer(address sender, address recipient, uint256 id, uint256 amount) external returns (bool)
```

{% hint style="info" %}
NOTE: This function can only be called by the Super Admin and the Transfer Router.
{% endhint %}

#### safeTransferFrom

Transfers `amount` amount of an `id` token ID from the `from` address to the `to` address specified (with safety call). The caller must be approved to manage the token being transferred out of the `from` account.

* MUST revert if `to` is the zero address.
* MUST revert if balance of holder for token `id` is lower than the `amount` sent.
* MUST revert on any other error.
* MUST emit the `TransferSingle` event to reflect the balance change (see "Safe Transfer Rules" section of the standard).

After the above conditions are met, this function MUST check if `to` is a smart contract (code size > 0). If so, it MUST call `onKAP1155Received` on `to` and act appropriately.

```solidity
function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external
```

#### safeBatchTransferFrom

Transfers `amounts` amount of `ids` token ID from the `from` address to the `to` address specified (with safety call). The caller must be approved to manage the tokens being transferred out of the `from` account.

* MUST revert if `to` is the zero address.
* MUST revert if the length of `ids` is not the same as the length of `amounts`.
* MUST revert if any of the balance(s) of the holder(s) for token(s) in `ids` is lower than the respective amount(s) in `amounts` sent to the recipient.
* MUST revert on any other error.
* MUST emit `TransferSingle` or `TransferBatch` event(s) such that all the balance changes are reflected (see "Safe Transfer Rules" section of the standard).

Balance changes and events MUST follow the ordering of the arrays ( `ids[0]`/ `amounts[0]` before `ids[1]`/ `amounts[1]`, etc).

After the above conditions for the transfer(s) in the batch are met, this function MUST check if `to` is a smart contract (code size > 0). If so, it MUST call the relevant `IKAP1155Receiver` hook(s) on `to` and act appropriately (see "Safe Transfer Rules" section of the standard).

```solidity
function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external
```

### Events

#### TransferSingle

Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning.

The `operator` MUST be the address of an account/contract that is approved to make the transfer (SHOULD be `msg.sender`).

The `from` MUST be the address of the holder whose balance is decreased.

The `to` MUST be the address of the recipient whose balance is increased.

The `id` MUST be the token type being transferred.

The `value` MUST be the number of tokens the holder balance is decreased by and match what the recipient balance is increased by.

When minting/creating tokens, the `from` argument MUST be set to `0x0` (zero address).

When burning/destroying tokens, the `to` argument MUST be set to `0x0` (zero address).

```solidity
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value)
```

#### TransferBatch

Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning.

The `operator` MUST be the address of an account/contract that is approved to make the transfer (SHOULD be `msg.sender`).

The `from` MUST be the address of the holder whose balance is decreased.

The `to` MUST be the address of the recipient whose balance is increased.

The `ids` MUST be the list of tokens being transferred.

The `values` MUST be the list of numbers of tokens (matching the list and order of tokens specified in `ids`) the holder balance is decreased by and match what the recipient's balance is increased by.

When minting/creating tokens, the `from` argument MUST be set to `0x0` (zero address).

When burning/destroying tokens, the `to` argument MUST be set to `0x0` (zero address).

```solidity
event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values)
```

#### ApprovalForAll

This event MUST be emitted when approval for an `operator` address to manage all tokens for an `account` address is enabled or disabled (absence of an event assumes disabled).

```solidity
event ApprovalForAll(address indexed account, address indexed operator, bool approved)
```

#### URI

This event MUST be emitted when the URI is updated for a token ID. URIs are defined in RFC 3986. The URI MUST point to a JSON file that conforms to the "KAP1155 Metadata URI JSON Schema".

```solidity
event URI(string value, uint256 indexed id)
```

### IKAP1155Receiver

#### onKAP1155Received

Handle the receipt of a single KAP1155 token type. A KAP1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeTransferFrom` after the balance has been updated.

This function MUST return `bytes4(keccak256("onKAP1155Received(address,address,uint256,uint256,bytes)"))` (i.e. 0xf23a6e61) if it accepts the transfer.

This function MUST revert if it rejects the transfer.

Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.

```solidity
function onKAP1155Received(address operator, address from, uint256 id, uint256 value, bytes calldata data) external returns (bytes4)
```

#### onKAP1155BatchReceived

Handle the receipt of multiple KAP1155 token types. A KAP1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeBatchTransferFrom` after the balances have been updated.

This function MUST return `bytes4(keccak256("onKAP1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` (i.e. 0xbc197c81) if it accepts the transfer(s).

This function MUST revert if it rejects the transfer(s).

Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.

```solidity
function onKAP1155BatchReceived(address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data) external returns (bytes4)
```

### IKAP1155Metadata

#### name

A descriptive name for a collection of tokens in this contract.

```solidity
function name() external view returns (string memory)
```

#### symbol

An abbreviated name for tokens in this contract.

```solidity
function symbol() external view returns (string memory)
```

#### uri

A distinct Uniform Resource Identifier (URI) for a given asset.

`throw` if `tokenID` is not a valid token. URIs are defined in RFC 3986. The URI may point to a JSON file that conforms to the “KAP1155 Metadata JSON Schema”.

```solidity
function uri(uint256 tokenId) external view returns (string memory)
```

#### kapURI

A distinct Uniform Resource Identifier (URI) for a given asset that is kept in the IPFS service.

`throw` if `tokenID` is not a valid token. URIs are defined in RFC 3986. The URI may point to a JSON file that conforms to the “KAP1155 Metadata JSON Schema”.

```solidity
function kapURI(uint256 tokenId) external view returns (string memory)
```

### IKAP1155Enumerable

#### totalSupply

Returns a count of valid tokens tracked by this contract, where each one of them has an assigned and queryable owner not equal to the zero address.

```solidity
function totalSupply() external view returns (uint256)
```


# KAP-22

The following standard outlines a smart contract interface and logic for loyalty points tokens on KUB that behaves similarly to traditional loyalty points, enabling interoperability and composability within the decentralized ecosystem. By adhering to this standard, loyalty programs can leverage the benefits of blockchain technology, such as transparency, immutability, and programmability, while maintaining the familiar functionality of traditional loyalty points. It is proposed to derive the KAP-20 standard for KUB, with additional functions for periods and token expiration.

## Token Interface

### IAdminProjectRouter

#### isSuperAdmin

Check whether `_addr` is the Super Admin role in `_project`.

```solidity
function isSuperAdmin(address _addr, string calldata _project) external view returns (bool)
```

#### isAdmin

Check whether `_addr` is the Admin role in `_project`.

```solidity
function isAdmin(address _addr, string calldata _project) external view returns (bool)
```

### IKYCBitkubChain

#### kycsLevel

Returns the KYC Level of `_addr`

```solidity
function kycsLevel(address _addr) external view returns (uint256)
```

### IKAP20

#### totalSupply

Returns the total token supply.

```solidity
function totalSupply() external view returns (uint256)
```

#### decimals

Returns the number of decimals the token uses - e.g. `8`, means to divide the token amount by `100000000` to get its user representation.

```solidity
function decimals() external view returns (uint8)
```

{% hint style="info" %}
NOTE: This method is optional in ERC-20. In KAP-20, this is a required method.
{% endhint %}

#### symbol

Returns the symbol of the token. E.g. "HIX".

```solidity
function symbol() external view returns (string memory)
```

{% hint style="info" %}
NOTE: This method is optional in ERC-20. In KAP-20, this is a required method.
{% endhint %}

#### name

Returns the name of the token - e.g.`"MyToken"`.

```solidity
function name() external view returns (string memory)
```

{% hint style="info" %}
NOTE: This method is optional in ERC-20. In KAP-20, this is a required method.
{% endhint %}

#### allowance

Returns the amount which `spender` is still allowed to withdraw from `owner`.

```solidity
function allowance(address owner, address spender) external view returns (uint256)
```

#### approve

Allows `spender` to withdraw from your account multiple times, up to the `amount` amount. If this function is called again it overwrites the current allowance with `amount`.

```solidity
function approve(address spender, uint256 amount) external returns (bool)
```

{% hint style="info" %}
NOTE: To prevent attack vectors, clients SHOULD make sure to create user interfaces in such a way that they set the allowance first to 0 before setting it to another value for the same spender. THOUGH The contract itself shouldn't enforce it, to allow backwards compatibility with contracts deployed before
{% endhint %}

#### adminApprove

Allows `spender` to withdraw from `owner` account multiple times, up to the `amount` amount. If this function is called again it overwrites the current allowance with `amount`. This method works similar to the `approve` method.

```solidity
function adminApprove(address owner, address spender, uint256 amount) external returns (bool)
```

{% hint style="info" %}
NOTE: This function can only be called by the Admin and Super Admin. This function is designed to create transactions automatically on behalf of token holders if they have been a victim of a fraudulent transaction.
{% endhint %}

#### transferFrom

Transfers `amount` amount of tokens from address `sender` to address `recipient`, and MUST fire the Transfer event.

The `transferFrom` method is used for a withdraw workflow, allowing contracts to transfer tokens on your behalf. This can be used for example to allow a contract to transfer tokens on your behalf and/or to charge fees in sub-currencies. The function SHOULD `throw` unless the `sender` account has deliberately authorized the sender of the message via some mechanism.

```solidity
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool)
```

{% hint style="info" %}
NOTE: Transfers of 0 values MUST be treated as normal transfers and fire the `Transfer` event.
{% endhint %}

#### adminTransfer

Transfers `amount` amount of tokens from address `sender` to address `recipient`, and MUST fire the Transfer event.

```solidity
function adminTransfer(address sender, address recipient, uint256 amount) external returns (bool)
```

{% hint style="info" %}
NOTE: This function can only be called by the Committee address required in the constructor. This function is designed to create transactions automatically on behalf of token holders if they have been a victim of a fraudulent transaction. This method works similar to the `transferFrom` method.
{% endhint %}

### Events

#### Transfer

MUST trigger when tokens are transferred, including zero value transfers.

A token contract which creates new tokens SHOULD trigger a Transfer event with the `from` address set to `0x0` when tokens are created.

```solidity
event Transfer(address indexed from, address indexed to, uint256 value)
```

#### Approval

MUST trigger on any successful call to `approve(address spender, uint256 value)`.

```solidity
event Approval(address indexed owner, address indexed spender, uint256 value)
```

### IKAP22

#### mint

Mint `amount` amount of token to `receiver` address without period, and MUST fire the `Mint` event.

```solidity
function mint(address receiver, uint256 amount) external returns (bool);
```

#### mintCurrentPeriod

Mint `amount` amount of token to `receiver` address with the current period.

```solidity
function mintCurrentPeriod(address receiver, uint256 amount) external returns (bool);
```

#### mintCustomPeriod

Mint `amount` amount of token to `receiver` address with the customizable `period` period.

```solidity
function mintCustomPeriod(address receiver, uint256 amount, uint256 period) external returns (bool);
```

#### transfer

Transfers `amount` amount of tokens to address `recipient`, and MUST fire the `TransferPeriod` event. The function SHOULD `throw` if the message caller's account balance does not have enough tokens to spend.

```solidity
function transfer(address recipient, uint256 amount) external returns (bool)
```

{% hint style="info" %}
NOTE: Tokens that are about to expired will be transferred first
{% endhint %}

#### transferNoPeriod

Transfer `amount` amount of token without period to `recipient` address.

```solidity
function transferNoPeriod(address recipient, uint256 amount) external returns (bool);
```

#### transferStampPeriod

Transfer `amount` amount of token without period to `recipient` address and stamp the `period` period to the token, and MUST fire the `TransferPeriod` event. The function SHOULD `throw` if the message caller's account balance does not have enough tokens to spend.

```solidity
function transferStampPeriod(address recipient, uint256 amount, uint256 period) external returns (bool);
```

#### transferCustomPeriod

Transfer `amount` amount of token within the desired `period` period to `recipient` address, and MUST fire the `TransferPeriod` event. The function SHOULD `throw` if the message caller's account balance does not have enough tokens to spend.

```solidity
function transferCustomPeriod(address recipient, uint256 amount, uint256 period) external returns (bool);
```

#### balanceOf

Returns the balance of active tokens in every period of `account` address.

```solidity
function balanceOf(address account) external view returns (uint256)
```

#### balanceOfAll

Returns the balance of tokens in every period of `account` address.

```solidity
function balanceOfAll(address account) external view returns (uint256);
```

#### balanceOfPeriod

Returns the balance of tokens in the selected `period` period of `account` address.

```solidity
function balanceOfPeriod(address account, uint256 period) external view returns (uint256);
```

#### balanceOfExpired

Returns the balance of expired tokens of `account` address.

```solidity
function balanceOfExpired(address account) external view returns (uint256);
```

#### burn

Burns the `amount` amount of tokens, and MUST fire the `Burn` event.

```solidity
function burn(uint256 amount) external returns (bool);
```

{% hint style="info" %}
NOTE: Tokens that are about to expired will be burned first
{% endhint %}

#### burnCustomPeriod

Burns the `amount` amount of tokens in the selected `period` period.

```solidity
function burnCustomPeriod(uint256 amount, uint256 period) external returns (bool);
```

#### pegToken

Returns the address of the token that is pegged with the loyalty token.

```solidity
function pegToken() external view returns (address);
```

#### ratio

Returns the ratio of the loyalty token and the pegged token.

```solidity
function ratio() external view returns (uint256);
```

#### currentIndex

Returns the index of the current period.

```solidity
function currentIndex() external view returns (uint256);
```

#### currentPeriod

Returns the current period.

```solidity
function currentPeriod() external view returns (uint256);
```

#### totalUnStampSupply

Returns the total amount of tokens without period.

```solidity
function totalUnStampSupply() external view returns (uint256);
```

#### totalExpiredUserSupply

Returns the total amount of expired tokens.

```solidity
function totalExpiredUserSupply() external view returns (uint256);
```

#### totalExpiredOwnerReceiverSupply

Returns the total amount of expired tokens of both `Owner` and `Receiver`.

```solidity
function totalExpiredOwnerReceiverSupply() external view returns (uint256);
```

#### readPeriodTimestamp

Returns the number of seconds in the selected period.

```solidity
function readPeriodTimestamp(uint256 page, uint256 limit) external view returns (uint256[] memory);
```

#### setPeriodTimeStamp

Sets the amount of seconds in the selected period.

```solidity
function setPeriodTimeStamp(uint256[] calldata index, uint256[] calldata timestamp) external returns (bool);
```

### KAP-22 Events

#### Mint

MUST trigger on any successful call to `mint(address receiver, uint256 amount)`.

```solidity
event Mint(uint256 indexed period, address indexed receiver, uint256 amount);
```

#### Burn

MUST trigger on any successful call to `burn(uint256 amount)`.

```solidity
event Burn(address indexed owner, uint256 amount);
```

#### TransferPeriod

MUST trigger on any successful call to `transfer(address recipient, uint256 amount)`, `transferStampPeriod(address recipient, uint256 amount, uint256 period)`, and `transferCustomPeriod(address recipient, uint256 amount, uint256 period)`.

```solidity
event TransferPeriod(address indexed sender, address indexed recipient, uint256 value, uint256 period);
```

### IKToken

#### internalTransfer

Transfers `amount` amount of tokens to address `recipient` internally from `sender`, and MUST fire the `Transfer` event. The function SHOULD `throw` if the message caller's account balance does not have enough tokens to spend. Tokens can be transferred between internal addresses that have completed KYC for both the sender and the recipient using the internalTransfer function.

```solidity
function internalTransfer(address sender, address recipient, uint256 amount) external returns (bool)
```

{% hint style="info" %}
NOTE: This function can only be called by the Super Admin and the Transfer Router.
{% endhint %}

#### externalTransfer

Transfers `amount` amount of tokens to address `recipient` externally from `sender`, and MUST fire the `Transfer` event. The function SHOULD `throw` if the message caller's account balance does not have enough tokens to spend. The function externalTransfer allows tokens to be transferred between addresses that have only passed the sender's KYC verification process.

```solidity
function externalTransfer(address sender, address recipient, uint256 amount) external returns (bool)
```

{% hint style="info" %}
NOTE: This function can only be called by the Super Admin and the Transfer Router.
{% endhint %}


# LLM Docs File

Use these files to give AI tools structured access to the KUB Docs.

## Choosing the Right File

### `llms.txt`

Use the documentation index first: <https://docs.kubchain.com/llms.txt>

This file lists the available documentation pages. It is the best starting point when your tool can fetch pages as needed.

### `llms-full.txt`

Use the full static file when your tool needs the docs in one file: <https://docs.kubchain.com/llms-full.txt>

This file contains a full text snapshot of the KUB Docs.

{% hint style="info" %}
Start with `llms.txt` when possible. Use `llms-full.txt` when your tool cannot browse the docs incrementally.
{% endhint %}

{% hint style="warning" %}
`llms-full.txt` is a snapshot. It may not include the latest documentation updates.
{% endhint %}

## Recommended Workflow

1. Load `llms.txt` to discover the relevant pages.
2. Fetch only the pages you need.
3. Fall back to `llms-full.txt` if your tool needs one local file.

## Use with Claude Code

[Claude Code](https://docs.claude.com/en/docs/claude-code/overview) runs in your terminal and can read local files during a session.

{% stepper %}
{% step %}

#### Download the file

Download <https://docs.kubchain.com/llms-full.txt>.
{% endstep %}

{% step %}

#### Save it locally

Place the file in your project directory or another known location.
{% endstep %}

{% step %}

#### Load it into the session

Use `/read` with the file path, or drag and drop the file into the chat.
{% endstep %}

{% step %}

#### Ask targeted questions

Reference the file in your prompts and ask about specific KUB topics, APIs, or workflows.
{% endstep %}
{% endstepper %}

## Use with Other AI tools

Most AI tools work with `llms-full.txt` the same way:

1. Download the file.
2. Upload or attach it to your session.
3. Ask questions about KUB using that file as context.

## Best Practices

* Prefer `llms.txt` for fresher, page-level discovery.
* Use `llms-full.txt` for offline or file-based workflows.
* Refresh the downloaded file regularly if you need the latest docs.


# KUB Docs MCP

Use this MCP server URL for the public KUB Docs:

```
https://docs.kubchain.com/~gitbook/mcp
```

{% hint style="info" %}
Opening the MCP URL in a browser returns an error. Add it to an AI tool or IDE that supports HTTP MCP servers.
{% endhint %}

## Add the server to your tool

{% stepper %}
{% step %}

#### Copy the MCP server URL

Copy `https://docs.kubchain.com/~gitbook/mcp`.
{% endstep %}

{% step %}

#### Add it to your AI tool

Choose your tool below and add the URL as an HTTP MCP server.
{% endstep %}

{% step %}

#### Test the connection

Ask a question from the [Prompt Examples](#prompt-examples) section below. The tool should search KUB Docs and cite its answer.
{% endstep %}
{% endstepper %}

{% tabs %}
{% tab title="Claude" %}
These steps work in Claude on the web and Claude Desktop.

1. Open **Settings** > **Connectors**.
2. Select **Add custom connector**.
3. Paste `https://docs.kubchain.com/~gitbook/mcp`.

If remote connectors are unavailable, your plan may not support them yet.
{% endtab %}

{% tab title="Claude Code" %}
Run the following command:

```shell
claude mcp add --transport http kub-docs https://docs.kubchain.com/~gitbook/mcp
```

{% endtab %}

{% tab title="Cursor" %}
Open **Settings** > **MCP**, then select **Add new MCP server**.

Use `https://docs.kubchain.com/~gitbook/mcp o` or add this to `.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "kub-docs": {
      "url": "https://docs.kubchain.com/~gitbook/mcp"
    }
  }
}
```

{% endtab %}

{% tab title="Codex" %}
Add the server from your terminal:

```shell
codex mcp add kub-docs https://docs.kubchain.com/~gitbook/mcp
```

Or add it to `config.toml`:

```toml
[mcp_servers.kub-docs]
url = "https://docs.kubchain.com/~gitbook/mcp"
```

{% endtab %}

{% tab title="VS Code (Copilot)" %}
Open your `mcp.json` file and add:

```json
{
  "servers": {
    "kub-docs": {
      "type": "http",
      "url": "https://docs.kubchain.com/~gitbook/mcp"
    }
  }
}
```

{% endtab %}
{% endtabs %}

## Prompt Examples

After connecting, ask one of these questions:

* `Using the KUB Docs MCP server, how do I add KUB Testnet to MetaMask?`
* `Search KUB Docs for the KUB Mainnet RPC URL and chain ID.`
* `Find the guide for deploying a smart contract on KUB Testnet. Summarize the required setup.`

For agentic tools, use this prompt:

```
Add an MCP server named kub-docs with HTTP transport at https://docs.kubchain.com/~gitbook/mcp. Then list its available tools to verify the connection.
```

## Troubleshooting

If your tool cannot connect:

* Confirm `https://docs.kubchain.com` is reachable.
* Confirm the URL ends with `/~gitbook/mcp`.
* Use `/~gitbook/mcp/auth` only for partially authenticated sites.
* Confirm the tool supports HTTP MCP transport.

{% hint style="warning" %}
Tools that require `stdio` or `SSE` cannot connect to the KUB Docs MCP server.
{% endhint %}


# Developer Center

[KUB Developer Center](https://developers.kubchain.com/) is a platform designed to allow you to create and submit your dApps to the KUB network. You can access related resources, such as SDK IDs, and submit your dApps to the KUB ecosystem.

{% hint style="warning" %}
You will need the [KUB Wallet](https://www.kubwallet.com/) to access the KUB Developer Center. Please register and complete the KYC process to log in to the KUB Developer Center.
{% endhint %}

## Submit your dApp

To submit your dApp to the KUB Ecosystem, please visit the KUB Developer Center to access our dApp submission form. Once you have submitted, your dApp will be showcased on the KUB Ecosystem. You will need to prepare the following information:

* Project Name
* Project Description
* Project Logo
  * Supported format: jpg, jpeg, and png
  * Recommended size is 512x512 px, maximum file size is 1 MB
* Website URL
* Social URL
* Category
* Contact Information
  * Name, E-mail, and Telegram

{% hint style="warning" %}
Please ensure that you are a member of the project team before submitting the application form.
{% endhint %}

{% hint style="info" %}
By submitting your project through the application form, you grant KUB permission to use your project name, logo, and any public information provided in your submission for marketing purposes or any purpose relating to broadcasting and advertising.
{% endhint %}


# Libraries & SDKs

Any package designed for Ethereum can seamlessly integrate and operate within the KUB environment. This interoperability enables developers to utilize existing Ethereum tools, libraries, and modules without facing compatibility issues. Furthermore, some packages provide dedicated support and enhancements tailored explicitly for KUB. Examples of packages that support KUB include:

| Library  | Link                                                   |
| -------- | ------------------------------------------------------ |
| NEXT SDK | [Read more](/build-on-kub/libraries-and-sdks/next-sdk) |


# NEXT SDK

The NEXT SDK allows you to integrate your dApps with the KUB Wallet, which provides native support for the KUB network. It offers various methods for managing user authentication, retrieving user information, and executing transactions on the blockchain. With the NEXT SDK, your dApps can integrate with the KUB Wallet authentication services and submit transactions directly on the network.

{% hint style="warning" %}
[Bitkub Blockchain Technology Co., Ltd.](https://bitkubblockchain.com/) is the sole party responsible for the operation and oversight of the NEXT SDK. Under no circumstances shall KUB Foundation be deemed to have any contractual or fiduciary obligation, nor any liability arising from the operation of the NEXT SDK.
{% endhint %}

## Prerequisites

Before installing or interacting with the NEXT SDK, we highly recommend generating the necessary keys, including the **Client ID** and **Project ID**.&#x20;

* For the KUB Testnet environment, visit the [KUB Playground](https://playground.kubchain.com/).&#x20;
* For the KUB Mainnet environment, enter your project details in this [form](https://forms.gle/paPJuF4JHZpKfRDj7), and we will contact you via email.

## Installation

To install the NEXT SDK, you can use npm, pnpm, or yarn.

{% tabs %}
{% tab title="npm" %}

```javascript
npm install @bitkub-chain/sdk.js
```

{% endtab %}

{% tab title="pnpm" %}

```javascript
pnpm install @bitkub-chain/sdk.js
```

{% endtab %}

{% tab title="yarn" %}

```javascript
yarn add @bitkub-chain/sdk.js
```

{% endtab %}
{% endtabs %}

## Initialization

To initialize the SDK, create `lib/bitkubchain-sdk/index.ts` at the root project with the `clientID` and `projectID`.

```javascript
import { initializeSDK, Network } from '@bitkub-chain/sdk.js';

const clientID = 'your-client-id';
const projectID = 'your-project-id';
const network = Network.BKC_TESTNET;
const initOpts = {
  loginRedirectPath: '/oauth/callback',
};

const sdk = initializeSDK(clientID, projectID, network, initOpts);
```

{% hint style="info" %}
Please declare your network as `Network.BKC_TESTNET` for KUB Testnet and `Network.BKC_MAINNET` for KUB Mainnet.
{% endhint %}

## Authentication

To begin with authentication, you must set up OAuth to allow your dApp to log in with KUB Wallet. The first step is to create `/oauth/callback` page, you can use the following code:

```javascript
import { useEffect } from 'react'
import { sdk } from '@lib/bitkubchain-sdk'

export default function Page() {
  useEffect(() => {
    const code = new URLSearchParams(window.location.search).get('code')
    if (code) {
      exchange(code)
    }
  }, [])

  const exchange = async (code: string) => {
    await sdk.exchangeAuthorizationCode(code)
    window.close()
  }

  return (
    <div>
      <h2>Callback Page</h2>
      <p>Exchanging code for tokens...</p>
    </div>
  )
}
```

### Redirect URI

You can visit the [KUB Playground](https://playground.kubchain.com/) to configure your redirect URI for your dApp.

If you have not specified a `loginRedirectPath`, the default redirect URI will be `/oauth/callback`. You should configure it as follows:

```url
http://your-application-domain.com/oauth/callback
```

If you have specified a custom `loginRedirectPath`, update your redirect UI as follows:

```url
http://your-application-domain.com/your-custom-loginRedirectPath
```

### Login

Opens a login window for KUB Wallet.

```javascript
await sdk.loginWithBitkubNext();
```

### **Logout**

Logs out the current user.

```javascript
await sdk.logout();
```

### Exchange Authorization Code

Exchanges the OAuth code for access and refresh tokens.

```javascript
const code = 'authorizationCode';
await sdk.exchangeAuthorizationCode(code);
```

## User Information

### Get User Information

Returns an object containing user details.

```javascript
const userInfo = await sdk.getUserInfo();
```

### **Get Wallet Address**

Fetches the user's wallet address.

```javascript
const walletAddress = await sdk.getUserWalletAddress();
```

### Get Phone Number

Fetches the user's phone number.

```javascript
const tel = await sdk.getUserTel();
```

### **Get Email**

Fetches the user's email address.

```javascript
const email = await sdk.getUserEmail();
```

### **Get User ID**

Fetches the user's unique ID.

```javascript
const userID = await sdk.getUserID();
```

## Balances

### Native Balance

Returns the user's native balance in *wei*.

```javascript
const balance = await sdk.getBalanceNative();
```

{% hint style="info" %}
If the network is `Network.BKC_MAINNET` or `Network.BKC_TESTNET`, KKUB balance will be returned. Otherwise, the native currency of the network will be returned.
{% endhint %}

### KAP-20 Token Balance

Returns the balance of a specific KAP-20 token in *wei*.

```javascript
const balance = await sdk.getBalance20(tokenAddress);
```

### **KAP-721 Token Balance**

Returns the number of KAP-721 tokens owned by the user.

```javascript
const balance = await sdk.getBalance721(tokenAddress);
```

### **KAP-1155 Token Balance**

Returns the quantity of a specific KAP-1155 token owned by the user.

```javascript
const balance = await sdk.getBalance1155(tokenAddress, tokenID);
```

## Token Approval and Transfers

Users must approve an allowance before transferring KAP-20 to ensure that only authorized smart contracts can spend their tokens, preventing unauthorized access and protecting their assets.

### Get Token Allowance

Gets the current token allowance for a given spender in *wei*.

```javascript
const allowanceAmount = await sdk.getAllowanceToken(tokenAddress, spenderAddress);
```

### Approve Token

Approves a spender to use a specified amount of tokens.

```javascript
const result = await sdk.approveToken(tokenAddress, amount, spenderAddress);
```

### **Transfer Native Token**

Transfers native KUB to a recipient.

```javascript
const result = await sdk.transferNative(toAddress, amount);
```

### **Transfer KAP-20 Token**

Transfers a specified KAP-20 token to a recipient.

```javascript
const result = await sdk.transfer20(tokenAddress, toAddress, amount);
```

## NFT Approval and Transfers

Users must approve before transferring NFTs to ensure that only authorized smart contracts can send their NFTs, preventing unauthorized access and protecting their assets.

### NFT Approval

Checks if a given operator is approved for the user's NFT.

```javascript
const isApprovedNFT = await sdk.getIsApprovedNFT(tokenAddress, operatorAddress);
```

### Approve NFT

Grants approval to an operator to manage the user's NFT.

```javascript
const result = await sdk.approveNFT(tokenAddress, operatorAddress);
```

### Transfer KAP-721 Token

Transfers a KAP-721 token to a recipient.

```javascript
const result = await sdk.transfer721(tokenAddress, toAddress, tokenID);
```

### **Transfer KAP-1155 Token**

Transfers a quantity of a KAP-1155 token to a recipient.

```javascript
const result = await sdk.transfer1155(tokenAddress, toAddress, tokenID, amount);
```

## Custom Transaction

Sends a custom smart contract transaction using human-readable ABI and parameters.

```javascript
const result = await sdk.sendCustomTx(toAddress, functionReadableABI, methodParams);
```

## Fetch Transaction Details

Returns the details of a submitted transaction using its queue ID.

```javascript
const details = await sdk.getTransactionDetails(queueId);
```

## Smart Contract Design for NEXT SDK

To allow KUB Wallet users to write data on a smart contract, you need to design the smart contract with additional functions. The additional functions are called through the **CallHelper** smart contract to execute commands on behalf of the KUB Wallet users. The function must also use an extra `address _bitkubNext` parameter at the end of the function.

### Example

This function for buying an NFT requires 2 parameters, which are `_recipeIndex` and `_amount`. MetaMask or other wallets can call this function to buy an NFT.

```solidity
function buyNft(uint256 _recipeIndex, uint256 _amount) external
```

The function must use an extra `address _bitkubNext` parameter at the end of the function to allow KUB Wallet users to call this function to buy an NFT.

```solidity
function buyNft(uint256 _recipeIndex, uint256 _amount, address _bitkubNext) external onlySdkCallHelperRouter
```

You can now apply the human-readable ABI when you are calling the NEXT SDK for your custom transaction.

```javascript
const functionReadableABI = "buyNft(uint256 _recipeIndex, uint256 _amount, address _bitkubNext)"
const methodParams = [1, 1]
```

### SDK CallHelper Router

When an end user invokes a function through the SDK library, the `msg.sender` interaction with your smart contract will be `sdkCallHelperRouter`. To ensure that only authorized calls are made to this function, you must include a modifier to check that `msg.sender` equals `sdkCallHelperRouter`.

### Example Modifier

```solidity
modifier onlySdkCallHelperRouter() {
   require(msg.sender == sdkCallHelperRouter, "Authorization: restricted only SDK CallHelper Router");
   _;
}
```

{% hint style="warning" %}
Confirm that the address of the `sdkCallHelperRouter` for `Network.BKC_TESTNET` is `0x96f4C25E4fEB02c8BCbAdb80d0088E0112F728Bc`.
{% endhint %}


# Code Cookbook

This document collects all developers' best practices for the NEXT SDK and distributes them widely to KUB developers. You can visit the [GitHub repository](https://github.com/kub-chain/bitkubnext-sdk-cookbook/tree/main) for more information.

## Authentication

| Projects       | Links                                                                                                             |
| -------------- | ----------------------------------------------------------------------------------------------------------------- |
| Authentication | [Source Code](https://github.com/kub-chain/bitkubnext-sdk-cookbook/blob/main/src/pages/authentications/index.tsx) |

## Token Interaction

| Projects                | Links                                                                                                              |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------ |
| KAP-20 Interaction      | [Source Code](https://github.com/kub-chain/bitkubnext-sdk-cookbook/blob/main/src/pages/balances/KAP20/index.tsx)   |
| KAP-721 Interaction     | [Source Code](https://github.com/kub-chain/bitkubnext-sdk-cookbook/blob/main/src/pages/balances/KAP721/index.tsx)  |
| KAP-1155 Interaction    | [Source Code](https://github.com/kub-chain/bitkubnext-sdk-cookbook/blob/main/src/pages/balances/KAP1155/index.tsx) |
| Native Coin Interaction | [Source Code](https://github.com/kub-chain/bitkubnext-sdk-cookbook/blob/main/src/pages/balances/NATIVE/index.tsx)  |

## Token Approval

| Projects       | Links                                                                                                            |
| -------------- | ---------------------------------------------------------------------------------------------------------------- |
| Token Approval | [Source Code](https://github.com/kub-chain/bitkubnext-sdk-cookbook/blob/main/src/pages/approval/token/index.tsx) |
| NFT Approval   | [Source Code](https://github.com/kub-chain/bitkubnext-sdk-cookbook/blob/main/src/pages/approval/nft/index.tsx)   |

## Custom Transaction

| Projects           | Links                                                                                                       |
| ------------------ | ----------------------------------------------------------------------------------------------------------- |
| Custom Transaction | [Source Code](https://github.com/kub-chain/bitkubnext-sdk-cookbook/blob/main/src/pages/custom-tx/index.tsx) |


# KUB Layer 2 Network

## **Introduction to Layer 2 Networks**

Blockchain technology, in its foundational form (known as a Layer 1 network), faces a well-known challenge: the **blockchain trilemma**. This concept states that a blockchain can only effectively achieve two of the three key properties: **scalability**, **security**, and **decentralization**.&#x20;

A Layer 1 network like KUB, or others like Ethereum, prioritizes security and decentralization, but this can lead to limitations in transaction speed and higher fees when network usage is high.

A Layer 2 network is a secondary framework or protocol built on top of a Layer 1 blockchain. Its primary purpose is to address the scalability issue by handling a large number of transactions off the main chain, thereby increasing the network's throughput and reducing transaction costs.

## **The Rollup Approach**

The KUB Layer 2 network, like many modern L2 solutions, utilizes a technology called a rollup. Rollups bundle hundreds of transactions into a single, compressed transaction that is then submitted to the main Layer 1 network. This significantly reduces the amount of data that needs to be processed on the main chain, leading to faster and cheaper transactions.

There are two main types of rollups:

* Optimistic Rollups: This model operates under the assumption that all transactions bundled in a rollup are valid. It only verifies the transactions if a fraud proof is submitted by a user who suspects fraudulent activity. This optimistic approach allows for very high transaction speeds. A challenge period is a key feature, giving users a window of time to submit a fraud-proof.
* Zero-Knowledge (ZK) Rollups: These rollups use complex cryptographic proofs (known as ZK-proofs) to instantly verify the validity of off-chain transactions. A small proof is submitted to the Layer 1 network, which cryptographically guarantees that all transactions in the bundle are valid. This provides near-instant finality without a challenge period.

## KUB Layer 2 Network

The KUB Layer 2 network is an extension of the main KUB network (Layer 1). It is designed to enhance the KUB network's performance by providing a low-cost, high-speed environment for decentralized applications (dApps) and user transactions.

### Connecting to the KUB Layer 2 Network

Connecting to the KUB Layer 2 network is a straightforward process, similar to connecting to other blockchain networks. You will need a compatible cryptocurrency wallet, such as [MetaMask](https://metamask.io/). You can follow the instructions in this [guide](/about-kub/connect-to-kub) or enter the following RPC details:

{% tabs %}
{% tab title="Layer 2 Mainnet" %}

| Name               | Value                           |
| ------------------ | ------------------------------- |
| Network Name       | KUB Layer 2 Mainnet             |
| RPC URL            | <https://kublayer2.kubchain.io> |
| Chain ID           | 9601                            |
| Currency Symbol    | KUB                             |
| Block Explorer URL | <https://kublayer2.kubscan.com> |
| {% endtab %}       |                                 |

{% tab title="Layer 2 Testnet" %}

| Name               | Value                                   |
| ------------------ | --------------------------------------- |
| Network Name       | KUB Layer 2 Testnet                     |
| RPC URL            | <https://kublayer2.testnet.kubchain.io> |
| Chain ID           | 259251                                  |
| Currency Symbol    | tKUB                                    |
| Block Explorer URL | <https://kublayer2.testnet.kubscan.com> |
| {% endtab %}       |                                         |
| {% endtabs %}      |                                         |

### Obtaining tKUB on the KUB Layer 2 Testnet

For developers wishing to develop their decentralized applications (dApps) on the KUB Layer 2 Testnet, you will need some tKUB. To obtain tKUB on the KUB Layer 2 Testnet, you first need to acquire tKUB on the KUB Testnet. Follow this [guide](/tools/testnet-faucet) or visit the [KUB Faucet](https://faucet.kubchain.com/) to obtain some tKUB.&#x20;

Once you have received your tKUB, navigate to the section labeled **Bridge to KUB Layer 2 Testnet**. You will be presented with options to select the amount of tKUB you want to transfer from the KUB Testnet to the KUB Layer 2 Testnet. After making your selection, follow the on-screen instructions to complete the bridging process.

{% hint style="info" %}
You'll be able to receive 5 tKUB every 24 hours using the KUB Faucet.
{% endhint %}


# KUB Application Protocol (KAP)

To better serve the network and provide a more customized solution to the ecosystem, a standard called the **KUB Application Protocol (KAP)** has been introduced. This standard is based on the [Ethereum Request for Comments (ERC)](https://ethereum.org/en/developers/docs/standards/) standard.

The most notable KAP standards with real-world applications are KAP-20, KAP-721, and KAP-1155. In summary, KAP tokens have a `adminTransfer` function that allows the token administrator to transfer tokens back from the attacker's address in case of a rug pull, fraud, or compromise. The `adminTransfer` function adds an extra layer of security to the KUB token system.&#x20;

Moreover, the KAP token standard also supports `internalTransfer` and `externalTransfer` functions to allow token transfers between internal addresses that have completed KYC for both the sender and the recipient. These functions are required to integrate the KUB Wallet into a project.

{% hint style="info" %}
The KUB network supports both KAP standard tokens and ERC standard tokens. Both standards are compatible with the KUB network.
{% endhint %}

## KAP-20

The [KAP-20](/quickstart/launching-a-token-on-kub/kap-token-interfaces/kap-20) token standard is a protocol used on the KUB network, which includes a `adminTransfer` function. This function is designed to automatically create transactions on behalf of token holders who have been victims of fraudulent transactions and have been deemed illegal by a court of law. The KAP-20 token developers can use the function at their discretion, and they also regulate the users who can use it.&#x20;

It is important to note that KUB has no control over user settings and access to the `adminTransfer` function, and it is solely operated by token developers. The KAP-20 token developers also have the right to disable the `adminTransfer` function. It is essential to keep in mind that the `adminTransfer` function does not apply to the KUB Coin in digital asset exchanges.

{% hint style="info" %}
If KUB holders transfer their KUB from a digital asset exchange to [KUB Wallet](https://www.kubwallet.com/), the transferred KUB will be wrapped into KKUB.
{% endhint %}

## KAP-721

On KUB, the standard for indicating ownership of non-fungible tokens (NFTs) is referred to as [KAP-721](/quickstart/launching-a-token-on-kub/kap-token-interfaces/kap-721). Compared to KAP-20, KAP-721 is a more complex standard that is distributed among different contracts and has many potential expansions. It provides a set of guidelines for creating unique tokens that represent digital assets. These tokens are non-fungible, meaning that they cannot be traded for each other due to their unique attributes. KAP-721 is significant because it simplifies the process of creating NFTs, which can be used for art, gaming, collectibles, and many other purposes.

## KAP-1155

KUB also uses a multi-token standard named [KAP-1155](#kap-1155). This standard allows for both fungible (KAP-20) and non-fungible (KAP-721) token representation in one smart contract. The KAP-1155 standard has many benefits, such as efficiency. It stores all token types within a single contract, which enables batch transfer of various token types in one transaction. Instead of deploying a new contract for each token type, a single KAP-1155 token contract can hold the whole system state, which reduces deployment costs and complexity.

## KAP-22

[KAP-22](/quickstart/launching-a-token-on-kub/kap-token-interfaces/kap-22) enables the use of loyalty point tokens on the KUB platform within its ecosystem. Traditional loyalty programs often face challenges such as centralized control, limited interoperability, and unclear reward mechanisms. KAP-22 addresses these issues by introducing a standardized token for loyalty points. By combining the advantages of blockchain technology with the familiar features of traditional loyalty points, this initiative aims to create a more efficient, transparent, and user-focused loyalty ecosystem.


# Overview

## KUB Proof-of-Stake

KUB Proof-of-Stake (PoS) is a consensus mechanism on the KUB network that allows participants with enough tokens to serve as validators and delegators by staking KUB Coin. The KUB PoS mechanism provides several benefits, including energy efficiency, scalability, faster transactions, and strong security measures that ensure network integrity, enable nodes to operate correctly, and enhance the security and decentralization of the blockchain network.

## Staking on KUB Network

[Staking](/run-a-kub-node/run-a-validator-node/validator-staking) involves depositing the KUB Coin to activate the validator. A validator's role includes storing data, processing transactions, and adding blocks to the blockchain. This active participation helps secure the KUB network, benefiting all users and allowing validators to earn additional KUB Coin rewards.

## Validators

A [validator](/run-a-kub-node/becoming-a-validator) is a group of individuals who validate transactions on the KUB network to ensure their security and the decentralization of KUB.

### Pool Node

A pool node on the KUB network allows delegators to delegate their KUB Coin to this node type, increasing staking power and the chances of the node validator to mine a block on the KUB network. Those considering pool staking should have at least 100,000 KUB and a computer connected to the internet, which must maintain 100% uptime.

## Delegators

[Delegators](/governance/delegate-kub-coin) are groups of individuals who participate in validating transactions with the validators. The delegators jointly stake the KUB coin with the validator to delegate authority to the validator to validate the transaction. The delegators receive rewards based on the proportion of staking power under which the delegator can do without its technical knowledge or infrastructure.


# Becoming a Validator

## Considerations

As much as we wish that staking were accessible and risk-free to everyone, this is not a reality. There are some practical and serious considerations to consider before deciding to become a validator and stake your KUB.&#x20;

### Technical Knowledge

Node setup requires reasonable technical knowledge when working with computers, although new tools make this easier over time. Understanding the command-line interface is helpful, but no longer strictly required. It also requires a basic hardware setup and an understanding of the minimum recommended specs.

### Secure Key Management

Similar to private keys that secure your wallet address, you will need to generate keys specifically for your validator. You must understand how to keep any seed phrases or private keys safe and secure.

### Maintenance

Hardware occasionally fails, network connections error out, and client software occasionally needs upgrading. Node maintenance is inevitable and will occasionally require your attention. You'll want to be sure you stay aware of any anticipated network upgrades or other critical client upgrades.

### Reliable Uptime

Your rewards are proportional to the time your validator is online and properly attested. Downtime incurs penalties that are proportional to how many other validators are offline simultaneously, but does not result in [slashing](/run-a-kub-node/run-a-validator-node/slashing). Bandwidth also matters, as rewards are decreased for attestations that are not received in time. You must keep your validator online and up to date. This is your responsibility, and your account will be penalized if it goes offline. The penalties for being offline are roughly equal to the rewards for actively participating.

## Become a Validator

| Resource                                                     | Description                                                                                      |
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ |
| [Run a Validator Node](/run-a-kub-node/run-a-validator-node) | Propose new blocks and verify transactions following the KUB Proof-of-Stake mechanism            |
| [Run a Full Node](/run-a-kub-node/run-a-full-node)           | Run the latest part of the blockchain state to ensure the stability and operation of the network |
| [Run an Archive Node](/run-a-kub-node/run-an-archive-node)   | Run a node that retains the complete block history of the KUB network                            |


# Run a Validator Node

## Requirements

### Linux Instance

OS - Ubuntu 22.04 or a higher version

### Specifications

| Specifications | Minimum  | Recommended                                                                                   |
| -------------- | -------- | --------------------------------------------------------------------------------------------- |
| CPU            | 4 Core   | 8 Core                                                                                        |
| RAM            | 16 GB    | 32 GB                                                                                         |
| Disk           | SSD 1 TB | <ul><li>SSD 1 TB 8,000 IOPS</li><li>250 MB/s throughput</li><li>Read latency < 1 ms</li></ul> |
| Network        | > 5 MB/s | > 50 MB/s                                                                                     |

{% hint style="danger" %}
Using a system with minimum specifications increases the risk of reaching full memory capacity, which may lead to [slashing](/run-a-kub-node/run-a-validator-node/slashing). Ensure you have enough memory and specifications to support the network data.
{% endhint %}

### Allowed Inbound and Outbound

* Protocol - TCP and UDP
* Port - 30303
* Source IP - 0.0.0.0/0

## Installation

Create a new directory for your validator node

```sh
mkdir -p kub-node && cd kub-node
```

Download the Genesis file and the configuration file using [wget](https://www.gnu.org/software/wget/)

```shell
wget https://raw.githubusercontent.com/kub-chain/bkc-node/main/mainnet/genesis.json
wget https://raw.githubusercontent.com/kub-chain/bkc-node/main/mainnet/config.toml
```

Download the [latest release](https://github.com/kub-chain/bkc/releases); the current version is `v2.4.0`

```sh
wget https://github.com/kub-chain/bkc/releases/download/v2.4.0-bkc/geth2.4.0.linux-amd64.tar.gz
```

{% hint style="warning" %}
Verify that the downloaded version is compatible with your device. KUB supports Darwin ARM64, Linux x86-64, and Linux ARM64. Visit the [latest release](https://github.com/kub-chain/bkc/releases) page to view the available versions under the assets section.
{% endhint %}

Extract the downloaded file

```sh
tar -xvf geth2.4.0.linux-amd64.tar.gz
```

Set the password, replace `YourPassword` with your password

```sh
echo "YourPassword" > ./password.sec
```

Create a new validator account

```sh
./geth --datadir ./data account new --password ./password.sec
```

{% hint style="info" %}
Your public address will be generated after creating the account. Please write it down, as you will need it in the later steps.
{% endhint %}

Initialize the Genesis file

```sh
./geth --datadir ./data init ./genesis.json
```

Run `geth` using the following command and replace `0xYourPublicAddress` with your public address retrieved in the earlier steps

```shell
./geth --datadir ./data \
    --config ./config.toml --password ./password.sec \
    --syncmode snap \
    --mine \
    --unlock 0xYourPublicAddress --allow-insecure-unlock 
```

Please allow some time for your system to download and sync the network data.

### Validator Staking

After successfully installing your node configuration on your system, please proceed to the [next steps](/run-a-kub-node/run-a-validator-node/validator-staking). Staking involves depositing the KUB Coin to activate the validator.


# Validator Staking

Staking involves depositing the KUB Coin to activate the validator. A validator's role includes storing data, processing transactions, and adding blocks to the blockchain. This active participation helps secure the KUB network, benefiting all users and allowing validators to earn additional KUB Coin rewards.

## Becoming a Pool Node

A pool node on the KUB network allows delegators to delegate their KUB Coin to this node type, increasing staking power and the likelihood that the node's validator will mine a block on the KUB network. Those considering pool staking should have at least 100,000 KUB and a computer connected to the internet, which must maintain 100% uptime.

1. Visit the [StakeManager](https://www.kubscan.com/address/0x443502b3F7C0934576F49CDa084f78640f56A80F?tab=write_contract) contract on KUB Scan
2. Connect your wallet on the **Write Contract** page
3. Select the [stake](https://www.kubscan.com/address/0x443502b3F7C0934576F49CDa084f78640f56A80F?tab=write_contract#b114e888) function (Number 15) and input the following
   1. **signer** - Your public address that was retrieved in the [earlier steps](/run-a-kub-node/run-a-validator-node), starts with `0x`
   2. **delegation**  - `true`
   3. **Send Native KUB** - At least `100,000` KUB
4. Click on the **Write** button to confirm the transaction
5. Check your Validator ID by selecting the [getValidatorID](https://www.kubscan.com/address/0x443502b3F7C0934576F49CDa084f78640f56A80F?tab=read_contract#174e6832) function on the **Read Contract** page and input your public address

## StakeManager Contract

The StakeManager contract serves as the core of KUB's staking mechanism. All staking-related actions that users can interact with can be executed through this contract. It enables node runners to stake, unstake, restake, claim rewards, and configure their ValidatorShare contracts. The contract also handles reward distribution and slashing; the related information can be found in the events emitted for clarity.

### Stake

```solidity
stake(address signer, bool delegation) payable
```

`signer` - The address of the EVM instance, starts with `0x`

`delegation` - Create a ValidatorShare contract and enable the delegation; set to `true`

`payable` - KUB Coin required to stake, not exceeding uint128

This method requires KUB Coin to be sent as a value along with the transaction that calls this method. Upon staking, an NFT will be minted and given to the staker. The NFT represents ownership of the newly created node, including the states, configurations, ValidatorShare contract, etc., but not the EVM instance running to operate the chain.

On creation, the infrastructure fee and the commission fee of the pool node will be set to the default value of 0%. You can change the commission fee by yourself after the node creation at the [StakeManager](https://www.kubscan.com/address/0x443502b3F7C0934576F49CDa084f78640f56A80F) contract on the [updateCommissionRate](https://www.kubscan.com/address/0x443502b3F7C0934576F49CDa084f78640f56A80F?tab=write_contract#dcd962b2) method. The initial status of the node will be active. The signer's address of the newly created node will be added to the minimal validator set and can be selected as a block validator in a span.

{% hint style="info" %}
The active status means the node is staked. It does not guarantee that the EVM instance of the node is running, nor that the signer's address is in the minimal validator set.
{% endhint %}

{% hint style="warning" %}
The signer address cannot be used or become a node again unless the node is unstaked first.
{% endhint %}

### Unstake

```solidity
unstake(uint256 validatorId)
```

**`validatorId`** - The token ID of the NFT that is received upon staking

Only owners of the NFTs can invoke this function, and the input validator ID must correspond to the token ID of one of the NFTs in the caller’s possession. Unstaking is not allowed for inactive nodes, and the official node cannot be unstaked using this function.

When a node is unstaked, the ownership NFT of the node will be burned, and the staked funds will be transferred back from the StakeManagerVault contract to the owner. Additionally, the node will be removed from the minimal validator set, and its status will be set to unstaked, resulting in it not being selected as a block validator anymore. The signer's address will also now be available to be used again.

All rewards earned by the model's staker will be sent to the node owner, including validator rewards, validator commissions, and delegator commissions.

The delegation flag inside the ValidatorShare contract will be set to false, preventing further delegation on the ValidatorShare contract side. However, delegators can still claim their rewards and undelegate their funds. The number of nodes will decrease by one, based on the type of the unstaked node.

### Restake

```solidity
restake(uint256 validatorId) payable
```

`validatorId` - The token ID of the NFT that is received upon staking

`payable` - KUB Coin required to stake, not exceeding uint128

Only owners of the NFTs can call this function, and the input validator ID must correspond to the token ID of one of the NFTs in the caller’s possession. The restaking of an inactive node is not possible.

This function increases the staked amount of the node with the funds sent in the transaction. If the node is not part of the minimal validator set before this function is called, and the final staked amount is greater than or equal to the minimum deposit amount, the signer address of the node will be included in the set. The funds will be transferred to the StakeManagerVault contract.

{% hint style="warning" %}
Retrieving a portion of your staked funds is not possible. The only way to retrieve your staked funds is to call the [unstake](#unstake) function.
{% endhint %}

### ClaimRewards

```solidity
claimRewards(uint256 validatorId)
```

`validatorId` - The token ID of the NFT that is received upon staking

Only owners of the NFTs can call this function, and the input validator ID must be the token ID of one of the NFTs in the caller’s possession.&#x20;

The reward from the node that is not active cannot be claimed. The function is solely for claiming the validator reward, which will be transferred only to the owner.

### ClaimCommissionRewards

```solidity
claimCommissionRewards(uint256 validatorId)
```

`validatorId` - The token ID of the NFT that is received upon staking

Only owners of the NFTs can call this function, and the input validator ID must be the token ID of one of the NFTs in the caller’s possession.&#x20;

The reward from the node that is not active cannot be claimed. The function is solely for claiming the commission reward, which will be transferred only to the owner.

### UpdateCommissionRate

```solidity
updateCommissionRate(uint256 validatorId, uint256 newCommissionRate)
```

`validatorId` - The token ID of the NFT that is received upon staking

`newCommissionRate` - The new value of the commission rate

This function allows you to change the validator commission rate. The minimum value is `0` for 0%, and the maximum value is `5000` for 50%. For example, if the value is 1234, the result of the new commission rate will be 12.34%

The commission rate affects both the validator and delegator rewards. The higher this value, the more the rewards are reduced. The taken portions are combined and referred to as the commission fee.

### UpdateMinDelegated

```solidity
updateMinDelegated(uint256 validatorId, uint256 newMinDelegated)
```

`validatorId` - The token ID of the NFT that is received upon staking

**`newMinDelegated`** - The new value of the minimum delegated amount in the *wei* unit

This function allows you to change the minimum delegated amount. The minimum delegated amount is the expected minimum amount of delegated funds within a node.&#x20;

This value is considered during delegation and undelegation. For delegation, if the final total delegated amount is less than the minimum delegated amount, the transaction will be reverted. For undelegation, if the final total delegated amount is less than this value, all delegated amounts will be undelegated instead of the desired value. The minimum delegated amount does not affect the existing delegated amounts of the users until delegation or undelegation is carried out by the users.

### UpdateValidatorDelegation

```solidity
updateValidatorDelegation(uint256 validatorId, bool delegation)
```

`validatorId` - The token ID of the NFT that is received upon staking

**`delegation`** - More delegation is allowed if set to `true`; no more delegation is allowed if set to `false`

This function allows you to change the delegation flag of a node. The delegation flag indicates whether a node allows delegation by delegators.

If the delegation flag is set to false, no more delegations will be possible. However, the existing users, before the delegation flag was set to false, will still be able to undelegate and claim their rewards.

## ValidatorShare Contract

The ValidatorShare contract is the core of the delegation mechanism of the KUB network. All delegation-related actions that users can interact with can be executed through this contract. In this contract, it's possible to delegate, undelegate, and claim your reward.

A ValidatorShare contract is created when a node validator is staked with the ValidatorShareFactory contract by the StakeManager contract. It is not intended to hold any funds through its capabilities. The ValidatorShare contract can be replaced as it is merely an implementation, with the data and funds located in other contracts.

### Delegate

```solidity
delegate() payable
```

`payable` - KUB Coin required to delegate, not exceeding uint128

This method requires KUB Coin to be sent as a value along with the transaction that calls this method. This function can only be called when the delegation flag in the ValidatorShare contract is set to **true**.&#x20;

Upon delegation, a token of the ValidatorShare contract will be minted in the same amount as the delegated amount to the sender. The token is the proof of ownership of the sender’s shares in the contract. It can be transferred and has the same standard functionality as other tokens.

When this function is called, the ValidatorShare contract’s states will be updated, and the pending reward of the sender will be sent to the sender. The sender's final total delegated amount (original delegated amount plus newly delegated amount) must be more than or equal to the minimum delegated amount. The funds will be sent to the StakeManagerVault contract.

### Undelegate

```solidity
undelegate(uint256 claimAmount)
```

**`claimAmount`** - The amount of KUB Coin, in the *wei* unit, that will be retrieved from the ValidatorShare contract

Upon calling this function, the ValidatorShare contract’s states will be updated, and the pending reward of the sender will be sent to the sender. The maximum value of the *claimAmount* argument is the balance of the sender's ownership token, and it cannot be 0.

In the case where the final total delegated amount (the balance of the sender's ownership token as deduced by the claimAmount argument) is less than the minimum delegated amount, the value of the claimAmount argument will be adjusted to the sender's ownership token balance, meaning all shares of the sender will be undelegated. The ownership token will be burned according to the *claimAmount* argument, which may have been adjusted. The funds will be sent from the StakeManagerVault contract to the sender.

### ClaimRewards <a href="#claimrewards" id="claimrewards"></a>

```solidity
claimRewards()
```

Upon calling this function, the ValidatorShare contract’s states will be updated, and the pending reward of the sender will be sent to the sender.


# Slashing

## **What is slashing?** <a href="#what-is-slashing" id="what-is-slashing"></a>

Slashing is a penalty system. If a validator misses their duties, such as not validating a block in time, they can lose a portion of their staked KUB. The deducted amount then gets awarded to the official pool as a reward. Slashing in the KUB network ensures that validators meant to secure the network act in the best interests of all users. If a validator doesn’t perform its duties, slashing comes into play.

### **Tracking** <a href="#how-does-it-work" id="how-does-it-work"></a>

After the first warning, the system starts tracking the validator's performance for roughly 24 hours. This tracking period is called the **Slashing Epoch**, which lasts 345 spans.

### **Slashing Threshold**

Suppose a validator misses block validations repeatedly and reaches a threshold of 50 spans (approximately 3 hours and 20 minutes) within 345 spans (approximately 24 hours) for the slash epoch in a network of KUB, the validator will be slashed. However, the counter resets if they don’t reach this threshold or if it reaches 345 spans.

### **Penalty Amount**

The amount of the penalty depends on the type of node:

* Pool Node: 100 KUB penalty

{% hint style="warning" %}
Before penalizing validators, there will be issued warnings as an initial measure against missed duties.
{% endhint %}

Once a validator doesn't propagate its block in time, the official node steps in. The official node creates a block, adds a slashing transaction, and signs it. This transaction triggers the [SlashManager](https://www.kubscan.com/address/0xEF6F6c6fdaEAc0326FFE1413D7d7CCAA7B56b753) smart contract, which takes care of the slashing procedure based on the abovementioned rules.


# Run a Full Node

## Requirements

### Linux Instance

OS - Ubuntu 22.04 or a higher version

### Specifications

| Specifications | Minimum    | Recommended                                                                                     |
| -------------- | ---------- | ----------------------------------------------------------------------------------------------- |
| CPU            | 4 Core     | 8 Core                                                                                          |
| RAM            | 16 GB      | 32 GB                                                                                           |
| Disk           | SSD 1.5 TB | <ul><li>SSD 1.5 TB 8,000 IOPS</li><li>250 MB/s throughput</li><li>Read latency < 1 ms</li></ul> |
| Network        | > 5 MB/s   | > 10 MB/s                                                                                       |

### Allowed Inbound and Outbound

* Protocol - TCP and UDP
* Port - 30303
* Source IP - 0.0.0.0/0

## Installation

Create a new directory for your validator node

```sh
mkdir -p kub-node && cd kub-node
```

Download the Genesis file and the configuration file using [wget](https://www.gnu.org/software/wget/)

{% tabs %}
{% tab title="KUB Mainnet" %}

<pre class="language-shell"><code class="lang-shell"><strong>wget https://raw.githubusercontent.com/kub-chain/bkc-node/main/mainnet/genesis.json
</strong>wget https://raw.githubusercontent.com/kub-chain/bkc-node/main/mainnet/config.toml
</code></pre>

{% endtab %}

{% tab title="KUB Testnet" %}

```shell
wget https://raw.githubusercontent.com/kub-chain/bkc-node/main/testnet/genesis.json
wget https://raw.githubusercontent.com/kub-chain/bkc-node/main/testnet/config.tom
```

{% endtab %}
{% endtabs %}

Download the [latest release](https://github.com/kub-chain/bkc/releases); the current version is `v2.4.0`

```sh
wget https://github.com/kub-chain/bkc/releases/download/v2.4.0-bkc/geth2.4.0.linux-amd64.tar.gz
```

{% hint style="warning" %}
Verify that the downloaded version is compatible with your device. KUB supports Darwin ARM64, Linux x86-64, and Linux ARM64. Visit the [latest release](https://github.com/kub-chain/bkc/releases) page to view the available versions under the assets section.
{% endhint %}

Extract the downloaded file

```sh
tar -xvf geth2.4.0.linux-amd64.tar.gz
```

Set the password, replace `YourPassword` with your password

```sh
echo "YourPassword" > ./password.sec
```

Create a new validator account

```sh
./geth --datadir ./data account new --password ./password.sec
```

{% hint style="info" %}
Your public address will be generated after creating the account. Please write it down, as you will need it in the later steps.
{% endhint %}

Initialize the Genesis file

```sh
./geth --datadir ./data init ./genesis.json
```

Run `geth` using the following command and replace `0xYourPublicAddress` with your public address retrieved in the earlier steps

```shell
./geth --datadir ./data \
    --config ./config.toml --password ./password.sec \
    --syncmode snap \
    --mine \
    --unlock 0xYourPublicAddress --allow-insecure-unlock 
```

Please allow some time for your system to download and sync the network data.


# Node Snapshots

This page provides download links for data directories and node snapshots to simplify node operations. While not mandatory, these resources can greatly simplify running your node.

| Snapshot Date   | Size      | Download Link                                                                                                              |
| --------------- | --------- | -------------------------------------------------------------------------------------------------------------------------- |
| August 24, 2023 | 812.47 GB | [Download](https://bkc-snapshots-sg.obs.ap-southeast-3.myhuaweicloud.com/mainnet/fullnode/geth-20230824.tar.lz4)           |
| March 30, 2023  | 764.35 GB | [Download](https://bitkubchain-chaindata.obs.ap-southeast-3.myhuaweicloud.com/fullnode/bkc-fullnode-20230330-1300.tar.lz4) |

## Download Using CLI

Using [`aria2`](https://aria2.github.io/) to download snapshots can significantly speed up the download process

```bash
aria2c -o geth.tar.lz4 -s 16 -x 16 -k 500M "https://bkc-snapshots-sg.obs.ap-southeast-3.myhuaweicloud.com/mainnet/fullnode/geth-20230824.tar.lz4"
```

Install `lz4` for lossless compression algorithm

```bash
sudo apt-get -y install lz4
```

Extract snapshot to the specified directory

```bash
tar -I lz4 -xvf geth.tar.lz4 -C /bkc-node/mainnet/data
```

Run `geth` using the following command

```bash
geth --datadir /bkc-node/mainnet/data --config /bkc-node/mainnet/config.toml
```


# Run an Archive Node

## Requirements

### Linux Instance

OS - Ubuntu 22.04 or a higher version

### Specifications

| Specifications | Recommended                                                       |
| -------------- | ----------------------------------------------------------------- |
| CPU            | 8 Core                                                            |
| RAM            | 32 GB                                                             |
| Disk           | <ul><li>SSD 6 TB 8,000 IOPS</li><li>250 MB/s throughput</li></ul> |
| Network        | > 10 MB/s                                                         |

### Allowed Inbound and Outbound

* Protocol - TCP and UDP
* Port - 30303
* Source IP - 0.0.0.0/0

## Installation

Create a new directory for your validator node

```sh
mkdir -p kub-node && cd kub-node
```

Download the Genesis file and the configuration file using [wget](https://www.gnu.org/software/wget/)

{% tabs %}
{% tab title="KUB Mainnet" %}

<pre class="language-shell"><code class="lang-shell"><strong>wget https://raw.githubusercontent.com/kub-chain/bkc-node/main/mainnet/genesis.json
</strong>wget https://raw.githubusercontent.com/kub-chain/bkc-node/main/mainnet/config.toml
</code></pre>

{% endtab %}

{% tab title="KUB Testnet" %}

```shell
wget https://raw.githubusercontent.com/kub-chain/bkc-node/main/testnet/genesis.json
wget https://raw.githubusercontent.com/kub-chain/bkc-node/main/testnet/config.tom
```

{% endtab %}
{% endtabs %}

Download the [latest release](https://github.com/kub-chain/bkc/releases); the current version is `v2.4.0`

```sh
wget https://github.com/kub-chain/bkc/releases/download/v2.4.0-bkc/geth2.4.0.linux-amd64.tar.gz
```

{% hint style="warning" %}
Verify that the downloaded version is compatible with your device. KUB supports Darwin ARM64, Linux x86-64, and Linux ARM64. Visit the [latest release](https://github.com/kub-chain/bkc/releases) page to view the available versions under the assets section.
{% endhint %}

Extract the downloaded file

```sh
tar -xvf geth2.4.0.linux-amd64.tar.gz -O /use/bin/
```

Initialize the Genesis file

```sh
./geth --datadir ./data init ./genesis.json
```

Run `geth` using the following command

```shell
./geth --datadir ./data \
    --config ./config.toml --gcmode
```

Please allow some time for your system to download and sync the network data.


# Run a Node with Docker

This guide outlines the process of setting up and operating a KUB node using [Docker](https://docs.docker.com/engine/install/). Docker provides a streamlined and efficient method for running KUB Mainnet nodes, including [Validator Node](/run-a-kub-node/run-a-validator-node), [Full Node](/run-a-kub-node/run-a-full-node), and [Archive Node](/run-a-kub-node/run-an-archive-node) configurations.

## Core Components

Running a KUB node using Docker is designed to simplify node deployment by providing pre-configured [Docker Compose](https://docs.docker.com/compose/install/) setups. It encapsulates all the essential services required to run various types of KUB Mainnet nodes, ensuring a quick and reliable deployment.

## Prerequisites

Before you begin, ensure you have the following software installed on your system:

* [Docker](https://docs.docker.com/engine/install/): A platform for developing, shipping, and running applications in containers.
* [Docker Compose](https://docs.docker.com/compose/install/): A tool for defining and running multi-container Docker applications.

## Getting Started

### Initial Setup

To initiate the node deployment, you'll first need to clone the [`bkc-node-docker`](https://github.com/kub-chain/bkc-node-docker) repository and navigate into the `mainnet` directory, which contains the specific configurations for the KUB Mainnet.

```sh
git clone https://github.com/kub-chain/bkc-node-docker
cd bkc-node-docker/mainnet
```

### Node Configuration Approach

Unlike some other blockchain node setups that rely on `.env` files for configuration, `bkc-node-docker` adopts a different strategy. It provides distinct `docker-compose` files tailored for each node type.

This approach simplifies configuration by allowing you to select the appropriate `docker-compose` file directly when launching your node, eliminating the need for extensive environment variable management.

### Launching Your KUB Node

Once you've successfully navigated to the `bkc-node-docker/mainnet` directory, you can proceed to launch your desired KUB node type using the respective Docker Compose command. These commands will start the node services in the background, allowing them to run continuously.

{% tabs %}
{% tab title="Validator Node" %}

```sh
docker compose -f docker-compose.validator.yaml up -d
```

{% endtab %}

{% tab title="Full Node" %}

```sh
docker compose -f docker-compose.fullnode.yaml up -d
```

{% endtab %}

{% tab title="Archive Node" %}

```sh
docker compose -f docker-compose.archivenode.yaml up -d
```

{% endtab %}
{% endtabs %}

## Managing Your KUB Node

Docker Compose provides robust tools for interacting with and managing the various containers that comprise your KUB node.

### Monitoring Node Status

The [`bkc-node-docker`](https://github.com/kub-chain/bkc-node-docker) setup includes integrated monitoring solutions to help you keep track of your node's health and synchronization progress.

### **Grafana Monitoring Dashboard**

A Grafana dashboard is available for detailed monitoring and visualization of your node's metrics. Access it by navigating to [`http://localhost:8080`](http://localhost:8080/) in your web browser.

* **Default Username**: `admin`
* **Default Password**: `admin`

### **Stats Dashboard**

For a more concise overview of your node's operational statistics, you can access the Stats Dashboard at [`http://localhost:8090`](http://localhost:8090/) in your browser.


# Lausanne (v2.3.0-bkc)

## Before Upgrading

* This upgrade may involve some downtime. Please ensure you have a maintenance plan in place **before proceeding** with the following upgrade instructions.
* During the upgrade, your Geth (go-ethereum) node will be temporarily unavailable to the KUB network.
* After upgrading to the new version, your node may take approximately **5 to 15 minutes** to resynchronize with the latest blockchain information.
* We **strongly recommend** creating a disk snapshot **before upgrading** to prevent any potential data loss during the process.

## Instructions

Ensure the Geth node is fully stopped before proceeding with the upgrade

```bash
systemctl stop geth
```

Download and extract the Geth v2.3.0 binary from the official GitHub releases

```bash
wget https://github.com/kub-chain/bkc/releases/download/v2.3.0-bkc/geth2.3.0.linux-amd64.tar.gz
tar -xvf ./geth2.3.0.linux-amd64.tar.gz -c /usr/bin/
```

Grant the necessary execution permissions to the downloaded binary

```bash
sudo chmod +x /usr/bin/geth
```

Confirm that the correct version has been installed

```shellscript
/usr/bin/geth version
```

The expected output must be: `v2.3.0-bkc`

```shellscript
Geth
Version: 2.3.0-bkc-stable
Git Commit: ccc47eed26444e7fc262705fd1c3561119da1664 # This may be different
Git Commit Date: 20250506 # This may be different
...
```

Retrieve the latest `genesis.json` via the following command

```bash
wget https://raw.githubusercontent.com/kub-chain/bkc-node/main/mainnet/genesis.json
```

Verify that the downloaded file contains the required hard fork configuration

```bash
cat ./genesis.json
```

The output should contain the following field:

<pre class="language-json"><code class="lang-json">{
  ...
  "lausanneBlock": &#x3C;hard-fork-block>,
  ...
<strong>}
</strong></code></pre>

Apply the new `genesis.json`

```bash
/usr/bin/geth --datadir /bkc-node/mainnet/data init ./genesis.json
```

{% hint style="warning" %}
The data directory path used in the guide may differ from your actual environment. Verify your data directory path before executing any command and substitute it accordingly.
{% endhint %}

Start the Geth service to resume normal operation

```bash
systemctl start geth
```

Monitor the output logs to confirm the node has started successfully and is operating as expected

```bash
journalctl -fu geth
```


# Basel (v2.4.0-bkc)

## Before Upgrading

* This upgrade may involve some downtime. Please ensure you have a maintenance plan in place **before proceeding** with the following upgrade instructions.
* During the upgrade, your Geth (go-ethereum) node will be temporarily unavailable to the KUB network.
* After upgrading to the new version, your node may take approximately **5 to 15 minutes** to resynchronize with the latest blockchain information.
* We **strongly recommend** creating a disk snapshot **before upgrading** to prevent any potential data loss during the process.

## Instructions

Ensure the Geth node is fully stopped before proceeding with the upgrade

```bash
systemctl stop geth
```

Download and extract the Geth v2.4.0 binary from the official GitHub releases

```bash
wget https://github.com/kub-chain/bkc/releases/download/v2.4.0-bkc/geth2.4.0.linux-amd64.tar.gz
tar -xvf ./geth2.4.0.linux-amd64.tar.gz -c /usr/bin/
```

Grant the necessary execution permissions to the downloaded binary

```bash
sudo chmod +x /usr/bin/geth
```

Confirm that the correct version has been installed

```shellscript
/usr/bin/geth version
```

The expected output must be: `v2.4.0-bkc-stable`

```shellscript
Geth
Version: 2.4.0-bkc-stable
Git Commit: 28cb5603e9c866a0ff67c5e0520274adf819402a # This may be different
Git Commit Date: 20260303 # This may be different
...
```

Retrieve the latest `genesis.json` via the following command

```bash
wget https://raw.githubusercontent.com/kub-chain/bkc-node/main/mainnet/genesis.json
```

Verify that the downloaded file contains the required hard fork configuration

```shellscript
cat ./genesis.json
```

The output should contain the following field:

```json
{
  ...
  "baselBlock": {
      "block": 31237946,
      "superNode": "0xcf723fE5a8118efE70D3fAdd56C5e6D01aDeC7A3",
      "superNodeOwner": "0x5106ffca7cC44E6cFfEE9bD016A0934130b0322f",
      "period": 3
  },
  ...
}
```

Apply the new `genesis.json`

```bash
/usr/bin/geth --datadir /bkc-node/mainnet/data init ./genesis.json
```

{% hint style="warning" %}
The data directory path used in the guide may differ from your actual environment. Verify your data directory path before executing any command and substitute it accordingly.
{% endhint %}

Start the Geth service to resume normal operation

```bash
systemctl start geth
```

Monitor the output logs to confirm the node has started successfully and is operating as expected

```bash
journalctl -fu geth
```


# Block Explorer

Block explorers provide valuable insights into the network's ledger, which records accounts, the tokens assigned to them, transactions between those accounts, and the creation of new tokens. As users engage in various activities on the network, changes occur within these accounts and tokens. A block explorer serves as an interface that allows you to access and examine this information in detail, offering transparency into the blockchain's operations.&#x20;

A block explorer is available for the [KUB Mainnet](https://www.kubscan.com/). This block explorer provides tools to help you debug smart contracts and transactions:

* View, verify, and interact with smart contract source code
* View detailed transaction information

A testnet explorer for [KUB Testnet](https://testnet.kubscan.com/) is also available.&#x20;

## API Endpoint

| Environment | End Point                         |
| ----------- | --------------------------------- |
| KUB Mainnet | <https://kubscan.com/api>         |
| KUB Testnet | <https://testnet.kubscan.com/api> |

{% hint style="warning" %}
The KUB Scan API enforces a rate limit of 12 requests per minute per IP address. If a user exceeds this rate limit, the system will automatically block the offending IP address for 1 minute
{% endhint %}


# Testnet Faucet

A testnet is a version of a blockchain specifically designed for testing purposes. Unlike a mainnet, which serves as a live production environment, testnets allow developers to test their applications and smart contracts without the risk of losing real-world assets. Testnet tokens can be easily obtained from testnet faucets, enabling users to experiment with transactions on these networks.

To start building on the KUB Testnet, you will need some testnet KUB (tKUB). The most efficient way to acquire tKUB is to use the KUB Faucet, which dispenses tKUB directly to your selected account.

## KUB Faucet

The [KUB Faucet](https://faucet.kubchain.com/) is a valuable tool offered by KUB, designed to assist developers in acquiring free tKUB for testing applications on the KUB Testnet. This resource serves as an ideal starting point for those seeking to obtain tKUB effectively.

{% hint style="info" %}
You'll be able to receive 5 tKUB every 24 hours using the KUB Faucet.
{% endhint %}


# Token Bridge

Blockchain bridges are protocols that facilitate the transfer of assets and data between different blockchain networks. In terms of functionality, a cross-chain bridge converts a native asset from one blockchain into its corresponding asset on another blockchain.

## KUB Bridge

[KUB Bridge](https://bridge.kubchain.com/en) is the native bridge of the KUB network. Users can bridge assets from selected networks to KUB by using our protocol. The current networks that are supported on KUB Bridge include:

* [Ethereum](https://ethereum.org/)
* [BNB Smart Chain](https://www.bnbchain.org/)
* [JFIN Chain](https://www.jfincoin.io/about-jfin-chain)

## Quickstart Guide

This quickstart is for users who want to deposit KUB or any ERC-20 tokens from selected networks to KUB or withdraw from KUB to selected networks. The only prerequisite for this quickstart is to have a Web3 wallet installed.

### Step 1: Get Native Tokens

You will need the native tokens of the source network to transfer your assets to the destination network. For example, if you want to bridge assets from Ethereum to KUB, you'll need ETH on Ethereum to start the process.

There are several ways to obtain the native currency:

* Using a supported centralized exchange, which allows you to purchase **ETH** and withdraw it to your wallet.
* Using an on-ramp service, which allows you to purchase **ETH** and send it directly to your wallet.

### Step 2: Add Network <a href="#step-2-add-the-preferred-network-to-your-wallet" id="step-2-add-the-preferred-network-to-your-wallet"></a>

You'll also need to add the desired network's RPC endpoint to your wallet. [KUB](/about-kub/connect-to-kub) can be added using any Web3 wallet that supports custom RPC. Most Web3 wallets should support Ethereum by default. For BNB Smart Chain and JFIN Chain, you should find their RPC details on their website to add their network to your Web3 wallet.

### Step 3: Initiate the Deposit

Visit the [KUB Bridge](https://bridge.kubchain.com/en) and log in using your wallet. Make sure you are connected to the source network (from which you want to deposit your assets) at the top of the page. Next, select the destination network (where you want your assets to go), e.g., Ethereum to KUB.

Choose the token you wish to bridge from the token drop-down menu. Enter the amount of **KUB** or ERC-20 tokens you want to transfer in the **From** box, and then press the **Bridge** button. Follow the instructions provided by your Web3 wallet.

After submitting the transaction through your Web3 wallet, you can expect your funds to arrive on the destination chain within approximately 5-10 minutes (depending on the chain congestion). Additionally, ensure your wallet is set to the destination chain so you can see your funds when they arrive.


# Governance Fundamentals

KUB network relies on community-driven governance. A broad set of stakeholders must approve and adopt any protocol upgrades. These include validators, full node operators, developers, infrastructure providers, and token holders. Without alignment, a change can result in a split of the chain, known as a [fork](#forks).

## Forks

There are two primary forms of protocol upgrades: hard forks and soft forks. A hard fork introduces changes that are not compatible with previous versions of the node software. Nodes that fail to upgrade by the designated activation block will no longer recognize new blocks, causing them to diverge from the main network. The network may experience a temporary halt or a full chain split if enough validating power is split between versions. In contrast, a soft fork is backward-compatible. Nodes running older software can continue validating transactions under the new rules, provided those changes are restrictive or additive rather than conflicting. This allows for gradual adoption and less risk of fragmentation.

### Upgrades on the KUB Network

In the early stages of upgrading the consensus mechanism on the KUB network, we changed the consensus from Proof-of-Authority (PoA) to Proof-of-Stake-Authority (PoSA) via a hard fork called the Erawan Upgrade. Since the transition to PoSA has run smoothly on the KUB network, we have upgraded the consensus from PoSA to Proof-of-Stake (PoS) via the Chaophraya Upgrade. The PoS consensus was designed to reduce the restrictions of PoSA, so that the validator node no longer needs permission or approval from the existing authority.&#x20;

The PoS on the KUB network includes a mechanism to randomly select validators and a staking contract. The consensus uses KUB Coin, which is staked in the staking contract as a signer’s power. In each period for selecting validators, the PoS mechanism will randomly target numbers from the total stake of the available validators in the PoS contract. All the numbers will be transformed into a list of authorized validator addresses and committed to the PoS contract.

The [Lausanne Upgrade](/node-upgrade-instruction/lausanne-v2.3.0-bkc) has introduced several parameters and features governed directly on-chain. Validators also benefit from the ability to reactivate themselves if they meet the necessary staking requirements after being removed for issues like missed conditions. Additionally, a new partial unstaking feature allows validators to partially withdraw their staking funds while maintaining operations, offering greater financial flexibility as thresholds evolve.

The recent [Basel Upgrade](/node-upgrade-instruction/basel-v2.4.0-bkc) significantly boosts KUB Chain’s performance by reducing block times from `5` to `3` seconds while maintaining stability through new system-owned Failsafe Supernodes. This strategic upgrade streamlines the ecosystem by merging Official Nodes into a unified Pool Node structure and halting new Solo Node registrations to prioritize scalability, though existing Solo operators remain the same.

## Roles in Governance

* Validators are responsible for confirming blocks and enforcing consensus rules. They play a critical role during upgrades, as their collective stake determines which version of the protocol becomes canonical.
* Full nodes, while not responsible for block production, validate all network activity and serve users, dApps, and service providers. These nodes must also be updated during upgrades to ensure compatibility.
* Core developers research, propose, and implement protocol changes. Meanwhile, token holders and end users participate by voicing support or concerns, often through delegated voting or off-chain feedback systems.

## Upgrade Testing and Deployment

Once approved, upgrades go through several technical stages. Developers implement changes and test them in private environments. When stable, the upgrade is deployed to a public testnet, where it operates under real-world conditions without affecting actual assets.

If the testnet phase shows no critical issues, a mainnet deployment is scheduled. Validators and node operators are given a timeline or block number by which they must upgrade. Widespread adoption ensures the new version becomes the official continuation of the KUB network.


# Delegate KUB Coin

Delegators are groups of individuals who participate in validating transactions with the validators. The delegators jointly stake the KUB coin with the validator to delegate authority to the validator to validate the transaction. The delegators receive rewards based on the proportion of staking power under which the delegator can do without its technical knowledge or infrastructure.

## Considerations <a href="#considerations-before-becoming-a-delegator" id="considerations-before-becoming-a-delegator"></a>

Before becoming a delegator in a blockchain network, several important considerations must be considered to ensure a rewarding and secure staking experience.

### Staking Power

One of the primary considerations before becoming a delegator is assessing the node's power and performance. A staking's power is determined by the total amount of tokens staked on a node validator. Look for nodes with a significant stake, as they are more likely to be selected as validators, leading to more consistent rewards for delegators.

### Fees and Rewards <a href="#fees-and-rewards" id="fees-and-rewards"></a>

Review the fee structure of the staking pool, including commission fees (staking fees) and any additional charges. Seek a balance between competitive fees and attractive rewards to maximize your earnings.

### Delegator Amount and Delegate Size <a href="#delegator-amount-and-delegate-size" id="delegator-amount-and-delegate-size"></a>

Assess the number of tokens you plan to delegate. While larger delegates may yield higher rewards, consider your risk tolerance and the amount of tokens you can comfortably lock up for the staking duration.

## Selecting a Validator Node

For delegators who would like to delegate using KUB Wallet or Metamask, please navigate to [KUB Stake](https://staking.kubchain.com). All validators carry a certain degree of risk. You should choose the validator that aligns with your specific purpose. Whether you prioritize a high distributed reward or a low service fee percentage, it is crucial to consider your own risk and preferences.

{% hint style="warning" %}
Slashing might happen if a validator misbehaves or tries to violate the chain. To minimize the risk of unnecessary reward loss, select reliable validators before delegating.
{% endhint %}

The more the staking power, the more chance the validator will be picked to validate a transaction. Note that if only a small group of validators control the majority of the staking power, it could raise doubts or skepticism about the principle of decentralization. On the other hand, choosing a validator with excessively low staking power reduces the chances of receiving distributed rewards. We do not assume responsibility or liability for any losses that may occur during the delegation process.&#x20;

### Service Fee

The service fee is a fee charged to the delegators. Some validators may start by offering zero service fees to attract new delegates, but it is important to note that these fee rates are subject to change later.

### Validator Reliability

When you delegate your funds to a validator, it is important to check the validator’s ​​trustworthiness to ensure that the validator is always acting in your best interest.

## Delegating to a Validator Node <a href="#step-2-delegate-to-a-validator-node" id="step-2-delegate-to-a-validator-node"></a>

1. Select your desired validator node and click on the **Delegate** button
2. Input the amount of KUB Coin you want to delegate to this validator node
3. As the total stake increases, staking power shows a positive correlation

{% hint style="warning" %}
Each pool node may have a minimum requirement for the delegated amount. Please ensure you have sufficient KUB Coin before you delegate to the validator node.
{% endhint %}

### Delegating More KUB Coin to a Validator Node

1. Navigate to the **My Delegation** page or click on the delegate button in the same validator that you have already delegated
2. Click on the **Delegate More** button
3. Preview the number of rewards that will be received after delegating more
4. Input the amount of KUB Coin you want to delegate
5. Click the **Delegate More** button to confirm the transaction

{% hint style="info" %}
When you submit a Delegate More transaction, you will receive any previous unclaimed rewards before starting to collect new rewards.
{% endhint %}

## Claiming Rewards

1. Navigate to the **My Delegation** page
2. Click on the **Claim** button to start the reward claim process
3. You can claim your reward immediately by clicking on the **Claim** button

{% hint style="info" %}
Every time you claim a reward, the amount you receive will be the reward amount subjected to the deduction of the service fee.
{% endhint %}

{% hint style="warning" %}
If your reward after deducting the service fee is less than 0.01 KUB for KUB Wallet or 0.00000001 KUB for MetaMask, you will not be able to claim the reward.
{% endhint %}

## Unstaking from a Validator Node <a href="#step-2-delegate-to-a-validator-node" id="step-2-delegate-to-a-validator-node"></a>

1. Navigate to the **My Delegation** page
2. Click on the **Unstake** button to start the unstaking process
3. You will receive the entire delegated amount, along with the distributed rewards

{% hint style="info" %}
The service fee will only be deducted from the reward, not from the staked amount.
{% endhint %}


# Delegation FAQs

## What are the differences between staking and delegation?

Staking refers to the process of actively participating in a Proof-of-Stake (PoS) blockchain network by locking up a certain amount of the native cryptocurrency (or token) as collateral to support network operations. This collateral is commonly known as a stake. Validators, who are responsible for verifying and validating transactions on the network, are chosen to create new blocks and secure the network based on the amount of cryptocurrency they have staked. The more tokens a user stakes, the higher their chances of being selected as a validator and earning rewards in return for their service.

Delegation, on the other hand, is a process within a Proof-of-Stake (PoS) blockchain network where delegators can participate in the consensus mechanism without the need to run a validator node themselves. Instead of staking and maintaining their validator node, users can delegate their tokens to an existing validator on the network. By doing so, they entrust the chosen validator to represent their stake and perform network validation on their behalf.

## Where can I check the delegation details?

Once you have completed your delegation, you will have to wait for six block confirmations on the KUB network, which is approximately 30 seconds to 1 minute. Navigate to the **My Delegation** page to view your dashboard and delegation details.

## What would happen if I earn rewards while delegating, and I add additional funds to the same validator node?

If you have not withdrawn your rewards before delegating additional funds to the same validator node, your rewards will be withdrawn automatically when you add additional funds.

## What is the minimum delegation amount?

The minimum KUB Coin required to delegate is the following:

* Official Pool: 1 KUB
* Validator Pool: 100 KUB

## Which wallets are currently supported to delegate?

Two wallets are currently supported for delegation: [KUB Wallet](https://www.kubwallet.com/) and [MetaMask](https://metamask.io/).

## Are hardware wallets supported?

Yes, hardware wallets are supported. You can use the **Connect Hardware Wallet** option on MetaMask, connect your Hardware wallet, and then continue with the delegation process.

## When does the reward get distributed?

KUB Coin is distributed proportionately on each successful checkpoint submission to each delegator based on their stake, relative to the overall staking pool of all validators and delegators. The percentage for the reward distributed to each delegator will vary with each checkpoint depending on the relative stake of the delegator, validator, and overall stake.

## What are the potential lossese for delegators?

The only risk for delegators is the loss of rewards when their staked validator is slashed or inactive. However, the delegator's KUB Coin will not be affected.


# KUB Vote

## Overview

[KUB Vote](https://vote.kubchain.com), an on-chain voting system, empowers KUB Coin holders to influence the network’s development and proposals through a transparent voting process. KUB Vote is a platform where community proposals are listed and voted on using gKUB tokens. The outcomes of these on-chain votes can drive real changes in the protocol, including new feature upgrades, system improvements, or policy changes, ensuring the network evolves with community consensus. KUB Vote supports both [KUB Wallet](https://www.kubwallet.com/) and [MetaMask](https://metamask.io).

## Understanding Proposals

A proposal is a submission by the core team or community members suggesting a change or action for the network. Each proposal has its page displaying important information.

### Title and Description

A summary of what the proposal is about. You can click on a proposal to read details of the suggested change or action.

### Proposer

The person or entity who created the proposal. Some proposals may be officially put forward by the KUB team, while others might be from community members or third parties.

### Status and Voting Period

Each proposal will show its status. Active proposals are open for voting, whereas upcoming proposals will have a **Starting Soon** label with a future start time. The start date and end date of the voting period are displayed so you know the timeframe during which you can vote.

### Vote Options and Tally&#x20;

The proposal page will list the voting options and will show the current tally or outcome. During an active vote, you might see how much gKUB has been voted for each option so far. For closed proposals, the final results and whether it passed or failed are shown.

## Getting gKUB

Before you can vote, you’ll need to obtain gKUB, the token used for voting on the KUB network. You can earn gKUB by staking your KUB Coin. In other words, gKUB represents your staked KUB and serves as your voting power in the system. To get gKUB, follow these steps:

1. Stake your KUB Coin on [KUB Stake](/governance/delegate-kub-coin)
2. Navigate to the **Stake** page on KUB Vote
3. Click on the **Stake BKC-D** button
4. Select the Pool Node where you have your KUB Coin staked
5. Enter the amount of BKC-D that you would like to stake
6. Select the **Stake Duration**
7. Click on the **Stake** button

The amount of gKUB you receive corresponds to the amount of KUB Coin you stake, and it may also depend on how long you choose to stake your tokens. Longer staking commitments yield more gKUB. In simple terms: the more KUB you stake (and the longer you stake it), the more gKUB voting power you’ll have.&#x20;

## Voting on a Proposal

Casting your vote on an active proposal is straightforward once you have gKUB. To vote on a proposal, follow these steps:

1. Navigate to the **Proposal** page on KUB Vote
2. Click on the proposal you want to vote on to open its details page
3. Read the proposal’s description and details carefully
4. Choose your voting option on the proposal page
5. Click on the **Vote** button
6. Confirm the transaction in your wallet to finalize your vote

Once confirmed on-chain, your vote is officially counted toward the proposal. Note that you cannot change your vote after it’s submitted, so double-check your choice before confirming. Voting with gKUB is irreversible for that proposal once done.

## Tracking Results and Participation

Once the voting period for a proposal ends, the proposal is considered closed, and the outcome is determined. After the end time, the proposal page will indicate whether the proposal passed or failed. This is usually based on whether the **For** votes met the required criteria. In most cases, a proposal passes if a majority of the gKUB votes are **For** and a minimum quorum (minimum number of total votes) is reached. If these conditions are not met, the proposal fails due to insufficient support.

You’ll be able to see the breakdown of votes. This tells you how much voting power was cast for each option. If the proposal was an official one from the KUB team and it passed, you can expect the suggested change to be implemented by the team according to the roadmap and timeline. The voting results send a clear signal of the community’s decision.

## Community Involvement

Community involvement is the cornerstone of on-chain governance. Every KUB Coin holder’s vote is vital in steering the network towards a secure and innovative future. Voting isn’t just a formality, it has real effects. Features that get approved by the community can be implemented, and policies the community rejects will not move forward. Your vote, no matter how small, contributes to these outcomes. We believe that using gKUB for on-chain voting will strengthen the ecosystem by allowing the community to truly participate in developing the infrastructure. When more community members participate, KUB becomes more robust and decentralized. Governance is most effective when a wide array of voices contributes. Together, the KUB community can ensure the chain’s future is built by and for its users.


# KUB Improvement Proposal (KIP)

## **What is the KUB Improvement Proposal (KIP)?**&#x20;

KIP stands for KUB Improvement Proposal. A KIP is a design document providing information to the KUB community or describing a new feature for KUB or its processes, or environment. The goal of the KIP project is to standardize and provide high-quality documentation for the KUB itself and the conventions built upon it. The KIP repository tracks past and ongoing improvements to KUB through KUB Improvement Proposals (KIPs).  &#x20;

## **How does it work?**&#x20;

Before you write a KIP, ideas must be thoroughly discussed on this forum. Once consensus is reached, thoroughly read and review KIP-1, which describes the KIP process. The following are the processes the author must follow to start working on the KIP:

1. The author opens a discussion thread on the KUB Discord server forum.
2. The author writes a draft KIP according to the guidelines. The author may include an implementation.
3. The author then files a pull request on the [KIPs repository](https://github.com/kub-chain/KIPs) for consideration.
4. The author submits changes to the draft until the KIP is mature and ready. The author then submits the draft for review.
5. The KIP will be listed on GitHub for changes and reviews by KUB. The author will have to make changes and edits.
6. KUB will finally review the KIP before moving to the Final status.
7. The KIP is implemented and adopted by the community. The KIP represents the final standard

## **Importance and Benefits of KIPs towards KUB Network**&#x20;

KIPs are intended to be the primary mechanisms for proposing new features, collecting community technical input on an issue, and documenting the design decisions that have gone into KUB. The KIP author is responsible for building consensus within the community and documenting dissenting opinions. KIPs are specifications intended to outline future KUB features or improvements. They enable the network's developers and community users to suggest new features, adjustments, protocol standards, and solutions. The KIP proposal seeks to enhance the KUB network with the suggested modifications or new features if it is approved by the community. For enhancement ideas, KIPs are comparable to the Bitcoin Enhancement Proposal (BIP) and Ethereum Improvement Proposal (EIP) used by Bitcoin and Ethereum, respectively.


