ThaiChain
Back to home

ThaiChain Documentation

Complete guide for interacting with ThaiChain using Foundry Cast. Learn how to query blocks, transactions, tokens, deploy contracts, and manage fees.

Download SKILL.md for AI agents

A ready-to-use skill file for vibe-coding agents (Claude Code, Cursor, etc.) — drop it into your project to give the agent full ThaiChain context.

Network Information

Chain ID
7
Block Time
0.5s
Max Throughput
~100,000 TPS
Consensus
Simplex BFT with DKG
RPC Endpoint
https://rpc.thaichain.org

Table of Contents

01. Install Foundry

Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust. castis Foundry's command-line tool for interacting with EVM smart contracts, sending transactions, and getting chain data.

Install via foundryup

Bash — macOS / Linux
curl -L https://getfoundry.sh/install | bash

After installation, restart your terminal and run:

Bash
foundryup

Verify Installation

Bash
cast --version

02. Gas Fee Model

Important: ThaiChain has no volatile native gas token. Fees are paid in TIP-20 stablecoins — not native ETH.

Because fees are paid in a stablecoin, you must hold a fee token balance (e.g. TCH) — not native ETH — to transact.

03. Setup

Common Variables

Bash
# RPC endpoint
RPC=https://rpc.thaichain.org

# Token & system addresses
TCH=0x20C0000000000000000000000000000000000000
TIP20_FACTORY=0x20fc000000000000000000000000000000000000
FEE_MANAGER=0xfeEC000000000000000000000000000000000000
STABLECOIN_DEX=0xdec0000000000000000000000000000000000000

# Private key (store as env variable)
export PRIVATE_KEY=<your_private_key>

Predeployed System Contracts

AddressNamePurpose
0x20C0...0000TCHFirst stablecoin (default fee token)
0x20fc...0000TIP-20 FactoryCreate new TIP-20 tokens
0xfeEC...0000Fee ManagerFee payments & conversions
0xdec0...0000Stablecoin DEXEnshrined DEX for stablecoin swaps
0x403c...0000TIP-403 RegistryTransfer policy registry
0xcA11...CA11Multicall3Batch multiple calls
0xba5E...a5EdCreateXDeterministic CREATE2 deployment
0x0000...8ba3Permit2Token approvals & transfers

04. TIP-20 Token Standard

TIP-20 extends ERC-20 with payment-native features:

05. Create a TIP-20 Token

Call createToken on the TIP-20 Factory:

Bash
cast send 0x20fc000000000000000000000000000000000000 \
  "createToken(string,string,uint8,string,uint256)" \
  "My USD Coin" "MUSD" 6 "USD" 1000000000000 \
  --rpc-url https://rpc.thaichain.org \
  --private-key $PRIVATE_KEY

Args: name, symbol, decimals, currency, maxSupply (use type(uint256).max for uncapped).

The factory deploys the token deterministically and assigns the caller all roles (issuer/pause/etc.). Read the new token's address from the TokenCreated event logs.

06. View Token Info

Bash
# View all token info at once
echo "Name:         $(cast call $TCH 'name()(string)' --rpc-url $RPC)"
echo "Symbol:       $(cast call $TCH 'symbol()(string)' --rpc-url $RPC)"
echo "Currency:     $(cast call $TCH 'currency()(string)' --rpc-url $RPC)"
echo "Decimals:     $(cast call $TCH 'decimals()(uint8)' --rpc-url $RPC)"
echo "Total Supply: $(cast call $TCH 'totalSupply()(uint256)' --rpc-url $RPC)"

Note: TIP-20 tokens always use 6 decimals (THAICHAIN-TIP21)

07. View Balance

Bash
cast call $TCH "balanceOf(address)(uint256)" $ADMIN --rpc-url $RPC

Conversion Table (6 decimals)

AmountRaw Value
1 TCH1000000
10 TCH10000000
100 TCH100000000
1,000 TCH1000000000
10,000 TCH10000000000

08. Mint Token

Note: You must have ISSUER_ROLE to mint tokens.

Bash
# Mint 100 TCH (100 * 10^6 = 100000000)
cast send $TCH \
  "mint(address,uint256)" \
  $RECIPIENT 100000000 \
  --private-key $PRIVATE_KEY \
  --rpc-url $RPC

09. Transfer Token

Bash
# Transfer 1 TCH (1,000,000 units) to recipient
cast send $TCH \
  "transfer(address,uint256)(bool)" \
  $RECIPIENT 1000000 \
  --private-key $PRIVATE_KEY \
  --rpc-url $RPC

10. Add Token to Fee AMM

To let users pay gas in a custom TIP-20 token (beyond the default TCH), add liquidity to the Stablecoin DEX.

Bash
# 1. Approve token for the DEX
cast send <TOKEN_ADDRESS> "approve(address,uint256)" \
  0xdec0000000000000000000000000000000000000 \
  $(cast max-uint256) \
  --rpc-url https://rpc.thaichain.org \
  --private-key $PRIVATE_KEY

# 2. Add liquidity (pair TOKEN + TCH)
cast send 0xdec0000000000000000000000000000000000000 \
  "addLiquidity(address,uint256,address,uint256)" \
  <TOKEN_ADDRESS> 1000000000 \
  0x20C0000000000000000000000000000000000000 1000000000 \
  --rpc-url https://rpc.thaichain.org \
  --private-key $PRIVATE_KEY

After liquidity exists, the Fee AMM will accept your token for fee payments and auto-convert to the validator's preferred fee token.

11. Fee Manager

Fee Manager precompile is located at 0xfeEC000000000000000000000000000000000000

Fee Flow

User sends transaction
    │
    ▼
collect_fee_pre_tx  → Deduct gas fee from user
    │
    ▼
Transaction executes
    │
    ▼
collect_fee_post_tx → Accumulate to collected_fees[validator][token]
    │
    ▼
distributeFees()   → Transfer accumulated fees → validator address

Check Validator Fees

Bash
# Accumulated fees
cast call $FEE_MANAGER \
  "collectedFees(address,address)(uint256)" \
  $VALIDATOR $TCH --rpc-url $RPC

# Validator fee token
cast call $FEE_MANAGER \
  "validatorTokens(address)(address)" \
  $VALIDATOR --rpc-url $RPC

Distribute Fees

Bash
# Anyone can call — transfers accumulated fees to validator
cast send $FEE_MANAGER \
  "distributeFees(address,address)" \
  $VALIDATOR $TCH \
  --private-key $PRIVATE_KEY --rpc-url $RPC

12. Gas Sponsorship

ThaiChain supports Tempo's fee sponsorship model — a third party (fee payer) signs the feePayerSignatureso users don't need to hold fee tokens.

Client-side (viem)

TypeScript
import { Account, withRelay } from "viem/tempo";

const account = Account.fromSecp256k1(privateKey);
const client = createWalletClient({
  account,
  chain: thaichain,
  transport: withRelay(
    http("https://rpc.thaichain.org"),
    http("https://sponsor.thaichain.org"),
    { policy: "sign-and-broadcast" },
  ),
});

await client.sendTransaction({
  to, data, value,
  feePayer: true, // ← enables sponsorship
});

Self-hosted Fee Payer

Deploy the fee-payer worker (Cloudflare Worker + Hono) with:

Env
SPONSOR_PRIVATE_KEY=<sponsor_wallet_key>
TEMPO_ENV=thaichain
TEMPO_RPC_URL=https://rpc.thaichain.org

13. Deploy Smart Contracts

Deploy with forge create

Bash
forge create src/MyContract.sol:MyContract \
  --rpc-url https://rpc.thaichain.org \
  --private-key $PRIVATE_KEY \
  --constructor-args 0x20C0000000000000000000000000000000000000 \
  --gas-limit 10000000 --slow

Deploy with forge script

Bash
forge script script/Deploy.s.sol \
  --rpc-url https://rpc.thaichain.org \
  --broadcast \
  --private-key $PRIVATE_KEY \
  --slow

⚠️ Gas limit gotcha: forge script may run out of gas. Add --gas-limit 10000000 --skip-simulation or use forge create per contract.

UUPS Upgradeable Proxy (two-step)

Bash
# Step 1 — Deploy implementation
forge create src/MyContractV2.sol:MyContractV2 \
  --rpc-url https://rpc.thaichain.org \
  --private-key $PRIVATE_KEY --gas-limit 10000000

# Step 2 — Deploy proxy
INIT_DATA=$(cast abi-encode "initialize(address)" 0xADMIN_ADDRESS)

forge create @openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol:ERC1967Proxy \
  --rpc-url https://rpc.thaichain.org \
  --private-key $PRIVATE_KEY --gas-limit 5000000 \
  --constructor-args 0xIMPLEMENTATION_ADDRESS $INIT_DATA

14. Verify Contracts

Bash
forge verify-contract 0xYOUR_CONTRACT_ADDRESS \
  src/MyContract.sol:MyContract \
  --chain-id 7 \
  --verifier sourcify \
  --verifier-url https://contracts.thaichain.org

15. Tempo Transactions (0x76)

ThaiChain uses Tempo's transaction envelope (type 0x76) which extends EIP-1559 with:

JSON-RPC Methods

Bash
# Fill missing fields (nonce, gas, fee payer)
eth_fillTransaction

# Broadcast and wait for receipt
eth_sendRawTransactionSync

# Sign-only policy
eth_signRawTransaction

16. Decode Data

Decode Function Selector

Bash
cast 4byte 0xa6c07924
# Output: distributeFees(address,address)

Decode Calldata

Bash
cast pretty-calldata 0xa6c079240000000000000000000000005266dfa5ae013674f8fdc832b7c601b838d94ee600000000000000000000000020c0000000000000000000000000000000000000

17. Example Scripts

Check All Tokens

Bash
#!/bin/bash
RPC=https://rpc.thaichain.org
TOKENS=(
  "0x20C0000000000000000000000000000000000000"
)

for TOKEN in "${TOKENS[@]}"; do
  echo "=== Token: $TOKEN ==="
  echo "Name:       $(cast call $TOKEN 'name()(string)' --rpc-url $RPC)"
  echo "Symbol:     $(cast call $TOKEN 'symbol()(string)' --rpc-url $RPC)"
  echo "Currency:   $(cast call $TOKEN 'currency()(string)' --rpc-url $RPC)"
  echo "Decimals:   $(cast call $TOKEN 'decimals()(uint8)' --rpc-url $RPC)"
  echo "Supply:     $(cast call $TOKEN 'totalSupply()(uint256)' --rpc-url $RPC)"
  echo ""
done

Check Validator Status

Bash
#!/bin/bash
RPC=https://rpc.thaichain.org
FEE_MANAGER=0xfeec000000000000000000000000000000000000
TCH=0x20C0000000000000000000000000000000000000
VALIDATORS=(
  "0x5266Dfa5ae013674f8FdC832b7c601B838D94eE6"
)

for V in "${VALIDATORS[@]}"; do
  echo "=== Validator: $V ==="
  echo "Fee Token:    $(cast call $FEE_MANAGER 'validatorTokens(address)(address)' $V --rpc-url $RPC)"
  echo "Collected Fees: $(cast call $FEE_MANAGER 'collectedFees(address,address)(uint256)' $V $TCH --rpc-url $RPC)"
  echo ""
done

18. Useful Resources

Building with an AI agent?

Download the SKILL.md file and add it to your project. It gives Claude Code, Cursor, and other vibe-coding agents full context about ThaiChain — chain config, gas model, system contracts, and all the commands above.

Download SKILL.md
↑ Back to top