Developer Guide
Building on Panoptis Chain offers the familiar Ethereum development experience with significant performance improvements. This guide will help you leverage Panoptis Chain's unique capabilities.
Familiar Tools : Panoptis Chain is fully EVM-compatible, so you can use existing Ethereum development tools like Hardhat, Foundry, and Remix without modification.
Add Panoptis Chain to your development environment:
// hardhat.config.js
module . exports = {
networks: {
panoptis: {
url: "https://rpc.panoptis.chain" ,
chainId: 4095 ,
accounts: [process.env. PRIVATE_KEY ]
},
panoptisTestnet: {
url: "https://testnet-rpc.panoptis.chain" ,
chainId: 4093 ,
accounts: [process.env. PRIVATE_KEY ]
}
}
};
Configure MetaMask for Panoptis Chain:
const panoptisNetwork = {
chainId: '0xfff' , // 4095 in hex
chainName: 'Panoptis Chain' ,
nativeCurrency: {
name: 'PANO' ,
symbol: 'PANO' ,
decimals: 18
},
rpcUrls: [ 'https://rpc.panoptis.chain' ],
blockExplorerUrls: [ 'https://explorer.panoptis.chain' ]
};
// Add network to MetaMask
await window.ethereum. request ({
method: 'wallet_addEthereumChain' ,
params: [panoptisNetwork]
});
Panoptis Chain's ~400ms block times enable new development patterns:
// Leverage sub-second finality
async function sendTransaction ( tx ) {
const signedTx = await wallet. signTransaction (tx);
const txResponse = await provider. sendTransaction (signedTx);
// Wait for just ONE block confirmation (~400ms)
const receipt = await txResponse. wait ( 1 );
console. log ( `Transaction confirmed in ${ receipt . blockNumber } (~400ms)` );
return receipt; // Proceed with confidence
}
Complex sequences become user-friendly:
// Multi-step DeFi operation (Approve + Swap + Deposit)
async function executeDeFiStrategy ( tokenAddress , amount ) {
const approveTx = await erc20. approve ( ROUTER_ADDRESS , amount);
await approveTx. wait ( 1 ); // ~400ms
const swapTx = await router. swapExactTokensForETH ( /* ... */ );
await swapTx. wait ( 1 ); // ~400ms
const depositTx = await lendingPool. deposit ( /* ... */ );
await depositTx. wait ( 1 ); // ~400ms
// Total time ~1.2 seconds
console. log ( 'Multi-step strategy completed.' );
}
Design contracts to maximize parallel execution benefits:
// ✅ Good: User-isolated state
contract ParallelFriendlyToken {
mapping ( address => uint256 ) private balances;
mapping ( address => mapping ( address => uint256 )) private allowances;
function transfer ( address to , uint256 amount ) external {
// Only touches sender and recipient balances
balances[ msg.sender ] -= amount;
balances[to] += amount;
emit Transfer ( msg.sender , to, amount);
}
}
// ❌ Bad: Global state dependencies
contract SerialContract {
uint256 public globalCounter; // Creates conflicts
function increment () external {
globalCounter ++ ; // All transactions conflict here
}
}
// Efficient batch processing
contract BatchProcessor {
function batchTransfer (
address [] calldata recipients ,
uint256 [] calldata amounts
) external {
require (recipients.length == amounts.length, "Length mismatch" );
for ( uint i = 0 ; i < recipients.length; i ++ ) {
_transfer ( msg.sender , recipients[i], amounts[i]);
}
}
function batchMint (
address [] calldata recipients ,
uint256 [] calldata amounts
) external onlyOwner {
for ( uint i = 0 ; i < recipients.length; i ++ ) {
_mint (recipients[i], amounts[i]);
}
}
}
// ✅ Optimized: Packed into single storage slot
struct PackedData {
uint128 amount; // 16 bytes
uint64 timestamp; // 8 bytes
uint32 id; // 4 bytes
bool active; // 1 byte -> 1 slot total
}
// ❌ Unoptimized: Uses multiple slots
struct UnpackedData {
uint256 amount; // 32 bytes -> 1 slot
uint256 timestamp; // 32 bytes -> 1 slot
uint256 id; // 32 bytes -> 1 slot
bool active; // 32 bytes -> 1 slot (4 slots total)
}
contract EventOptimized {
event StateChange ( address indexed user , uint256 indexed action , bytes data );
function performAction ( uint256 actionType , bytes calldata data ) external {
// Minimal on-chain state
userLastAction[ msg.sender ] = block .timestamp;
// Detailed data in events (cheaper than storage)
emit StateChange ( msg.sender , actionType, data);
}
}
// hooks/useContract.ts
import { useContractRead, useContractWrite } from 'wagmi' ;
import { parseEther } from 'viem' ;
export function useTokenBalance ( address : `0x${ string }` ) {
return useContractRead ({
address: TOKEN_ADDRESS ,
abi: TokenABI,
functionName: 'balanceOf' ,
args: [address],
watch: true // Auto-refresh on new blocks (~400ms)
});
}
export function useTokenTransfer () {
const { writeAsync } = useContractWrite ({
address: TOKEN_ADDRESS ,
abi: TokenABI,
functionName: 'transfer'
});
const transfer = async ( to : string , amount : string ) => {
const tx = await writeAsync ({
args: [to, parseEther (amount)]
});
// Fast confirmation on Panoptis Chain
return tx. wait ( 1 ); // ~400ms
};
return { transfer };
}
Leverage fast block times for responsive UIs:
// Real-time balance tracking
function useRealTimeBalance ( address : string ) {
const [ balance , setBalance ] = useState ( '0' );
useEffect (() => {
const updateBalance = async () => {
const newBalance = await provider. getBalance (address);
setBalance ( formatEther (newBalance));
};
// Update every block (~400ms)
const subscription = provider. on ( 'block' , updateBalance);
return () => provider. off ( 'block' , subscription);
}, [address]);
return balance;
}
Panoptis Chain's fast finality makes state channels more practical:
contract StateChannel {
struct Channel {
address [ 2 ] participants;
uint256 deposit;
uint256 nonce;
uint256 timeout;
}
function closeChannel (
uint256 channelId ,
uint256 finalBalance0 ,
uint256 finalBalance1 ,
bytes [] calldata signatures
) external {
// Fast settlement due to quick finality
_settleChannel (channelId, finalBalance0, finalBalance1);
}
}
Real-time price feeds become feasible:
contract FastOracle {
struct PriceData {
uint256 price;
uint256 timestamp;
uint256 blockNumber;
}
mapping ( string => PriceData) public prices;
function updatePrice ( string calldata asset , uint256 newPrice ) external onlyOracle {
prices[asset] = PriceData ({
price : newPrice,
timestamp : block .timestamp,
blockNumber : block .number
});
emit PriceUpdate (asset, newPrice, block .timestamp);
}
function getPrice ( string calldata asset ) external view returns ( uint256 ) {
PriceData memory data = prices[asset];
// Price data is fresh due to fast blocks
require ( block .timestamp - data.timestamp < 5 , "Price too old" );
return data.price;
}
}
// test/FastTest.js
describe ( "Token Contract" , function () {
it ( "should handle rapid transactions" , async function () {
const [ owner , user1 , user2 ] = await ethers. getSigners ();
const token = await Token. deploy ();
// Multiple rapid transactions possible due to fast blocks
const tx1 = await token. transfer (user1.address, 100 );
const tx2 = await token. transfer (user2.address, 200 );
// Both confirm quickly
await Promise . all ([tx1. wait ( 1 ), tx2. wait ( 1 )]);
expect ( await token. balanceOf (user1.address)).to. equal ( 100 );
expect ( await token. balanceOf (user2.address)).to. equal ( 200 );
});
});
// Test parallel transaction handling
describe ( "Parallel Execution" , function () {
it ( "should handle non-conflicting transactions in parallel" , async function () {
const users = await ethers. getSigners ();
const token = await Token. deploy ();
// Mint to different users (non-conflicting)
const mintPromises = users. slice ( 0 , 10 ). map ( user =>
token. mint (user.address, 1000 )
);
// All should succeed in parallel
const receipts = await Promise . all (
mintPromises. map ( p => p. then ( tx => tx. wait ( 1 )))
);
// Verify all transactions succeeded
receipts. forEach ( receipt => {
expect (receipt.status).to. equal ( 1 );
});
});
});
// deploy/001_deploy_contracts.js
module . exports = async ({ getNamedAccounts , deployments }) => {
const { deploy } = deployments;
const { deployer } = await getNamedAccounts ();
// Deploy core contract
const token = await deploy ( 'PanoptisToken' , {
from: deployer,
args: [ 'Panoptis Token' , 'PANO' , ethers. parseEther ( '1000000' )],
log: true ,
waitConfirmations: 1 // Fast on Panoptis Chain
});
console. log ( `Token deployed at ${ token . address }` );
};
# Fast contract verification due to quick finality
npx hardhat verify --network panoptis CONTRACT_ADDRESS "Constructor" "Arguments"
State Isolation : Design contracts where operations on different entities don't conflict
Batch Operations : Group multiple operations to amortize gas costs
Event-Driven : Use events for off-chain data and indexing
Upgrade Patterns : Implement proxy patterns for upgradability
Access Control : Use role-based permissions for admin functions
✅ Pack structs to minimize storage slots
✅ Use events for historical data
✅ Cache array lengths in loops
✅ Use unchecked
blocks where safe
✅ Batch operations when possible
✅ Minimize external calls
✅ Isolate state by user/entity
✅ Avoid global counters
✅ Use mapping over arrays for lookups
✅ Design for optimistic execution
✅ Minimize shared state dependencies
Now that you understand Panoptis Chain development patterns:
Explore Examples : Review sample contracts and dApps
Join Community : Connect with other developers building on Panoptis Chain
Deploy & Test : Start with testnet deployment and testing
Optimize : Leverage parallel execution patterns for maximum performance
Launch : Deploy to mainnet and benefit from sub-second finality
Ready to build lightning-fast dApps? Panoptis Chain provides the performance foundation for next-generation decentralized applications.